1*4643Swnj /* uipc_mbuf.c 1.4 81/10/28 */ 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" 114585Swnj #include "../bbnnet/net.h" 124585Swnj #include "../bbnnet/tcp.h" 134585Swnj #include "../bbnnet/ip.h" 144585Swnj #include "../h/vm.h" 154585Swnj 164585Swnj struct mbuf * 174585Swnj m_get(canwait) 184585Swnj int canwait; 194585Swnj { 204585Swnj register struct mbuf *m; 214585Swnj 224585Swnj COUNT(M_GET); 234585Swnj MGET(m, canwait); 244585Swnj return (m); 254585Swnj } 264585Swnj 274585Swnj struct mbuf * 284585Swnj m_free(m) 294585Swnj struct mbuf *m; 304585Swnj { 314585Swnj register struct mbuf *n; 324585Swnj 334585Swnj COUNT(M_FREE); 344585Swnj MFREE(m, n); 354585Swnj return (n); 364585Swnj } 374585Swnj 384585Swnj struct mbuf * 394585Swnj m_more(type) 404585Swnj int type; 414585Swnj { 424585Swnj int s; 434585Swnj register struct mbuf *m; 444585Swnj 454585Swnj COUNT(M_MORE); 464585Swnj if (!m_expand()) { 474585Swnj netstat.m_drops++; 484585Swnj return (NULL); 494585Swnj } 504585Swnj #define m_more(x) ((struct mbuf *)panic("m_more")) 514585Swnj MGET(m, 0); 524585Swnj return (m); 534585Swnj } 544585Swnj 554585Swnj m_freem(m) /* free mbuf chain headed by m */ 564585Swnj register struct mbuf *m; 574585Swnj { 584585Swnj register struct mbuf *n; 594585Swnj register int s, cnt; 604585Swnj 614585Swnj COUNT(M_FREEM); 624585Swnj if (m == NULL) 634585Swnj return (0); 644585Swnj cnt = 0; 654585Swnj s = spl_imp(); 664585Swnj do { 674585Swnj MFREE(m, n); 684585Swnj cnt++; 694585Swnj } while (m = n); 704585Swnj splx(s); 714585Swnj return (cnt); 724585Swnj } 734585Swnj 744585Swnj 754585Swnj mbufinit() /* init network buffer mgmt system */ 764585Swnj { 774585Swnj register struct mbuf *m; 784585Swnj register i; 794585Swnj 804585Swnj COUNT(MBUFINIT); 814585Swnj m = (struct mbuf *)&netutl[0]; /* ->start of buffer virt mem */ 824585Swnj vmemall(&Netmap[0], 2, proc, CSYS); 834585Swnj vmaccess(&Netmap[0], m, 2); 844585Swnj for (i=0; i < NMBPG; i++) { 854587Swnj m->m_off = 0; 864585Swnj m_free(m); 874585Swnj m++; 884585Swnj } 894585Swnj pg_alloc(3); 904585Swnj netcb.n_pages = 4; 914585Swnj netcb.n_bufs = 32; 924585Swnj netcb.n_lowat = 16; 934585Swnj netcb.n_hiwat = 32; 944585Swnj } 954585Swnj 964585Swnj pg_alloc(n) 974585Swnj register int n; 984585Swnj { 994585Swnj register i, j, k; 1004585Swnj register struct mbuf *m; 1014585Swnj int bufs, s; 1024585Swnj 1034585Swnj COUNT(PG_ALLOC); 1044585Swnj k = n << 1; 1054585Swnj if ((i = rmalloc(netmap, n)) == 0) 1064585Swnj return (0); 1074585Swnj j = i<<1; 1084585Swnj m = pftom(i); 1094585Swnj /* should use vmemall sometimes */ 1104585Swnj if (memall(&Netmap[j], k, proc, CSYS) == 0) 1114585Swnj return (0); 1124585Swnj vmaccess(&Netmap[j], (caddr_t)m, k); 1134585Swnj bufs = n << 3; 1144585Swnj s = spl_imp(); 1154585Swnj for (j=0; j < bufs; j++) { 1164587Swnj m->m_off = 0; 1174585Swnj m_free(m); 1184585Swnj m++; 1194585Swnj } 1204585Swnj splx(s); 1214585Swnj netcb.n_pages += n; 1224585Swnj return (1); 1234585Swnj } 1244585Swnj 1254585Swnj m_expand() 1264585Swnj { 1274585Swnj register i; 1284585Swnj register struct ipq *fp; 1294585Swnj register struct ip *q; 1304585Swnj register struct tcb *tp; 1314585Swnj register struct mbuf *m, *n; 1324585Swnj int need, needp, needs; 1334585Swnj 1344585Swnj COUNT(M_EXPAND); 1354585Swnj needs = need = netcb.n_hiwat - netcb.n_bufs; /* #bufs to add */ 1364585Swnj needp = need >> 3; /* #pages to add */ 1374585Swnj if (pg_alloc(needp)) 1384585Swnj return (1); 1394585Swnj for (i=0; i < needp; i++, need-=NMBPG) 1404585Swnj if (needp == 1 || pg_alloc(1) == 0) /* ??? */ 1414585Swnj goto steal; 1424585Swnj return (need < needs); 1434585Swnj steal: 1444585Swnj fp = netcb.n_ip_tail; /* ip reass.q */ 1454585Swnj while (need > 0 && fp) { 1464585Swnj q = fp->iqx.ip_next; /* free mbufs assoc. w/chain */ 1474585Swnj while (q != (struct ip *)fp) { 1484585Swnj need -= m_freem(dtom(q)); 1494585Swnj q = q->ip_next; 1504585Swnj } 1514585Swnj ip_freef(fp); /* free header */ 1524585Swnj fp = netcb.n_ip_tail; 1534585Swnj } 1544585Swnj tp = netcb.n_tcb_tail; /* ->tcbs */ 1554585Swnj while (need > 0 && tp != NULL) { 1564585Swnj m = tp->t_rcv_unack; 1574585Swnj while (m != NULL) { 1584585Swnj n = m->m_act; 1594585Swnj need -= m_freem(m); 1604585Swnj m = n; 1614585Swnj } 1624585Swnj tp->t_rcv_unack = NULL; 1634585Swnj tp = tp->t_tcb_prev; 1644585Swnj } 1654585Swnj return (need < needs); 1664585Swnj } 1674585Swnj 1684585Swnj #ifdef notdef 1694585Swnj m_relse() 1704585Swnj { 1714585Swnj int free; 1724585Swnj 1734585Swnj COUNT(M_RELSE); 1744585Swnj free = (netcb.n_bufs - netcb.n_hiwat) >> 3; /* # excess free pages */ 1754585Swnj return; 1764585Swnj } 1774585Swnj #endif 1784585Swnj 1794585Swnj struct mbuf * 1804585Swnj m_adj(mp, len) 1814585Swnj struct mbuf *mp; 1824585Swnj register len; 1834585Swnj { 1844585Swnj register struct mbuf *m, *n; 1854585Swnj 1864585Swnj COUNT(M_ADJ); 1874585Swnj if ((m = mp) == NULL) 1884585Swnj return; 1894585Swnj if (len >= 0) { /* adjust from top of msg chain */ 1904585Swnj while (m != NULL && len > 0) { 1914585Swnj if (m->m_len <= len) { /* free this mbuf */ 1924585Swnj len -= m->m_len; 1934585Swnj m->m_len = 0; 1944585Swnj m = m->m_next; 1954585Swnj } else { /* adjust mbuf */ 1964585Swnj m->m_len -= len; 1974585Swnj m->m_off += len; 1984585Swnj break; 1994585Swnj } 2004585Swnj } 2014585Swnj 2024585Swnj } else { /* adjust from bottom of msg chain */ 2034585Swnj len = -len; 2044585Swnj while (len > 0 && m->m_len != 0) { 2054585Swnj /* find end of chain */ 2064585Swnj while (m != NULL && m->m_len != 0) { 2074585Swnj n = m; 2084585Swnj m = m->m_next; 2094585Swnj } 2104585Swnj if (n->m_len <= len) { /* last mbuf */ 2114585Swnj len -= n->m_len; 2124585Swnj n->m_len = 0; 2134585Swnj m = mp; 2144585Swnj } else { /* adjust length */ 2154585Swnj n->m_len -= len; 2164585Swnj break; 2174585Swnj } 2184585Swnj } 2194585Swnj } 2204585Swnj } 2214585Swnj 2224585Swnj /* 2234585Swnj * convert mbuf virtual to physical addr for uballoc 2244585Swnj */ 2254585Swnj mtophys(m) 2264585Swnj register struct mbuf *m; 2274585Swnj { 2284585Swnj register i; 2294585Swnj register unsigned long addr; 2304585Swnj register struct pte *pte; 2314585Swnj 2324585Swnj COUNT(MTOPHYS); 2334585Swnj i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT; 2344585Swnj pte = &Netmap[i]; 2354585Swnj addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET); 2364585Swnj return (addr); 2374585Swnj } 2384641Swnj 2394641Swnj m_cat(m, n) 2404641Swnj register struct mbuf *m, *n; 2414641Swnj { 2424641Swnj 2434641Swnj while (m->m_next) 2444641Swnj m = m->m_next; 2454641Swnj while (n) 2464641Swnj if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { 247*4643Swnj bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len); 2484641Swnj m->m_len += n->m_len; 2494641Swnj n = m_free(n); 2504641Swnj } else { 2514641Swnj m->m_next = n; 2524641Swnj m = n; 2534641Swnj n = m->m_next; 2544641Swnj } 2554641Swnj } 256