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