Annotation of qemu/slirp/mbuf.c, revision 1.1.1.7

1.1       root        1: /*
                      2:  * Copyright (c) 1995 Danny Gasparovski
                      3:  *
                      4:  * Please read the file COPYRIGHT for the
                      5:  * terms and conditions of the copyright.
                      6:  */
                      7: 
                      8: /*
                      9:  * mbuf's in SLiRP are much simpler than the real mbufs in
                     10:  * FreeBSD.  They are fixed size, determined by the MTU,
                     11:  * so that one whole packet can fit.  Mbuf's cannot be
                     12:  * chained together.  If there's more data than the mbuf
                     13:  * could hold, an external malloced buffer is pointed to
                     14:  * by m_ext (and the data pointers) and M_EXT is set in
                     15:  * the flags
                     16:  */
                     17: 
                     18: #include <slirp.h>
                     19: 
1.1.1.3   root       20: #define MBUF_THRESH 30
                     21: 
                     22: /*
                     23:  * Find a nice value for msize
                     24:  * XXX if_maxlinkhdr already in mtu
                     25:  */
1.1.1.7 ! root       26: #define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6)
1.1       root       27: 
                     28: void
1.1.1.5   root       29: m_init(Slirp *slirp)
1.1       root       30: {
1.1.1.5   root       31:     slirp->m_freelist.m_next = slirp->m_freelist.m_prev = &slirp->m_freelist;
                     32:     slirp->m_usedlist.m_next = slirp->m_usedlist.m_prev = &slirp->m_usedlist;
1.1       root       33: }
                     34: 
                     35: /*
                     36:  * Get an mbuf from the free list, if there are none
                     37:  * malloc one
1.1.1.3   root       38:  *
1.1       root       39:  * Because fragmentation can occur if we alloc new mbufs and
                     40:  * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
                     41:  * which tells m_free to actually free() it
                     42:  */
                     43: struct mbuf *
1.1.1.5   root       44: m_get(Slirp *slirp)
1.1       root       45: {
                     46:        register struct mbuf *m;
                     47:        int flags = 0;
1.1.1.3   root       48: 
1.1       root       49:        DEBUG_CALL("m_get");
1.1.1.3   root       50: 
1.1.1.5   root       51:        if (slirp->m_freelist.m_next == &slirp->m_freelist) {
1.1.1.4   root       52:                m = (struct mbuf *)malloc(SLIRP_MSIZE);
1.1       root       53:                if (m == NULL) goto end_error;
1.1.1.5   root       54:                slirp->mbuf_alloced++;
                     55:                if (slirp->mbuf_alloced > MBUF_THRESH)
1.1       root       56:                        flags = M_DOFREE;
1.1.1.5   root       57:                m->slirp = slirp;
1.1       root       58:        } else {
1.1.1.5   root       59:                m = slirp->m_freelist.m_next;
1.1       root       60:                remque(m);
                     61:        }
1.1.1.3   root       62: 
1.1       root       63:        /* Insert it in the used list */
1.1.1.5   root       64:        insque(m,&slirp->m_usedlist);
1.1       root       65:        m->m_flags = (flags | M_USEDLIST);
1.1.1.3   root       66: 
1.1       root       67:        /* Initialise it */
1.1.1.7 ! root       68:        m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
1.1       root       69:        m->m_data = m->m_dat;
                     70:        m->m_len = 0;
1.1.1.5   root       71:         m->m_nextpkt = NULL;
                     72:         m->m_prevpkt = NULL;
1.1       root       73: end_error:
                     74:        DEBUG_ARG("m = %lx", (long )m);
                     75:        return m;
                     76: }
                     77: 
                     78: void
1.1.1.5   root       79: m_free(struct mbuf *m)
1.1       root       80: {
1.1.1.3   root       81: 
1.1       root       82:   DEBUG_CALL("m_free");
                     83:   DEBUG_ARG("m = %lx", (long )m);
1.1.1.3   root       84: 
1.1       root       85:   if(m) {
                     86:        /* Remove from m_usedlist */
                     87:        if (m->m_flags & M_USEDLIST)
                     88:           remque(m);
1.1.1.3   root       89: 
1.1       root       90:        /* If it's M_EXT, free() it */
                     91:        if (m->m_flags & M_EXT)
                     92:           free(m->m_ext);
                     93: 
                     94:        /*
                     95:         * Either free() it or put it on the free list
                     96:         */
                     97:        if (m->m_flags & M_DOFREE) {
1.1.1.5   root       98:                m->slirp->mbuf_alloced--;
1.1.1.6   root       99:                free(m);
1.1       root      100:        } else if ((m->m_flags & M_FREELIST) == 0) {
1.1.1.5   root      101:                insque(m,&m->slirp->m_freelist);
1.1       root      102:                m->m_flags = M_FREELIST; /* Clobber other flags */
                    103:        }
                    104:   } /* if(m) */
                    105: }
                    106: 
                    107: /*
                    108:  * Copy data from one mbuf to the end of
                    109:  * the other.. if result is too big for one mbuf, malloc()
                    110:  * an M_EXT data segment
                    111:  */
                    112: void
1.1.1.5   root      113: m_cat(struct mbuf *m, struct mbuf *n)
1.1       root      114: {
                    115:        /*
                    116:         * If there's no room, realloc
                    117:         */
                    118:        if (M_FREEROOM(m) < n->m_len)
                    119:                m_inc(m,m->m_size+MINCSIZE);
1.1.1.3   root      120: 
1.1       root      121:        memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
                    122:        m->m_len += n->m_len;
                    123: 
                    124:        m_free(n);
                    125: }
                    126: 
                    127: 
                    128: /* make m size bytes large */
                    129: void
1.1.1.5   root      130: m_inc(struct mbuf *m, int size)
1.1       root      131: {
1.1.1.2   root      132:        int datasize;
                    133: 
1.1       root      134:        /* some compiles throw up on gotos.  This one we can fake. */
                    135:         if(m->m_size>size) return;
                    136: 
                    137:         if (m->m_flags & M_EXT) {
1.1.1.2   root      138:          datasize = m->m_data - m->m_ext;
1.1       root      139:          m->m_ext = (char *)realloc(m->m_ext,size);
1.1.1.2   root      140:          m->m_data = m->m_ext + datasize;
1.1       root      141:         } else {
                    142:          char *dat;
                    143:          datasize = m->m_data - m->m_dat;
                    144:          dat = (char *)malloc(size);
                    145:          memcpy(dat, m->m_dat, m->m_size);
1.1.1.3   root      146: 
1.1       root      147:          m->m_ext = dat;
                    148:          m->m_data = m->m_ext + datasize;
                    149:          m->m_flags |= M_EXT;
                    150:         }
1.1.1.3   root      151: 
1.1       root      152:         m->m_size = size;
                    153: 
                    154: }
                    155: 
                    156: 
                    157: 
                    158: void
1.1.1.5   root      159: m_adj(struct mbuf *m, int len)
1.1       root      160: {
                    161:        if (m == NULL)
                    162:                return;
                    163:        if (len >= 0) {
                    164:                /* Trim from head */
                    165:                m->m_data += len;
                    166:                m->m_len -= len;
                    167:        } else {
                    168:                /* Trim from tail */
                    169:                len = -len;
                    170:                m->m_len -= len;
                    171:        }
                    172: }
                    173: 
                    174: 
                    175: /*
                    176:  * Copy len bytes from m, starting off bytes into n
                    177:  */
                    178: int
1.1.1.5   root      179: m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
1.1       root      180: {
                    181:        if (len > M_FREEROOM(n))
                    182:                return -1;
                    183: 
                    184:        memcpy((n->m_data + n->m_len), (m->m_data + off), len);
                    185:        n->m_len += len;
                    186:        return 0;
                    187: }
                    188: 
                    189: 
                    190: /*
                    191:  * Given a pointer into an mbuf, return the mbuf
                    192:  * XXX This is a kludge, I should eliminate the need for it
                    193:  * Fortunately, it's not used often
                    194:  */
                    195: struct mbuf *
1.1.1.5   root      196: dtom(Slirp *slirp, void *dat)
1.1       root      197: {
                    198:        struct mbuf *m;
1.1.1.3   root      199: 
1.1       root      200:        DEBUG_CALL("dtom");
                    201:        DEBUG_ARG("dat = %lx", (long )dat);
                    202: 
                    203:        /* bug corrected for M_EXT buffers */
1.1.1.5   root      204:        for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
                    205:             m = m->m_next) {
1.1       root      206:          if (m->m_flags & M_EXT) {
                    207:            if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
                    208:              return m;
                    209:          } else {
                    210:            if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
                    211:              return m;
                    212:          }
                    213:        }
1.1.1.3   root      214: 
1.1       root      215:        DEBUG_ERROR((dfd, "dtom failed"));
1.1.1.3   root      216: 
1.1       root      217:        return (struct mbuf *)0;
                    218: }

unix.superglobalmegacorp.com