mbuf.c revision 49582
1/*
2 *	      PPP Memory handling module
3 *
4 *	    Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan, Inc.  The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $Id: mbuf.c,v 1.27 1999/06/02 15:59:04 brian Exp $
21 *
22 */
23#include <sys/types.h>
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <sysexits.h>
29#include <termios.h>
30
31#include "defs.h"
32#include "command.h"
33#include "mbuf.h"
34#include "log.h"
35#include "descriptor.h"
36#include "prompt.h"
37#include "main.h"
38
39static struct memmap {
40  struct mbuf *queue;
41  int fragments, octets;
42} MemMap[MB_MAX + 1];
43
44static int totalalloced;
45static unsigned long long mbuf_Mallocs, mbuf_Frees;
46
47int
48mbuf_Length(struct mbuf *bp)
49{
50  int len;
51
52  for (len = 0; bp; bp = bp->next)
53    len += bp->cnt;
54  return len;
55}
56
57struct mbuf *
58mbuf_Alloc(int cnt, int type)
59{
60  struct mbuf *bp;
61
62  if (type > MB_MAX) {
63    log_Printf(LogERROR, "Bad mbuf type %d\n", type);
64    type = MB_UNKNOWN;
65  }
66  bp = malloc(sizeof(struct mbuf) + cnt);
67  if (bp == NULL) {
68    log_Printf(LogALERT, "failed to allocate memory: %ld\n",
69               (long)sizeof(struct mbuf));
70    AbortProgram(EX_OSERR);
71  }
72  mbuf_Mallocs++;
73  memset(bp, '\0', sizeof(struct mbuf));
74  MemMap[type].fragments++;
75  MemMap[type].octets += cnt;
76  totalalloced += cnt;
77  bp->size = bp->cnt = cnt;
78  bp->type = type;
79  return bp;
80}
81
82struct mbuf *
83mbuf_FreeSeg(struct mbuf *bp)
84{
85  struct mbuf *nbp;
86
87  if (bp) {
88    nbp = bp->next;
89    MemMap[bp->type].fragments--;
90    MemMap[bp->type].octets -= bp->size;
91    totalalloced -= bp->size;
92    free(bp);
93    mbuf_Frees++;
94    bp = nbp;
95  }
96
97  return bp;
98}
99
100void
101mbuf_Free(struct mbuf *bp)
102{
103  while (bp)
104    bp = mbuf_FreeSeg(bp);
105}
106
107struct mbuf *
108mbuf_Read(struct mbuf *bp, void *v, size_t len)
109{
110  int nb;
111  u_char *ptr = v;
112
113  while (bp && len > 0) {
114    if (len > bp->cnt)
115      nb = bp->cnt;
116    else
117      nb = len;
118    if (nb) {
119      memcpy(ptr, MBUF_CTOP(bp), nb);
120      ptr += nb;
121      bp->cnt -= nb;
122      len -= nb;
123      bp->offset += nb;
124    }
125    if (bp->cnt == 0)
126      bp = mbuf_FreeSeg(bp);
127  }
128
129  while (bp && bp->cnt == 0)
130    bp = mbuf_FreeSeg(bp);
131
132  return bp;
133}
134
135size_t
136mbuf_View(struct mbuf *bp, void *v, size_t len)
137{
138  size_t nb, l = len;
139  u_char *ptr = v;
140
141  while (bp && l > 0) {
142    if (l > bp->cnt)
143      nb = bp->cnt;
144    else
145      nb = l;
146    memcpy(ptr, MBUF_CTOP(bp), nb);
147    ptr += nb;
148    l -= nb;
149    bp = bp->next;
150  }
151
152  return len - l;
153}
154
155struct mbuf *
156mbuf_Prepend(struct mbuf *bp, const void *ptr, size_t len, size_t extra)
157{
158  struct mbuf *head;
159
160  if (bp && bp->offset) {
161    if (bp->offset >= len) {
162      bp->offset -= len;
163      bp->cnt += len;
164      memcpy(MBUF_CTOP(bp), ptr, len);
165      return bp;
166    }
167    len -= bp->offset;
168    memcpy(bp + sizeof *bp, (const char *)ptr + len, bp->offset);
169    bp->cnt += bp->offset;
170    bp->offset = 0;
171  }
172
173  head = mbuf_Alloc(len + extra, bp ? bp->type : MB_UNKNOWN);
174  head->offset = extra;
175  head->cnt -= extra;
176  memcpy(MBUF_CTOP(head), ptr, len);
177  head->next = bp;
178
179  return head;
180}
181
182struct mbuf *
183mbuf_Truncate(struct mbuf *bp, size_t n)
184{
185  if (n == 0) {
186    mbuf_Free(bp);
187    return NULL;
188  }
189
190  for (; bp; bp = bp->next, n -= bp->cnt)
191    if (n < bp->cnt) {
192      bp->cnt = n;
193      mbuf_Free(bp->next);
194      bp->next = NULL;
195      break;
196    }
197
198  return bp;
199}
200
201void
202mbuf_Write(struct mbuf *bp, const void *ptr, size_t cnt)
203{
204  int plen;
205  int nb;
206
207  plen = mbuf_Length(bp);
208  if (plen < cnt)
209    cnt = plen;
210
211  while (cnt > 0) {
212    nb = (cnt < bp->cnt) ? cnt : bp->cnt;
213    memcpy(MBUF_CTOP(bp), ptr, nb);
214    cnt -= bp->cnt;
215    bp = bp->next;
216  }
217}
218
219int
220mbuf_Show(struct cmdargs const *arg)
221{
222  int i;
223  static const char *mbuftype[] = {
224    "ip in", "ip out", "alias in", "alias out", "mp in", "mp out",
225    "vj in", "vj out", "icompd in", "icompd out", "compd in", "compd out",
226    "lqr in", "lqr out", "echo in", "echo out", "proto in", "proto out",
227    "acf in", "acf out", "sync in", "sync out", "hdlc in", "hdlc out",
228    "async in", "async out", "cbcp in", "cbcp out", "chap in", "chap out",
229    "pap in", "pap out", "ccp in", "ccp out", "ipcp in", "ipcp out",
230    "lcp in", "lcp out", "unknown"
231  };
232
233  prompt_Printf(arg->prompt, "Fragments (octets) in use:\n");
234  for (i = 0; i < MB_MAX; i += 2)
235    prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\t%10.10s: %04d (%06d)\n",
236	    mbuftype[i], MemMap[i].fragments, MemMap[i].octets,
237            mbuftype[i+1], MemMap[i+1].fragments, MemMap[i+1].octets);
238
239  if (i == MB_MAX)
240    prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\n",
241                  mbuftype[i], MemMap[i].fragments, MemMap[i].octets);
242
243  prompt_Printf(arg->prompt, "Mallocs: %llu,   Frees: %llu\n",
244                mbuf_Mallocs, mbuf_Frees);
245
246  return 0;
247}
248
249struct mbuf *
250mbuf_Dequeue(struct mqueue *q)
251{
252  struct mbuf *bp;
253
254  log_Printf(LogDEBUG, "mbuf_Dequeue: queue len = %d\n", q->qlen);
255  bp = q->top;
256  if (bp) {
257    q->top = q->top->pnext;
258    q->qlen--;
259    if (q->top == NULL) {
260      q->last = q->top;
261      if (q->qlen)
262	log_Printf(LogERROR, "mbuf_Dequeue: Not zero (%d)!!!\n", q->qlen);
263    }
264    bp->pnext = NULL;
265  }
266
267  return bp;
268}
269
270void
271mbuf_Enqueue(struct mqueue *queue, struct mbuf *bp)
272{
273  if (bp != NULL) {
274    if (queue->last) {
275      queue->last->pnext = bp;
276      queue->last = bp;
277    } else
278      queue->last = queue->top = bp;
279    queue->qlen++;
280    log_Printf(LogDEBUG, "mbuf_Enqueue: len = %d\n", queue->qlen);
281  }
282}
283
284struct mbuf *
285mbuf_Contiguous(struct mbuf *bp)
286{
287  /* Put it all in one contigous (aligned) mbuf */
288
289  if (bp != NULL) {
290    if (bp->next != NULL) {
291      struct mbuf *nbp;
292      u_char *cp;
293
294      nbp = mbuf_Alloc(mbuf_Length(bp), bp->type);
295
296      for (cp = MBUF_CTOP(nbp); bp; bp = mbuf_FreeSeg(bp)) {
297        memcpy(cp, MBUF_CTOP(bp), bp->cnt);
298        cp += bp->cnt;
299      }
300      bp = nbp;
301    }
302#ifndef __i386__	/* Do any other archs not care about alignment ? */
303    else if ((bp->offset & 0x03) != 0) {
304      bcopy(MBUF_CTOP(bp), bp + 1, bp->cnt);
305      bp->offset = 0;
306    }
307#endif
308  }
309
310  return bp;
311}
312
313void
314mbuf_SetType(struct mbuf *bp, int type)
315{
316  for (; bp; bp = bp->next)
317    if (type != bp->type) {
318      MemMap[bp->type].fragments--;
319      MemMap[bp->type].octets -= bp->size;
320      bp->type = type;
321      MemMap[type].fragments++;
322      MemMap[type].octets += bp->size;
323    }
324}
325