Deleted Added
full compact
mbuf.c (78189) mbuf.c (81634)
1/*-
2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
1/*-
2 * Copyright (c) 1996 - 2001 Brian Somers <brian@Awfulhak.org>
3 * based on work by Toshiharu OHNO <tony-o@iij.ad.jp>
4 * Internet Initiative Japan, Inc (IIJ)
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: head/usr.sbin/ppp/mbuf.c 78189 2001-06-13 21:52:19Z brian $
28 * $FreeBSD: head/usr.sbin/ppp/mbuf.c 81634 2001-08-14 16:05:52Z brian $
29 */
30
31#include <sys/types.h>
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <sysexits.h>
37#include <termios.h>
38
39#include "defs.h"
40#include "command.h"
41#include "mbuf.h"
42#include "log.h"
43#include "descriptor.h"
44#include "prompt.h"
45#include "main.h"
46
47#define BUCKET_CHUNK 20
48#define BUCKET_HASH 256
49
50struct mbucket;
51
52struct mfree {
53 struct mbucket *next;
54 size_t count;
55};
56
57static struct mbucket {
58 union {
59 struct mbuf m;
60 struct mfree f;
61 } u;
62} *bucket[(M_MAXLEN + sizeof(struct mbuf)) / BUCKET_HASH];
63
64#define M_BINDEX(sz) (((sz) + sizeof(struct mbuf) - 1) / BUCKET_HASH)
65#define M_BUCKET(sz) (bucket + M_BINDEX(sz))
66#define M_ROUNDUP(sz) ((M_BINDEX(sz) + 1) * BUCKET_HASH)
67
68static struct memmap {
69 struct mbuf *queue;
70 size_t fragments;
71 size_t octets;
72} MemMap[MB_MAX + 1];
73
74static unsigned long long mbuf_Mallocs, mbuf_Frees;
75
76int
77m_length(struct mbuf *bp)
78{
79 int len;
80
81 for (len = 0; bp; bp = bp->m_next)
82 len += bp->m_len;
83 return len;
84}
85
86static const char *
87mbuftype(int type)
88{
89 static const char * const mbufdesc[MB_MAX] = {
29 */
30
31#include <sys/types.h>
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <sysexits.h>
37#include <termios.h>
38
39#include "defs.h"
40#include "command.h"
41#include "mbuf.h"
42#include "log.h"
43#include "descriptor.h"
44#include "prompt.h"
45#include "main.h"
46
47#define BUCKET_CHUNK 20
48#define BUCKET_HASH 256
49
50struct mbucket;
51
52struct mfree {
53 struct mbucket *next;
54 size_t count;
55};
56
57static struct mbucket {
58 union {
59 struct mbuf m;
60 struct mfree f;
61 } u;
62} *bucket[(M_MAXLEN + sizeof(struct mbuf)) / BUCKET_HASH];
63
64#define M_BINDEX(sz) (((sz) + sizeof(struct mbuf) - 1) / BUCKET_HASH)
65#define M_BUCKET(sz) (bucket + M_BINDEX(sz))
66#define M_ROUNDUP(sz) ((M_BINDEX(sz) + 1) * BUCKET_HASH)
67
68static struct memmap {
69 struct mbuf *queue;
70 size_t fragments;
71 size_t octets;
72} MemMap[MB_MAX + 1];
73
74static unsigned long long mbuf_Mallocs, mbuf_Frees;
75
76int
77m_length(struct mbuf *bp)
78{
79 int len;
80
81 for (len = 0; bp; bp = bp->m_next)
82 len += bp->m_len;
83 return len;
84}
85
86static const char *
87mbuftype(int type)
88{
89 static const char * const mbufdesc[MB_MAX] = {
90 "ip in", "ip out", "nat in", "nat out", "mp in", "mp out",
91 "vj in", "vj out", "icompd in", "icompd out", "compd in", "compd out",
92 "lqr in", "lqr out", "echo in", "echo out", "proto in", "proto out",
93 "acf in", "acf out", "sync in", "sync out", "hdlc in", "hdlc out",
94 "async in", "async out", "cbcp in", "cbcp out", "chap in", "chap out",
95 "pap in", "pap out", "ccp in", "ccp out", "ipcp in", "ipcp out",
96 "lcp in", "lcp out"
90 "ip in", "ip out", "ipv6 in", "ipv6 out", "nat in", "nat out",
91 "mp in", "mp out", "vj in", "vj out", "icompd in", "icompd out",
92 "compd in", "compd out", "lqr in", "lqr out", "echo in", "echo out",
93 "proto in", "proto out", "acf in", "acf out", "sync in", "sync out",
94 "hdlc in", "hdlc out", "async in", "async out", "cbcp in", "cbcp out",
95 "chap in", "chap out", "pap in", "pap out", "ccp in", "ccp out",
96 "ipcp in", "ipcp out", "ipv6cp in", "ipv6cp out", "lcp in", "lcp out"
97 };
98
99 return type < 0 || type >= MB_MAX ? "unknown" : mbufdesc[type];
100}
101
102struct mbuf *
103m_get(size_t m_len, int type)
104{
105 struct mbucket **mb;
106 struct mbuf *bp;
107 size_t size;
108
109 if (type > MB_MAX) {
110 log_Printf(LogERROR, "Bad mbuf type %d\n", type);
111 type = MB_UNKNOWN;
112 }
113
114 if (m_len > M_MAXLEN || m_len == 0) {
115 log_Printf(LogERROR, "Request for mbuf size %lu (\"%s\") denied !\n",
116 (u_long)m_len, mbuftype(type));
117 AbortProgram(EX_OSERR);
118 }
119
120 mb = M_BUCKET(m_len);
121 size = M_ROUNDUP(m_len);
122
123 if (*mb) {
124 /* We've got some free blocks of the right size */
125 bp = &(*mb)->u.m;
126 if (--(*mb)->u.f.count == 0)
127 *mb = (*mb)->u.f.next;
128 else {
129 ((struct mbucket *)((char *)*mb + size))->u.f.count = (*mb)->u.f.count;
130 *mb = (struct mbucket *)((char *)*mb + size);
131 (*mb)->u.f.next = NULL;
132 }
133 } else {
134 /*
135 * Allocate another chunk of mbufs, use the first and put the rest on
136 * the free list
137 */
138 *mb = (struct mbucket *)malloc(BUCKET_CHUNK * size);
139 if (*mb == NULL) {
140 log_Printf(LogALERT, "Failed to allocate memory (%lu)\n",
141 (unsigned long)BUCKET_CHUNK * size);
142 AbortProgram(EX_OSERR);
143 }
144 bp = &(*mb)->u.m;
145 *mb = (struct mbucket *)((char *)*mb + size);
146 (*mb)->u.f.count = BUCKET_CHUNK - 1;
147 (*mb)->u.f.next = NULL;
148 }
149
150 mbuf_Mallocs++;
151
152 memset(bp, '\0', sizeof(struct mbuf));
153 bp->m_size = size - sizeof *bp;
154 bp->m_len = m_len;
155 bp->m_type = type;
156
157 MemMap[type].fragments++;
158 MemMap[type].octets += bp->m_size;
159
160 return bp;
161}
162
163struct mbuf *
164m_free(struct mbuf *bp)
165{
166 struct mbucket **mb, *f;
167 struct mbuf *nbp;
168
169 if ((f = (struct mbucket *)bp) != NULL) {
170 MemMap[bp->m_type].fragments--;
171 MemMap[bp->m_type].octets -= bp->m_size;
172
173 nbp = bp->m_next;
174 mb = M_BUCKET(bp->m_size);
175 f->u.f.next = *mb;
176 f->u.f.count = 1;
177 *mb = f;
178
179 mbuf_Frees++;
180 bp = nbp;
181 }
182
183 return bp;
184}
185
186void
187m_freem(struct mbuf *bp)
188{
189 while (bp)
190 bp = m_free(bp);
191}
192
193struct mbuf *
194mbuf_Read(struct mbuf *bp, void *v, size_t len)
195{
196 int nb;
197 u_char *ptr = v;
198
199 while (bp && len > 0) {
200 if (len > bp->m_len)
201 nb = bp->m_len;
202 else
203 nb = len;
204 if (nb) {
205 memcpy(ptr, MBUF_CTOP(bp), nb);
206 ptr += nb;
207 bp->m_len -= nb;
208 len -= nb;
209 bp->m_offset += nb;
210 }
211 if (bp->m_len == 0)
212 bp = m_free(bp);
213 }
214
215 while (bp && bp->m_len == 0)
216 bp = m_free(bp);
217
218 return bp;
219}
220
221size_t
222mbuf_View(struct mbuf *bp, void *v, size_t len)
223{
224 size_t nb, l = len;
225 u_char *ptr = v;
226
227 while (bp && l > 0) {
228 if (l > bp->m_len)
229 nb = bp->m_len;
230 else
231 nb = l;
232 memcpy(ptr, MBUF_CTOP(bp), nb);
233 ptr += nb;
234 l -= nb;
235 bp = bp->m_next;
236 }
237
238 return len - l;
239}
240
241struct mbuf *
242m_prepend(struct mbuf *bp, const void *ptr, size_t len, size_t extra)
243{
244 struct mbuf *head;
245
246 if (bp && bp->m_offset) {
247 if (bp->m_offset >= len) {
248 bp->m_offset -= len;
249 bp->m_len += len;
250 memcpy(MBUF_CTOP(bp), ptr, len);
251 return bp;
252 }
253 len -= bp->m_offset;
254 memcpy(bp + 1, (const char *)ptr + len, bp->m_offset);
255 bp->m_len += bp->m_offset;
256 bp->m_offset = 0;
257 }
258
259 head = m_get(len + extra, bp ? bp->m_type : MB_UNKNOWN);
260 head->m_offset = extra;
261 head->m_len -= extra;
262 if (ptr)
263 memcpy(MBUF_CTOP(head), ptr, len);
264 head->m_next = bp;
265
266 return head;
267}
268
269struct mbuf *
270m_adj(struct mbuf *bp, ssize_t n)
271{
272 if (n > 0) {
273 while (bp) {
274 if (n < bp->m_len) {
275 bp->m_len = n;
276 bp->m_offset += n;
277 return bp;
278 }
279 n -= bp->m_len;
280 bp = m_free(bp);
281 }
282 } else {
283 if ((n = m_length(bp) + n) <= 0) {
284 m_freem(bp);
285 return NULL;
286 }
287 for (; bp; bp = bp->m_next, n -= bp->m_len)
288 if (n < bp->m_len) {
289 bp->m_len = n;
290 m_freem(bp->m_next);
291 bp->m_next = NULL;
292 break;
293 }
294 }
295
296 return bp;
297}
298
299void
300mbuf_Write(struct mbuf *bp, const void *ptr, size_t m_len)
301{
302 int plen;
303 int nb;
304
305 plen = m_length(bp);
306 if (plen < m_len)
307 m_len = plen;
308
309 while (m_len > 0) {
310 nb = (m_len < bp->m_len) ? m_len : bp->m_len;
311 memcpy(MBUF_CTOP(bp), ptr, nb);
312 m_len -= bp->m_len;
313 bp = bp->m_next;
314 }
315}
316
317int
318mbuf_Show(struct cmdargs const *arg)
319{
320 int i;
321
322 prompt_Printf(arg->prompt, "Fragments (octets) in use:\n");
323 for (i = 0; i < MB_MAX; i += 2)
324 prompt_Printf(arg->prompt, "%10.10s: %04lu (%06lu)\t"
325 "%10.10s: %04lu (%06lu)\n",
326 mbuftype(i), (u_long)MemMap[i].fragments,
327 (u_long)MemMap[i].octets, mbuftype(i+1),
328 (u_long)MemMap[i+1].fragments, (u_long)MemMap[i+1].octets);
329
330 if (i == MB_MAX)
331 prompt_Printf(arg->prompt, "%10.10s: %04lu (%06lu)\n",
332 mbuftype(i), (u_long)MemMap[i].fragments,
333 (u_long)MemMap[i].octets);
334
335 prompt_Printf(arg->prompt, "Mallocs: %llu, Frees: %llu\n",
336 mbuf_Mallocs, mbuf_Frees);
337
338 return 0;
339}
340
341struct mbuf *
342m_dequeue(struct mqueue *q)
343{
344 struct mbuf *bp;
345
346 log_Printf(LogDEBUG, "m_dequeue: queue len = %lu\n", (u_long)q->len);
347 bp = q->top;
348 if (bp) {
349 q->top = q->top->m_nextpkt;
350 q->len--;
351 if (q->top == NULL) {
352 q->last = q->top;
353 if (q->len)
354 log_Printf(LogERROR, "m_dequeue: Not zero (%lu)!!!\n",
355 (u_long)q->len);
356 }
357 bp->m_nextpkt = NULL;
358 }
359
360 return bp;
361}
362
363void
364m_enqueue(struct mqueue *queue, struct mbuf *bp)
365{
366 if (bp != NULL) {
367 if (queue->last) {
368 queue->last->m_nextpkt = bp;
369 queue->last = bp;
370 } else
371 queue->last = queue->top = bp;
372 queue->len++;
373 log_Printf(LogDEBUG, "m_enqueue: len = %lu\n", (unsigned long)queue->len);
374 }
375}
376
377struct mbuf *
378m_pullup(struct mbuf *bp)
379{
380 /* Put it all in one contigous (aligned) mbuf */
381
382 if (bp != NULL) {
383 if (bp->m_next != NULL) {
384 struct mbuf *nbp;
385 u_char *cp;
386
387 nbp = m_get(m_length(bp), bp->m_type);
388
389 for (cp = MBUF_CTOP(nbp); bp; bp = m_free(bp)) {
390 memcpy(cp, MBUF_CTOP(bp), bp->m_len);
391 cp += bp->m_len;
392 }
393 bp = nbp;
394 }
395#ifndef __i386__ /* Do any other archs not care about alignment ? */
396 else if ((bp->m_offset & (sizeof(long) - 1)) != 0) {
397 bcopy(MBUF_CTOP(bp), bp + 1, bp->m_len);
398 bp->m_offset = 0;
399 }
400#endif
401 }
402
403 return bp;
404}
405
406void
407m_settype(struct mbuf *bp, int type)
408{
409 for (; bp; bp = bp->m_next)
410 if (type != bp->m_type) {
411 MemMap[bp->m_type].fragments--;
412 MemMap[bp->m_type].octets -= bp->m_size;
413 bp->m_type = type;
414 MemMap[type].fragments++;
415 MemMap[type].octets += bp->m_size;
416 }
417}
418
419struct mbuf *
420m_append(struct mbuf *bp, const void *v, size_t sz)
421{
422 struct mbuf *m = bp;
423
424 if (m) {
425 while (m->m_next)
426 m = m->m_next;
427 if (m->m_size - m->m_len > sz)
428 m->m_len += sz;
429 else
430 m->m_next = m_prepend(NULL, v, sz, 0);
431 } else
432 bp = m_prepend(NULL, v, sz, 0);
433
434 return bp;
435}
97 };
98
99 return type < 0 || type >= MB_MAX ? "unknown" : mbufdesc[type];
100}
101
102struct mbuf *
103m_get(size_t m_len, int type)
104{
105 struct mbucket **mb;
106 struct mbuf *bp;
107 size_t size;
108
109 if (type > MB_MAX) {
110 log_Printf(LogERROR, "Bad mbuf type %d\n", type);
111 type = MB_UNKNOWN;
112 }
113
114 if (m_len > M_MAXLEN || m_len == 0) {
115 log_Printf(LogERROR, "Request for mbuf size %lu (\"%s\") denied !\n",
116 (u_long)m_len, mbuftype(type));
117 AbortProgram(EX_OSERR);
118 }
119
120 mb = M_BUCKET(m_len);
121 size = M_ROUNDUP(m_len);
122
123 if (*mb) {
124 /* We've got some free blocks of the right size */
125 bp = &(*mb)->u.m;
126 if (--(*mb)->u.f.count == 0)
127 *mb = (*mb)->u.f.next;
128 else {
129 ((struct mbucket *)((char *)*mb + size))->u.f.count = (*mb)->u.f.count;
130 *mb = (struct mbucket *)((char *)*mb + size);
131 (*mb)->u.f.next = NULL;
132 }
133 } else {
134 /*
135 * Allocate another chunk of mbufs, use the first and put the rest on
136 * the free list
137 */
138 *mb = (struct mbucket *)malloc(BUCKET_CHUNK * size);
139 if (*mb == NULL) {
140 log_Printf(LogALERT, "Failed to allocate memory (%lu)\n",
141 (unsigned long)BUCKET_CHUNK * size);
142 AbortProgram(EX_OSERR);
143 }
144 bp = &(*mb)->u.m;
145 *mb = (struct mbucket *)((char *)*mb + size);
146 (*mb)->u.f.count = BUCKET_CHUNK - 1;
147 (*mb)->u.f.next = NULL;
148 }
149
150 mbuf_Mallocs++;
151
152 memset(bp, '\0', sizeof(struct mbuf));
153 bp->m_size = size - sizeof *bp;
154 bp->m_len = m_len;
155 bp->m_type = type;
156
157 MemMap[type].fragments++;
158 MemMap[type].octets += bp->m_size;
159
160 return bp;
161}
162
163struct mbuf *
164m_free(struct mbuf *bp)
165{
166 struct mbucket **mb, *f;
167 struct mbuf *nbp;
168
169 if ((f = (struct mbucket *)bp) != NULL) {
170 MemMap[bp->m_type].fragments--;
171 MemMap[bp->m_type].octets -= bp->m_size;
172
173 nbp = bp->m_next;
174 mb = M_BUCKET(bp->m_size);
175 f->u.f.next = *mb;
176 f->u.f.count = 1;
177 *mb = f;
178
179 mbuf_Frees++;
180 bp = nbp;
181 }
182
183 return bp;
184}
185
186void
187m_freem(struct mbuf *bp)
188{
189 while (bp)
190 bp = m_free(bp);
191}
192
193struct mbuf *
194mbuf_Read(struct mbuf *bp, void *v, size_t len)
195{
196 int nb;
197 u_char *ptr = v;
198
199 while (bp && len > 0) {
200 if (len > bp->m_len)
201 nb = bp->m_len;
202 else
203 nb = len;
204 if (nb) {
205 memcpy(ptr, MBUF_CTOP(bp), nb);
206 ptr += nb;
207 bp->m_len -= nb;
208 len -= nb;
209 bp->m_offset += nb;
210 }
211 if (bp->m_len == 0)
212 bp = m_free(bp);
213 }
214
215 while (bp && bp->m_len == 0)
216 bp = m_free(bp);
217
218 return bp;
219}
220
221size_t
222mbuf_View(struct mbuf *bp, void *v, size_t len)
223{
224 size_t nb, l = len;
225 u_char *ptr = v;
226
227 while (bp && l > 0) {
228 if (l > bp->m_len)
229 nb = bp->m_len;
230 else
231 nb = l;
232 memcpy(ptr, MBUF_CTOP(bp), nb);
233 ptr += nb;
234 l -= nb;
235 bp = bp->m_next;
236 }
237
238 return len - l;
239}
240
241struct mbuf *
242m_prepend(struct mbuf *bp, const void *ptr, size_t len, size_t extra)
243{
244 struct mbuf *head;
245
246 if (bp && bp->m_offset) {
247 if (bp->m_offset >= len) {
248 bp->m_offset -= len;
249 bp->m_len += len;
250 memcpy(MBUF_CTOP(bp), ptr, len);
251 return bp;
252 }
253 len -= bp->m_offset;
254 memcpy(bp + 1, (const char *)ptr + len, bp->m_offset);
255 bp->m_len += bp->m_offset;
256 bp->m_offset = 0;
257 }
258
259 head = m_get(len + extra, bp ? bp->m_type : MB_UNKNOWN);
260 head->m_offset = extra;
261 head->m_len -= extra;
262 if (ptr)
263 memcpy(MBUF_CTOP(head), ptr, len);
264 head->m_next = bp;
265
266 return head;
267}
268
269struct mbuf *
270m_adj(struct mbuf *bp, ssize_t n)
271{
272 if (n > 0) {
273 while (bp) {
274 if (n < bp->m_len) {
275 bp->m_len = n;
276 bp->m_offset += n;
277 return bp;
278 }
279 n -= bp->m_len;
280 bp = m_free(bp);
281 }
282 } else {
283 if ((n = m_length(bp) + n) <= 0) {
284 m_freem(bp);
285 return NULL;
286 }
287 for (; bp; bp = bp->m_next, n -= bp->m_len)
288 if (n < bp->m_len) {
289 bp->m_len = n;
290 m_freem(bp->m_next);
291 bp->m_next = NULL;
292 break;
293 }
294 }
295
296 return bp;
297}
298
299void
300mbuf_Write(struct mbuf *bp, const void *ptr, size_t m_len)
301{
302 int plen;
303 int nb;
304
305 plen = m_length(bp);
306 if (plen < m_len)
307 m_len = plen;
308
309 while (m_len > 0) {
310 nb = (m_len < bp->m_len) ? m_len : bp->m_len;
311 memcpy(MBUF_CTOP(bp), ptr, nb);
312 m_len -= bp->m_len;
313 bp = bp->m_next;
314 }
315}
316
317int
318mbuf_Show(struct cmdargs const *arg)
319{
320 int i;
321
322 prompt_Printf(arg->prompt, "Fragments (octets) in use:\n");
323 for (i = 0; i < MB_MAX; i += 2)
324 prompt_Printf(arg->prompt, "%10.10s: %04lu (%06lu)\t"
325 "%10.10s: %04lu (%06lu)\n",
326 mbuftype(i), (u_long)MemMap[i].fragments,
327 (u_long)MemMap[i].octets, mbuftype(i+1),
328 (u_long)MemMap[i+1].fragments, (u_long)MemMap[i+1].octets);
329
330 if (i == MB_MAX)
331 prompt_Printf(arg->prompt, "%10.10s: %04lu (%06lu)\n",
332 mbuftype(i), (u_long)MemMap[i].fragments,
333 (u_long)MemMap[i].octets);
334
335 prompt_Printf(arg->prompt, "Mallocs: %llu, Frees: %llu\n",
336 mbuf_Mallocs, mbuf_Frees);
337
338 return 0;
339}
340
341struct mbuf *
342m_dequeue(struct mqueue *q)
343{
344 struct mbuf *bp;
345
346 log_Printf(LogDEBUG, "m_dequeue: queue len = %lu\n", (u_long)q->len);
347 bp = q->top;
348 if (bp) {
349 q->top = q->top->m_nextpkt;
350 q->len--;
351 if (q->top == NULL) {
352 q->last = q->top;
353 if (q->len)
354 log_Printf(LogERROR, "m_dequeue: Not zero (%lu)!!!\n",
355 (u_long)q->len);
356 }
357 bp->m_nextpkt = NULL;
358 }
359
360 return bp;
361}
362
363void
364m_enqueue(struct mqueue *queue, struct mbuf *bp)
365{
366 if (bp != NULL) {
367 if (queue->last) {
368 queue->last->m_nextpkt = bp;
369 queue->last = bp;
370 } else
371 queue->last = queue->top = bp;
372 queue->len++;
373 log_Printf(LogDEBUG, "m_enqueue: len = %lu\n", (unsigned long)queue->len);
374 }
375}
376
377struct mbuf *
378m_pullup(struct mbuf *bp)
379{
380 /* Put it all in one contigous (aligned) mbuf */
381
382 if (bp != NULL) {
383 if (bp->m_next != NULL) {
384 struct mbuf *nbp;
385 u_char *cp;
386
387 nbp = m_get(m_length(bp), bp->m_type);
388
389 for (cp = MBUF_CTOP(nbp); bp; bp = m_free(bp)) {
390 memcpy(cp, MBUF_CTOP(bp), bp->m_len);
391 cp += bp->m_len;
392 }
393 bp = nbp;
394 }
395#ifndef __i386__ /* Do any other archs not care about alignment ? */
396 else if ((bp->m_offset & (sizeof(long) - 1)) != 0) {
397 bcopy(MBUF_CTOP(bp), bp + 1, bp->m_len);
398 bp->m_offset = 0;
399 }
400#endif
401 }
402
403 return bp;
404}
405
406void
407m_settype(struct mbuf *bp, int type)
408{
409 for (; bp; bp = bp->m_next)
410 if (type != bp->m_type) {
411 MemMap[bp->m_type].fragments--;
412 MemMap[bp->m_type].octets -= bp->m_size;
413 bp->m_type = type;
414 MemMap[type].fragments++;
415 MemMap[type].octets += bp->m_size;
416 }
417}
418
419struct mbuf *
420m_append(struct mbuf *bp, const void *v, size_t sz)
421{
422 struct mbuf *m = bp;
423
424 if (m) {
425 while (m->m_next)
426 m = m->m_next;
427 if (m->m_size - m->m_len > sz)
428 m->m_len += sz;
429 else
430 m->m_next = m_prepend(NULL, v, sz, 0);
431 } else
432 bp = m_prepend(NULL, v, sz, 0);
433
434 return bp;
435}