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

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: 
1.1.1.9 ! root       35: void m_cleanup(Slirp *slirp)
        !            36: {
        !            37:     struct mbuf *m, *next;
        !            38: 
        !            39:     m = slirp->m_usedlist.m_next;
        !            40:     while (m != &slirp->m_usedlist) {
        !            41:         next = m->m_next;
        !            42:         if (m->m_flags & M_EXT) {
        !            43:             free(m->m_ext);
        !            44:         }
        !            45:         free(m);
        !            46:         m = next;
        !            47:     }
        !            48:     m = slirp->m_freelist.m_next;
        !            49:     while (m != &slirp->m_freelist) {
        !            50:         next = m->m_next;
        !            51:         free(m);
        !            52:         m = next;
        !            53:     }
        !            54: }
        !            55: 
1.1       root       56: /*
                     57:  * Get an mbuf from the free list, if there are none
                     58:  * malloc one
1.1.1.3   root       59:  *
1.1       root       60:  * Because fragmentation can occur if we alloc new mbufs and
                     61:  * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
                     62:  * which tells m_free to actually free() it
                     63:  */
                     64: struct mbuf *
1.1.1.5   root       65: m_get(Slirp *slirp)
1.1       root       66: {
                     67:        register struct mbuf *m;
                     68:        int flags = 0;
1.1.1.3   root       69: 
1.1       root       70:        DEBUG_CALL("m_get");
1.1.1.3   root       71: 
1.1.1.5   root       72:        if (slirp->m_freelist.m_next == &slirp->m_freelist) {
1.1.1.4   root       73:                m = (struct mbuf *)malloc(SLIRP_MSIZE);
1.1       root       74:                if (m == NULL) goto end_error;
1.1.1.5   root       75:                slirp->mbuf_alloced++;
                     76:                if (slirp->mbuf_alloced > MBUF_THRESH)
1.1       root       77:                        flags = M_DOFREE;
1.1.1.5   root       78:                m->slirp = slirp;
1.1       root       79:        } else {
1.1.1.5   root       80:                m = slirp->m_freelist.m_next;
1.1       root       81:                remque(m);
                     82:        }
1.1.1.3   root       83: 
1.1       root       84:        /* Insert it in the used list */
1.1.1.5   root       85:        insque(m,&slirp->m_usedlist);
1.1       root       86:        m->m_flags = (flags | M_USEDLIST);
1.1.1.3   root       87: 
1.1       root       88:        /* Initialise it */
1.1.1.7   root       89:        m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
1.1       root       90:        m->m_data = m->m_dat;
                     91:        m->m_len = 0;
1.1.1.5   root       92:         m->m_nextpkt = NULL;
                     93:         m->m_prevpkt = NULL;
1.1.1.8   root       94:         m->arp_requested = false;
                     95:         m->expiration_date = (uint64_t)-1;
1.1       root       96: end_error:
                     97:        DEBUG_ARG("m = %lx", (long )m);
                     98:        return m;
                     99: }
                    100: 
                    101: void
1.1.1.5   root      102: m_free(struct mbuf *m)
1.1       root      103: {
1.1.1.3   root      104: 
1.1       root      105:   DEBUG_CALL("m_free");
                    106:   DEBUG_ARG("m = %lx", (long )m);
1.1.1.3   root      107: 
1.1       root      108:   if(m) {
                    109:        /* Remove from m_usedlist */
                    110:        if (m->m_flags & M_USEDLIST)
                    111:           remque(m);
1.1.1.3   root      112: 
1.1       root      113:        /* If it's M_EXT, free() it */
                    114:        if (m->m_flags & M_EXT)
                    115:           free(m->m_ext);
                    116: 
                    117:        /*
                    118:         * Either free() it or put it on the free list
                    119:         */
                    120:        if (m->m_flags & M_DOFREE) {
1.1.1.5   root      121:                m->slirp->mbuf_alloced--;
1.1.1.6   root      122:                free(m);
1.1       root      123:        } else if ((m->m_flags & M_FREELIST) == 0) {
1.1.1.5   root      124:                insque(m,&m->slirp->m_freelist);
1.1       root      125:                m->m_flags = M_FREELIST; /* Clobber other flags */
                    126:        }
                    127:   } /* if(m) */
                    128: }
                    129: 
                    130: /*
                    131:  * Copy data from one mbuf to the end of
                    132:  * the other.. if result is too big for one mbuf, malloc()
                    133:  * an M_EXT data segment
                    134:  */
                    135: void
1.1.1.5   root      136: m_cat(struct mbuf *m, struct mbuf *n)
1.1       root      137: {
                    138:        /*
                    139:         * If there's no room, realloc
                    140:         */
                    141:        if (M_FREEROOM(m) < n->m_len)
                    142:                m_inc(m,m->m_size+MINCSIZE);
1.1.1.3   root      143: 
1.1       root      144:        memcpy(m->m_data+m->m_len, n->m_data, n->m_len);
                    145:        m->m_len += n->m_len;
                    146: 
                    147:        m_free(n);
                    148: }
                    149: 
                    150: 
                    151: /* make m size bytes large */
                    152: void
1.1.1.5   root      153: m_inc(struct mbuf *m, int size)
1.1       root      154: {
1.1.1.2   root      155:        int datasize;
                    156: 
1.1       root      157:        /* some compiles throw up on gotos.  This one we can fake. */
                    158:         if(m->m_size>size) return;
                    159: 
                    160:         if (m->m_flags & M_EXT) {
1.1.1.2   root      161:          datasize = m->m_data - m->m_ext;
1.1       root      162:          m->m_ext = (char *)realloc(m->m_ext,size);
1.1.1.2   root      163:          m->m_data = m->m_ext + datasize;
1.1       root      164:         } else {
                    165:          char *dat;
                    166:          datasize = m->m_data - m->m_dat;
                    167:          dat = (char *)malloc(size);
                    168:          memcpy(dat, m->m_dat, m->m_size);
1.1.1.3   root      169: 
1.1       root      170:          m->m_ext = dat;
                    171:          m->m_data = m->m_ext + datasize;
                    172:          m->m_flags |= M_EXT;
                    173:         }
1.1.1.3   root      174: 
1.1       root      175:         m->m_size = size;
                    176: 
                    177: }
                    178: 
                    179: 
                    180: 
                    181: void
1.1.1.5   root      182: m_adj(struct mbuf *m, int len)
1.1       root      183: {
                    184:        if (m == NULL)
                    185:                return;
                    186:        if (len >= 0) {
                    187:                /* Trim from head */
                    188:                m->m_data += len;
                    189:                m->m_len -= len;
                    190:        } else {
                    191:                /* Trim from tail */
                    192:                len = -len;
                    193:                m->m_len -= len;
                    194:        }
                    195: }
                    196: 
                    197: 
                    198: /*
                    199:  * Copy len bytes from m, starting off bytes into n
                    200:  */
                    201: int
1.1.1.5   root      202: m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
1.1       root      203: {
                    204:        if (len > M_FREEROOM(n))
                    205:                return -1;
                    206: 
                    207:        memcpy((n->m_data + n->m_len), (m->m_data + off), len);
                    208:        n->m_len += len;
                    209:        return 0;
                    210: }
                    211: 
                    212: 
                    213: /*
                    214:  * Given a pointer into an mbuf, return the mbuf
                    215:  * XXX This is a kludge, I should eliminate the need for it
                    216:  * Fortunately, it's not used often
                    217:  */
                    218: struct mbuf *
1.1.1.5   root      219: dtom(Slirp *slirp, void *dat)
1.1       root      220: {
                    221:        struct mbuf *m;
1.1.1.3   root      222: 
1.1       root      223:        DEBUG_CALL("dtom");
                    224:        DEBUG_ARG("dat = %lx", (long )dat);
                    225: 
                    226:        /* bug corrected for M_EXT buffers */
1.1.1.5   root      227:        for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
                    228:             m = m->m_next) {
1.1       root      229:          if (m->m_flags & M_EXT) {
                    230:            if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
                    231:              return m;
                    232:          } else {
                    233:            if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
                    234:              return m;
                    235:          }
                    236:        }
1.1.1.3   root      237: 
1.1       root      238:        DEBUG_ERROR((dfd, "dtom failed"));
1.1.1.3   root      239: 
1.1       root      240:        return (struct mbuf *)0;
                    241: }

unix.superglobalmegacorp.com