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 "pool.h"
8 #include "ureg.h"
9 #include "../port/error.h"
10 #include "../port/netif.h"
11
12 #include "etherif.h"
13
14 static Ether *etherxx[MaxEther];
15
16 Chan*
etherattach(char * spec)17 etherattach(char* spec)
18 {
19 ulong 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 || (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*
etherwalk(Chan * chan,Chan * nchan,char ** name,int nname)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
etherstat(Chan * chan,uchar * dp,int n)51 etherstat(Chan* chan, uchar* dp, int n)
52 {
53 return netifstat(etherxx[chan->dev], chan, dp, n);
54 }
55
56 static Chan*
etheropen(Chan * chan,int omode)57 etheropen(Chan* chan, int omode)
58 {
59 return netifopen(etherxx[chan->dev], chan, omode);
60 }
61
62 static void
ethercreate(Chan *,char *,int,ulong)63 ethercreate(Chan*, char*, int, ulong)
64 {
65 }
66
67 static void
etherclose(Chan * chan)68 etherclose(Chan* chan)
69 {
70 netifclose(etherxx[chan->dev], chan);
71 }
72
73 static long
etherread(Chan * chan,void * buf,long n,vlong off)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*
etherbread(Chan * chan,long n,ulong offset)95 etherbread(Chan* chan, long n, ulong offset)
96 {
97 return netifbread(etherxx[chan->dev], chan, n, offset);
98 }
99
100 static int
etherwstat(Chan * chan,uchar * dp,int n)101 etherwstat(Chan* chan, uchar* dp, int n)
102 {
103 return netifwstat(etherxx[chan->dev], chan, dp, n);
104 }
105
106 static void
etherrtrace(Netfile * f,Etherpkt * pkt,int len)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*
etheriq(Ether * ether,Block * bp,int fromwire)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 && ether->prom == 0){
153 if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
154 if(fromwire){
155 freeb(bp);
156 bp = 0;
157 }
158 return bp;
159 }
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)
174 if(f->type == type || f->type < 0)
175 if(tome || multi || f->prom){
176 /* Don't want to hear bridged packets */
177 if(f->bridge && !fromwire && !fromme)
178 continue;
179 if(!f->headersonly){
180 if(fromwire && fx == 0)
181 fx = f;
182 else if(xbp = iallocb(len)){
183 memmove(xbp->wp, pkt, len);
184 xbp->wp += len;
185 if(qpass(f->in, xbp) < 0){
186 // print("soverflow for f->in\n");
187 ether->soverflows++;
188 }
189 }
190 else{
191 // print("soverflow iallocb\n");
192 ether->soverflows++;
193 }
194 }
195 else
196 etherrtrace(f, pkt, len);
197 }
198 }
199
200 if(fx){
201 if(qpass(fx->in, bp) < 0){
202 // print("soverflow for fx->in\n");
203 ether->soverflows++;
204 }
205 return 0;
206 }
207 if(fromwire){
208 freeb(bp);
209 return 0;
210 }
211
212 return bp;
213 }
214
215 static int
etheroq(Ether * ether,Block * bp)216 etheroq(Ether* ether, Block* bp)
217 {
218 int len, loopback, s;
219 Etherpkt *pkt;
220
221 ether->outpackets++;
222
223 /*
224 * Check if the packet has to be placed back onto the input queue,
225 * i.e. if it's a loopback or broadcast packet or the interface is
226 * in promiscuous mode.
227 * If it's a loopback packet indicate to etheriq that the data isn't
228 * needed and return, etheriq will pass-on or free the block.
229 * To enable bridging to work, only packets that were originated
230 * by this interface are fed back.
231 */
232 pkt = (Etherpkt*)bp->rp;
233 len = BLEN(bp);
234 loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
235 if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){
236 s = splhi();
237 etheriq(ether, bp, 0);
238 splx(s);
239 }
240
241 if(!loopback){
242 if(qfull(ether->oq))
243 print("etheroq: WARNING: ether->oq full!\n");
244 qbwrite(ether->oq, bp);
245 if(ether->transmit != nil)
246 ether->transmit(ether);
247 } else
248 freeb(bp);
249
250 return len;
251 }
252
253 static long
etherwrite(Chan * chan,void * buf,long n,vlong)254 etherwrite(Chan* chan, void* buf, long n, vlong)
255 {
256 Ether *ether;
257 Block *bp;
258 int nn, onoff;
259 Cmdbuf *cb;
260
261 ether = etherxx[chan->dev];
262 if(NETTYPE(chan->qid.path) != Ndataqid) {
263 nn = netifwrite(ether, chan, buf, n);
264 if(nn >= 0)
265 return nn;
266 cb = parsecmd(buf, n);
267 if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
268 if(cb->nf <= 1)
269 onoff = 1;
270 else
271 onoff = atoi(cb->f[1]);
272 qnoblock(ether->oq, onoff);
273 free(cb);
274 return n;
275 }
276 free(cb);
277 if(ether->ctl != nil)
278 return ether->ctl(ether, buf, n);
279
280 error(Ebadctl);
281 }
282
283 if(n > ether->mtu)
284 error(Etoobig);
285 if(n < ether->minmtu)
286 error(Etoosmall);
287
288 bp = allocb(n);
289 if(waserror()){
290 freeb(bp);
291 nexterror();
292 }
293 memmove(bp->rp, buf, n);
294 memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
295 poperror();
296 bp->wp += n;
297
298 return etheroq(ether, bp);
299 }
300
301 static long
etherbwrite(Chan * chan,Block * bp,ulong)302 etherbwrite(Chan* chan, Block* bp, ulong)
303 {
304 Ether *ether;
305 long n;
306
307 n = BLEN(bp);
308 if(NETTYPE(chan->qid.path) != Ndataqid){
309 if(waserror()) {
310 freeb(bp);
311 nexterror();
312 }
313 n = etherwrite(chan, bp->rp, n, 0);
314 poperror();
315 freeb(bp);
316 return n;
317 }
318 ether = etherxx[chan->dev];
319
320 if(n > ether->mtu){
321 freeb(bp);
322 error(Etoobig);
323 }
324 if(n < ether->minmtu){
325 freeb(bp);
326 error(Etoosmall);
327 }
328
329 return etheroq(ether, bp);
330 }
331
332 static struct {
333 char* type;
334 int (*reset)(Ether*);
335 } cards[MaxEther+1];
336
337 void
addethercard(char * t,int (* r)(Ether *))338 addethercard(char* t, int (*r)(Ether*))
339 {
340 static int ncard;
341
342 if(ncard == MaxEther)
343 panic("too many ether cards");
344 cards[ncard].type = t;
345 cards[ncard].reset = r;
346 ncard++;
347 }
348
349 int
parseether(uchar * to,char * from)350 parseether(uchar *to, char *from)
351 {
352 char nip[4];
353 char *p;
354 int i;
355
356 p = from;
357 for(i = 0; i < Eaddrlen; i++){
358 if(*p == 0)
359 return -1;
360 nip[0] = *p++;
361 if(*p == 0)
362 return -1;
363 nip[1] = *p++;
364 nip[2] = 0;
365 to[i] = strtoul(nip, 0, 16);
366 if(*p == ':')
367 p++;
368 }
369 return 0;
370 }
371
372 static Ether*
etherprobe(int cardno,int ctlrno)373 etherprobe(int cardno, int ctlrno)
374 {
375 int i, lg;
376 ulong mb, bsz;
377 Ether *ether;
378 char buf[128], name[32];
379
380 ether = malloc(sizeof(Ether));
381 if(ether == nil)
382 error(Enomem);
383 memset(ether, 0, sizeof(Ether));
384 ether->ctlrno = ctlrno;
385 ether->tbdf = BUSUNKNOWN;
386 ether->mbps = 10;
387 ether->minmtu = ETHERMINTU;
388 ether->maxmtu = ETHERMAXTU;
389 ether->mtu = ETHERMAXTU;
390
391 if(cardno < 0){
392 if(isaconfig("ether", ctlrno, ether) == 0){
393 free(ether);
394 return nil;
395 }
396 for(cardno = 0; cards[cardno].type; cardno++){
397 if(cistrcmp(cards[cardno].type, ether->type))
398 continue;
399 for(i = 0; i < ether->nopt; i++){
400 if(strncmp(ether->opt[i], "ea=", 3))
401 continue;
402 if(parseether(ether->ea, ðer->opt[i][3]))
403 memset(ether->ea, 0, Eaddrlen);
404 }
405 break;
406 }
407 }
408
409 if(cardno >= MaxEther || cards[cardno].type == nil){
410 free(ether);
411 return nil;
412 }
413 if(cards[cardno].reset(ether) < 0){
414 free(ether);
415 return nil;
416 }
417
418 /*
419 * IRQ2 doesn't really exist, it's used to gang the interrupt
420 * controllers together. A device set to IRQ2 will appear on
421 * the second interrupt controller as IRQ9.
422 */
423 if(ether->irq == 2)
424 ether->irq = 9;
425 snprint(name, sizeof(name), "ether%d", ctlrno);
426
427 /*
428 * If ether->irq is <0, it is a hack to indicate no interrupt
429 * used by ethersink.
430 */
431 if(ether->irq >= 0)
432 intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
433
434 i = sprint(buf, "#l%d: %s: ", ctlrno, cards[cardno].type);
435 if(ether->mbps >= 1000)
436 i += sprint(buf+i, "%dGbps", ether->mbps/1000);
437 else
438 i += sprint(buf+i, "%dMbps", ether->mbps);
439 i += sprint(buf+i, " port 0x%luX irq %d", ether->port, ether->irq);
440 if(ether->mem)
441 i += sprint(buf+i, " addr 0x%luX", ether->mem);
442 if(ether->size)
443 i += sprint(buf+i, " size 0x%luX", ether->size);
444 i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
445 ether->ea[0], ether->ea[1], ether->ea[2],
446 ether->ea[3], ether->ea[4], ether->ea[5]);
447 sprint(buf+i, "\n");
448 print(buf);
449
450 /*
451 * input queues are allocated by ../port/netif.c:/^openfile.
452 * the size will be the last argument to netifinit() below.
453 *
454 * output queues should be small, to minimise `bufferbloat',
455 * which confuses tcp's feedback loop. at 1Gb/s, it only takes
456 * ~15µs to transmit a full-sized non-jumbo packet.
457 */
458
459 /* compute log10(ether->mbps) into lg */
460 for(lg = 0, mb = ether->mbps; mb >= 10; lg++)
461 mb /= 10;
462 if (lg > 14) /* sanity cap; 2**(14+15) = 2²⁹ */
463 lg = 14;
464
465 /* allocate larger input queues for higher-speed interfaces */
466 bsz = 1UL << (lg + 15); /* 2ⁱ⁵ = 32K, bsz = 2ⁿ × 32K */
467 while (bsz > mainmem->maxsize / 8 && bsz > 128*1024) /* sanity */
468 bsz /= 2;
469 netifinit(ether, name, Ntypes, bsz);
470
471 if(ether->oq == nil)
472 ether->oq = qopen(1 << (lg + 13), Qmsg, 0, 0);
473 if(ether->oq == nil)
474 panic("etherreset %s: can't allocate output queue", name);
475
476 ether->alen = Eaddrlen;
477 memmove(ether->addr, ether->ea, Eaddrlen);
478 memset(ether->bcast, 0xFF, Eaddrlen);
479
480 return ether;
481 }
482
483 static void
etherreset(void)484 etherreset(void)
485 {
486 Ether *ether;
487 int cardno, ctlrno;
488
489 for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
490 if((ether = etherprobe(-1, ctlrno)) == nil)
491 continue;
492 etherxx[ctlrno] = ether;
493 }
494
495 if(getconf("*noetherprobe"))
496 return;
497
498 cardno = ctlrno = 0;
499 while(cards[cardno].type != nil && ctlrno < MaxEther){
500 if(etherxx[ctlrno] != nil){
501 ctlrno++;
502 continue;
503 }
504 if((ether = etherprobe(cardno, ctlrno)) == nil){
505 cardno++;
506 continue;
507 }
508 etherxx[ctlrno] = ether;
509 ctlrno++;
510 }
511 }
512
513 static void
ethershutdown(void)514 ethershutdown(void)
515 {
516 Ether *ether;
517 int i;
518
519 for(i = 0; i < MaxEther; i++){
520 ether = etherxx[i];
521 if(ether == nil)
522 continue;
523 if(ether->shutdown == nil) {
524 print("#l%d: no shutdown function\n", i);
525 continue;
526 }
527 (*ether->shutdown)(ether);
528 }
529 }
530
531
532 #define POLY 0xedb88320
533
534 /* really slow 32 bit crc for ethers */
535 ulong
ethercrc(uchar * p,int len)536 ethercrc(uchar *p, int len)
537 {
538 int i, j;
539 ulong crc, b;
540
541 crc = 0xffffffff;
542 for(i = 0; i < len; i++){
543 b = *p++;
544 for(j = 0; j < 8; j++){
545 crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
546 b >>= 1;
547 }
548 }
549 return crc;
550 }
551
552 Dev etherdevtab = {
553 'l',
554 "ether",
555
556 etherreset,
557 devinit,
558 ethershutdown,
559 etherattach,
560 etherwalk,
561 etherstat,
562 etheropen,
563 ethercreate,
564 etherclose,
565 etherread,
566 etherbread,
567 etherwrite,
568 etherbwrite,
569 devremove,
570 etherwstat,
571 };
572