mbuf.c revision 45103
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.23 1999/02/06 02:54:47 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 + 2];
43
44static int totalalloced;
45
46int
47mbuf_Length(struct mbuf * bp)
48{
49  int len;
50
51  for (len = 0; bp; bp = bp->next)
52    len += bp->cnt;
53  return (len);
54}
55
56struct mbuf *
57mbuf_Alloc(int cnt, int type)
58{
59  struct mbuf *bp;
60
61  if (type > MB_MAX)
62    log_Printf(LogERROR, "Bad mbuf type %d\n", type);
63  bp = malloc(sizeof(struct mbuf) + cnt);
64  if (bp == NULL) {
65    log_Printf(LogALERT, "failed to allocate memory: %ld\n",
66               (long)sizeof(struct mbuf));
67    AbortProgram(EX_OSERR);
68  }
69  memset(bp, '\0', sizeof(struct mbuf));
70  MemMap[type].fragments++;
71  MemMap[type].octets += cnt;
72  totalalloced += cnt;
73  bp->size = bp->cnt = cnt;
74  bp->type = type;
75  return bp;
76}
77
78struct mbuf *
79mbuf_FreeSeg(struct mbuf * bp)
80{
81  struct mbuf *nbp;
82
83  if (bp) {
84    nbp = bp->next;
85    MemMap[bp->type].fragments--;
86    MemMap[bp->type].octets -= bp->size;
87    totalalloced -= bp->size;
88    free(bp);
89    bp = nbp;
90  }
91
92  return bp;
93}
94
95void
96mbuf_Free(struct mbuf * bp)
97{
98  while (bp)
99    bp = mbuf_FreeSeg(bp);
100}
101
102struct mbuf *
103mbuf_Read(struct mbuf * bp, u_char * ptr, int len)
104{
105  int nb;
106
107  while (bp && len > 0) {
108    if (len > bp->cnt)
109      nb = bp->cnt;
110    else
111      nb = len;
112    memcpy(ptr, MBUF_CTOP(bp), nb);
113    ptr += nb;
114    bp->cnt -= nb;
115    len -= nb;
116    bp->offset += nb;
117    if (bp->cnt == 0)
118      bp = mbuf_FreeSeg(bp);
119  }
120  return (bp);
121}
122
123void
124mbuf_Write(struct mbuf * bp, u_char * ptr, int cnt)
125{
126  int plen;
127  int nb;
128
129  plen = mbuf_Length(bp);
130  if (plen < cnt)
131    cnt = plen;
132
133  while (cnt > 0) {
134    nb = (cnt < bp->cnt) ? cnt : bp->cnt;
135    memcpy(MBUF_CTOP(bp), ptr, nb);
136    cnt -= bp->cnt;
137    bp = bp->next;
138  }
139}
140
141int
142mbuf_Show(struct cmdargs const *arg)
143{
144  int i;
145  static const char *mbuftype[] = {
146    "async", "fsm", "cbcp", "hdlcout", "ipin", "echo", "lqr", "link",
147    "vjcomp", "ipq", "mp" };
148
149  prompt_Printf(arg->prompt, "Fragments (octets) in use:\n");
150  for (i = 1; i < MB_MAX; i += 2)
151    prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\t%10.10s: %04d (%06d)\n",
152	    mbuftype[i-1], MemMap[i].fragments, MemMap[i].octets, mbuftype[i],
153            MemMap[i+1].fragments, MemMap[i+1].octets);
154
155  if (i == MB_MAX)
156    prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\n",
157                  mbuftype[i-1], MemMap[i].fragments, MemMap[i].octets);
158
159  return 0;
160}
161
162void
163mbuf_Log()
164{
165  log_Printf(LogDEBUG, "mbuf_Log: mem alloced: %d\n", totalalloced);
166  log_Printf(LogDEBUG, "mbuf_Log:  1: %d  2: %d   3: %d   4: %d\n",
167	MemMap[1].octets, MemMap[2].octets, MemMap[3].octets, MemMap[4].octets);
168  log_Printf(LogDEBUG, "mbuf_Log:  5: %d  6: %d   7: %d   8: %d\n",
169	MemMap[5].octets, MemMap[6].octets, MemMap[7].octets, MemMap[8].octets);
170  log_Printf(LogDEBUG, "mbuf_Log:  9: %d 10: %d  11: %d\n",
171	MemMap[9].octets, MemMap[10].octets, MemMap[11].octets);
172}
173
174struct mbuf *
175mbuf_Dequeue(struct mqueue *q)
176{
177  struct mbuf *bp;
178
179  log_Printf(LogDEBUG, "mbuf_Dequeue: queue len = %d\n", q->qlen);
180  bp = q->top;
181  if (bp) {
182    q->top = q->top->pnext;
183    q->qlen--;
184    if (q->top == NULL) {
185      q->last = q->top;
186      if (q->qlen)
187	log_Printf(LogERROR, "mbuf_Dequeue: Not zero (%d)!!!\n", q->qlen);
188    }
189    bp->pnext = NULL;
190  }
191
192  return bp;
193}
194
195void
196mbuf_Enqueue(struct mqueue *queue, struct mbuf *bp)
197{
198  if (queue->last) {
199    queue->last->pnext = bp;
200    queue->last = bp;
201  } else
202    queue->last = queue->top = bp;
203  queue->qlen++;
204  log_Printf(LogDEBUG, "mbuf_Enqueue: len = %d\n", queue->qlen);
205}
206
207struct mbuf *
208mbuf_Contiguous(struct mbuf *bp)
209{
210  /* Put it all in one contigous (aligned) mbuf */
211
212  if (bp->next != NULL) {
213    struct mbuf *nbp;
214    u_char *cp;
215
216    nbp = mbuf_Alloc(mbuf_Length(bp), bp->type);
217
218    for (cp = MBUF_CTOP(nbp); bp; bp = mbuf_FreeSeg(bp)) {
219      memcpy(cp, MBUF_CTOP(bp), bp->cnt);
220      cp += bp->cnt;
221    }
222    bp = nbp;
223  }
224#ifndef __i386__	/* Do any other archs not care about alignment ? */
225  else if ((bp->offset & 0x03) != 0) {
226    bcopy(MBUF_CTOP(bp), bp + 1, bp->cnt);
227    bp->offset = 0;
228  }
229#endif
230
231  return bp;
232}
233