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