xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4643)
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