xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4585)
1*4585Swnj /* mbuf.c 1.6 81/10/21 */
2*4585Swnj 
3*4585Swnj #include "../h/param.h"
4*4585Swnj #include "../h/dir.h"
5*4585Swnj #include "../h/user.h"
6*4585Swnj #include "../h/proc.h"
7*4585Swnj #include "../h/pte.h"
8*4585Swnj #include "../h/cmap.h"
9*4585Swnj #include "../h/map.h"
10*4585Swnj #include "../bbnnet/net.h"
11*4585Swnj #include "../bbnnet/mbuf.h"
12*4585Swnj #include "../bbnnet/tcp.h"
13*4585Swnj #include "../bbnnet/ip.h"
14*4585Swnj #include "../h/vm.h"
15*4585Swnj 
16*4585Swnj struct mbuf *
17*4585Swnj m_get(canwait)
18*4585Swnj 	int canwait;
19*4585Swnj {
20*4585Swnj 	register struct mbuf *m;
21*4585Swnj 
22*4585Swnj COUNT(M_GET);
23*4585Swnj 	MGET(m, canwait);
24*4585Swnj 	return (m);
25*4585Swnj }
26*4585Swnj 
27*4585Swnj struct mbuf *
28*4585Swnj m_free(m)
29*4585Swnj 	struct mbuf *m;
30*4585Swnj {
31*4585Swnj 	register struct mbuf *n;
32*4585Swnj 
33*4585Swnj COUNT(M_FREE);
34*4585Swnj 	MFREE(m, n);
35*4585Swnj 	return (n);
36*4585Swnj }
37*4585Swnj 
38*4585Swnj struct mbuf *
39*4585Swnj m_more(type)
40*4585Swnj 	int type;
41*4585Swnj {
42*4585Swnj 	int s;
43*4585Swnj 	register struct mbuf *m;
44*4585Swnj 
45*4585Swnj COUNT(M_MORE);
46*4585Swnj 	if (!m_expand()) {
47*4585Swnj 		netstat.m_drops++;
48*4585Swnj 		return (NULL);
49*4585Swnj 	}
50*4585Swnj #define m_more(x) ((struct mbuf *)panic("m_more"))
51*4585Swnj 	MGET(m, 0);
52*4585Swnj 	return (m);
53*4585Swnj }
54*4585Swnj 
55*4585Swnj m_freem(m)                      /* free mbuf chain headed by m */
56*4585Swnj 	register struct mbuf *m;
57*4585Swnj {
58*4585Swnj 	register struct mbuf *n;
59*4585Swnj 	register int s, cnt;
60*4585Swnj 
61*4585Swnj COUNT(M_FREEM);
62*4585Swnj 	if (m == NULL)
63*4585Swnj 		return (0);
64*4585Swnj 	cnt = 0;
65*4585Swnj 	s = spl_imp();
66*4585Swnj 	do {
67*4585Swnj 		MFREE(m, n);
68*4585Swnj 		cnt++;
69*4585Swnj 	} while (m = n);
70*4585Swnj 	splx(s);
71*4585Swnj 	return (cnt);
72*4585Swnj }
73*4585Swnj 
74*4585Swnj 
75*4585Swnj mbufinit()                      /* init network buffer mgmt system */
76*4585Swnj {
77*4585Swnj 	register struct mbuf *m;
78*4585Swnj 	register i;
79*4585Swnj 
80*4585Swnj COUNT(MBUFINIT);
81*4585Swnj 	m = (struct mbuf *)&netutl[0];  /* ->start of buffer virt mem */
82*4585Swnj 	vmemall(&Netmap[0], 2, proc, CSYS);
83*4585Swnj 	vmaccess(&Netmap[0], m, 2);
84*4585Swnj 	for (i=0; i < NMBPG; i++) {
85*4585Swnj 		m_free(m);
86*4585Swnj 		m++;
87*4585Swnj 	}
88*4585Swnj 	pg_alloc(3);
89*4585Swnj 	netcb.n_pages = 4;
90*4585Swnj 	netcb.n_bufs = 32;
91*4585Swnj 	netcb.n_lowat = 16;
92*4585Swnj 	netcb.n_hiwat = 32;
93*4585Swnj }
94*4585Swnj 
95*4585Swnj pg_alloc(n)
96*4585Swnj 	register int n;
97*4585Swnj {
98*4585Swnj 	register i, j, k;
99*4585Swnj 	register struct mbuf *m;
100*4585Swnj 	int bufs, s;
101*4585Swnj 
102*4585Swnj COUNT(PG_ALLOC);
103*4585Swnj 	k = n << 1;
104*4585Swnj 	if ((i = rmalloc(netmap, n)) == 0)
105*4585Swnj 		return (0);
106*4585Swnj 	j = i<<1;
107*4585Swnj 	m = pftom(i);
108*4585Swnj 	/* should use vmemall sometimes */
109*4585Swnj 	if (memall(&Netmap[j], k, proc, CSYS) == 0)
110*4585Swnj 		return (0);
111*4585Swnj 	vmaccess(&Netmap[j], (caddr_t)m, k);
112*4585Swnj 	bufs = n << 3;
113*4585Swnj 	s = spl_imp();
114*4585Swnj 	for (j=0; j < bufs; j++) {
115*4585Swnj 		m_free(m);
116*4585Swnj 		m++;
117*4585Swnj 	}
118*4585Swnj 	splx(s);
119*4585Swnj 	netcb.n_pages += n;
120*4585Swnj 	return (1);
121*4585Swnj }
122*4585Swnj 
123*4585Swnj m_expand()
124*4585Swnj {
125*4585Swnj 	register i;
126*4585Swnj 	register struct ipq *fp;
127*4585Swnj 	register struct ip *q;
128*4585Swnj 	register struct tcb *tp;
129*4585Swnj 	register struct mbuf *m, *n;
130*4585Swnj 	int need, needp, needs;
131*4585Swnj 
132*4585Swnj COUNT(M_EXPAND);
133*4585Swnj 	needs = need = netcb.n_hiwat - netcb.n_bufs;    /* #bufs to add */
134*4585Swnj 	needp = need >> 3;                              /* #pages to add */
135*4585Swnj 	if (pg_alloc(needp))
136*4585Swnj 		return (1);
137*4585Swnj 	for (i=0; i < needp; i++, need-=NMBPG)
138*4585Swnj 		if (needp == 1 || pg_alloc(1) == 0)		/* ??? */
139*4585Swnj 			goto steal;
140*4585Swnj 	return (need < needs);
141*4585Swnj steal:
142*4585Swnj 	fp = netcb.n_ip_tail;           /* ip reass.q */
143*4585Swnj 	while (need > 0 && fp) {
144*4585Swnj 		q = fp->iqx.ip_next;    /* free mbufs assoc. w/chain */
145*4585Swnj 		while (q != (struct ip *)fp) {
146*4585Swnj 			need -= m_freem(dtom(q));
147*4585Swnj 			q = q->ip_next;
148*4585Swnj 		}
149*4585Swnj 		ip_freef(fp);           /* free header */
150*4585Swnj 		fp = netcb.n_ip_tail;
151*4585Swnj 	}
152*4585Swnj 	tp = netcb.n_tcb_tail;          /* ->tcbs */
153*4585Swnj 	while (need > 0 && tp != NULL) {
154*4585Swnj 		m = tp->t_rcv_unack;
155*4585Swnj 		while (m != NULL) {
156*4585Swnj 			n = m->m_act;
157*4585Swnj 			need -= m_freem(m);
158*4585Swnj 			m = n;
159*4585Swnj 		}
160*4585Swnj 		tp->t_rcv_unack = NULL;
161*4585Swnj 		tp = tp->t_tcb_prev;
162*4585Swnj 	}
163*4585Swnj 	return (need < needs);
164*4585Swnj }
165*4585Swnj 
166*4585Swnj #ifdef notdef
167*4585Swnj m_relse()
168*4585Swnj {
169*4585Swnj 	int free;
170*4585Swnj 
171*4585Swnj COUNT(M_RELSE);
172*4585Swnj 	free = (netcb.n_bufs - netcb.n_hiwat) >> 3;    /* # excess free pages */
173*4585Swnj 	return;
174*4585Swnj }
175*4585Swnj #endif
176*4585Swnj 
177*4585Swnj struct mbuf *
178*4585Swnj m_adj(mp, len)
179*4585Swnj 	struct mbuf *mp;
180*4585Swnj 	register len;
181*4585Swnj {
182*4585Swnj 	register struct mbuf *m, *n;
183*4585Swnj 
184*4585Swnj COUNT(M_ADJ);
185*4585Swnj 	if ((m = mp) == NULL)
186*4585Swnj 		return;
187*4585Swnj 	if (len >= 0) {                 /* adjust from top of msg chain */
188*4585Swnj 		while (m != NULL && len > 0) {
189*4585Swnj 			if (m->m_len <= len) {          /* free this mbuf */
190*4585Swnj 				len -= m->m_len;
191*4585Swnj 				m->m_len = 0;
192*4585Swnj 				m = m->m_next;
193*4585Swnj 			} else {                        /* adjust mbuf */
194*4585Swnj 				m->m_len -= len;
195*4585Swnj 				m->m_off += len;
196*4585Swnj 				break;
197*4585Swnj 			}
198*4585Swnj 		}
199*4585Swnj 
200*4585Swnj 	} else {                        /* adjust from bottom of msg chain */
201*4585Swnj 		len = -len;
202*4585Swnj 		while (len > 0 && m->m_len != 0) {
203*4585Swnj 			/* find end of chain */
204*4585Swnj 			while (m != NULL && m->m_len != 0) {
205*4585Swnj 				n = m;
206*4585Swnj 				m = m->m_next;
207*4585Swnj 			}
208*4585Swnj 			if (n->m_len <= len) {          /* last mbuf */
209*4585Swnj 				len -= n->m_len;
210*4585Swnj 				n->m_len = 0;
211*4585Swnj 				m = mp;
212*4585Swnj 			} else {                        /* adjust length */
213*4585Swnj 				n->m_len -= len;
214*4585Swnj 				break;
215*4585Swnj 			}
216*4585Swnj 		}
217*4585Swnj 	}
218*4585Swnj }
219*4585Swnj 
220*4585Swnj /*
221*4585Swnj  * convert mbuf virtual to physical addr for uballoc
222*4585Swnj  */
223*4585Swnj mtophys(m)
224*4585Swnj 	register struct mbuf *m;
225*4585Swnj {
226*4585Swnj 	register i;
227*4585Swnj 	register unsigned long addr;
228*4585Swnj 	register struct pte *pte;
229*4585Swnj 
230*4585Swnj COUNT(MTOPHYS);
231*4585Swnj 	i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT;
232*4585Swnj 	pte = &Netmap[i];
233*4585Swnj 	addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET);
234*4585Swnj 	return (addr);
235*4585Swnj }
236