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