mbuf.c revision 54912
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 * $FreeBSD: head/usr.sbin/ppp/mbuf.c 54912 1999-12-20 20:29:47Z brian $
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  size_t fragments;
42  size_t octets;
43} MemMap[MB_MAX + 1];
44
45static int totalalloced;
46static unsigned long long mbuf_Mallocs, mbuf_Frees;
47
48int
49m_length(struct mbuf *bp)
50{
51  int len;
52
53  for (len = 0; bp; bp = bp->m_next)
54    len += bp->m_len;
55  return len;
56}
57
58struct mbuf *
59m_get(size_t m_len, int type)
60{
61  struct mbuf *bp;
62
63  if (type > MB_MAX) {
64    log_Printf(LogERROR, "Bad mbuf type %d\n", type);
65    type = MB_UNKNOWN;
66  }
67  bp = malloc(sizeof *bp + m_len);
68  if (bp == NULL) {
69    log_Printf(LogALERT, "failed to allocate memory: %ld\n",
70               (long)sizeof(struct mbuf));
71    AbortProgram(EX_OSERR);
72  }
73  mbuf_Mallocs++;
74  memset(bp, '\0', sizeof(struct mbuf));
75  MemMap[type].fragments++;
76  MemMap[type].octets += m_len;
77  totalalloced += m_len;
78  bp->m_size = bp->m_len = m_len;
79  bp->m_type = type;
80  return bp;
81}
82
83struct mbuf *
84m_free(struct mbuf *bp)
85{
86  struct mbuf *nbp;
87
88  if (bp) {
89    nbp = bp->m_next;
90    MemMap[bp->m_type].fragments--;
91    MemMap[bp->m_type].octets -= bp->m_size;
92    totalalloced -= bp->m_size;
93    free(bp);
94    mbuf_Frees++;
95    bp = nbp;
96  }
97
98  return bp;
99}
100
101void
102m_freem(struct mbuf *bp)
103{
104  while (bp)
105    bp = m_free(bp);
106}
107
108struct mbuf *
109mbuf_Read(struct mbuf *bp, void *v, size_t len)
110{
111  int nb;
112  u_char *ptr = v;
113
114  while (bp && len > 0) {
115    if (len > bp->m_len)
116      nb = bp->m_len;
117    else
118      nb = len;
119    if (nb) {
120      memcpy(ptr, MBUF_CTOP(bp), nb);
121      ptr += nb;
122      bp->m_len -= nb;
123      len -= nb;
124      bp->m_offset += nb;
125    }
126    if (bp->m_len == 0)
127      bp = m_free(bp);
128  }
129
130  while (bp && bp->m_len == 0)
131    bp = m_free(bp);
132
133  return bp;
134}
135
136size_t
137mbuf_View(struct mbuf *bp, void *v, size_t len)
138{
139  size_t nb, l = len;
140  u_char *ptr = v;
141
142  while (bp && l > 0) {
143    if (l > bp->m_len)
144      nb = bp->m_len;
145    else
146      nb = l;
147    memcpy(ptr, MBUF_CTOP(bp), nb);
148    ptr += nb;
149    l -= nb;
150    bp = bp->m_next;
151  }
152
153  return len - l;
154}
155
156struct mbuf *
157m_prepend(struct mbuf *bp, const void *ptr, size_t len, size_t extra)
158{
159  struct mbuf *head;
160
161  if (bp && bp->m_offset) {
162    if (bp->m_offset >= len) {
163      bp->m_offset -= len;
164      bp->m_len += len;
165      memcpy(MBUF_CTOP(bp), ptr, len);
166      return bp;
167    }
168    len -= bp->m_offset;
169    memcpy(bp + 1, (const char *)ptr + len, bp->m_offset);
170    bp->m_len += bp->m_offset;
171    bp->m_offset = 0;
172  }
173
174  head = m_get(len + extra, bp ? bp->m_type : MB_UNKNOWN);
175  head->m_offset = extra;
176  head->m_len -= extra;
177  memcpy(MBUF_CTOP(head), ptr, len);
178  head->m_next = bp;
179
180  return head;
181}
182
183struct mbuf *
184m_adj(struct mbuf *bp, ssize_t n)
185{
186  if (n > 0) {
187    while (bp) {
188      if (n < bp->m_len) {
189        bp->m_len = n;
190        bp->m_offset += n;
191        return bp;
192      }
193      n -= bp->m_len;
194      bp = m_free(bp);
195    }
196  } else {
197    if ((n = m_length(bp) + n) <= 0) {
198      m_freem(bp);
199      return NULL;
200    }
201    for (; bp; bp = bp->m_next, n -= bp->m_len)
202      if (n < bp->m_len) {
203        bp->m_len = n;
204        m_freem(bp->m_next);
205        bp->m_next = NULL;
206        break;
207      }
208  }
209
210  return bp;
211}
212
213void
214mbuf_Write(struct mbuf *bp, const void *ptr, size_t m_len)
215{
216  int plen;
217  int nb;
218
219  plen = m_length(bp);
220  if (plen < m_len)
221    m_len = plen;
222
223  while (m_len > 0) {
224    nb = (m_len < bp->m_len) ? m_len : bp->m_len;
225    memcpy(MBUF_CTOP(bp), ptr, nb);
226    m_len -= bp->m_len;
227    bp = bp->m_next;
228  }
229}
230
231int
232mbuf_Show(struct cmdargs const *arg)
233{
234  int i;
235  static const char *mbuftype[] = {
236    "ip in", "ip out", "nat in", "nat out", "mp in", "mp out",
237    "vj in", "vj out", "icompd in", "icompd out", "compd in", "compd out",
238    "lqr in", "lqr out", "echo in", "echo out", "proto in", "proto out",
239    "acf in", "acf out", "sync in", "sync out", "hdlc in", "hdlc out",
240    "async in", "async out", "cbcp in", "cbcp out", "chap in", "chap out",
241    "pap in", "pap out", "ccp in", "ccp out", "ipcp in", "ipcp out",
242    "lcp in", "lcp out", "unknown"
243  };
244
245  prompt_Printf(arg->prompt, "Fragments (octets) in use:\n");
246  for (i = 0; i < MB_MAX; i += 2)
247    prompt_Printf(arg->prompt, "%10.10s: %04lu (%06lu)\t"
248                  "%10.10s: %04lu (%06lu)\n",
249	          mbuftype[i], (u_long)MemMap[i].fragments,
250                  (u_long)MemMap[i].octets, mbuftype[i+1],
251                  (u_long)MemMap[i+1].fragments, (u_long)MemMap[i+1].octets);
252
253  if (i == MB_MAX)
254    prompt_Printf(arg->prompt, "%10.10s: %04lu (%06lu)\n",
255                  mbuftype[i], (u_long)MemMap[i].fragments,
256                  (u_long)MemMap[i].octets);
257
258  prompt_Printf(arg->prompt, "Mallocs: %llu,   Frees: %llu\n",
259                mbuf_Mallocs, mbuf_Frees);
260
261  return 0;
262}
263
264struct mbuf *
265m_dequeue(struct mqueue *q)
266{
267  struct mbuf *bp;
268
269  log_Printf(LogDEBUG, "m_dequeue: queue len = %lu\n", (u_long)q->len);
270  bp = q->top;
271  if (bp) {
272    q->top = q->top->m_nextpkt;
273    q->len--;
274    if (q->top == NULL) {
275      q->last = q->top;
276      if (q->len)
277	log_Printf(LogERROR, "m_dequeue: Not zero (%lu)!!!\n",
278                   (u_long)q->len);
279    }
280    bp->m_nextpkt = NULL;
281  }
282
283  return bp;
284}
285
286void
287m_enqueue(struct mqueue *queue, struct mbuf *bp)
288{
289  if (bp != NULL) {
290    if (queue->last) {
291      queue->last->m_nextpkt = bp;
292      queue->last = bp;
293    } else
294      queue->last = queue->top = bp;
295    queue->len++;
296    log_Printf(LogDEBUG, "m_enqueue: len = %d\n", queue->len);
297  }
298}
299
300struct mbuf *
301m_pullup(struct mbuf *bp)
302{
303  /* Put it all in one contigous (aligned) mbuf */
304
305  if (bp != NULL) {
306    if (bp->m_next != NULL) {
307      struct mbuf *nbp;
308      u_char *cp;
309
310      nbp = m_get(m_length(bp), bp->m_type);
311
312      for (cp = MBUF_CTOP(nbp); bp; bp = m_free(bp)) {
313        memcpy(cp, MBUF_CTOP(bp), bp->m_len);
314        cp += bp->m_len;
315      }
316      bp = nbp;
317    }
318#ifndef __i386__	/* Do any other archs not care about alignment ? */
319    else if ((bp->m_offset & (sizeof(long) - 1)) != 0) {
320      bcopy(MBUF_CTOP(bp), bp + 1, bp->m_len);
321      bp->m_offset = 0;
322    }
323#endif
324  }
325
326  return bp;
327}
328
329void
330m_settype(struct mbuf *bp, int type)
331{
332  for (; bp; bp = bp->m_next)
333    if (type != bp->m_type) {
334      MemMap[bp->m_type].fragments--;
335      MemMap[bp->m_type].octets -= bp->m_size;
336      bp->m_type = type;
337      MemMap[type].fragments++;
338      MemMap[type].octets += bp->m_size;
339    }
340}
341