1 /* uipc_mbuf.c 1.7 81/11/04 */ 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 "../inet/inet.h" 12 #include "../inet/inet_systm.h" 13 #include "../inet/ip.h" 14 #include "../inet/tcp.h" 15 #include "../h/vm.h" 16 17 m_reserve(mbufs) 18 int mbufs; 19 { 20 21 if (mbstat.m_lowat + mbufs > NNETPAGES * NMBPG - 32) 22 return (0); 23 mbstat.m_lowat += mbufs; 24 mbstat.m_hiwat = 2 * mbstat.m_lowat; 25 } 26 27 m_release(mbufs) 28 int mbufs; 29 { 30 31 mbstat.m_lowat -= mbufs; 32 mbstat.m_hiwat = 2 * mbstat.m_lowat; 33 } 34 35 struct mbuf * 36 m_get(canwait) 37 int canwait; 38 { 39 register struct mbuf *m; 40 41 COUNT(M_GET); 42 MGET(m, canwait); 43 return (m); 44 } 45 46 struct mbuf * 47 m_free(m) 48 struct mbuf *m; 49 { 50 register struct mbuf *n; 51 52 COUNT(M_FREE); 53 MFREE(m, n); 54 return (n); 55 } 56 57 struct mbuf * 58 m_more(type) 59 int type; 60 { 61 int s; 62 register struct mbuf *m; 63 64 COUNT(M_MORE); 65 if (!m_expand()) { 66 netstat.m_drops++; 67 return (NULL); 68 } 69 #define m_more(x) ((struct mbuf *)panic("m_more")) 70 MGET(m, 0); 71 return (m); 72 } 73 74 m_freem(m) 75 register struct mbuf *m; 76 { 77 register struct mbuf *n; 78 register int s, cnt; 79 80 COUNT(M_FREEM); 81 if (m == NULL) 82 return (0); 83 cnt = 0; 84 s = splimp(); 85 do { 86 if (m->m_off > MMAXOFF) 87 cnt += NMBPG; 88 cnt++; 89 MFREE(m, n); 90 } while (m = n); 91 splx(s); 92 return (cnt); 93 } 94 95 mbufinit() 96 { 97 register struct mbuf *m; 98 register i; 99 100 COUNT(MBUFINIT); 101 m = (struct mbuf *)&netutl[0]; /* ->start of buffer virt mem */ 102 vmemall(&Netmap[0], 2, proc, CSYS); 103 vmaccess(&Netmap[0], m, 2); 104 for (i=0; i < NMBPG; i++) { 105 m->m_off = 0; 106 m_free(m); 107 m++; 108 } 109 pg_alloc(3); 110 mbstat.m_pages = 4; 111 mbstat.m_bufs = 32; 112 mbstat.m_lowat = 16; 113 mbstat.m_hiwat = 32; 114 { int i,j,k,n; 115 n = 32; 116 k = n << 1; 117 if ((i = rmalloc(netmap, n)) == 0) 118 return (0); 119 j = i<<1; 120 m = pftom(i); 121 /* should use vmemall sometimes */ 122 if (memall(&Netmap[j], k, proc, CSYS) == 0) { 123 printf("botch\n"); 124 return; 125 } 126 vmaccess(&Netmap[j], (caddr_t)m, k); 127 for (j=0; j < n; j++) { 128 m->m_off = 0; 129 m->m_next = mpfree; 130 mpfree = m; 131 m += NMBPG; 132 nmpfree++; 133 } 134 } 135 } 136 137 pg_alloc(n) 138 register int n; 139 { 140 register i, j, k; 141 register struct mbuf *m; 142 int bufs, s; 143 144 COUNT(PG_ALLOC); 145 k = n << 1; 146 if ((i = rmalloc(netmap, n)) == 0) 147 return (0); 148 j = i<<1; 149 m = pftom(i); 150 /* should use vmemall sometimes */ 151 if (memall(&Netmap[j], k, proc, CSYS) == 0) 152 return (0); 153 vmaccess(&Netmap[j], (caddr_t)m, k); 154 bufs = n << 3; 155 s = splimp(); 156 for (j=0; j < bufs; j++) { 157 m->m_off = 0; 158 m_free(m); 159 m++; 160 } 161 splx(s); 162 mbstat.m_pages += n; 163 return (1); 164 } 165 166 m_expand() 167 { 168 register i; 169 register struct mbuf *m, *n; 170 int need, needp, needs; 171 172 COUNT(M_EXPAND); 173 needs = need = mbstat.m_hiwat - mbstat.m_bufs; 174 needp = need >> 3; 175 if (pg_alloc(needp)) 176 return (1); 177 for (i=0; i < needp; i++, need -= NMBPG) 178 if (pg_alloc(1) == 0) 179 goto steal; 180 return (need < needs); 181 steal: 182 /* while (not enough) ask protocols to free code */ 183 ; 184 } 185 186 #ifdef notdef 187 m_relse() 188 { 189 190 COUNT(M_RELSE); 191 } 192 #endif 193 194 m_cat(m, n) 195 register struct mbuf *m, *n; 196 { 197 198 while (m->m_next) 199 m = m->m_next; 200 while (n) 201 if (m->m_off + m->m_len + n->m_len <= MMAXOFF) { 202 bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, n->m_len); 203 m->m_len += n->m_len; 204 n = m_free(n); 205 } else { 206 m->m_next = n; 207 m = n; 208 n = m->m_next; 209 } 210 } 211 212 m_adj(mp, len) 213 struct mbuf *mp; 214 register len; 215 { 216 register struct mbuf *m, *n; 217 218 /* 219 for (m = mp; m; m = m->m_next) { 220 printf("a %x %d\n", m, m->m_len); 221 } 222 */ 223 COUNT(M_ADJ); 224 if ((m = mp) == NULL) 225 return; 226 if (len >= 0) { /* adjust from top of msg chain */ 227 while (m != NULL && len > 0) { 228 if (m->m_len <= len) { /* free this mbuf */ 229 len -= m->m_len; 230 m->m_len = 0; 231 m = m->m_next; 232 } else { /* adjust mbuf */ 233 m->m_len -= len; 234 m->m_off += len; 235 break; 236 } 237 } 238 239 } else { /* adjust from bottom of msg chain */ 240 len = -len; 241 while (len > 0 && m->m_len != 0) { 242 /* find end of chain */ 243 while (m != NULL && m->m_len != 0) { 244 n = m; 245 m = m->m_next; 246 } 247 if (n->m_len <= len) { /* last mbuf */ 248 len -= n->m_len; 249 n->m_len = 0; 250 m = mp; 251 } else { /* adjust length */ 252 n->m_len -= len; 253 break; 254 } 255 } 256 } 257 } 258 259 /* 260 * convert mbuf virtual to physical addr for uballoc 261 */ 262 mtophys(m) 263 register struct mbuf *m; 264 { 265 register i; 266 register unsigned long addr; 267 register struct pte *pte; 268 269 COUNT(MTOPHYS); 270 i = (((int)m & ~PGOFSET) - (int)netutl) >> PGSHIFT; 271 pte = &Netmap[i]; 272 addr = (pte->pg_pfnum << PGSHIFT) | ((int)m & PGOFSET); 273 return (addr); 274 } 275