File:  [Qemu by Fabrice Bellard] / qemu / slirp / mbuf.c
Revision 1.1.1.9 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:51:42 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1101, HEAD
qemu 1.1.1

    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: 
   20: #define MBUF_THRESH 30
   21: 
   22: /*
   23:  * Find a nice value for msize
   24:  * XXX if_maxlinkhdr already in mtu
   25:  */
   26: #define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6)
   27: 
   28: void
   29: m_init(Slirp *slirp)
   30: {
   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;
   33: }
   34: 
   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: 
   56: /*
   57:  * Get an mbuf from the free list, if there are none
   58:  * malloc one
   59:  *
   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 *
   65: m_get(Slirp *slirp)
   66: {
   67: 	register struct mbuf *m;
   68: 	int flags = 0;
   69: 
   70: 	DEBUG_CALL("m_get");
   71: 
   72: 	if (slirp->m_freelist.m_next == &slirp->m_freelist) {
   73: 		m = (struct mbuf *)malloc(SLIRP_MSIZE);
   74: 		if (m == NULL) goto end_error;
   75: 		slirp->mbuf_alloced++;
   76: 		if (slirp->mbuf_alloced > MBUF_THRESH)
   77: 			flags = M_DOFREE;
   78: 		m->slirp = slirp;
   79: 	} else {
   80: 		m = slirp->m_freelist.m_next;
   81: 		remque(m);
   82: 	}
   83: 
   84: 	/* Insert it in the used list */
   85: 	insque(m,&slirp->m_usedlist);
   86: 	m->m_flags = (flags | M_USEDLIST);
   87: 
   88: 	/* Initialise it */
   89: 	m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
   90: 	m->m_data = m->m_dat;
   91: 	m->m_len = 0;
   92:         m->m_nextpkt = NULL;
   93:         m->m_prevpkt = NULL;
   94:         m->arp_requested = false;
   95:         m->expiration_date = (uint64_t)-1;
   96: end_error:
   97: 	DEBUG_ARG("m = %lx", (long )m);
   98: 	return m;
   99: }
  100: 
  101: void
  102: m_free(struct mbuf *m)
  103: {
  104: 
  105:   DEBUG_CALL("m_free");
  106:   DEBUG_ARG("m = %lx", (long )m);
  107: 
  108:   if(m) {
  109: 	/* Remove from m_usedlist */
  110: 	if (m->m_flags & M_USEDLIST)
  111: 	   remque(m);
  112: 
  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) {
  121: 		m->slirp->mbuf_alloced--;
  122: 		free(m);
  123: 	} else if ((m->m_flags & M_FREELIST) == 0) {
  124: 		insque(m,&m->slirp->m_freelist);
  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
  136: m_cat(struct mbuf *m, struct mbuf *n)
  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);
  143: 
  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
  153: m_inc(struct mbuf *m, int size)
  154: {
  155: 	int datasize;
  156: 
  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) {
  161: 	  datasize = m->m_data - m->m_ext;
  162: 	  m->m_ext = (char *)realloc(m->m_ext,size);
  163: 	  m->m_data = m->m_ext + datasize;
  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);
  169: 
  170: 	  m->m_ext = dat;
  171: 	  m->m_data = m->m_ext + datasize;
  172: 	  m->m_flags |= M_EXT;
  173:         }
  174: 
  175:         m->m_size = size;
  176: 
  177: }
  178: 
  179: 
  180: 
  181: void
  182: m_adj(struct mbuf *m, int len)
  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
  202: m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
  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 *
  219: dtom(Slirp *slirp, void *dat)
  220: {
  221: 	struct mbuf *m;
  222: 
  223: 	DEBUG_CALL("dtom");
  224: 	DEBUG_ARG("dat = %lx", (long )dat);
  225: 
  226: 	/* bug corrected for M_EXT buffers */
  227: 	for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
  228: 	     m = m->m_next) {
  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: 	}
  237: 
  238: 	DEBUG_ERROR((dfd, "dtom failed"));
  239: 
  240: 	return (struct mbuf *)0;
  241: }

unix.superglobalmegacorp.com