2 #include "../port/lib.h"
9 #include "../port/error.h"
10 #include "../port/netif.h"
11 #include "../port/etherif.h"
13 extern int eipfmt(Fmt*);
14 extern ushort ipcsum(uchar *);
16 static Ether *etherxx[MaxEther];
17 static Ether *etherprobe(int cardno, int ctlrno, char *conf);
20 etherattach(char* spec)
28 ctlrno = strtoul(spec, &conf, 10);
29 if(ctlrno >= MaxEther)
39 if(etherxx[ctlrno] != nil)
41 etherxx[ctlrno] = etherprobe(-1, ctlrno, conf);
44 if(etherxx[ctlrno] == nil)
46 chan = devattach('l', spec);
52 if(etherxx[ctlrno]->attach)
53 etherxx[ctlrno]->attach(etherxx[ctlrno]);
59 etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
61 return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
65 etherstat(Chan* chan, uchar* dp, int n)
67 return netifstat(etherxx[chan->dev], chan, dp, n);
71 etheropen(Chan* chan, int omode)
73 return netifopen(etherxx[chan->dev], chan, omode);
77 ethercreate(Chan*, char*, int, ulong)
84 etherclose(Chan* chan)
86 Ether *ether = etherxx[chan->dev];
88 if(NETTYPE(chan->qid.path) == Ndataqid && ether->f[NETID(chan->qid.path)]->bridge)
89 memset(ether->mactab, 0, sizeof(ether->mactab));
91 netifclose(ether, chan);
95 etherread(Chan* chan, void* buf, long n, vlong off)
100 ether = etherxx[chan->dev];
101 if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
103 * With some controllers it is necessary to reach
104 * into the chip to extract statistics.
106 if(NETTYPE(chan->qid.path) == Nifstatqid)
107 return ether->ifstat(ether, buf, n, offset);
108 else if(NETTYPE(chan->qid.path) == Nstatqid)
109 ether->ifstat(ether, buf, 0, offset);
112 return netifread(ether, chan, buf, n, offset);
116 etherbread(Chan* chan, long n, ulong offset)
118 return netifbread(etherxx[chan->dev], chan, n, offset);
122 etherwstat(Chan* chan, uchar* dp, int n)
124 return netifwstat(etherxx[chan->dev], chan, dp, n);
128 etherrtrace(Netfile* f, Etherpkt* pkt, int len)
132 if(qwindow(f->in) <= 0)
137 memmove(bp->wp, pkt, len < 64 ? len : 64);
139 u32int ms = TK2MS(MACHP(0)->ticks);
152 macent(Ether *ether, uchar *ea)
154 u32int h = (ea[0] | ea[1]<<8 | ea[2]<<16 | ea[3]<<24) ^ (ea[4] | ea[5]<<8);
155 return ðer->mactab[h % nelem(ether->mactab)];
159 * Multiplex the packet to all the connections which want it.
160 * If the packet is not to be used subsequently (tome || from == nil),
161 * attempt to simply pass it into one of the connections, thereby
162 * saving a copy of the data (usual case hopefully).
165 ethermux(Ether *ether, Block *bp, Netfile **from)
169 Netfile *f, *x, **fp;
170 int len, multi, tome, port, type, dispose;
173 if(len < ETHERHDRSIZE)
175 pkt = (Etherpkt*)bp->rp;
176 if(!(multi = pkt->d[0] & 1)){
177 tome = memcmp(pkt->d, ether->ea, Eaddrlen) == 0;
178 if(!tome && from != nil && ether->prom == 0)
182 if(from == nil && ether->prom == 0
183 && memcmp(pkt->d, ether->bcast, Eaddrlen) != 0
184 && !activemulti(ether, pkt->d, Eaddrlen))
190 if((from == nil || (*from)->bridge) && (pkt->s[0] & 1) == 0){
191 Macent *t = macent(ether, pkt->s);
192 t->port = from == nil ? 0 : 1+(from - ether->f);
193 memmove(t->ea, pkt->s, Eaddrlen);
196 Macent *t = macent(ether, pkt->d);
197 if(memcmp(t->ea, pkt->d, Eaddrlen) == 0)
203 type = (pkt->type[0]<<8)|pkt->type[1];
204 dispose = tome || from == nil || port > 0;
206 for(fp = ether->f; fp < ðer->f[Ntypes]; fp++){
209 if(f->type != type && f->type >= 0)
211 if(!tome && !multi && !f->prom)
214 if(tome || fp == from)
216 if(port >= 0 && port != 1+(fp - ether->f))
219 if(f->headersonly || f->type == -2){
220 etherrtrace(f, pkt, len);
223 if(dispose && x == nil)
225 else if((xbp = iallocb(len)) != nil){
226 memmove(xbp->wp, pkt, len);
228 xbp->flag = bp->flag;
229 if(qpass(f->in, xbp) < 0)
235 if(qpass(x->in, bp) < 0)
248 etheriq(Ether* ether, Block* bp)
251 ethermux(ether, bp, nil);
255 etheroq(Ether* ether, Block* bp, Netfile **from)
257 if((*from)->bridge == 0)
258 memmove(((Etherpkt*)bp->rp)->s, ether->ea, Eaddrlen);
260 bp = ethermux(ether, bp, from);
265 qbwrite(ether->oq, bp);
266 if(ether->transmit != nil)
267 ether->transmit(ether);
271 etherwrite(Chan* chan, void* buf, long n, vlong)
273 Ether *ether = etherxx[chan->dev];
278 if(NETTYPE(chan->qid.path) != Ndataqid) {
279 nn = netifwrite(ether, chan, buf, n);
282 cb = parsecmd(buf, n);
283 if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
287 onoff = atoi(cb->f[1]);
288 qnoblock(ether->oq, onoff);
294 return ether->ctl(ether,buf,n);
299 if(n > ether->maxmtu)
301 if(n < ether->minmtu)
309 memmove(bp->rp, buf, n);
313 etheroq(ether, bp, ðer->f[NETID(chan->qid.path)]);
318 etherbwrite(Chan* chan, Block* bp, ulong)
323 if(NETTYPE(chan->qid.path) != Ndataqid){
328 n = etherwrite(chan, bp->rp, n, 0);
334 ether = etherxx[chan->dev];
335 if(n > ether->maxmtu){
339 if(n < ether->minmtu){
343 etheroq(ether, bp, ðer->f[NETID(chan->qid.path)]);
349 int (*reset)(Ether*);
353 addethercard(char* t, int (*r)(Ether*))
357 if(ncard == MaxEther)
358 panic("too many ether cards");
359 cards[ncard].type = t;
360 cards[ncard].reset = r;
365 etherprobe(int cardno, int ctlrno, char *conf)
371 ether = malloc(sizeof(Ether));
373 print("etherprobe: no memory for Ether\n");
376 memset(ether, 0, sizeof(Ether));
377 ether->tbdf = BUSUNKNOWN;
379 ether->ctlrno = ctlrno;
381 ether->minmtu = ETHERMINTU;
382 ether->maxmtu = ETHERMAXTU;
386 kstrdup(ðer->type, conf);
387 ether->nopt = tokenize(ether->type, ether->opt, nelem(ether->opt));
390 memmove(ðer->opt[0], ðer->opt[1], --ether->nopt*sizeof(ether->opt[0]));
391 } else if(isaconfig("ether", ctlrno, ether) == 0)
394 for(cardno = 0; cards[cardno].type != nil; cardno++)
395 if(cistrcmp(cards[cardno].type, ether->type) == 0)
397 if(cards[cardno].type == nil)
400 for(i = 0; i < ether->nopt; i++){
401 if(strncmp(ether->opt[i], "ea=", 3) == 0){
402 if(parseether(ether->ea, ðer->opt[i][3]))
403 memset(ether->ea, 0, Eaddrlen);
407 if(cardno >= MaxEther || cards[cardno].type == nil)
409 snprint(ether->name, sizeof(ether->name), "ether%d", ctlrno);
410 if(cards[cardno].reset(ether) < 0){
412 if(conf != nil) free(ether->type); /* see kstrdup() above */
416 ether->type = cards[cardno].type;
418 print("#l%d: %s: %dMbps port 0x%lluX irq %d ea %E\n",
419 ctlrno, ether->type, ether->mbps, (uvlong)ether->port, ether->irq, ether->ea);
421 /* compute log10(ether->mbps) into lg */
422 for(lg = 0, mb = ether->mbps; mb >= 10; lg++)
426 if (lg > 14) /* 2^(14+17) = 2³¹ */
428 /* allocate larger output queues for higher-speed interfaces */
429 bsz = 1UL << (lg + 17); /* 2¹⁷ = 128K, bsz = 2ⁿ × 128K */
430 while (bsz > mainmem->maxsize / 8 && bsz > 128*1024)
433 netifinit(ether, ether->name, Ntypes, bsz);
434 if(ether->oq == nil) {
435 ether->oq = qopen(bsz, Qmsg, 0, 0);
439 panic("etherreset %s: can't allocate output queue of %ld bytes", ether->name, bsz);
441 ether->alen = Eaddrlen;
442 memmove(ether->addr, ether->ea, Eaddrlen);
443 memset(ether->bcast, 0xFF, Eaddrlen);
448 static void netconsole(int);
456 fmtinstall('E', eipfmt);
458 for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
459 if((ether = etherprobe(-1, ctlrno, nil)) == nil)
461 etherxx[ctlrno] = ether;
464 if(getconf("*noetherprobe") == nil){
466 while(cards[cardno].type != nil && ctlrno < MaxEther){
467 if(etherxx[ctlrno] != nil){
471 if((ether = etherprobe(cardno, ctlrno, nil)) == nil){
475 etherxx[ctlrno] = ether;
491 for(i = 0; i < MaxEther; i++){
495 if(ether->shutdown == nil) {
496 print("#l%d: no shutdown function\n", i);
499 (*ether->shutdown)(ether);
504 #define POLY 0xedb88320
506 /* really slow 32 bit crc for ethers */
508 ethercrc(uchar *p, int len)
514 for(i = 0; i < len; i++){
516 for(j = 0; j < 8; j++){
517 crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
545 enum { PktHdr = 42 };
546 typedef struct Netconsole Netconsole;
553 static Netconsole *netcons;
556 netconsputc(Uart *, int c)
562 netcons->buf[netcons->n++] = c;
563 if(c != '\n' && netcons->n < sizeof(netcons->buf)){
568 p[16] = netcons->n - 14 >> 8;
569 p[17] = netcons->n - 14;
572 cs = ipcsum((uchar*) p + 14);
575 p[38] = netcons->n - 34 >> 8;
576 p[39] = netcons->n - 34;
577 memmove(p+Eaddrlen, netcons->ether->ea, Eaddrlen);
578 qiwrite(netcons->ether->oq, p, netcons->n);
581 if(netcons->ether->transmit != nil)
582 netcons->ether->transmit(netcons->ether);
585 static PhysUart netconsphys = { .putc = netconsputc };
586 static Uart netconsuart = { .phys = &netconsphys };
594 int srcport, devno, dstport;
595 u8int srcip[4], dstip[4];
600 if(consuart == &netconsuart)
605 if((p = getconf("console")) == nil || strncmp(p, "net ", 4) != 0)
609 for(i = 0; i < 4; i++){
610 srcip[i] = strtol(p, &r, 0);
613 if(*r != '.') goto err;
616 srcport = strtol(p, &r, 0);
621 devno = strtol(p, &r, 0);
625 if(*r != ',') goto err;
626 for(i = 0; i < 4; i++){
627 dstip[i] = strtol(p, &r, 0);
630 if(*r != '.') goto err;
633 dstport = strtol(p, &r, 0);
638 dstmac = strtoull(p, &r, 16);
639 if(r - p != 12) goto err;
641 dstmac = ((uvlong)-1) >> 16;
642 if(*r != 0) goto err;
644 if(devno >= MaxEther || etherxx[devno] == nil){
645 print("netconsole: no device #l%d\n", devno);
649 nc = malloc(sizeof(Netconsole));
651 print("netconsole: out of memory");
654 memset(nc, 0, sizeof(Netconsole));
655 nc->ether = etherxx[devno];
657 uchar header[PktHdr] = {
658 /* 0 */ dstmac >> 40, dstmac >> 32, dstmac >> 24, dstmac >> 16, dstmac >> 8, dstmac >> 0,
659 /* 6 */ 0, 0, 0, 0, 0, 0,
662 /* 16 */ 0x00, 0x00, /* total length */
663 /* 18 */ 0x00, 0x00, 0x00, 0x00,
664 /* 22 */ 64, /* ttl */
665 /* 23 */ 0x11, /* protocol */
666 /* 24 */ 0x00, 0x00, /* checksum */
667 /* 26 */ srcip[0], srcip[1], srcip[2], srcip[3],
668 /* 30 */ dstip[0], dstip[1], dstip[2], dstip[3],
669 /* 34 */ srcport >> 8, srcport, dstport >> 8, dstport,
670 /* 38 */ 0x00, 0x00, /* length */
671 /* 40 */ 0x00, 0x00 /* checksum */
674 memmove(nc->buf, header, PktHdr);
678 consuart = &netconsuart;
682 print("netconsole: invalid string %#q\n", getconf("console"));
683 print("netconsole: usage: srcip[!srcport][/srcdev],dstip[!dstport][/dstmac]\n");