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