xref: /plan9/sys/src/9/pc/devether.c (revision 6520663fb7ebac8d17e4a1dbc55d10bf525f7b14)
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 = &ether->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, &ether->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