xref: /csrg-svn/sys/kern/uipc_mbuf.c (revision 4585)
1 /* mbuf.c 1.6 81/10/21 */
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 "../bbnnet/net.h"
11 #include "../bbnnet/mbuf.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_free(m);
86 		m++;
87 	}
88 	pg_alloc(3);
89 	netcb.n_pages = 4;
90 	netcb.n_bufs = 32;
91 	netcb.n_lowat = 16;
92 	netcb.n_hiwat = 32;
93 }
94 
95 pg_alloc(n)
96 	register int n;
97 {
98 	register i, j, k;
99 	register struct mbuf *m;
100 	int bufs, s;
101 
102 COUNT(PG_ALLOC);
103 	k = n << 1;
104 	if ((i = rmalloc(netmap, n)) == 0)
105 		return (0);
106 	j = i<<1;
107 	m = pftom(i);
108 	/* should use vmemall sometimes */
109 	if (memall(&Netmap[j], k, proc, CSYS) == 0)
110 		return (0);
111 	vmaccess(&Netmap[j], (caddr_t)m, k);
112 	bufs = n << 3;
113 	s = spl_imp();
114 	for (j=0; j < bufs; j++) {
115 		m_free(m);
116 		m++;
117 	}
118 	splx(s);
119 	netcb.n_pages += n;
120 	return (1);
121 }
122 
123 m_expand()
124 {
125 	register i;
126 	register struct ipq *fp;
127 	register struct ip *q;
128 	register struct tcb *tp;
129 	register struct mbuf *m, *n;
130 	int need, needp, needs;
131 
132 COUNT(M_EXPAND);
133 	needs = need = netcb.n_hiwat - netcb.n_bufs;    /* #bufs to add */
134 	needp = need >> 3;                              /* #pages to add */
135 	if (pg_alloc(needp))
136 		return (1);
137 	for (i=0; i < needp; i++, need-=NMBPG)
138 		if (needp == 1 || pg_alloc(1) == 0)		/* ??? */
139 			goto steal;
140 	return (need < needs);
141 steal:
142 	fp = netcb.n_ip_tail;           /* ip reass.q */
143 	while (need > 0 && fp) {
144 		q = fp->iqx.ip_next;    /* free mbufs assoc. w/chain */
145 		while (q != (struct ip *)fp) {
146 			need -= m_freem(dtom(q));
147 			q = q->ip_next;
148 		}
149 		ip_freef(fp);           /* free header */
150 		fp = netcb.n_ip_tail;
151 	}
152 	tp = netcb.n_tcb_tail;          /* ->tcbs */
153 	while (need > 0 && tp != NULL) {
154 		m = tp->t_rcv_unack;
155 		while (m != NULL) {
156 			n = m->m_act;
157 			need -= m_freem(m);
158 			m = n;
159 		}
160 		tp->t_rcv_unack = NULL;
161 		tp = tp->t_tcb_prev;
162 	}
163 	return (need < needs);
164 }
165 
166 #ifdef notdef
167 m_relse()
168 {
169 	int free;
170 
171 COUNT(M_RELSE);
172 	free = (netcb.n_bufs - netcb.n_hiwat) >> 3;    /* # excess free pages */
173 	return;
174 }
175 #endif
176 
177 struct mbuf *
178 m_adj(mp, len)
179 	struct mbuf *mp;
180 	register len;
181 {
182 	register struct mbuf *m, *n;
183 
184 COUNT(M_ADJ);
185 	if ((m = mp) == NULL)
186 		return;
187 	if (len >= 0) {                 /* adjust from top of msg chain */
188 		while (m != NULL && len > 0) {
189 			if (m->m_len <= len) {          /* free this mbuf */
190 				len -= m->m_len;
191 				m->m_len = 0;
192 				m = m->m_next;
193 			} else {                        /* adjust mbuf */
194 				m->m_len -= len;
195 				m->m_off += len;
196 				break;
197 			}
198 		}
199 
200 	} else {                        /* adjust from bottom of msg chain */
201 		len = -len;
202 		while (len > 0 && m->m_len != 0) {
203 			/* find end of chain */
204 			while (m != NULL && m->m_len != 0) {
205 				n = m;
206 				m = m->m_next;
207 			}
208 			if (n->m_len <= len) {          /* last mbuf */
209 				len -= n->m_len;
210 				n->m_len = 0;
211 				m = mp;
212 			} else {                        /* adjust length */
213 				n->m_len -= len;
214 				break;
215 			}
216 		}
217 	}
218 }
219 
220 /*
221  * convert mbuf virtual to physical addr for uballoc
222  */
223 mtophys(m)
224 	register struct mbuf *m;
225 {
226 	register i;
227 	register unsigned long addr;
228 	register struct pte *pte;
229 
230 COUNT(MTOPHYS);
231 	i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT;
232 	pte = &Netmap[i];
233 	addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET);
234 	return (addr);
235 }
236