1*4732Swnj /* uipc_mbuf.c 1.7 81/11/04 */ 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" 114662Swnj #include "../inet/inet.h" 124662Swnj #include "../inet/inet_systm.h" 134669Swnj #include "../inet/ip.h" 144662Swnj #include "../inet/tcp.h" 154585Swnj #include "../h/vm.h" 164585Swnj 17*4732Swnj m_reserve(mbufs) 18*4732Swnj int mbufs; 19*4732Swnj { 20*4732Swnj 21*4732Swnj if (mbstat.m_lowat + mbufs > NNETPAGES * NMBPG - 32) 22*4732Swnj return (0); 23*4732Swnj mbstat.m_lowat += mbufs; 24*4732Swnj mbstat.m_hiwat = 2 * mbstat.m_lowat; 25*4732Swnj } 26*4732Swnj 27*4732Swnj m_release(mbufs) 28*4732Swnj int mbufs; 29*4732Swnj { 30*4732Swnj 31*4732Swnj mbstat.m_lowat -= mbufs; 32*4732Swnj mbstat.m_hiwat = 2 * mbstat.m_lowat; 33*4732Swnj } 34*4732Swnj 354585Swnj struct mbuf * 364585Swnj m_get(canwait) 374585Swnj int canwait; 384585Swnj { 394585Swnj register struct mbuf *m; 404585Swnj 414585Swnj COUNT(M_GET); 424585Swnj MGET(m, canwait); 434585Swnj return (m); 444585Swnj } 454585Swnj 464585Swnj struct mbuf * 474585Swnj m_free(m) 484585Swnj struct mbuf *m; 494585Swnj { 504585Swnj register struct mbuf *n; 514585Swnj 524585Swnj COUNT(M_FREE); 534585Swnj MFREE(m, n); 544585Swnj return (n); 554585Swnj } 564585Swnj 574585Swnj struct mbuf * 584585Swnj m_more(type) 594585Swnj int type; 604585Swnj { 614585Swnj int s; 624585Swnj register struct mbuf *m; 634585Swnj 644585Swnj COUNT(M_MORE); 654585Swnj if (!m_expand()) { 664585Swnj netstat.m_drops++; 674585Swnj return (NULL); 684585Swnj } 694585Swnj #define m_more(x) ((struct mbuf *)panic("m_more")) 704585Swnj MGET(m, 0); 714585Swnj return (m); 724585Swnj } 734585Swnj 744669Swnj m_freem(m) 754585Swnj register struct mbuf *m; 764585Swnj { 774585Swnj register struct mbuf *n; 784585Swnj register int s, cnt; 794585Swnj 804585Swnj COUNT(M_FREEM); 814585Swnj if (m == NULL) 824585Swnj return (0); 834585Swnj cnt = 0; 844662Swnj s = splimp(); 854585Swnj do { 864669Swnj if (m->m_off > MMAXOFF) 874669Swnj cnt += NMBPG; 884669Swnj cnt++; 894585Swnj MFREE(m, n); 904585Swnj } while (m = n); 914585Swnj splx(s); 924585Swnj return (cnt); 934585Swnj } 944585Swnj 954669Swnj mbufinit() 964585Swnj { 974585Swnj register struct mbuf *m; 984585Swnj register i; 994585Swnj 1004585Swnj COUNT(MBUFINIT); 1014585Swnj m = (struct mbuf *)&netutl[0]; /* ->start of buffer virt mem */ 1024585Swnj vmemall(&Netmap[0], 2, proc, CSYS); 1034585Swnj vmaccess(&Netmap[0], m, 2); 1044585Swnj for (i=0; i < NMBPG; i++) { 1054587Swnj m->m_off = 0; 1064585Swnj m_free(m); 1074585Swnj m++; 1084585Swnj } 1094585Swnj pg_alloc(3); 1104662Swnj mbstat.m_pages = 4; 1114662Swnj mbstat.m_bufs = 32; 1124662Swnj mbstat.m_lowat = 16; 1134662Swnj mbstat.m_hiwat = 32; 1144669Swnj { int i,j,k,n; 1154669Swnj n = 32; 1164669Swnj k = n << 1; 1174669Swnj if ((i = rmalloc(netmap, n)) == 0) 1184669Swnj return (0); 1194669Swnj j = i<<1; 1204669Swnj m = pftom(i); 1214669Swnj /* should use vmemall sometimes */ 1224669Swnj if (memall(&Netmap[j], k, proc, CSYS) == 0) { 1234669Swnj printf("botch\n"); 1244669Swnj return; 1254669Swnj } 1264669Swnj vmaccess(&Netmap[j], (caddr_t)m, k); 1274669Swnj for (j=0; j < n; j++) { 1284669Swnj m->m_off = 0; 1294669Swnj m->m_next = mpfree; 1304669Swnj mpfree = m; 1314669Swnj m += NMBPG; 1324669Swnj nmpfree++; 1334669Swnj } 1344669Swnj } 1354585Swnj } 1364585Swnj 1374585Swnj pg_alloc(n) 1384585Swnj register int n; 1394585Swnj { 1404585Swnj register i, j, k; 1414585Swnj register struct mbuf *m; 1424585Swnj int bufs, s; 1434585Swnj 1444585Swnj COUNT(PG_ALLOC); 1454585Swnj k = n << 1; 1464585Swnj if ((i = rmalloc(netmap, n)) == 0) 1474585Swnj return (0); 1484585Swnj j = i<<1; 1494585Swnj m = pftom(i); 1504585Swnj /* should use vmemall sometimes */ 1514585Swnj if (memall(&Netmap[j], k, proc, CSYS) == 0) 1524585Swnj return (0); 1534585Swnj vmaccess(&Netmap[j], (caddr_t)m, k); 1544585Swnj bufs = n << 3; 1554662Swnj s = splimp(); 1564585Swnj for (j=0; j < bufs; j++) { 1574587Swnj m->m_off = 0; 1584585Swnj m_free(m); 1594585Swnj m++; 1604585Swnj } 1614585Swnj splx(s); 1624662Swnj mbstat.m_pages += n; 1634585Swnj return (1); 1644585Swnj } 1654585Swnj 1664585Swnj m_expand() 1674585Swnj { 1684585Swnj register i; 1694585Swnj register struct mbuf *m, *n; 1704585Swnj int need, needp, needs; 1714585Swnj 1724585Swnj COUNT(M_EXPAND); 1734662Swnj needs = need = mbstat.m_hiwat - mbstat.m_bufs; 1744662Swnj needp = need >> 3; 1754585Swnj if (pg_alloc(needp)) 1764585Swnj return (1); 1774669Swnj for (i=0; i < needp; i++, need -= NMBPG) 1784669Swnj if (pg_alloc(1) == 0) 1794585Swnj goto steal; 1804585Swnj return (need < needs); 1814585Swnj steal: 1824669Swnj /* while (not enough) ask protocols to free code */ 1834669Swnj ; 1844585Swnj } 1854585Swnj 1864585Swnj #ifdef notdef 1874585Swnj m_relse() 1884585Swnj { 1894669Swnj 1904662Swnj COUNT(M_RELSE); 1914585Swnj } 1924585Swnj #endif 1934585Swnj 1944669Swnj m_cat(m, n) 1954669Swnj register struct mbuf *m, *n; 1964669Swnj { 1974669Swnj 1984669Swnj while (m->m_next) 1994669Swnj m = m->m_next; 2004669Swnj while (n) 2014669Swnj if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { 2024669Swnj bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len); 2034669Swnj m->m_len += n->m_len; 2044669Swnj n = m_free(n); 2054669Swnj } else { 2064669Swnj m->m_next = n; 2074669Swnj m = n; 2084669Swnj n = m->m_next; 2094669Swnj } 2104669Swnj } 2114669Swnj 2124585Swnj m_adj(mp, len) 2134585Swnj struct mbuf *mp; 2144585Swnj register len; 2154585Swnj { 2164585Swnj register struct mbuf *m, *n; 2174585Swnj 2184669Swnj /* 2194669Swnj for (m = mp; m; m = m->m_next) { 2204669Swnj printf("a %x %d\n", m, m->m_len); 2214669Swnj } 2224669Swnj */ 2234585Swnj COUNT(M_ADJ); 2244585Swnj if ((m = mp) == NULL) 2254585Swnj return; 2264585Swnj if (len >= 0) { /* adjust from top of msg chain */ 2274585Swnj while (m != NULL && len > 0) { 2284585Swnj if (m->m_len <= len) { /* free this mbuf */ 2294585Swnj len -= m->m_len; 2304585Swnj m->m_len = 0; 2314585Swnj m = m->m_next; 2324585Swnj } else { /* adjust mbuf */ 2334585Swnj m->m_len -= len; 2344585Swnj m->m_off += len; 2354585Swnj break; 2364585Swnj } 2374585Swnj } 2384585Swnj 2394585Swnj } else { /* adjust from bottom of msg chain */ 2404585Swnj len = -len; 2414585Swnj while (len > 0 && m->m_len != 0) { 2424585Swnj /* find end of chain */ 2434585Swnj while (m != NULL && m->m_len != 0) { 2444585Swnj n = m; 2454585Swnj m = m->m_next; 2464585Swnj } 2474585Swnj if (n->m_len <= len) { /* last mbuf */ 2484585Swnj len -= n->m_len; 2494585Swnj n->m_len = 0; 2504585Swnj m = mp; 2514585Swnj } else { /* adjust length */ 2524585Swnj n->m_len -= len; 2534585Swnj break; 2544585Swnj } 2554585Swnj } 2564585Swnj } 2574585Swnj } 2584585Swnj 2594585Swnj /* 2604585Swnj * convert mbuf virtual to physical addr for uballoc 2614585Swnj */ 2624585Swnj mtophys(m) 2634585Swnj register struct mbuf *m; 2644585Swnj { 2654585Swnj register i; 2664585Swnj register unsigned long addr; 2674585Swnj register struct pte *pte; 2684585Swnj 2694585Swnj COUNT(MTOPHYS); 2704585Swnj i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT; 2714585Swnj pte = &Netmap[i]; 2724585Swnj addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET); 2734585Swnj return (addr); 2744585Swnj } 275