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*
etherattach(char * spec)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*
etherwalk(Chan * chan,Chan * nchan,char ** name,int nname)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
etherstat(Chan * chan,uchar * dp,int n)53 etherstat(Chan* chan, uchar* dp, int n)
54 {
55 return netifstat(etherxx[chan->dev], chan, dp, n);
56 }
57
58 static Chan*
etheropen(Chan * chan,int omode)59 etheropen(Chan* chan, int omode)
60 {
61 return netifopen(etherxx[chan->dev], chan, omode);
62 }
63
64 static void
ethercreate(Chan *,char *,int,ulong)65 ethercreate(Chan*, char*, int, ulong)
66 {
67 }
68
69 static void
etherclose(Chan * chan)70 etherclose(Chan* chan)
71 {
72 netifclose(etherxx[chan->dev], chan);
73 }
74
75 static long
etherread(Chan * chan,void * buf,long n,vlong off)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*
etherbread(Chan * chan,long n,ulong offset)97 etherbread(Chan* chan, long n, ulong offset)
98 {
99 return netifbread(etherxx[chan->dev], chan, n, offset);
100 }
101
102 static int
etherwstat(Chan * chan,uchar * dp,int n)103 etherwstat(Chan* chan, uchar* dp, int n)
104 {
105 return netifwstat(etherxx[chan->dev], chan, dp, n);
106 }
107
108 static void
etherrtrace(Netfile * f,Etherpkt * pkt,int len)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*
etheriq(Ether * ether,Block * bp,int fromwire)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
etheroq(Ether * ether,Block * bp)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
etherwrite(Chan * chan,void * buf,long n,vlong)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
etherbwrite(Chan * chan,Block * bp,ulong)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
addethercard(char * t,int (* r)(Ether *))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
parseether(uchar * to,char * from)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
etherreset(void)365 etherreset(void)
366 {
367 Ether *ether;
368 int i, n, ctlrno, subirq;
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 for(n = 0; cards[n].type; n++){
384 if(cistrcmp(cards[n].type, ether->type))
385 continue;
386 for(i = 0; i < ether->nopt; i++)
387 if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
388 if(parseether(ether->ea,
389 ðer->opt[i][3]) == -1)
390 memset(ether->ea, 0, Eaddrlen);
391 } else if(cistrcmp(ether->opt[i],
392 "100BASE-TXFD") == 0)
393 ether->mbps = 100;
394 if(cards[n].reset(ether))
395 break;
396 snprint(name, sizeof(name), "ether%d", ctlrno);
397
398 subirq = pcisubirq(ether->tbdf);
399 if(ether->interrupt != nil && ether->irq >= 0)
400 intrenable(ether->irq, ether->interrupt, ether, subirq);
401
402 i = snprint(buf, sizeof buf,
403 "#l%d: %s: %dMbps port %#lux irq %d.%d",
404 ctlrno, ether->type, ether->mbps, ether->port,
405 ether->irq, subirq);
406 if(ether->mem)
407 i += snprint(buf+i, sizeof buf - i,
408 " addr %#p", PADDR(ether->mem));
409 if(ether->size)
410 i += snprint(buf+i, sizeof buf - i,
411 " size %#luX", ether->size);
412 i += snprint(buf+i, sizeof buf - i,
413 ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
414 ether->ea[0], ether->ea[1], ether->ea[2],
415 ether->ea[3], ether->ea[4], ether->ea[5]);
416 snprint(buf+i, sizeof buf - i, "\n");
417 iprint("%s", buf); /* it may be too early for print */
418
419 if(ether->mbps >= 1000)
420 netifinit(ether, name, Ntypes, 4*1024*1024);
421 else if(ether->mbps >= 100)
422 netifinit(ether, name, Ntypes, 1024*1024);
423 else
424 netifinit(ether, name, Ntypes, 65*1024);
425 if(ether->oq == 0)
426 ether->oq = qopen(ether->limit, Qmsg, 0, 0);
427 if(ether->oq == 0)
428 panic("etherreset %s", name);
429 ether->alen = Eaddrlen;
430 memmove(ether->addr, ether->ea, Eaddrlen);
431 memset(ether->bcast, 0xFF, Eaddrlen);
432
433 etherxx[ctlrno] = ether;
434 ether = 0;
435 break;
436 }
437 }
438 if(ether)
439 free(ether);
440 }
441
442 static void
ethershutdown(void)443 ethershutdown(void)
444 {
445 Ether *ether;
446 int i;
447
448 for(i = 0; i < MaxEther; i++){
449 ether = etherxx[i];
450 if(ether == nil)
451 continue;
452 if(ether->shutdown == nil) {
453 print("#l%d: no shutdown function\n", i);
454 continue;
455 }
456 (*ether->shutdown)(ether);
457 }
458 }
459
460
461 #define POLY 0xedb88320
462
463 /* really slow 32 bit crc for ethers */
464 ulong
ethercrc(uchar * p,int len)465 ethercrc(uchar *p, int len)
466 {
467 int i, j;
468 ulong crc, b;
469
470 crc = 0xffffffff;
471 for(i = 0; i < len; i++){
472 b = *p++;
473 for(j = 0; j < 8; j++){
474 crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
475 b >>= 1;
476 }
477 }
478 return crc;
479 }
480
481 void
dumpoq(Queue * oq)482 dumpoq(Queue *oq)
483 {
484 if (oq == nil)
485 print("no outq! ");
486 else if (qisclosed(oq))
487 print("outq closed ");
488 else if (qfull(oq))
489 print("outq full ");
490 else
491 print("outq %d ", qlen(oq));
492 }
493
494 void
dumpnetif(Netif * netif)495 dumpnetif(Netif *netif)
496 {
497 print("netif %s ", netif->name);
498 print("limit %d mbps %d link %d ",
499 netif->limit, netif->mbps, netif->link);
500 print("inpkts %lld outpkts %lld errs %d\n",
501 netif->inpackets, netif->outpackets,
502 netif->crcs + netif->oerrs + netif->frames + netif->overflows +
503 netif->buffs + netif->soverflows);
504 }
505
506 Dev etherdevtab = {
507 'l',
508 "ether",
509
510 etherreset,
511 devinit,
512 ethershutdown,
513 etherattach,
514 etherwalk,
515 etherstat,
516 etheropen,
517 ethercreate,
518 etherclose,
519 etherread,
520 etherbread,
521 etherwrite,
522 etherbwrite,
523 devremove,
524 etherwstat,
525 };
526