1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "io.h" 7 #include "../port/error.h" 8 9 #include "../port/netif.h" 10 #include "etherif.h" 11 12 static Ether *etherxx[MaxEther]; 13 14 Chan* 15 etherattach(char* spec) 16 { 17 int ctlrno; 18 char *p; 19 Chan *chan; 20 21 ctlrno = 0; 22 if(spec && *spec){ 23 ctlrno = strtoul(spec, &p, 0); 24 if((ctlrno == 0 && p == spec) || *p != 0) 25 error(Ebadarg); 26 if(ctlrno < 0 || ctlrno >= MaxEther) 27 error(Ebadarg); 28 } 29 if(etherxx[ctlrno] == 0) 30 error(Enodev); 31 32 chan = devattach('l', spec); 33 if(waserror()){ 34 chanfree(chan); 35 nexterror(); 36 } 37 chan->dev = ctlrno; 38 if(etherxx[ctlrno]->attach) 39 etherxx[ctlrno]->attach(etherxx[ctlrno]); 40 poperror(); 41 return chan; 42 } 43 44 static Walkqid* 45 etherwalk(Chan* chan, Chan* nchan, char** name, int nname) 46 { 47 return netifwalk(etherxx[chan->dev], chan, nchan, name, nname); 48 } 49 50 static int 51 etherstat(Chan* chan, uchar* dp, int n) 52 { 53 return netifstat(etherxx[chan->dev], chan, dp, n); 54 } 55 56 static Chan* 57 etheropen(Chan* chan, int omode) 58 { 59 return netifopen(etherxx[chan->dev], chan, omode); 60 } 61 62 static void 63 ethercreate(Chan*, char*, int, ulong) 64 { 65 } 66 67 static void 68 etherclose(Chan* chan) 69 { 70 netifclose(etherxx[chan->dev], chan); 71 } 72 73 static long 74 etherread(Chan* chan, void* buf, long n, vlong off) 75 { 76 Ether *ether; 77 ulong offset = off; 78 79 ether = etherxx[chan->dev]; 80 if((chan->qid.type & QTDIR) == 0 && ether->ifstat){ 81 /* 82 * With some controllers it is necessary to reach 83 * into the chip to extract statistics. 84 */ 85 if(NETTYPE(chan->qid.path) == Nifstatqid) 86 return ether->ifstat(ether, buf, n, offset); 87 else if(NETTYPE(chan->qid.path) == Nstatqid) 88 ether->ifstat(ether, buf, 0, offset); 89 } 90 91 return netifread(ether, chan, buf, n, offset); 92 } 93 94 static Block* 95 etherbread(Chan* chan, long n, ulong offset) 96 { 97 return netifbread(etherxx[chan->dev], chan, n, offset); 98 } 99 100 static int 101 etherwstat(Chan* chan, uchar* dp, int n) 102 { 103 return netifwstat(etherxx[chan->dev], chan, dp, n); 104 } 105 106 static void 107 etherrtrace(Netfile* f, Etherpkt* pkt, int len) 108 { 109 int i, n; 110 Block *bp; 111 112 if(qwindow(f->in) <= 0) 113 return; 114 if(len > 58) 115 n = 58; 116 else 117 n = len; 118 bp = iallocb(64); 119 if(bp == nil) 120 return; 121 memmove(bp->wp, pkt->d, n); 122 i = TK2MS(MACHP(0)->ticks); 123 bp->wp[58] = len>>8; 124 bp->wp[59] = len; 125 bp->wp[60] = i>>24; 126 bp->wp[61] = i>>16; 127 bp->wp[62] = i>>8; 128 bp->wp[63] = i; 129 bp->wp += 64; 130 qpass(f->in, bp); 131 } 132 133 Block* 134 etheriq(Ether* ether, Block* bp, int fromwire) 135 { 136 Etherpkt *pkt; 137 ushort type; 138 int len, multi, tome, fromme; 139 Netfile **ep, *f, **fp, *fx; 140 Block *xbp; 141 142 ether->inpackets++; 143 144 pkt = (Etherpkt*)bp->rp; 145 len = BLEN(bp); 146 type = (pkt->type[0]<<8)|pkt->type[1]; 147 fx = 0; 148 ep = ðer->f[Ntypes]; 149 150 multi = pkt->d[0] & 1; 151 /* check for valid multicast addresses */ 152 if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && 153 ether->prom == 0){ 154 if(!activemulti(ether, pkt->d, sizeof(pkt->d))){ 155 if(fromwire){ 156 freeb(bp); 157 bp = 0; 158 } 159 return bp; 160 } 161 } 162 /* is it for me? */ 163 tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; 164 fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0; 165 166 /* 167 * Multiplex the packet to all the connections which want it. 168 * If the packet is not to be used subsequently (fromwire != 0), 169 * attempt to simply pass it into one of the connections, thereby 170 * saving a copy of the data (usual case hopefully). 171 */ 172 for(fp = ether->f; fp < ep; fp++){ 173 if((f = *fp) != nil && (f->type == type || f->type < 0) && 174 (tome || multi || f->prom)){ 175 /* Don't want to hear bridged packets */ 176 if(f->bridge && !fromwire && !fromme) 177 continue; 178 if(!f->headersonly){ 179 if(fromwire && fx == 0) 180 fx = f; 181 else if(xbp = iallocb(len)){ 182 memmove(xbp->wp, pkt, len); 183 xbp->wp += len; 184 if(qpass(f->in, xbp) < 0) 185 ether->soverflows++; 186 } 187 else 188 ether->soverflows++; 189 } 190 else 191 etherrtrace(f, pkt, len); 192 } 193 } 194 195 if(fx){ 196 if(qpass(fx->in, bp) < 0) 197 ether->soverflows++; 198 return 0; 199 } 200 if(fromwire){ 201 freeb(bp); 202 return 0; 203 } 204 return bp; 205 } 206 207 static int 208 etheroq(Ether* ether, Block* bp) 209 { 210 int len, loopback, s; 211 Etherpkt *pkt; 212 213 ether->outpackets++; 214 215 /* 216 * Check if the packet has to be placed back onto the input queue, 217 * i.e. if it's a loopback or broadcast packet or the interface is 218 * in promiscuous mode. 219 * If it's a loopback packet indicate to etheriq that the data isn't 220 * needed and return, etheriq will pass-on or free the block. 221 * To enable bridging to work, only packets that were originated 222 * by this interface are fed back. 223 */ 224 pkt = (Etherpkt*)bp->rp; 225 len = BLEN(bp); 226 loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; 227 if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){ 228 s = splhi(); 229 etheriq(ether, bp, 0); 230 splx(s); 231 } 232 233 if(!loopback){ 234 qbwrite(ether->oq, bp); 235 if(ether->transmit != nil) 236 ether->transmit(ether); 237 } else 238 freeb(bp); 239 240 return len; 241 } 242 243 static long 244 etherwrite(Chan* chan, void* buf, long n, vlong) 245 { 246 Ether *ether; 247 Block *bp; 248 int nn, onoff; 249 Cmdbuf *cb; 250 251 ether = etherxx[chan->dev]; 252 if(NETTYPE(chan->qid.path) != Ndataqid) { 253 nn = netifwrite(ether, chan, buf, n); 254 if(nn >= 0) 255 return nn; 256 cb = parsecmd(buf, n); 257 if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){ 258 if(cb->nf <= 1) 259 onoff = 1; 260 else 261 onoff = atoi(cb->f[1]); 262 qnoblock(ether->oq, onoff); 263 free(cb); 264 return n; 265 } 266 free(cb); 267 if(ether->ctl!=nil) 268 return ether->ctl(ether,buf,n); 269 270 error(Ebadctl); 271 } 272 273 if(n > ether->maxmtu) 274 error(Etoobig); 275 if(n < ether->minmtu) 276 error(Etoosmall); 277 278 bp = allocb(n); 279 if(waserror()){ 280 freeb(bp); 281 nexterror(); 282 } 283 memmove(bp->rp, buf, n); 284 memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen); 285 poperror(); 286 bp->wp += n; 287 288 return etheroq(ether, bp); 289 } 290 291 static long 292 etherbwrite(Chan* chan, Block* bp, ulong) 293 { 294 Ether *ether; 295 long n; 296 297 n = BLEN(bp); 298 if(NETTYPE(chan->qid.path) != Ndataqid){ 299 if(waserror()) { 300 freeb(bp); 301 nexterror(); 302 } 303 n = etherwrite(chan, bp->rp, n, 0); 304 poperror(); 305 freeb(bp); 306 return n; 307 } 308 ether = etherxx[chan->dev]; 309 310 if(n > ether->maxmtu){ 311 freeb(bp); 312 error(Etoobig); 313 } 314 if(n < ether->minmtu){ 315 freeb(bp); 316 error(Etoosmall); 317 } 318 319 return etheroq(ether, bp); 320 } 321 322 static struct { 323 char* type; 324 int (*reset)(Ether*); 325 } cards[MaxEther+1]; 326 327 void 328 addethercard(char* t, int (*r)(Ether*)) 329 { 330 static int ncard; 331 332 if(ncard == MaxEther) 333 panic("too many ether cards"); 334 cards[ncard].type = t; 335 cards[ncard].reset = r; 336 ncard++; 337 } 338 339 int 340 parseether(uchar *to, char *from) 341 { 342 char nip[4]; 343 char *p; 344 int i; 345 346 p = from; 347 for(i = 0; i < Eaddrlen; i++){ 348 if(*p == 0) 349 return -1; 350 nip[0] = *p++; 351 if(*p == 0) 352 return -1; 353 nip[1] = *p++; 354 nip[2] = 0; 355 to[i] = strtoul(nip, 0, 16); 356 if(*p == ':') 357 p++; 358 } 359 return 0; 360 } 361 362 static void 363 etherreset(void) 364 { 365 Ether *ether; 366 int i, n, ctlrno; 367 char name[KNAMELEN], buf[128]; 368 369 for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ 370 if(ether == 0) 371 ether = malloc(sizeof(Ether)); 372 memset(ether, 0, sizeof(Ether)); 373 ether->ctlrno = ctlrno; 374 ether->mbps = 10; 375 ether->minmtu = ETHERMINTU; 376 ether->maxmtu = ETHERMAXTU; 377 378 if(archether(ctlrno, ether) <= 0) 379 continue; 380 381 if(isaconfig("ether", ctlrno, ether) == 0){ 382 // free(ether); 383 // return nil; 384 continue; 385 } 386 for(n = 0; cards[n].type; n++){ 387 if(cistrcmp(cards[n].type, ether->type)) 388 continue; 389 for(i = 0; i < ether->nopt; i++) 390 if(cistrncmp(ether->opt[i], "ea=", 3) == 0){ 391 if(parseether(ether->ea, 392 ðer->opt[i][3]) == -1) 393 memset(ether->ea, 0, Eaddrlen); 394 } else if(cistrcmp(ether->opt[i], 395 "100BASE-TXFD") == 0) 396 ether->mbps = 100; 397 if(cards[n].reset(ether)) 398 break; 399 snprint(name, sizeof(name), "ether%d", ctlrno); 400 401 if(ether->interrupt != nil && ether->irq >= 0) 402 intrenable(ether->irq, ether->interrupt, 403 ether, 0, name); 404 405 i = snprint(buf, sizeof buf, 406 "#l%d: %s: %dMbps port %#lux irq %d", 407 ctlrno, ether->type, ether->mbps, ether->port, 408 ether->irq); 409 if(ether->mem) 410 i += snprint(buf+i, sizeof buf - i, 411 " addr %#lux", PADDR(ether->mem)); 412 if(ether->size) 413 i += snprint(buf+i, sizeof buf - i, 414 " size %#luX", ether->size); 415 i += snprint(buf+i, sizeof buf - i, 416 ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux", 417 ether->ea[0], ether->ea[1], ether->ea[2], 418 ether->ea[3], ether->ea[4], ether->ea[5]); 419 snprint(buf+i, sizeof buf - i, "\n"); 420 iprint("%s", buf); /* it may be too early for print */ 421 422 if(ether->mbps >= 1000) 423 netifinit(ether, name, Ntypes, 4*1024*1024); 424 else if(ether->mbps >= 100) 425 netifinit(ether, name, Ntypes, 1024*1024); 426 else 427 netifinit(ether, name, Ntypes, 65*1024); 428 if(ether->oq == 0) 429 ether->oq = qopen(ether->limit, Qmsg, 0, 0); 430 if(ether->oq == 0) 431 panic("etherreset %s", name); 432 ether->alen = Eaddrlen; 433 memmove(ether->addr, ether->ea, Eaddrlen); 434 memset(ether->bcast, 0xFF, Eaddrlen); 435 436 etherxx[ctlrno] = ether; 437 ether = 0; 438 break; 439 } 440 } 441 if(ether) 442 free(ether); 443 } 444 445 static void 446 ethershutdown(void) 447 { 448 Ether *ether; 449 int i; 450 451 for(i = 0; i < MaxEther; i++){ 452 ether = etherxx[i]; 453 if(ether == nil) 454 continue; 455 if(ether->shutdown == nil) { 456 print("#l%d: no shutdown function\n", i); 457 continue; 458 } 459 (*ether->shutdown)(ether); 460 } 461 } 462 463 464 #define POLY 0xedb88320 465 466 /* really slow 32 bit crc for ethers */ 467 ulong 468 ethercrc(uchar *p, int len) 469 { 470 int i, j; 471 ulong crc, b; 472 473 crc = 0xffffffff; 474 for(i = 0; i < len; i++){ 475 b = *p++; 476 for(j = 0; j < 8; j++){ 477 crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0); 478 b >>= 1; 479 } 480 } 481 return crc; 482 } 483 484 void 485 dumpoq(Queue *oq) 486 { 487 if (oq == nil) 488 print("no outq! "); 489 else if (qisclosed(oq)) 490 print("outq closed "); 491 else if (qfull(oq)) 492 print("outq full "); 493 else 494 print("outq %d ", qlen(oq)); 495 } 496 497 void 498 dumpnetif(Netif *netif) 499 { 500 print("netif %s ", netif->name); 501 print("limit %d mbps %d link %d ", 502 netif->limit, netif->mbps, netif->link); 503 print("inpkts %lld outpkts %lld errs %d\n", 504 netif->inpackets, netif->outpackets, 505 netif->crcs + netif->oerrs + netif->frames + netif->overflows + 506 netif->buffs + netif->soverflows); 507 } 508 509 Dev etherdevtab = { 510 'l', 511 "ether", 512 513 etherreset, 514 devinit, 515 ethershutdown, 516 etherattach, 517 etherwalk, 518 etherstat, 519 etheropen, 520 ethercreate, 521 etherclose, 522 etherread, 523 etherbread, 524 etherwrite, 525 etherbwrite, 526 devremove, 527 etherwstat, 528 }; 529