1*5310Sroot /* uipc_mbuf.c 1.25 81/12/23 */ 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; 415228Swnj mbx = rmalloc(mbmap, npg); 425228Swnj if (mbx == 0) 435228Swnj return (0); 445228Swnj m = cltom(mbx / CLSIZE); 455228Swnj if (memall(&Mbmap[mbx], ncl * CLSIZE, proc, CSYS) == 0) 465228Swnj return (0); 475228Swnj vmaccess(&Mbmap[mbx], (caddr_t)m, npg); 485228Swnj switch (how) { 495228Swnj 505228Swnj case MPG_CLUSTERS: 515228Swnj s = splimp(); 525228Swnj for (i = 0; i < ncl; i++) { 535228Swnj m->m_off = 0; 545228Swnj m->m_next = mclfree; 555228Swnj mclfree = m; 565228Swnj m += CLBYTES / sizeof (*m); 575228Swnj nmclfree++; 585228Swnj } 595228Swnj mbstat.m_clusters += ncl; 605228Swnj splx(s); 615228Swnj break; 625228Swnj 635228Swnj case MPG_MBUFS: 645228Swnj for (i = ncl * CLBYTES / sizeof (*m); i > 0; i--) { 655228Swnj m->m_off = 0; 665273Sroot m->m_free = 0; 675228Swnj (void) m_free(m); 685228Swnj m++; 695228Swnj } 705228Swnj mbstat.m_clusters += ncl; 715232Swnj break; 725228Swnj } 735228Swnj return ((caddr_t)m); 745228Swnj } 755228Swnj 765228Swnj m_pgfree(addr, n) 775228Swnj caddr_t addr; 785228Swnj int n; 795228Swnj { 805228Swnj 815228Swnj COUNT(M_PGFREE); 825228Swnj } 835228Swnj 845228Swnj m_expand() 855228Swnj { 865228Swnj 875228Swnj COUNT(M_EXPAND); 885228Swnj if (mbstat.m_bufs >= mbstat.m_hiwat) 895228Swnj return (0); 905228Swnj if (m_clalloc(1, MPG_MBUFS) == 0) 915228Swnj goto steal; 925228Swnj return (1); 935228Swnj steal: 945228Swnj /* should ask protocols to free code */ 955228Swnj return (0); 965228Swnj } 975228Swnj 985228Swnj /* NEED SOME WAY TO RELEASE SPACE */ 995228Swnj 1005228Swnj /* 1015228Swnj * Space reservation routines 1025228Swnj */ 1035015Sroot m_reserve(mbufs) 1045015Sroot int mbufs; 1054732Swnj { 1064732Swnj 1075147Swnj if (mbstat.m_lowat + (mbufs>>1) > (NMBCLUSTERS-32) * CLBYTES) 1084732Swnj return (0); 1095016Swnj mbstat.m_hiwat += mbufs; 1105016Swnj mbstat.m_lowat = mbstat.m_hiwat >> 1; 1114916Swnj return (1); 1124732Swnj } 1134732Swnj 1145015Sroot m_release(mbufs) 1155015Sroot int mbufs; 1164732Swnj { 1174732Swnj 1185016Swnj mbstat.m_hiwat -= mbufs; 1195016Swnj mbstat.m_lowat = mbstat.m_hiwat >> 1; 1204732Swnj } 1214732Swnj 1225228Swnj /* 1235228Swnj * Space allocation routines. 1245228Swnj * These are also available as macros 1255228Swnj * for critical paths. 1265228Swnj */ 1274585Swnj struct mbuf * 1284585Swnj m_get(canwait) 1294585Swnj int canwait; 1304585Swnj { 1314585Swnj register struct mbuf *m; 1324585Swnj 1334585Swnj COUNT(M_GET); 1344585Swnj MGET(m, canwait); 1354585Swnj return (m); 1364585Swnj } 1374585Swnj 1384585Swnj struct mbuf * 1394890Swnj m_getclr(canwait) 1404890Swnj int canwait; 1414890Swnj { 1424890Swnj register struct mbuf *m; 1434890Swnj 1444890Swnj COUNT(M_GETCLR); 1454916Swnj m = m_get(canwait); 1464890Swnj if (m == 0) 1474890Swnj return (0); 1484890Swnj m->m_off = MMINOFF; 1494890Swnj bzero(mtod(m, caddr_t), MLEN); 1504890Swnj return (m); 1514890Swnj } 1524890Swnj 1534890Swnj struct mbuf * 1544585Swnj m_free(m) 1554585Swnj struct mbuf *m; 1564585Swnj { 1574585Swnj register struct mbuf *n; 1584585Swnj 1594585Swnj COUNT(M_FREE); 1604585Swnj MFREE(m, n); 1614585Swnj return (n); 1624585Swnj } 1634585Swnj 1644916Swnj /*ARGSUSED*/ 1654585Swnj struct mbuf * 1664585Swnj m_more(type) 1674585Swnj int type; 1684585Swnj { 1694585Swnj register struct mbuf *m; 1704585Swnj 1714585Swnj COUNT(M_MORE); 1724585Swnj if (!m_expand()) { 1734822Swnj mbstat.m_drops++; 1744585Swnj return (NULL); 1754585Swnj } 1764916Swnj #define m_more(x) (panic("m_more"), (struct mbuf *)0) 1774916Swnj MGET(m, type); 1785282Sroot #undef m_more 1794585Swnj return (m); 1804585Swnj } 1814585Swnj 1824669Swnj m_freem(m) 1834585Swnj register struct mbuf *m; 1844585Swnj { 1854585Swnj register struct mbuf *n; 1864927Swnj register int s; 1874585Swnj 1884585Swnj COUNT(M_FREEM); 1894585Swnj if (m == NULL) 1904916Swnj return; 1914662Swnj s = splimp(); 1924585Swnj do { 1934585Swnj MFREE(m, n); 1944585Swnj } while (m = n); 1954585Swnj splx(s); 1964585Swnj } 1974585Swnj 1985228Swnj /* 1995228Swnj * Mbuffer utility routines. 2005228Swnj */ 2014927Swnj struct mbuf * 2024927Swnj m_copy(m, off, len) 2034927Swnj register struct mbuf *m; 2044927Swnj int off; 2054927Swnj register int len; 2064927Swnj { 2074927Swnj register struct mbuf *n, **np; 2084927Swnj struct mbuf *top, *p; 2094927Swnj COUNT(M_COPY); 2104927Swnj 2114927Swnj if (len == 0) 2124927Swnj return (0); 2134927Swnj if (off < 0 || len < 0) 2144927Swnj panic("m_copy"); 2154927Swnj while (off > 0) { 2164927Swnj if (m == 0) 2174927Swnj panic("m_copy"); 2184927Swnj if (off < m->m_len) 2194927Swnj break; 2204927Swnj off -= m->m_len; 2214927Swnj m = m->m_next; 2224927Swnj } 2234927Swnj np = ⊤ 2244927Swnj top = 0; 2254927Swnj while (len > 0) { 2264927Swnj MGET(n, 1); 2274927Swnj *np = n; 2284927Swnj if (n == 0) 2294927Swnj goto nospace; 2304927Swnj if (m == 0) 2314927Swnj panic("m_copy"); 2324927Swnj n->m_len = MIN(len, m->m_len - off); 2334927Swnj if (m->m_off > MMAXOFF) { 2344927Swnj p = mtod(m, struct mbuf *); 2354927Swnj n->m_off = ((int)p - (int)n) + off; 2365090Swnj mclrefcnt[mtocl(p)]++; 2374927Swnj } else { 2384927Swnj n->m_off = MMINOFF; 2394927Swnj bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t), 2404927Swnj (unsigned)n->m_len); 2414927Swnj } 2424927Swnj len -= n->m_len; 2434927Swnj off = 0; 2444927Swnj m = m->m_next; 2454927Swnj np = &n->m_next; 2464927Swnj } 2474927Swnj return (top); 2484927Swnj nospace: 2494927Swnj m_freem(top); 2504927Swnj return (0); 2514927Swnj } 2524927Swnj 2534669Swnj m_cat(m, n) 2544669Swnj register struct mbuf *m, *n; 2554669Swnj { 2564669Swnj 2574669Swnj while (m->m_next) 2584669Swnj m = m->m_next; 2594669Swnj while (n) 2604669Swnj if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { 2614916Swnj bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, 2624916Swnj (u_int)n->m_len); 2634669Swnj m->m_len += n->m_len; 2644669Swnj n = m_free(n); 2654669Swnj } else { 2664669Swnj m->m_next = n; 2674669Swnj m = n; 2684669Swnj n = m->m_next; 2694669Swnj } 2704669Swnj } 2714669Swnj 2724585Swnj m_adj(mp, len) 2734585Swnj struct mbuf *mp; 2744916Swnj register int len; 2754585Swnj { 2764585Swnj register struct mbuf *m, *n; 2774585Swnj 2784585Swnj COUNT(M_ADJ); 2794585Swnj if ((m = mp) == NULL) 2804585Swnj return; 2814822Swnj if (len >= 0) { 2824585Swnj while (m != NULL && len > 0) { 2834822Swnj if (m->m_len <= len) { 2844585Swnj len -= m->m_len; 2854585Swnj m->m_len = 0; 2864585Swnj m = m->m_next; 2874822Swnj } else { 2884585Swnj m->m_len -= len; 2894585Swnj m->m_off += len; 2904585Swnj break; 2914585Swnj } 2924585Swnj } 2934822Swnj } else { 2944822Swnj /* a 2 pass algorithm might be better */ 2954585Swnj len = -len; 2964585Swnj while (len > 0 && m->m_len != 0) { 2974585Swnj while (m != NULL && m->m_len != 0) { 2984585Swnj n = m; 2994585Swnj m = m->m_next; 3004585Swnj } 3014822Swnj if (n->m_len <= len) { 3024585Swnj len -= n->m_len; 3034585Swnj n->m_len = 0; 3044585Swnj m = mp; 3054822Swnj } else { 3064585Swnj n->m_len -= len; 3074585Swnj break; 3084585Swnj } 3094585Swnj } 3104585Swnj } 3114585Swnj } 3125228Swnj 313*5310Sroot struct mbuf * 314*5310Sroot m_pullup(m0, len) 315*5310Sroot struct mbuf *m0; 3165228Swnj int len; 3175228Swnj { 318*5310Sroot register struct mbuf *m, *n; 319*5310Sroot int cnt; 3205228Swnj 321*5310Sroot if (len > MLEN) 322*5310Sroot goto bad; 323*5310Sroot MGET(m, 0); 324*5310Sroot if (m == 0) 325*5310Sroot goto bad; 326*5310Sroot m->m_off = MMINOFF; 327*5310Sroot m->m_len = 0; 328*5310Sroot n = m0; 329*5310Sroot do { 330*5310Sroot cnt = MIN(MLEN - m->m_len, len); 331*5310Sroot if (cnt > n->m_len) 332*5310Sroot cnt = n->m_len; 333*5310Sroot bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len, cnt); 334*5310Sroot len -= cnt; 335*5310Sroot m->m_len += cnt; 336*5310Sroot n->m_off += cnt; 337*5310Sroot n->m_len -= cnt; 338*5310Sroot if (n->m_len) 339*5310Sroot break; 340*5310Sroot n = m_free(n); 341*5310Sroot } while (n); 342*5310Sroot if (len) { 343*5310Sroot (void) m_free(m); 344*5310Sroot goto bad; 345*5310Sroot } 346*5310Sroot m->m_next = n; 347*5310Sroot return (m); 348*5310Sroot bad: 349*5310Sroot m_freem(m0); 3505228Swnj return (0); 3515228Swnj } 352