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