mbuf.c revision 49582
16059Samurai/*
26059Samurai *	      PPP Memory handling module
36059Samurai *
46059Samurai *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
56059Samurai *
66059Samurai *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
76059Samurai *
86059Samurai * Redistribution and use in source and binary forms are permitted
96059Samurai * provided that the above copyright notice and this paragraph are
106059Samurai * duplicated in all such forms and that any documentation,
116059Samurai * advertising materials, and other materials related to such
126059Samurai * distribution and use acknowledge that the software was developed
136059Samurai * by the Internet Initiative Japan, Inc.  The name of the
146059Samurai * IIJ may not be used to endorse or promote products derived
156059Samurai * from this software without specific prior written permission.
166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
196059Samurai *
2049582Sbrian * $Id: mbuf.c,v 1.27 1999/06/02 15:59:04 brian Exp $
218857Srgrimes *
226059Samurai */
2336285Sbrian#include <sys/types.h>
2430715Sbrian
2530715Sbrian#include <stdio.h>
2630715Sbrian#include <stdlib.h>
2730715Sbrian#include <string.h>
2836285Sbrian#include <sysexits.h>
2936285Sbrian#include <termios.h>
3030715Sbrian
3137009Sbrian#include "defs.h"
3231343Sbrian#include "command.h"
3330715Sbrian#include "mbuf.h"
3430715Sbrian#include "log.h"
3536285Sbrian#include "descriptor.h"
3636285Sbrian#include "prompt.h"
3736285Sbrian#include "main.h"
386059Samurai
3932663Sbrianstatic struct memmap {
406059Samurai  struct mbuf *queue;
4138471Sbrian  int fragments, octets;
4247695Sbrian} MemMap[MB_MAX + 1];
436059Samurai
446059Samuraistatic int totalalloced;
4546686Sbrianstatic unsigned long long mbuf_Mallocs, mbuf_Frees;
466059Samurai
476059Samuraiint
4846828Sbrianmbuf_Length(struct mbuf *bp)
496059Samurai{
506059Samurai  int len;
516059Samurai
526059Samurai  for (len = 0; bp; bp = bp->next)
536059Samurai    len += bp->cnt;
5446828Sbrian  return len;
556059Samurai}
566059Samurai
576059Samuraistruct mbuf *
5836285Sbrianmbuf_Alloc(int cnt, int type)
596059Samurai{
606059Samurai  struct mbuf *bp;
616059Samurai
6247695Sbrian  if (type > MB_MAX) {
6336285Sbrian    log_Printf(LogERROR, "Bad mbuf type %d\n", type);
6447695Sbrian    type = MB_UNKNOWN;
6547695Sbrian  }
6638472Sbrian  bp = malloc(sizeof(struct mbuf) + cnt);
6725630Sbrian  if (bp == NULL) {
6837210Sbrian    log_Printf(LogALERT, "failed to allocate memory: %ld\n",
6937210Sbrian               (long)sizeof(struct mbuf));
7036285Sbrian    AbortProgram(EX_OSERR);
7125630Sbrian  }
7246686Sbrian  mbuf_Mallocs++;
7330715Sbrian  memset(bp, '\0', sizeof(struct mbuf));
7438471Sbrian  MemMap[type].fragments++;
7538471Sbrian  MemMap[type].octets += cnt;
766059Samurai  totalalloced += cnt;
776059Samurai  bp->size = bp->cnt = cnt;
786059Samurai  bp->type = type;
7945103Sbrian  return bp;
806059Samurai}
816059Samurai
826059Samuraistruct mbuf *
8346686Sbrianmbuf_FreeSeg(struct mbuf *bp)
846059Samurai{
856059Samurai  struct mbuf *nbp;
866059Samurai
876059Samurai  if (bp) {
886059Samurai    nbp = bp->next;
8938471Sbrian    MemMap[bp->type].fragments--;
9038471Sbrian    MemMap[bp->type].octets -= bp->size;
916059Samurai    totalalloced -= bp->size;
926059Samurai    free(bp);
9346686Sbrian    mbuf_Frees++;
9445103Sbrian    bp = nbp;
956059Samurai  }
9645103Sbrian
9745103Sbrian  return bp;
986059Samurai}
996059Samurai
1006059Samuraivoid
10146686Sbrianmbuf_Free(struct mbuf *bp)
1026059Samurai{
1036059Samurai  while (bp)
10436285Sbrian    bp = mbuf_FreeSeg(bp);
1056059Samurai}
1066059Samurai
1076059Samuraistruct mbuf *
10846686Sbrianmbuf_Read(struct mbuf *bp, void *v, size_t len)
1096059Samurai{
1106059Samurai  int nb;
11146686Sbrian  u_char *ptr = v;
1126059Samurai
1136059Samurai  while (bp && len > 0) {
1146059Samurai    if (len > bp->cnt)
1156059Samurai      nb = bp->cnt;
1166059Samurai    else
1176059Samurai      nb = len;
11846686Sbrian    if (nb) {
11946686Sbrian      memcpy(ptr, MBUF_CTOP(bp), nb);
12046686Sbrian      ptr += nb;
12146686Sbrian      bp->cnt -= nb;
12246686Sbrian      len -= nb;
12346686Sbrian      bp->offset += nb;
12446686Sbrian    }
12543693Sbrian    if (bp->cnt == 0)
12636285Sbrian      bp = mbuf_FreeSeg(bp);
1276059Samurai  }
12846686Sbrian
12946686Sbrian  while (bp && bp->cnt == 0)
13046686Sbrian    bp = mbuf_FreeSeg(bp);
13146686Sbrian
13246686Sbrian  return bp;
1336059Samurai}
1348857Srgrimes
13546686Sbriansize_t
13646686Sbrianmbuf_View(struct mbuf *bp, void *v, size_t len)
13746686Sbrian{
13846686Sbrian  size_t nb, l = len;
13946686Sbrian  u_char *ptr = v;
14046686Sbrian
14146686Sbrian  while (bp && l > 0) {
14246686Sbrian    if (l > bp->cnt)
14346686Sbrian      nb = bp->cnt;
14446686Sbrian    else
14546686Sbrian      nb = l;
14646686Sbrian    memcpy(ptr, MBUF_CTOP(bp), nb);
14746686Sbrian    ptr += nb;
14846686Sbrian    l -= nb;
14946686Sbrian    bp = bp->next;
15046686Sbrian  }
15146686Sbrian
15246686Sbrian  return len - l;
15346686Sbrian}
15446686Sbrian
15546686Sbrianstruct mbuf *
15646686Sbrianmbuf_Prepend(struct mbuf *bp, const void *ptr, size_t len, size_t extra)
15746686Sbrian{
15846686Sbrian  struct mbuf *head;
15946686Sbrian
16046828Sbrian  if (bp && bp->offset) {
16146686Sbrian    if (bp->offset >= len) {
16246686Sbrian      bp->offset -= len;
16346686Sbrian      bp->cnt += len;
16446686Sbrian      memcpy(MBUF_CTOP(bp), ptr, len);
16546686Sbrian      return bp;
16646686Sbrian    }
16746686Sbrian    len -= bp->offset;
16846686Sbrian    memcpy(bp + sizeof *bp, (const char *)ptr + len, bp->offset);
16946686Sbrian    bp->cnt += bp->offset;
17046686Sbrian    bp->offset = 0;
17146686Sbrian  }
17246686Sbrian
17347695Sbrian  head = mbuf_Alloc(len + extra, bp ? bp->type : MB_UNKNOWN);
17446686Sbrian  head->offset = extra;
17546686Sbrian  head->cnt -= extra;
17646686Sbrian  memcpy(MBUF_CTOP(head), ptr, len);
17746686Sbrian  head->next = bp;
17846686Sbrian
17946686Sbrian  return head;
18046686Sbrian}
18146686Sbrian
18246686Sbrianstruct mbuf *
18346686Sbrianmbuf_Truncate(struct mbuf *bp, size_t n)
18446686Sbrian{
18546686Sbrian  if (n == 0) {
18646686Sbrian    mbuf_Free(bp);
18746686Sbrian    return NULL;
18846686Sbrian  }
18946686Sbrian
19046686Sbrian  for (; bp; bp = bp->next, n -= bp->cnt)
19146686Sbrian    if (n < bp->cnt) {
19246686Sbrian      bp->cnt = n;
19346686Sbrian      mbuf_Free(bp->next);
19446686Sbrian      bp->next = NULL;
19546686Sbrian      break;
19646686Sbrian    }
19746686Sbrian
19846686Sbrian  return bp;
19946686Sbrian}
20046686Sbrian
2016059Samuraivoid
20246686Sbrianmbuf_Write(struct mbuf *bp, const void *ptr, size_t cnt)
2036059Samurai{
2046059Samurai  int plen;
2056059Samurai  int nb;
2066059Samurai
20736285Sbrian  plen = mbuf_Length(bp);
2086059Samurai  if (plen < cnt)
2096059Samurai    cnt = plen;
2106059Samurai
2116059Samurai  while (cnt > 0) {
21228679Sbrian    nb = (cnt < bp->cnt) ? cnt : bp->cnt;
21330715Sbrian    memcpy(MBUF_CTOP(bp), ptr, nb);
2146059Samurai    cnt -= bp->cnt;
2156059Samurai    bp = bp->next;
2166059Samurai  }
2176059Samurai}
2186059Samurai
2196059Samuraiint
22036285Sbrianmbuf_Show(struct cmdargs const *arg)
2216059Samurai{
2226059Samurai  int i;
22336285Sbrian  static const char *mbuftype[] = {
22447695Sbrian    "ip in", "ip out", "alias in", "alias out", "mp in", "mp out",
22547695Sbrian    "vj in", "vj out", "icompd in", "icompd out", "compd in", "compd out",
22647695Sbrian    "lqr in", "lqr out", "echo in", "echo out", "proto in", "proto out",
22747695Sbrian    "acf in", "acf out", "sync in", "sync out", "hdlc in", "hdlc out",
22847695Sbrian    "async in", "async out", "cbcp in", "cbcp out", "chap in", "chap out",
22947695Sbrian    "pap in", "pap out", "ccp in", "ccp out", "ipcp in", "ipcp out",
23047695Sbrian    "lcp in", "lcp out", "unknown"
23147695Sbrian  };
2326059Samurai
23338471Sbrian  prompt_Printf(arg->prompt, "Fragments (octets) in use:\n");
23447695Sbrian  for (i = 0; i < MB_MAX; i += 2)
23538471Sbrian    prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\t%10.10s: %04d (%06d)\n",
23647695Sbrian	    mbuftype[i], MemMap[i].fragments, MemMap[i].octets,
23747695Sbrian            mbuftype[i+1], MemMap[i+1].fragments, MemMap[i+1].octets);
23826516Sbrian
23936285Sbrian  if (i == MB_MAX)
24038471Sbrian    prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\n",
24147695Sbrian                  mbuftype[i], MemMap[i].fragments, MemMap[i].octets);
24226516Sbrian
24349582Sbrian  prompt_Printf(arg->prompt, "Mallocs: %llu,   Frees: %llu\n",
24446686Sbrian                mbuf_Mallocs, mbuf_Frees);
24546686Sbrian
24626516Sbrian  return 0;
2476059Samurai}
2486059Samurai
24936285Sbrianstruct mbuf *
25036285Sbrianmbuf_Dequeue(struct mqueue *q)
25136285Sbrian{
25236285Sbrian  struct mbuf *bp;
25336285Sbrian
25436285Sbrian  log_Printf(LogDEBUG, "mbuf_Dequeue: queue len = %d\n", q->qlen);
25536285Sbrian  bp = q->top;
25636285Sbrian  if (bp) {
25736285Sbrian    q->top = q->top->pnext;
25836285Sbrian    q->qlen--;
25936285Sbrian    if (q->top == NULL) {
26036285Sbrian      q->last = q->top;
26136285Sbrian      if (q->qlen)
26236285Sbrian	log_Printf(LogERROR, "mbuf_Dequeue: Not zero (%d)!!!\n", q->qlen);
26336285Sbrian    }
26437017Sbrian    bp->pnext = NULL;
26536285Sbrian  }
26636285Sbrian
26736285Sbrian  return bp;
26836285Sbrian}
26936285Sbrian
27036285Sbrianvoid
27136285Sbrianmbuf_Enqueue(struct mqueue *queue, struct mbuf *bp)
27236285Sbrian{
27346828Sbrian  if (bp != NULL) {
27446828Sbrian    if (queue->last) {
27546828Sbrian      queue->last->pnext = bp;
27646828Sbrian      queue->last = bp;
27746828Sbrian    } else
27846828Sbrian      queue->last = queue->top = bp;
27946828Sbrian    queue->qlen++;
28046828Sbrian    log_Printf(LogDEBUG, "mbuf_Enqueue: len = %d\n", queue->qlen);
28146828Sbrian  }
28236285Sbrian}
28345103Sbrian
28445103Sbrianstruct mbuf *
28545103Sbrianmbuf_Contiguous(struct mbuf *bp)
28645103Sbrian{
28745103Sbrian  /* Put it all in one contigous (aligned) mbuf */
28845103Sbrian
28946828Sbrian  if (bp != NULL) {
29046828Sbrian    if (bp->next != NULL) {
29146828Sbrian      struct mbuf *nbp;
29246828Sbrian      u_char *cp;
29345103Sbrian
29446828Sbrian      nbp = mbuf_Alloc(mbuf_Length(bp), bp->type);
29545103Sbrian
29646828Sbrian      for (cp = MBUF_CTOP(nbp); bp; bp = mbuf_FreeSeg(bp)) {
29746828Sbrian        memcpy(cp, MBUF_CTOP(bp), bp->cnt);
29846828Sbrian        cp += bp->cnt;
29946828Sbrian      }
30046828Sbrian      bp = nbp;
30145103Sbrian    }
30245103Sbrian#ifndef __i386__	/* Do any other archs not care about alignment ? */
30346828Sbrian    else if ((bp->offset & 0x03) != 0) {
30446828Sbrian      bcopy(MBUF_CTOP(bp), bp + 1, bp->cnt);
30546828Sbrian      bp->offset = 0;
30646828Sbrian    }
30746828Sbrian#endif
30845103Sbrian  }
30945103Sbrian
31045103Sbrian  return bp;
31145103Sbrian}
31247695Sbrian
31347695Sbrianvoid
31447695Sbrianmbuf_SetType(struct mbuf *bp, int type)
31547695Sbrian{
31647695Sbrian  for (; bp; bp = bp->next)
31747695Sbrian    if (type != bp->type) {
31847695Sbrian      MemMap[bp->type].fragments--;
31947695Sbrian      MemMap[bp->type].octets -= bp->size;
32047695Sbrian      bp->type = type;
32147695Sbrian      MemMap[type].fragments++;
32247695Sbrian      MemMap[type].octets += bp->size;
32347695Sbrian    }
32447695Sbrian}
325