File:  [Qemu by Fabrice Bellard] / qemu / slirp / mbuf.c
Revision 1.1.1.7 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:40:51 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1000, qemu0151, qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.0

    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: /*
   36:  * Get an mbuf from the free list, if there are none
   37:  * malloc one
   38:  *
   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 *
   44: m_get(Slirp *slirp)
   45: {
   46: 	register struct mbuf *m;
   47: 	int flags = 0;
   48: 
   49: 	DEBUG_CALL("m_get");
   50: 
   51: 	if (slirp->m_freelist.m_next == &slirp->m_freelist) {
   52: 		m = (struct mbuf *)malloc(SLIRP_MSIZE);
   53: 		if (m == NULL) goto end_error;
   54: 		slirp->mbuf_alloced++;
   55: 		if (slirp->mbuf_alloced > MBUF_THRESH)
   56: 			flags = M_DOFREE;
   57: 		m->slirp = slirp;
   58: 	} else {
   59: 		m = slirp->m_freelist.m_next;
   60: 		remque(m);
   61: 	}
   62: 
   63: 	/* Insert it in the used list */
   64: 	insque(m,&slirp->m_usedlist);
   65: 	m->m_flags = (flags | M_USEDLIST);
   66: 
   67: 	/* Initialise it */
   68: 	m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
   69: 	m->m_data = m->m_dat;
   70: 	m->m_len = 0;
   71:         m->m_nextpkt = NULL;
   72:         m->m_prevpkt = NULL;
   73: end_error:
   74: 	DEBUG_ARG("m = %lx", (long )m);
   75: 	return m;
   76: }
   77: 
   78: void
   79: m_free(struct mbuf *m)
   80: {
   81: 
   82:   DEBUG_CALL("m_free");
   83:   DEBUG_ARG("m = %lx", (long )m);
   84: 
   85:   if(m) {
   86: 	/* Remove from m_usedlist */
   87: 	if (m->m_flags & M_USEDLIST)
   88: 	   remque(m);
   89: 
   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) {
   98: 		m->slirp->mbuf_alloced--;
   99: 		free(m);
  100: 	} else if ((m->m_flags & M_FREELIST) == 0) {
  101: 		insque(m,&m->slirp->m_freelist);
  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
  113: m_cat(struct mbuf *m, struct mbuf *n)
  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);
  120: 
  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
  130: m_inc(struct mbuf *m, int size)
  131: {
  132: 	int datasize;
  133: 
  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) {
  138: 	  datasize = m->m_data - m->m_ext;
  139: 	  m->m_ext = (char *)realloc(m->m_ext,size);
  140: 	  m->m_data = m->m_ext + datasize;
  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);
  146: 
  147: 	  m->m_ext = dat;
  148: 	  m->m_data = m->m_ext + datasize;
  149: 	  m->m_flags |= M_EXT;
  150:         }
  151: 
  152:         m->m_size = size;
  153: 
  154: }
  155: 
  156: 
  157: 
  158: void
  159: m_adj(struct mbuf *m, int len)
  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
  179: m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
  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 *
  196: dtom(Slirp *slirp, void *dat)
  197: {
  198: 	struct mbuf *m;
  199: 
  200: 	DEBUG_CALL("dtom");
  201: 	DEBUG_ARG("dat = %lx", (long )dat);
  202: 
  203: 	/* bug corrected for M_EXT buffers */
  204: 	for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
  205: 	     m = m->m_next) {
  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: 	}
  214: 
  215: 	DEBUG_ERROR((dfd, "dtom failed"));
  216: 
  217: 	return (struct mbuf *)0;
  218: }

unix.superglobalmegacorp.com