mbuf.c revision 49582
16059Samurai/* 26059Samurai * PPP Memory handling module 36059Samurai * 46059Samurai * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 56059Samurai * 66059Samurai * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 76059Samurai * 86059Samurai * Redistribution and use in source and binary forms are permitted 96059Samurai * provided that the above copyright notice and this paragraph are 106059Samurai * duplicated in all such forms and that any documentation, 116059Samurai * advertising materials, and other materials related to such 126059Samurai * distribution and use acknowledge that the software was developed 136059Samurai * by the Internet Initiative Japan, Inc. The name of the 146059Samurai * IIJ may not be used to endorse or promote products derived 156059Samurai * from this software without specific prior written permission. 166059Samurai * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 176059Samurai * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 186059Samurai * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 196059Samurai * 2049582Sbrian * $Id: mbuf.c,v 1.27 1999/06/02 15:59:04 brian Exp $ 218857Srgrimes * 226059Samurai */ 2336285Sbrian#include <sys/types.h> 2430715Sbrian 2530715Sbrian#include <stdio.h> 2630715Sbrian#include <stdlib.h> 2730715Sbrian#include <string.h> 2836285Sbrian#include <sysexits.h> 2936285Sbrian#include <termios.h> 3030715Sbrian 3137009Sbrian#include "defs.h" 3231343Sbrian#include "command.h" 3330715Sbrian#include "mbuf.h" 3430715Sbrian#include "log.h" 3536285Sbrian#include "descriptor.h" 3636285Sbrian#include "prompt.h" 3736285Sbrian#include "main.h" 386059Samurai 3932663Sbrianstatic struct memmap { 406059Samurai struct mbuf *queue; 4138471Sbrian int fragments, octets; 4247695Sbrian} MemMap[MB_MAX + 1]; 436059Samurai 446059Samuraistatic int totalalloced; 4546686Sbrianstatic unsigned long long mbuf_Mallocs, mbuf_Frees; 466059Samurai 476059Samuraiint 4846828Sbrianmbuf_Length(struct mbuf *bp) 496059Samurai{ 506059Samurai int len; 516059Samurai 526059Samurai for (len = 0; bp; bp = bp->next) 536059Samurai len += bp->cnt; 5446828Sbrian return len; 556059Samurai} 566059Samurai 576059Samuraistruct mbuf * 5836285Sbrianmbuf_Alloc(int cnt, int type) 596059Samurai{ 606059Samurai struct mbuf *bp; 616059Samurai 6247695Sbrian if (type > MB_MAX) { 6336285Sbrian log_Printf(LogERROR, "Bad mbuf type %d\n", type); 6447695Sbrian type = MB_UNKNOWN; 6547695Sbrian } 6638472Sbrian bp = malloc(sizeof(struct mbuf) + cnt); 6725630Sbrian if (bp == NULL) { 6837210Sbrian log_Printf(LogALERT, "failed to allocate memory: %ld\n", 6937210Sbrian (long)sizeof(struct mbuf)); 7036285Sbrian AbortProgram(EX_OSERR); 7125630Sbrian } 7246686Sbrian mbuf_Mallocs++; 7330715Sbrian memset(bp, '\0', sizeof(struct mbuf)); 7438471Sbrian MemMap[type].fragments++; 7538471Sbrian MemMap[type].octets += cnt; 766059Samurai totalalloced += cnt; 776059Samurai bp->size = bp->cnt = cnt; 786059Samurai bp->type = type; 7945103Sbrian return bp; 806059Samurai} 816059Samurai 826059Samuraistruct mbuf * 8346686Sbrianmbuf_FreeSeg(struct mbuf *bp) 846059Samurai{ 856059Samurai struct mbuf *nbp; 866059Samurai 876059Samurai if (bp) { 886059Samurai nbp = bp->next; 8938471Sbrian MemMap[bp->type].fragments--; 9038471Sbrian MemMap[bp->type].octets -= bp->size; 916059Samurai totalalloced -= bp->size; 926059Samurai free(bp); 9346686Sbrian mbuf_Frees++; 9445103Sbrian bp = nbp; 956059Samurai } 9645103Sbrian 9745103Sbrian return bp; 986059Samurai} 996059Samurai 1006059Samuraivoid 10146686Sbrianmbuf_Free(struct mbuf *bp) 1026059Samurai{ 1036059Samurai while (bp) 10436285Sbrian bp = mbuf_FreeSeg(bp); 1056059Samurai} 1066059Samurai 1076059Samuraistruct mbuf * 10846686Sbrianmbuf_Read(struct mbuf *bp, void *v, size_t len) 1096059Samurai{ 1106059Samurai int nb; 11146686Sbrian u_char *ptr = v; 1126059Samurai 1136059Samurai while (bp && len > 0) { 1146059Samurai if (len > bp->cnt) 1156059Samurai nb = bp->cnt; 1166059Samurai else 1176059Samurai nb = len; 11846686Sbrian if (nb) { 11946686Sbrian memcpy(ptr, MBUF_CTOP(bp), nb); 12046686Sbrian ptr += nb; 12146686Sbrian bp->cnt -= nb; 12246686Sbrian len -= nb; 12346686Sbrian bp->offset += nb; 12446686Sbrian } 12543693Sbrian if (bp->cnt == 0) 12636285Sbrian bp = mbuf_FreeSeg(bp); 1276059Samurai } 12846686Sbrian 12946686Sbrian while (bp && bp->cnt == 0) 13046686Sbrian bp = mbuf_FreeSeg(bp); 13146686Sbrian 13246686Sbrian return bp; 1336059Samurai} 1348857Srgrimes 13546686Sbriansize_t 13646686Sbrianmbuf_View(struct mbuf *bp, void *v, size_t len) 13746686Sbrian{ 13846686Sbrian size_t nb, l = len; 13946686Sbrian u_char *ptr = v; 14046686Sbrian 14146686Sbrian while (bp && l > 0) { 14246686Sbrian if (l > bp->cnt) 14346686Sbrian nb = bp->cnt; 14446686Sbrian else 14546686Sbrian nb = l; 14646686Sbrian memcpy(ptr, MBUF_CTOP(bp), nb); 14746686Sbrian ptr += nb; 14846686Sbrian l -= nb; 14946686Sbrian bp = bp->next; 15046686Sbrian } 15146686Sbrian 15246686Sbrian return len - l; 15346686Sbrian} 15446686Sbrian 15546686Sbrianstruct mbuf * 15646686Sbrianmbuf_Prepend(struct mbuf *bp, const void *ptr, size_t len, size_t extra) 15746686Sbrian{ 15846686Sbrian struct mbuf *head; 15946686Sbrian 16046828Sbrian if (bp && bp->offset) { 16146686Sbrian if (bp->offset >= len) { 16246686Sbrian bp->offset -= len; 16346686Sbrian bp->cnt += len; 16446686Sbrian memcpy(MBUF_CTOP(bp), ptr, len); 16546686Sbrian return bp; 16646686Sbrian } 16746686Sbrian len -= bp->offset; 16846686Sbrian memcpy(bp + sizeof *bp, (const char *)ptr + len, bp->offset); 16946686Sbrian bp->cnt += bp->offset; 17046686Sbrian bp->offset = 0; 17146686Sbrian } 17246686Sbrian 17347695Sbrian head = mbuf_Alloc(len + extra, bp ? bp->type : MB_UNKNOWN); 17446686Sbrian head->offset = extra; 17546686Sbrian head->cnt -= extra; 17646686Sbrian memcpy(MBUF_CTOP(head), ptr, len); 17746686Sbrian head->next = bp; 17846686Sbrian 17946686Sbrian return head; 18046686Sbrian} 18146686Sbrian 18246686Sbrianstruct mbuf * 18346686Sbrianmbuf_Truncate(struct mbuf *bp, size_t n) 18446686Sbrian{ 18546686Sbrian if (n == 0) { 18646686Sbrian mbuf_Free(bp); 18746686Sbrian return NULL; 18846686Sbrian } 18946686Sbrian 19046686Sbrian for (; bp; bp = bp->next, n -= bp->cnt) 19146686Sbrian if (n < bp->cnt) { 19246686Sbrian bp->cnt = n; 19346686Sbrian mbuf_Free(bp->next); 19446686Sbrian bp->next = NULL; 19546686Sbrian break; 19646686Sbrian } 19746686Sbrian 19846686Sbrian return bp; 19946686Sbrian} 20046686Sbrian 2016059Samuraivoid 20246686Sbrianmbuf_Write(struct mbuf *bp, const void *ptr, size_t cnt) 2036059Samurai{ 2046059Samurai int plen; 2056059Samurai int nb; 2066059Samurai 20736285Sbrian plen = mbuf_Length(bp); 2086059Samurai if (plen < cnt) 2096059Samurai cnt = plen; 2106059Samurai 2116059Samurai while (cnt > 0) { 21228679Sbrian nb = (cnt < bp->cnt) ? cnt : bp->cnt; 21330715Sbrian memcpy(MBUF_CTOP(bp), ptr, nb); 2146059Samurai cnt -= bp->cnt; 2156059Samurai bp = bp->next; 2166059Samurai } 2176059Samurai} 2186059Samurai 2196059Samuraiint 22036285Sbrianmbuf_Show(struct cmdargs const *arg) 2216059Samurai{ 2226059Samurai int i; 22336285Sbrian static const char *mbuftype[] = { 22447695Sbrian "ip in", "ip out", "alias in", "alias out", "mp in", "mp out", 22547695Sbrian "vj in", "vj out", "icompd in", "icompd out", "compd in", "compd out", 22647695Sbrian "lqr in", "lqr out", "echo in", "echo out", "proto in", "proto out", 22747695Sbrian "acf in", "acf out", "sync in", "sync out", "hdlc in", "hdlc out", 22847695Sbrian "async in", "async out", "cbcp in", "cbcp out", "chap in", "chap out", 22947695Sbrian "pap in", "pap out", "ccp in", "ccp out", "ipcp in", "ipcp out", 23047695Sbrian "lcp in", "lcp out", "unknown" 23147695Sbrian }; 2326059Samurai 23338471Sbrian prompt_Printf(arg->prompt, "Fragments (octets) in use:\n"); 23447695Sbrian for (i = 0; i < MB_MAX; i += 2) 23538471Sbrian prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\t%10.10s: %04d (%06d)\n", 23647695Sbrian mbuftype[i], MemMap[i].fragments, MemMap[i].octets, 23747695Sbrian mbuftype[i+1], MemMap[i+1].fragments, MemMap[i+1].octets); 23826516Sbrian 23936285Sbrian if (i == MB_MAX) 24038471Sbrian prompt_Printf(arg->prompt, "%10.10s: %04d (%06d)\n", 24147695Sbrian mbuftype[i], MemMap[i].fragments, MemMap[i].octets); 24226516Sbrian 24349582Sbrian prompt_Printf(arg->prompt, "Mallocs: %llu, Frees: %llu\n", 24446686Sbrian mbuf_Mallocs, mbuf_Frees); 24546686Sbrian 24626516Sbrian return 0; 2476059Samurai} 2486059Samurai 24936285Sbrianstruct mbuf * 25036285Sbrianmbuf_Dequeue(struct mqueue *q) 25136285Sbrian{ 25236285Sbrian struct mbuf *bp; 25336285Sbrian 25436285Sbrian log_Printf(LogDEBUG, "mbuf_Dequeue: queue len = %d\n", q->qlen); 25536285Sbrian bp = q->top; 25636285Sbrian if (bp) { 25736285Sbrian q->top = q->top->pnext; 25836285Sbrian q->qlen--; 25936285Sbrian if (q->top == NULL) { 26036285Sbrian q->last = q->top; 26136285Sbrian if (q->qlen) 26236285Sbrian log_Printf(LogERROR, "mbuf_Dequeue: Not zero (%d)!!!\n", q->qlen); 26336285Sbrian } 26437017Sbrian bp->pnext = NULL; 26536285Sbrian } 26636285Sbrian 26736285Sbrian return bp; 26836285Sbrian} 26936285Sbrian 27036285Sbrianvoid 27136285Sbrianmbuf_Enqueue(struct mqueue *queue, struct mbuf *bp) 27236285Sbrian{ 27346828Sbrian if (bp != NULL) { 27446828Sbrian if (queue->last) { 27546828Sbrian queue->last->pnext = bp; 27646828Sbrian queue->last = bp; 27746828Sbrian } else 27846828Sbrian queue->last = queue->top = bp; 27946828Sbrian queue->qlen++; 28046828Sbrian log_Printf(LogDEBUG, "mbuf_Enqueue: len = %d\n", queue->qlen); 28146828Sbrian } 28236285Sbrian} 28345103Sbrian 28445103Sbrianstruct mbuf * 28545103Sbrianmbuf_Contiguous(struct mbuf *bp) 28645103Sbrian{ 28745103Sbrian /* Put it all in one contigous (aligned) mbuf */ 28845103Sbrian 28946828Sbrian if (bp != NULL) { 29046828Sbrian if (bp->next != NULL) { 29146828Sbrian struct mbuf *nbp; 29246828Sbrian u_char *cp; 29345103Sbrian 29446828Sbrian nbp = mbuf_Alloc(mbuf_Length(bp), bp->type); 29545103Sbrian 29646828Sbrian for (cp = MBUF_CTOP(nbp); bp; bp = mbuf_FreeSeg(bp)) { 29746828Sbrian memcpy(cp, MBUF_CTOP(bp), bp->cnt); 29846828Sbrian cp += bp->cnt; 29946828Sbrian } 30046828Sbrian bp = nbp; 30145103Sbrian } 30245103Sbrian#ifndef __i386__ /* Do any other archs not care about alignment ? */ 30346828Sbrian else if ((bp->offset & 0x03) != 0) { 30446828Sbrian bcopy(MBUF_CTOP(bp), bp + 1, bp->cnt); 30546828Sbrian bp->offset = 0; 30646828Sbrian } 30746828Sbrian#endif 30845103Sbrian } 30945103Sbrian 31045103Sbrian return bp; 31145103Sbrian} 31247695Sbrian 31347695Sbrianvoid 31447695Sbrianmbuf_SetType(struct mbuf *bp, int type) 31547695Sbrian{ 31647695Sbrian for (; bp; bp = bp->next) 31747695Sbrian if (type != bp->type) { 31847695Sbrian MemMap[bp->type].fragments--; 31947695Sbrian MemMap[bp->type].octets -= bp->size; 32047695Sbrian bp->type = type; 32147695Sbrian MemMap[type].fragments++; 32247695Sbrian MemMap[type].octets += bp->size; 32347695Sbrian } 32447695Sbrian} 325