1*6164Ssam /* uipc_mbuf.c 1.32 82/03/13 */ 24585Swnj 34585Swnj #include "../h/param.h" 44585Swnj #include "../h/dir.h" 54585Swnj #include "../h/user.h" 64585Swnj #include "../h/proc.h" 74585Swnj #include "../h/pte.h" 84585Swnj #include "../h/cmap.h" 94585Swnj #include "../h/map.h" 104641Swnj #include "../h/mbuf.h" 115090Swnj #include "../net/in_systm.h" /* XXX */ 124585Swnj #include "../h/vm.h" 134585Swnj 145228Swnj mbinit() 155228Swnj { 165228Swnj 175228Swnj COUNT(MBINIT); 185228Swnj if (m_reserve(32) == 0) 195228Swnj goto bad; 205228Swnj if (m_clalloc(4, MPG_MBUFS) == 0) 215228Swnj goto bad; 225228Swnj if (m_clalloc(32, MPG_CLUSTERS) == 0) 235228Swnj goto bad; 245228Swnj return; 255228Swnj bad: 265228Swnj panic("mbinit"); 275228Swnj } 285228Swnj 295228Swnj caddr_t 305228Swnj m_clalloc(ncl, how) 315228Swnj register int ncl; 325228Swnj int how; 335228Swnj { 345228Swnj int npg, mbx; 355228Swnj register struct mbuf *m; 365228Swnj register int i; 375228Swnj int s; 385228Swnj 395228Swnj COUNT(M_CLALLOC); 405228Swnj npg = ncl * CLSIZE; 415581Swnj s = splimp(); /* careful: rmalloc isn't reentrant */ 425228Swnj mbx = rmalloc(mbmap, npg); 435581Swnj splx(s); 445228Swnj if (mbx == 0) 455228Swnj return (0); 465228Swnj m = cltom(mbx / CLSIZE); 475228Swnj if (memall(&Mbmap[mbx], ncl * CLSIZE, proc, CSYS) == 0) 485228Swnj return (0); 495228Swnj vmaccess(&Mbmap[mbx], (caddr_t)m, npg); 505228Swnj switch (how) { 515228Swnj 525228Swnj case MPG_CLUSTERS: 535228Swnj s = splimp(); 545228Swnj for (i = 0; i < ncl; i++) { 555228Swnj m->m_off = 0; 565228Swnj m->m_next = mclfree; 575228Swnj mclfree = m; 585228Swnj m += CLBYTES / sizeof (*m); 595228Swnj nmclfree++; 605228Swnj } 615228Swnj mbstat.m_clusters += ncl; 625228Swnj splx(s); 635228Swnj break; 645228Swnj 655228Swnj case MPG_MBUFS: 665228Swnj for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) { 675228Swnj m->m_off = 0; 685273Sroot m->m_free = 0; 695228Swnj (void) m_free(m); 705228Swnj m++; 715228Swnj } 725228Swnj mbstat.m_clusters += ncl; 735232Swnj break; 745228Swnj } 755228Swnj return ((caddr_t)m); 765228Swnj } 775228Swnj 785228Swnj m_pgfree(addr, n) 795228Swnj caddr_t addr; 805228Swnj int n; 815228Swnj { 825228Swnj 835228Swnj COUNT(M_PGFREE); 846141Ssam #ifdef lint 856141Ssam addr = addr; n = n; 866141Ssam #endif 875228Swnj } 885228Swnj 895228Swnj m_expand() 905228Swnj { 915228Swnj 925228Swnj COUNT(M_EXPAND); 935228Swnj if (mbstat.m_bufs >= mbstat.m_hiwat) 945228Swnj return (0); 955228Swnj if (m_clalloc(1, MPG_MBUFS) == 0) 965228Swnj goto steal; 975228Swnj return (1); 985228Swnj steal: 995228Swnj /* should ask protocols to free code */ 1005228Swnj return (0); 1015228Swnj } 1025228Swnj 1035228Swnj /* NEED SOME WAY TO RELEASE SPACE */ 1045228Swnj 1055228Swnj /* 1065228Swnj * Space reservation routines 1075228Swnj */ 1085015Sroot m_reserve(mbufs) 1095015Sroot int mbufs; 1104732Swnj { 1114732Swnj 1125147Swnj if (mbstat.m_lowat + (mbufs>>1) > (NMBCLUSTERS-32) * CLBYTES) 1134732Swnj return (0); 1145016Swnj mbstat.m_hiwat += mbufs; 1155016Swnj mbstat.m_lowat = mbstat.m_hiwat >> 1; 1164916Swnj return (1); 1174732Swnj } 1184732Swnj 1195015Sroot m_release(mbufs) 1205015Sroot int mbufs; 1214732Swnj { 1224732Swnj 1235016Swnj mbstat.m_hiwat -= mbufs; 1245016Swnj mbstat.m_lowat = mbstat.m_hiwat >> 1; 1254732Swnj } 1264732Swnj 1275228Swnj /* 1285228Swnj * Space allocation routines. 1295228Swnj * These are also available as macros 1305228Swnj * for critical paths. 1315228Swnj */ 1324585Swnj struct mbuf * 1334585Swnj m_get(canwait) 1344585Swnj int canwait; 1354585Swnj { 1364585Swnj register struct mbuf *m; 1374585Swnj 1384585Swnj COUNT(M_GET); 1394585Swnj MGET(m, canwait); 1404585Swnj return (m); 1414585Swnj } 1424585Swnj 1434585Swnj struct mbuf * 1444890Swnj m_getclr(canwait) 1454890Swnj int canwait; 1464890Swnj { 1474890Swnj register struct mbuf *m; 1484890Swnj 1494890Swnj COUNT(M_GETCLR); 1504916Swnj m = m_get(canwait); 1514890Swnj if (m == 0) 1524890Swnj return (0); 1534890Swnj m->m_off = MMINOFF; 1544890Swnj bzero(mtod(m, caddr_t), MLEN); 1554890Swnj return (m); 1564890Swnj } 1574890Swnj 1584890Swnj struct mbuf * 1594585Swnj m_free(m) 1604585Swnj struct mbuf *m; 1614585Swnj { 1624585Swnj register struct mbuf *n; 1634585Swnj 1644585Swnj COUNT(M_FREE); 1654585Swnj MFREE(m, n); 1664585Swnj return (n); 1674585Swnj } 1684585Swnj 1694916Swnj /*ARGSUSED*/ 1704585Swnj struct mbuf * 1714585Swnj m_more(type) 1724585Swnj int type; 1734585Swnj { 1744585Swnj register struct mbuf *m; 1754585Swnj 1764585Swnj COUNT(M_MORE); 1774585Swnj if (!m_expand()) { 1784822Swnj mbstat.m_drops++; 1794585Swnj return (NULL); 1804585Swnj } 1814916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0) 1824916Swnj MGET(m, type); 1835282Sroot #undef m_more 1844585Swnj return (m); 1854585Swnj } 1864585Swnj 1874669Swnj m_freem(m) 1884585Swnj register struct mbuf *m; 1894585Swnj { 1904585Swnj register struct mbuf *n; 1914927Swnj register int s; 1924585Swnj 1934585Swnj COUNT(M_FREEM); 1944585Swnj if (m == NULL) 1954916Swnj return; 1964662Swnj s = splimp(); 1974585Swnj do { 1984585Swnj MFREE(m, n); 1994585Swnj } while (m = n); 2004585Swnj splx(s); 2014585Swnj } 2024585Swnj 2035228Swnj /* 2045228Swnj * Mbuffer utility routines. 2055228Swnj */ 2064927Swnj struct mbuf * 2074927Swnj m_copy(m, off, len) 2084927Swnj register struct mbuf *m; 2094927Swnj int off; 2104927Swnj register int len; 2114927Swnj { 2124927Swnj register struct mbuf *n, **np; 2134927Swnj struct mbuf *top, *p; 2144927Swnj COUNT(M_COPY); 2154927Swnj 2164927Swnj if (len == 0) 2174927Swnj return (0); 2184927Swnj if (off < 0 || len < 0) 2194927Swnj panic("m_copy"); 2204927Swnj while (off > 0) { 2214927Swnj if (m == 0) 2224927Swnj panic("m_copy"); 2234927Swnj if (off < m->m_len) 2244927Swnj break; 2254927Swnj off -= m->m_len; 2264927Swnj m = m->m_next; 2274927Swnj } 2284927Swnj np = ⊤ 2294927Swnj top = 0; 2304927Swnj while (len > 0) { 2315609Swnj if (m == 0) { 2325609Swnj if (len != M_COPYALL) 2335609Swnj panic("m_copy"); 2345609Swnj break; 2355609Swnj } 2364927Swnj MGET(n, 1); 2374927Swnj *np = n; 2384927Swnj if (n == 0) 2394927Swnj goto nospace; 2404927Swnj n->m_len = MIN(len, m->m_len - off); 2414927Swnj if (m->m_off > MMAXOFF) { 2424927Swnj p = mtod(m, struct mbuf *); 2434927Swnj n->m_off = ((int)p - (int)n) + off; 2445090Swnj mclrefcnt[mtocl(p)]++; 2454927Swnj } else { 2464927Swnj n->m_off = MMINOFF; 2474927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 2484927Swnj (unsigned)n->m_len); 2494927Swnj } 2505609Swnj if (len != M_COPYALL) 2515609Swnj len -= n->m_len; 2524927Swnj off = 0; 2534927Swnj m = m->m_next; 2544927Swnj np = &n->m_next; 2554927Swnj } 2564927Swnj return (top); 2574927Swnj nospace: 2584927Swnj m_freem(top); 2594927Swnj return (0); 2604927Swnj } 2614927Swnj 2624669Swnj m_cat(m, n) 2634669Swnj register struct mbuf *m, *n; 2644669Swnj { 2654669Swnj while (m->m_next) 2664669Swnj m = m->m_next; 2676091Sroot while (n) { 2686091Sroot if (m->m_off >= MMAXOFF || 2696091Sroot m->m_off + m->m_len + n->m_len > MMAXOFF) { 2706091Sroot /* just join the two chains */ 2714669Swnj m->m_next = n; 2726091Sroot return; 2734669Swnj } 2746091Sroot /* splat the data from one into the other */ 2756091Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 2766091Sroot (u_int)n->m_len); 2776091Sroot m->m_len += n->m_len; 2786091Sroot n = m_free(n); 2796091Sroot } 2804669Swnj } 2814669Swnj 2824585Swnj m_adj(mp, len) 2834585Swnj struct mbuf *mp; 2844916Swnj register int len; 2854585Swnj { 2864585Swnj register struct mbuf *m, *n; 2874585Swnj 2884585Swnj COUNT(M_ADJ); 2894585Swnj if ((m = mp) == NULL) 2904585Swnj return; 2914822Swnj if (len >= 0) { 2924585Swnj while (m != NULL && len > 0) { 2934822Swnj if (m->m_len <= len) { 2944585Swnj len -= m->m_len; 2954585Swnj m->m_len = 0; 2964585Swnj m = m->m_next; 2974822Swnj } else { 2984585Swnj m->m_len -= len; 2994585Swnj m->m_off += len; 3004585Swnj break; 3014585Swnj } 3024585Swnj } 3034822Swnj } else { 3044822Swnj /* a 2 pass algorithm might be better */ 3054585Swnj len = -len; 3064585Swnj while (len > 0 && m->m_len != 0) { 3074585Swnj while (m != NULL && m->m_len != 0) { 3084585Swnj n = m; 3094585Swnj m = m->m_next; 3104585Swnj } 3114822Swnj if (n->m_len <= len) { 3124585Swnj len -= n->m_len; 3134585Swnj n->m_len = 0; 3144585Swnj m = mp; 3154822Swnj } else { 3164585Swnj n->m_len -= len; 3174585Swnj break; 3184585Swnj } 3194585Swnj } 3204585Swnj } 3214585Swnj } 3225228Swnj 3235310Sroot struct mbuf * 3245310Sroot m_pullup(m0, len) 3255310Sroot struct mbuf *m0; 3265228Swnj int len; 3275228Swnj { 3285310Sroot register struct mbuf *m, *n; 329*6164Ssam int count; 3305228Swnj 3315732Sroot n = m0; 3325310Sroot if (len > MLEN) 3335310Sroot goto bad; 3345310Sroot MGET(m, 0); 3355310Sroot if (m == 0) 3365310Sroot goto bad; 3375310Sroot m->m_off = MMINOFF; 3385310Sroot m->m_len = 0; 3395310Sroot do { 340*6164Ssam count = MIN(MLEN - m->m_len, len); 341*6164Ssam if (count > n->m_len) 342*6164Ssam count = n->m_len; 343*6164Ssam bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, 344*6164Ssam (unsigned)count); 345*6164Ssam len -= count; 346*6164Ssam m->m_len += count; 347*6164Ssam n->m_off += count; 348*6164Ssam n->m_len -= count; 3495310Sroot if (n->m_len) 3505310Sroot break; 3515310Sroot n = m_free(n); 3525310Sroot } while (n); 3535310Sroot if (len) { 3545310Sroot (void) m_free(m); 3555310Sroot goto bad; 3565310Sroot } 3575310Sroot m->m_next = n; 3585310Sroot return (m); 3595310Sroot bad: 3605732Sroot m_freem(n); 3615228Swnj return (0); 3625228Swnj } 363