1 /* uipc_mbuf.c 1.2 81/10/23 */ 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->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