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