32 #include <sys/cdefs.h> 
   35 #include "opt_param.h" 
   36 #include "opt_mbuf_stress_test.h" 
   37 #include "opt_mbuf_profiling.h" 
   39 #include <sys/param.h> 
   40 #include <sys/systm.h> 
   41 #include <sys/kernel.h> 
   42 #include <sys/limits.h> 
   44 #include <sys/malloc.h> 
   46 #include <sys/sysctl.h> 
   47 #include <sys/domain.h> 
   48 #include <sys/protosw.h> 
   55 #ifdef MBUF_STRESS_TEST 
   60 int     m_defragrandomfailures;
 
   67            &
max_linkhdr, 0, 
"Size of largest link layer header");
 
   69            &
max_protohdr, 0, 
"Size of largest protocol layer header");
 
   71            &
max_hdr, 0, 
"Size of largest link plus protocol header");
 
   73            &
max_datalen, 0, 
"Minimum space left in mbuf after max_hdr");
 
   74 #ifdef MBUF_STRESS_TEST 
   75 SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragpackets, CTLFLAG_RD,
 
   76            &m_defragpackets, 0, 
"");
 
   77 SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragbytes, CTLFLAG_RD,
 
   78            &m_defragbytes, 0, 
"");
 
   79 SYSCTL_INT(_kern_ipc, OID_AUTO, m_defraguseless, CTLFLAG_RD,
 
   80            &m_defraguseless, 0, 
"");
 
   81 SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragfailure, CTLFLAG_RD,
 
   82            &m_defragfailure, 0, 
"");
 
   83 SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragrandomfailures, CTLFLAG_RW,
 
   84            &m_defragrandomfailures, 0, 
"");
 
   95 m_getm2(
struct mbuf *m, 
int len, 
int how, 
short type, 
int flags)
 
   97         struct mbuf *mb, *nm = NULL, *mtail = NULL;
 
   99         KASSERT(len >= 0, (
"%s: len is < 0", __func__));
 
  102         flags &= (M_PKTHDR | M_EOR);
 
  105         if ((flags & M_PKTHDR) && m != NULL)
 
  111                         mb = m_getjcl(how, type, (flags & M_PKTHDR),
 
  113                 else if (len >= MINCLSIZE)
 
  114                         mb = m_getcl(how, type, (flags & M_PKTHDR));
 
  115                 else if (flags & M_PKTHDR)
 
  116                         mb = m_gethdr(how, type);
 
  118                         mb = m_get(how, type);
 
  128                 len -= (mb->m_flags & M_EXT) ? mb->m_ext.ext_size :
 
  129                         ((mb->m_flags & M_PKTHDR) ? MHLEN : MLEN);
 
  138                 mtail->m_flags |= M_EOR;  
 
  142                 for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next)
 
  145                 mtail->m_flags &= ~M_EOR;
 
  187     void (*freef)(
void *, 
void *), 
void *arg1, 
void *arg2, 
int flags, 
int type)
 
  189         KASSERT(type != EXT_CLUSTER, (
"%s: EXT_CLUSTER not allowed", __func__));
 
  191         if (type != EXT_EXTREF)
 
  193         if (mb->m_ext.ref_cnt != NULL) {
 
  194                 *(mb->m_ext.ref_cnt) = 1;
 
  195                 mb->m_flags |= (M_EXT | flags);
 
  196                 mb->m_ext.ext_buf = 
buf;
 
  197                 mb->m_data = mb->m_ext.ext_buf;
 
  198                 mb->m_ext.ext_size = size;
 
  199                 mb->m_ext.ext_free = freef;
 
  200                 mb->m_ext.ext_arg1 = arg1;
 
  201                 mb->m_ext.ext_arg2 = arg2;
 
  202                 mb->m_ext.ext_type = 
type;
 
  215         KASSERT((m->m_flags & M_EXT) == M_EXT, (
"%s: M_EXT not set", __func__));
 
  216         KASSERT(m->m_ext.ref_cnt != NULL, (
"%s: ref_cnt not set", __func__));
 
  222         skipmbuf = (m->m_flags & M_NOFREE);
 
  225         if (*(m->m_ext.ref_cnt) == 1 ||
 
  226             atomic_fetchadd_int(m->m_ext.ref_cnt, -1) == 1) {
 
  227                 switch (m->m_ext.ext_type) {
 
  229                         if (*(m->m_ext.ref_cnt) == 0)
 
  230                                 *(m->m_ext.ref_cnt) = 1;
 
  249                         *(m->m_ext.ref_cnt) = 0;
 
  254                         KASSERT(m->m_ext.ext_free != NULL,
 
  255                                 (
"%s: ext_free not set", __func__));
 
  256                         (*(m->m_ext.ext_free))(m->m_ext.ext_arg1,
 
  260                         KASSERT(m->m_ext.ext_type == 0,
 
  261                                 (
"%s: unknown ext_type", __func__));
 
  271         m->m_ext.ext_buf = NULL;
 
  272         m->m_ext.ext_free = NULL;
 
  273         m->m_ext.ext_arg1 = NULL;
 
  274         m->m_ext.ext_arg2 = NULL;
 
  275         m->m_ext.ref_cnt = NULL;
 
  276         m->m_ext.ext_size = 0;
 
  277         m->m_ext.ext_type = 0;
 
  278         m->m_flags &= ~M_EXT;
 
  289         KASSERT((m->m_flags & M_EXT) == M_EXT, (
"%s: M_EXT not set", __func__));
 
  290         KASSERT(m->m_ext.ref_cnt != NULL, (
"%s: ref_cnt not set", __func__));
 
  291         KASSERT((n->m_flags & M_EXT) == 0, (
"%s: M_EXT set", __func__));
 
  293         if (*(m->m_ext.ref_cnt) == 1)
 
  294                 *(m->m_ext.ref_cnt) += 1;
 
  296                 atomic_add_int(m->m_ext.ref_cnt, 1);
 
  297         n->m_ext.ext_buf = m->m_ext.ext_buf;
 
  298         n->m_ext.ext_free = m->m_ext.ext_free;
 
  299         n->m_ext.ext_arg1 = m->m_ext.ext_arg1;
 
  300         n->m_ext.ext_arg2 = m->m_ext.ext_arg2;
 
  301         n->m_ext.ext_size = m->m_ext.ext_size;
 
  302         n->m_ext.ref_cnt = m->m_ext.ref_cnt;
 
  303         n->m_ext.ext_type = m->m_ext.ext_type;
 
  305         n->m_flags |= m->m_flags & M_RDONLY;
 
  318         for (m = all ? m0 : m0->m_next; m != NULL; m = m->m_next) {
 
  319                 if (m->m_flags & M_PKTHDR) {
 
  321                         m->m_flags &= ~M_PKTHDR;
 
  322                         bzero(&m->m_pkthdr, 
sizeof(
struct pkthdr));
 
  324                 if (m != m0 && m->m_nextpkt != NULL) {
 
  325                         KASSERT(m->m_nextpkt == NULL,
 
  326                             (
"%s: m_nextpkt not NULL", __func__));
 
  330                 m->m_flags = m->m_flags & (M_EXT|M_RDONLY|M_FREELIST|M_NOFREE);
 
  349 #define M_SANITY_ACTION(s)      panic("mbuf %p: " s, m) 
  351 #define M_SANITY_ACTION(s)      printf("mbuf %p: " s, m) 
  354         for (m = m0; m != NULL; m = m->m_next) {
 
  360                 a = ((m->m_flags & M_EXT) ? m->m_ext.ext_buf :
 
  361                         ((m->m_flags & M_PKTHDR) ? (caddr_t)(&m->m_pktdat) :
 
  362                          (caddr_t)(&m->m_dat)) );
 
  363                 b = (caddr_t)(a + (m->m_flags & M_EXT ? m->m_ext.ext_size :
 
  364                         ((m->m_flags & M_PKTHDR) ? MHLEN : MLEN)));
 
  365                 if ((caddr_t)m->m_data < a)
 
  367                 if ((caddr_t)m->m_data > b)
 
  369                 if ((caddr_t)m->m_data + m->m_len > b)
 
  371                 if ((m->m_flags & M_PKTHDR) && m->m_pkthdr.header) {
 
  372                         if ((caddr_t)m->m_pkthdr.header < a ||
 
  373                             (caddr_t)m->m_pkthdr.header > b)
 
  378                 if (m != m0 && m->m_nextpkt != NULL) {
 
  381                                 m->m_nextpkt = (
struct mbuf *)0xDEADC0DE;
 
  387                 if (m0->m_flags & M_PKTHDR)
 
  391                 if (m != m0 && m->m_flags & M_PKTHDR &&
 
  392                     !SLIST_EMPTY(&m->m_pkthdr.tags)) {
 
  401                 if (m != m0 && m->m_flags & M_PKTHDR) {
 
  403                                 bzero(&m->m_pkthdr, 
sizeof(m->m_pkthdr));
 
  404                                 m->m_flags &= ~M_PKTHDR;
 
  411         if (pktlen && pktlen != m->m_pkthdr.len) {
 
  419 #undef  M_SANITY_ACTION 
  435         KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags),
 
  436             (
"m_move_pkthdr: to has tags"));
 
  442         if (to->m_flags & M_PKTHDR)
 
  445         to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT);
 
  446         if ((to->m_flags & M_EXT) == 0)
 
  447                 to->m_data = to->m_pktdat;
 
  448         to->m_pkthdr = from->m_pkthdr;          
 
  449         SLIST_INIT(&from->m_pkthdr.tags);       
 
  450         from->m_flags &= ~M_PKTHDR;
 
  472         KASSERT(SLIST_EMPTY(&to->m_pkthdr.tags), (
"m_dup_pkthdr: to has tags"));
 
  474         MBUF_CHECKSLEEP(how);
 
  476         if (to->m_flags & M_PKTHDR)
 
  479         to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT);
 
  480         if ((to->m_flags & M_EXT) == 0)
 
  481                 to->m_data = to->m_pktdat;
 
  482         to->m_pkthdr = from->m_pkthdr;
 
  483         SLIST_INIT(&to->m_pkthdr.tags);
 
  497         if (m->m_flags & M_PKTHDR)
 
  498                 MGETHDR(mn, how, m->m_type);
 
  500                 MGET(mn, how, m->m_type);
 
  505         if (m->m_flags & M_PKTHDR)
 
  506                 M_MOVE_PKTHDR(mn, m);
 
  509         if(m->m_flags & M_PKTHDR) {
 
  528 m_copym(
struct mbuf *m, 
int off0, 
int len, 
int wait)
 
  530         struct mbuf *n, **np;
 
  535         KASSERT(off >= 0, (
"m_copym, negative off %d", off));
 
  536         KASSERT(len >= 0, (
"m_copym, negative len %d", len));
 
  537         MBUF_CHECKSLEEP(wait);
 
  538         if (off == 0 && m->m_flags & M_PKTHDR)
 
  541                 KASSERT(m != NULL, (
"m_copym, offset > size of mbuf chain"));
 
  551                         KASSERT(len == M_COPYALL, 
 
  552                             (
"m_copym, length > size of mbuf chain"));
 
  556                         MGETHDR(n, wait, m->m_type);
 
  558                         MGET(n, wait, m->m_type);
 
  565                         if (len == M_COPYALL)
 
  566                                 n->m_pkthdr.len -= off0;
 
  568                                 n->m_pkthdr.len = len;
 
  571                 n->m_len = min(len, m->m_len - off);
 
  572                 if (m->m_flags & M_EXT) {
 
  573                         n->m_data = m->m_data + off;
 
  576                         bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
 
  578                 if (len != M_COPYALL)
 
  608         bcopy(s, t, (
size_t)len);
 
  616         struct mbuf *mm, *x, *z, *prev = NULL;
 
  621         KASSERT(m != NULL && n != NULL, (
"m_copymdata, no target or source"));
 
  622         KASSERT(off >= 0, (
"m_copymdata, negative off %d", off));
 
  623         KASSERT(len >= 0, (
"m_copymdata, negative len %d", len));
 
  624         KASSERT(prep == 0 || prep == 1, (
"m_copymdata, unknown direction %d", prep));
 
  633         for (z = n; z != NULL; z = z->m_next)
 
  635         if (len == M_COPYALL)
 
  637         if (off + len > nlen || len < 1)
 
  640         if (!M_WRITABLE(mm)) {
 
  642                 x = m_getcl(how, MT_DATA, mm->m_flags);
 
  645                 bcopy(mm->m_ext.ext_buf, x->m_ext.ext_buf, x->m_ext.ext_size);
 
  646                 p = x->m_ext.ext_buf + (mm->m_data - mm->m_ext.ext_buf);
 
  659         if (!prep && M_TRAILINGSPACE(mm) >= len) {
 
  663                 mm->m_pkthdr.len += len;
 
  666         if (prep && M_LEADINGSPACE(mm) >= len) {
 
  667                 mm->m_data = mtod(mm, caddr_t) - len;
 
  670                 mm->m_pkthdr.len += len;
 
  675         if (!prep && !(mm->m_flags & M_EXT) && len > M_TRAILINGSPACE(mm)) {
 
  676                 bcopy(mm->m_data, &buf, mm->m_len);
 
  678                 if (!(mm->m_flags & M_EXT))
 
  680                 bcopy(&buf, mm->m_ext.ext_buf, mm->m_len);
 
  681                 mm->m_data = mm->m_ext.ext_buf;
 
  682                 mm->m_pkthdr.header = NULL;
 
  684         if (prep && !(mm->m_flags & M_EXT) && len > M_LEADINGSPACE(mm)) {
 
  685                 bcopy(mm->m_data, &buf, mm->m_len);
 
  687                 if (!(mm->m_flags & M_EXT))
 
  689                 bcopy(&buf, (caddr_t *)mm->m_ext.ext_buf +
 
  690                        mm->m_ext.ext_size - mm->m_len, mm->m_len);
 
  691                 mm->m_data = (caddr_t)mm->m_ext.ext_buf +
 
  692                               mm->m_ext.ext_size - mm->m_len;
 
  693                 mm->m_pkthdr.header = NULL;
 
  697         if (!prep && len > M_TRAILINGSPACE(mm)) {
 
  698                 if (!m_getm(mm, len - M_TRAILINGSPACE(mm), how, MT_DATA))
 
  701         if (prep && len > M_LEADINGSPACE(mm)) {
 
  702                 if (!(z = m_getm(NULL, len - M_LEADINGSPACE(mm), how, MT_DATA)))
 
  705                 for (x = z; x != NULL; x = x->m_next) {
 
  706                         i += x->m_flags & M_EXT ? x->m_ext.ext_size :
 
  707                               (x->m_flags & M_PKTHDR ? MHLEN : MLEN);
 
  711                 z->m_data += i - len;
 
  728                 KASSERT(z != NULL, (
"m_copymdata, falling off target edge"));
 
  729                 i = M_TRAILINGSPACE(z);
 
  733                 if ((prep ? mm : m)->m_flags & M_PKTHDR)
 
  734                         (prep ? mm : m)->m_pkthdr.len += i;
 
  739         return (prep ? mm : m);
 
  754         struct mbuf *top, *n, *o;
 
  756         MBUF_CHECKSLEEP(how);
 
  757         MGET(n, how, m->m_type);
 
  765         if (m->m_flags & M_EXT) {
 
  766                 n->m_data = m->m_data;
 
  769                 n->m_data = n->m_pktdat + (m->m_data - m->m_pktdat );
 
  770                 bcopy(mtod(m, 
char *), mtod(n, 
char *), n->m_len);
 
  775                 MGET(o, how, m->m_type);
 
  783                 if (m->m_flags & M_EXT) {
 
  784                         n->m_data = m->m_data;
 
  787                         bcopy(mtod(m, 
char *), mtod(n, 
char *), n->m_len);
 
  804 m_copydata(
const struct mbuf *m, 
int off, 
int len, caddr_t cp)
 
  808         KASSERT(off >= 0, (
"m_copydata, negative off %d", off));
 
  809         KASSERT(len >= 0, (
"m_copydata, negative len %d", len));
 
  811                 KASSERT(m != NULL, (
"m_copydata, offset > size of mbuf chain"));
 
  818                 KASSERT(m != NULL, (
"m_copydata, length > size of mbuf chain"));
 
  819                 count = min(m->m_len - off, len);
 
  820                 bcopy(mtod(m, caddr_t) + off, cp, count);
 
  836         struct mbuf **p, *top = NULL;
 
  837         int remain, moff, nsize;
 
  839         MBUF_CHECKSLEEP(how);
 
  846         remain = m->m_pkthdr.len;
 
  849         while (remain > 0 || top == NULL) {     
 
  853                 if (remain >= MINCLSIZE) {
 
  854                         n = m_getcl(how, m->m_type, 0);
 
  857                         n = m_get(how, m->m_type);
 
  868                         if ((n->m_flags & M_EXT) == 0)
 
  870                         n->m_flags &= ~M_RDONLY;
 
  879                 while (n->m_len < nsize && m != NULL) {
 
  880                         int chunk = min(nsize - n->m_len, m->m_len - moff);
 
  882                         bcopy(m->m_data + moff, n->m_data + n->m_len, chunk);
 
  886                         if (moff == m->m_len) {
 
  893                 KASSERT((remain > 0 && m != NULL) || (remain == 0 && m == NULL),
 
  894                         (
"%s: bogus m_pkthdr.len", __func__));
 
  910 m_cat(
struct mbuf *m, 
struct mbuf *n)
 
  915                 if (!M_WRITABLE(m) ||
 
  916                     M_TRAILINGSPACE(m) < n->m_len) {
 
  922                 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
 
  924                 m->m_len += n->m_len;
 
  936         if ((m = mp) == NULL)
 
  942                 while (m != NULL && len > 0) {
 
  943                         if (m->m_len <= len) {
 
  953                 if (mp->m_flags & M_PKTHDR)
 
  954                         mp->m_pkthdr.len -= (req_len - len);
 
  967                         if (m->m_next == (
struct mbuf *)0)
 
  971                 if (m->m_len >= len) {
 
  973                         if (mp->m_flags & M_PKTHDR)
 
  974                                 mp->m_pkthdr.len -= len;
 
  986                 if (m->m_flags & M_PKTHDR)
 
  987                         m->m_pkthdr.len = 
count;
 
  988                 for (; m; m = m->m_next) {
 
  989                         if (m->m_len >= count) {
 
  991                                 if (m->m_next != NULL) {
 
 1022         if ((n->m_flags & M_EXT) == 0 &&
 
 1023             n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
 
 1024                 if (n->m_len >= len)
 
 1032                 MGET(m, M_DONTWAIT, n->m_type);
 
 1036                 if (n->m_flags & M_PKTHDR)
 
 1037                         M_MOVE_PKTHDR(m, n);
 
 1039         space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
 
 1041                 count = min(min(max(len, 
max_protohdr), space), n->m_len);
 
 1042                 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
 
 1052         } 
while (len > 0 && n);
 
 1078         if (len > (MHLEN - dstoff))
 
 1080         MGET(m, M_DONTWAIT, n->m_type);
 
 1084         if (n->m_flags & M_PKTHDR)
 
 1085                 M_MOVE_PKTHDR(m, n);
 
 1086         m->m_data += dstoff;
 
 1087         space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
 
 1089                 count = min(min(max(len, 
max_protohdr), space), n->m_len);
 
 1090                 memcpy(mtod(m, caddr_t) + m->m_len, mtod(n, caddr_t),
 
 1100         } 
while (len > 0 && n);
 
 1127         u_int len = len0, remain;
 
 1129         MBUF_CHECKSLEEP(wait);
 
 1130         for (m = m0; m && len > m->m_len; m = m->m_next)
 
 1134         remain = m->m_len - len;
 
 1135         if (m0->m_flags & M_PKTHDR) {
 
 1136                 MGETHDR(n, wait, m0->m_type);
 
 1139                 n->m_pkthdr.rcvif = m0->m_pkthdr.rcvif;
 
 1140                 n->m_pkthdr.len = m0->m_pkthdr.len - len0;
 
 1141                 m0->m_pkthdr.len = len0;
 
 1142                 if (m->m_flags & M_EXT)
 
 1144                 if (remain > MHLEN) {
 
 1147                         n->m_next = 
m_split(m, len, wait);
 
 1148                         if (n->m_next == NULL) {
 
 1156                         MH_ALIGN(n, remain);
 
 1157         } 
else if (remain == 0) {
 
 1162                 MGET(n, wait, m->m_type);
 
 1168         if (m->m_flags & M_EXT) {
 
 1169                 n->m_data = m->m_data + len;
 
 1172                 bcopy(mtod(m, caddr_t) + len, mtod(n, caddr_t), remain);
 
 1176         n->m_next = m->m_next;
 
 1186 m_devget(
char *buf, 
int totlen, 
int off, 
struct ifnet *ifp,
 
 1187     void (*copy)(
char *from, caddr_t to, u_int len))
 
 1190         struct mbuf *top = NULL, **mp = ⊤
 
 1193         if (off < 0 || off > MHLEN)
 
 1196         while (totlen > 0) {
 
 1198                         if (totlen + off >= MINCLSIZE) {
 
 1199                                 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
 
 1202                                 m = m_gethdr(M_DONTWAIT, MT_DATA);
 
 1213                         m->m_pkthdr.rcvif = ifp;
 
 1214                         m->m_pkthdr.len = totlen;
 
 1216                         if (totlen + off >= MINCLSIZE) {
 
 1217                                 m = m_getcl(M_DONTWAIT, MT_DATA, 0);
 
 1220                                 m = m_get(M_DONTWAIT, MT_DATA);
 
 1233                 m->m_len = len = min(totlen, len);
 
 1235                         copy(buf, mtod(m, caddr_t), (u_int)len);
 
 1237                         bcopy(buf, mtod(m, caddr_t), (u_int)len);
 
 1255         struct mbuf *m = m0, *n;
 
 1260         while (off > (mlen = m->m_len)) {
 
 1263                 if (m->m_next == NULL) {
 
 1264                         n = m_get(M_DONTWAIT, m->m_type);
 
 1267                         bzero(mtod(n, caddr_t), MLEN);
 
 1268                         n->m_len = min(MLEN, len + off);
 
 1274                 if (m->m_next == NULL && (len > m->m_len - off)) {
 
 1275                         m->m_len += min(len - (m->m_len - off),
 
 1276                             M_TRAILINGSPACE(m));
 
 1278                 mlen = min (m->m_len - off, len);
 
 1279                 bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen);
 
 1287                 if (m->m_next == NULL) {
 
 1288                         n = m_get(M_DONTWAIT, m->m_type);
 
 1291                         n->m_len = min(MLEN, len);
 
 1296 out:    
if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
 
 1297                 m->m_pkthdr.len = totlen;
 
 1311         int remainder, space;
 
 1313         for (m = m0; m->m_next != NULL; m = m->m_next)
 
 1316         space = M_TRAILINGSPACE(m);
 
 1321                 if (space > remainder)
 
 1323                 bcopy(cp, mtod(m, caddr_t) + m->m_len, space);
 
 1325                 cp += space, remainder -= space;
 
 1327         while (remainder > 0) {
 
 1332                 n = m_get(M_DONTWAIT, m->m_type);
 
 1335                 n->m_len = min(MLEN, remainder);
 
 1336                 bcopy(cp, mtod(n, caddr_t), n->m_len);
 
 1337                 cp += n->m_len, remainder -= n->m_len;
 
 1341         if (m0->m_flags & M_PKTHDR)
 
 1342                 m0->m_pkthdr.len += len - remainder;
 
 1343         return (remainder == 0);
 
 1352     int (*f)(
void *, 
void *, u_int), 
void *arg)
 
 1357         KASSERT(off >= 0, (
"m_apply, negative off %d", off));
 
 1358         KASSERT(len >= 0, (
"m_apply, negative len %d", len));
 
 1360                 KASSERT(m != NULL, (
"m_apply, offset > size of mbuf chain"));
 
 1367                 KASSERT(m != NULL, (
"m_apply, offset > size of mbuf chain"));
 
 1368                 count = min(m->m_len - off, len);
 
 1369                 rval = (*f)(arg, mtod(m, caddr_t) + off, 
count);
 
 1388                 if (m->m_len > loc) {
 
 1393                         if (m->m_next == NULL) {
 
 1412         const struct mbuf *m2;
 
 1419         if (m->m_flags & M_PKTHDR)
 
 1420                 len = m->m_pkthdr.len;
 
 1424         while (m2 != NULL && (len == -1 || len)) {
 
 1426                 if (maxlen != -1 && pdata > maxlen)
 
 1428                 printf(
"mbuf: %p len: %d, next: %p, %b%s", m2, m2->m_len,
 
 1429                     m2->m_next, m2->m_flags, 
"\20\20freelist\17skipfw" 
 1430                     "\11proto5\10proto4\7proto3\6proto2\5proto1\4rdonly" 
 1431                     "\3eor\2pkthdr\1ext", pdata ? 
"" : 
"\n");
 
 1433                         printf(
", %*D\n", pdata, (u_char *)m2->m_data, 
"-");
 
 1439                 printf(
"%d bytes unaccounted for.\n", len);
 
 1449         m0->m_pkthdr.len = len;
 
 1460         for (m = m0; m != NULL; m = m->m_next) {
 
 1462                 if (m->m_next == NULL)
 
 1484         struct mbuf *m_new = NULL, *m_final = NULL;
 
 1485         int progress = 0, length;
 
 1487         MBUF_CHECKSLEEP(how);
 
 1488         if (!(m0->m_flags & M_PKTHDR))
 
 1493 #ifdef MBUF_STRESS_TEST 
 1494         if (m_defragrandomfailures) {
 
 1495                 int temp = arc4random() & 0xff;
 
 1501         if (m0->m_pkthdr.len > MHLEN)
 
 1502                 m_final = m_getcl(how, MT_DATA, M_PKTHDR);
 
 1504                 m_final = m_gethdr(how, MT_DATA);
 
 1506         if (m_final == NULL)
 
 1514         while (progress < m0->m_pkthdr.len) {
 
 1515                 length = m0->m_pkthdr.len - progress;
 
 1516                 if (length > MCLBYTES)
 
 1519                 if (m_new == NULL) {
 
 1521                                 m_new = m_getcl(how, MT_DATA, 0);
 
 1523                                 m_new = m_get(how, MT_DATA);
 
 1528                 m_copydata(m0, progress, length, mtod(m_new, caddr_t));
 
 1530                 m_new->m_len = length;
 
 1531                 if (m_new != m_final)
 
 1532                         m_cat(m_final, m_new);
 
 1535 #ifdef MBUF_STRESS_TEST 
 1536         if (m0->m_next == NULL)
 
 1541 #ifdef MBUF_STRESS_TEST 
 1543         m_defragbytes += m0->m_pkthdr.len;
 
 1547 #ifdef MBUF_STRESS_TEST 
 1567         struct mbuf *m, *n, *n2, **prev;
 
 1574         for (m = m0; m != NULL; m = m->m_next)
 
 1588                 if (M_WRITABLE(m) &&
 
 1589                     n->m_len < M_TRAILINGSPACE(m)) {
 
 1590                         bcopy(mtod(n, 
void *), mtod(m, 
char *) + m->m_len,
 
 1592                         m->m_len += n->m_len;
 
 1593                         m->m_next = n->m_next;
 
 1595                         if (--curfrags <= maxfrags)
 
 1600         KASSERT(maxfrags > 1,
 
 1601                 (
"maxfrags %u, but normal collapse failed", maxfrags));
 
 1606         while ((n = *prev) != NULL) {
 
 1607                 if ((n2 = n->m_next) != NULL &&
 
 1608                     n->m_len + n2->m_len < MCLBYTES) {
 
 1609                         m = m_getcl(how, MT_DATA, 0);
 
 1612                         bcopy(mtod(n, 
void *), mtod(m, 
void *), n->m_len);
 
 1613                         bcopy(mtod(n2, 
void *), mtod(m, 
char *) + n->m_len,
 
 1615                         m->m_len = n->m_len + n2->m_len;
 
 1616                         m->m_next = n2->m_next;
 
 1620                         if (--curfrags <= maxfrags)     
 
 1641 #ifdef MBUF_STRESS_TEST 
 1659 m_fragment(
struct mbuf *m0, 
int how, 
int length)
 
 1661         struct mbuf *m_new = NULL, *m_final = NULL;
 
 1664         if (!(m0->m_flags & M_PKTHDR))
 
 1667         if ((length == 0) || (length < -2))
 
 1672         m_final = m_getcl(how, MT_DATA, M_PKTHDR);
 
 1674         if (m_final == NULL)
 
 1683                 length = 1 + (arc4random() & 255);
 
 1685         while (progress < m0->m_pkthdr.len) {
 
 1691                         fraglen = 1 + (arc4random() & 255);
 
 1692                 if (fraglen > m0->m_pkthdr.len - progress)
 
 1693                         fraglen = m0->m_pkthdr.len - progress;
 
 1695                 if (fraglen > MCLBYTES)
 
 1698                 if (m_new == NULL) {
 
 1699                         m_new = m_getcl(how, MT_DATA, 0);
 
 1704                 m_copydata(m0, progress, fraglen, mtod(m_new, caddr_t));
 
 1705                 progress += fraglen;
 
 1706                 m_new->m_len = fraglen;
 
 1707                 if (m_new != m_final)
 
 1708                         m_cat(m_final, m_new);
 
 1729         struct mbuf *m, *mb;
 
 1739                 total = min(uio->uio_resid, len);
 
 1741                 total = uio->uio_resid;
 
 1754         m = 
m_getm2(NULL, max(total + align, 1), how, MT_DATA, flags);
 
 1760         for (mb = m; mb != NULL; mb = mb->m_next) {
 
 1761                 length = min(M_TRAILINGSPACE(mb), total - progress);
 
 1763                 error = 
uiomove(mtod(mb, 
void *), length, uio);
 
 1771                 if (flags & M_PKTHDR)
 
 1772                         m->m_pkthdr.len += length;
 
 1774         KASSERT(progress == total, (
"%s: progress != total", __func__));
 
 1785         int error, length, total;
 
 1789                 total = min(uio->uio_resid, len);
 
 1791                 total = uio->uio_resid;
 
 1794         for (; m != NULL; m = m->m_next) {
 
 1795                 length = min(m->m_len, total - progress);
 
 1797                 error = 
uiomove(mtod(m, 
void *), length, uio);
 
 1817         if (m->m_flags & M_EXT)
 
 1818                 adjust = m->m_ext.ext_size - len;
 
 1819         else if (m->m_flags & M_PKTHDR)
 
 1820                 adjust = MHLEN - len;
 
 1822                 adjust = MLEN - len;
 
 1823         m->m_data += adjust &~ (
sizeof(long)-1);
 
 1838         struct mbuf *m, *mprev;
 
 1839         struct mbuf *n, *mfirst, *mlast;
 
 1843         for (m = m0; m != NULL; m = mprev->m_next) {
 
 1856                 if ((m->m_flags & M_EXT) == 0) {
 
 1857                         if (mprev && (mprev->m_flags & M_EXT) &&
 
 1858                             m->m_len <= M_TRAILINGSPACE(mprev)) {
 
 1860                                 memcpy(mtod(mprev, caddr_t) + mprev->m_len,
 
 1861                                        mtod(m, caddr_t), m->m_len);
 
 1862                                 mprev->m_len += m->m_len;
 
 1863                                 mprev->m_next = m->m_next;      
 
 1866                                 newipsecstat.ips_mbcoalesced++;
 
 1876                 if (M_WRITABLE(m)) {
 
 1887                 KASSERT(m->m_flags & M_EXT, (
"m_flags 0x%x", m->m_flags));
 
 1889                 if (mprev != NULL && (mprev->m_flags & M_EXT) &&
 
 1890                     m->m_len <= M_TRAILINGSPACE(mprev)) {
 
 1892                         memcpy(mtod(mprev, caddr_t) + mprev->m_len,
 
 1893                                mtod(m, caddr_t), m->m_len);
 
 1894                         mprev->m_len += m->m_len;
 
 1895                         mprev->m_next = m->m_next;      
 
 1898                         newipsecstat.ips_clcoalesced++;
 
 1907                 if (mprev == NULL && (m->m_flags & M_PKTHDR)) {
 
 1914                         MGETHDR(n, how, m->m_type);
 
 1919                         M_MOVE_PKTHDR(n, m);
 
 1921                         if ((n->m_flags & M_EXT) == 0) {
 
 1927                         n = m_getcl(how, m->m_type, m->m_flags);
 
 1946                         int cc = min(len, MCLBYTES);
 
 1947                         memcpy(mtod(n, caddr_t), mtod(m, caddr_t) + off, cc);
 
 1953                         newipsecstat.ips_clcopied++;
 
 1961                         n = m_getcl(how, m->m_type, m->m_flags);
 
 1968                 n->m_next = m->m_next; 
 
 1972                         mprev->m_next = mfirst; 
 
 1979 #ifdef MBUF_PROFILING 
 1981 #define MP_BUCKETS 32  
 1982 struct mbufprofile {
 
 1983         uintmax_t wasted[MP_BUCKETS];
 
 1984         uintmax_t used[MP_BUCKETS];
 
 1985         uintmax_t segments[MP_BUCKETS];
 
 1988 #define MP_MAXDIGITS 21  
 1989 #define MP_NUMLINES 6 
 1990 #define MP_NUMSPERLINE 16 
 1991 #define MP_EXTRABYTES 64         
 1993 #define MP_MAXLINE ((MP_MAXDIGITS+1) * MP_NUMSPERLINE) 
 1994 #define MP_BUFSIZE ((MP_MAXLINE * MP_NUMLINES) + 1 + MP_EXTRABYTES) 
 1996 char mbprofbuf[MP_BUFSIZE];
 
 1999 m_profile(
struct mbuf *m)
 
 2008                 if (m->m_flags & M_EXT) {
 
 2009                         wasted += MHLEN - 
sizeof(m->m_ext) +
 
 2010                             m->m_ext.ext_size - m->m_len;
 
 2012                         if (m->m_flags & M_PKTHDR)
 
 2013                                 wasted += MHLEN - m->m_len;
 
 2015                                 wasted += MLEN - m->m_len;
 
 2020         if (segments > MP_BUCKETS - 1)
 
 2021                 segments = MP_BUCKETS - 1;
 
 2024         if (wasted > 100000)
 
 2028         mbprof.segments[segments]++;
 
 2029         mbprof.used[fls(used)]++;
 
 2030         mbprof.wasted[fls(wasted)]++;
 
 2034 mbprof_textify(
void)
 
 2041         p = &mbprof.wasted[0];
 
 2043         offset = 
snprintf(c, MP_MAXLINE + 10, 
 
 2045             "%ju %ju %ju %ju %ju %ju %ju %ju " 
 2046             "%ju %ju %ju %ju %ju %ju %ju %ju\n",
 
 2047             p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
 
 2048             p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
 
 2050         p = &mbprof.wasted[16];
 
 2053             "%ju %ju %ju %ju %ju %ju %ju %ju " 
 2054             "%ju %ju %ju %ju %ju %ju %ju %ju\n",
 
 2055             p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
 
 2056             p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
 
 2058         p = &mbprof.used[0];
 
 2060         offset = 
snprintf(c, MP_MAXLINE + 10, 
 
 2062             "%ju %ju %ju %ju %ju %ju %ju %ju " 
 2063             "%ju %ju %ju %ju %ju %ju %ju %ju\n",
 
 2064             p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
 
 2065             p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
 
 2067         p = &mbprof.used[16];
 
 2070             "%ju %ju %ju %ju %ju %ju %ju %ju " 
 2071             "%ju %ju %ju %ju %ju %ju %ju %ju\n",
 
 2072             p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
 
 2073             p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
 
 2075         p = &mbprof.segments[0];
 
 2077         offset = 
snprintf(c, MP_MAXLINE + 10, 
 
 2079             "%ju %ju %ju %ju %ju %ju %ju %ju " 
 2080             "%ju %ju %ju %ju %ju %ju %ju %ju\n",
 
 2081             p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
 
 2082             p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
 
 2084         p = &mbprof.segments[16];
 
 2087             "%ju %ju %ju %ju %ju %ju %ju %ju " 
 2088             "%ju %ju %ju %ju %ju %ju %ju %jju",
 
 2089             p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
 
 2090             p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]);
 
 2095 mbprof_handler(SYSCTL_HANDLER_ARGS)
 
 2100         error = SYSCTL_OUT(req, mbprofbuf, strlen(mbprofbuf) + 1);
 
 2105 mbprof_clr_handler(SYSCTL_HANDLER_ARGS)
 
 2111         if (error || !req->newptr)
 
 2115                 bzero(&mbprof, 
sizeof(mbprof));
 
 2122 SYSCTL_PROC(_kern_ipc, OID_AUTO, mbufprofile, CTLTYPE_STRING|CTLFLAG_RD,
 
 2123             NULL, 0, mbprof_handler, 
"A", 
"mbuf profiling statistics");
 
 2125 SYSCTL_PROC(_kern_ipc, OID_AUTO, mbufprofileclr, CTLTYPE_INT|CTLFLAG_RW,
 
 2126             NULL, 0, mbprof_clr_handler, 
"I", 
"clear mbuf profiling statistics");
 
int m_append(struct mbuf *m0, int len, c_caddr_t cp)
 
void m_copyback(struct mbuf *m0, int off, int len, c_caddr_t cp)
 
int m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how)
 
int m_apply(struct mbuf *m, int off, int len, int(*f)(void *, void *, u_int), void *arg)
 
struct mbuf * m_unshare(struct mbuf *m0, int how)
 
int snprintf(char *str, size_t size, const char *format,...)
 
struct mbuf * m_collapse(struct mbuf *m0, int how, int maxfrags)
 
uma_zone_t zone_ext_refcnt
 
struct mbuf * m_split(struct mbuf *m0, int len0, int wait)
 
struct mbuf * m_getm2(struct mbuf *m, int len, int how, short type, int flags)
 
int m_sanity(struct mbuf *m0, int sanitize)
 
struct mbuf * m_uiotombuf(struct uio *uio, int how, int len, int align, int flags)
 
u_int m_fixhdr(struct mbuf *m0)
 
void m_freem(struct mbuf *mb)
 
struct mbuf * m_copym(struct mbuf *m, int off0, int len, int wait)
 
void m_move_pkthdr(struct mbuf *to, struct mbuf *from)
 
struct mbuf * m_pullup(struct mbuf *n, int len)
 
void m_demote(struct mbuf *m0, int all)
 
void m_extadd(struct mbuf *mb, caddr_t buf, u_int size, void(*freef)(void *, void *), void *arg1, void *arg2, int flags, int type)
 
void m_copydata(const struct mbuf *m, int off, int len, caddr_t cp)
 
struct mbuf * m_copypacket(struct mbuf *m, int how)
 
int m_mbuftouio(struct uio *uio, struct mbuf *m, int len)
 
int m_tag_copy_chain(struct mbuf *to, struct mbuf *from, int how)
 
static int m_bcopyxxx(void *s, void *t, u_int len)
 
int sysctl_handle_int(SYSCTL_HANDLER_ARGS)
 
struct mbuf * m_copymdata(struct mbuf *m, struct mbuf *n, int off, int len, int prep, int how)
 
struct mbuf * m_dup(struct mbuf *m, int how)
 
struct mbuf * m_prepend(struct mbuf *m, int len, int how)
 
void m_adj(struct mbuf *mp, int req_len)
 
struct mbuf * m_copyup(struct mbuf *n, int len, int dstoff)
 
SYSCTL_PROC(_kern, OID_AUTO, acct_chkfreq, CTLTYPE_INT|CTLFLAG_RW,&acctchkfreq, 0, sysctl_acct_chkfreq,"I","frequency for checking the free space")
 
struct mbuf * m_devget(char *buf, int totlen, int off, struct ifnet *ifp, void(*copy)(char *from, caddr_t to, u_int len))
 
int uiomove(void *cp, int n, struct uio *uio)
 
int printf(const char *fmt,...)
 
SYSCTL_INT(_kern_ipc, KIPC_MAX_LINKHDR, max_linkhdr, CTLFLAG_RD,&max_linkhdr, 0,"Size of largest link layer header")
 
void m_cat(struct mbuf *m, struct mbuf *n)
 
void mb_free_ext(struct mbuf *m)
 
void m_print(const struct mbuf *m, int maxlen)
 
u_int m_length(struct mbuf *m0, struct mbuf **last)
 
#define M_SANITY_ACTION(s)
 
struct mbuf * m_defrag(struct mbuf *m0, int how)
 
static void mb_dupcl(struct mbuf *n, struct mbuf *m)
 
void m_align(struct mbuf *m, int len)
 
struct mbuf * m_getptr(struct mbuf *m, int loc, int *off)
 
void m_tag_delete_chain(struct mbuf *m, struct m_tag *t)