From 393f6ebcc16afd2037d2fe6bc4ea7dc415f5ae8a Mon Sep 17 00:00:00 2001 From: Geoff Collyer Date: Mon, 11 Jan 2016 17:05:19 -0800 Subject: [PATCH 1/3] Fix ipv6 icmp bugs in locking and freeing in icmphostunr() per current Plan 9. --- kern/src/net/icmp6.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/kern/src/net/icmp6.c b/kern/src/net/icmp6.c index fd316deab9..4bc2ed3750 100644 --- a/kern/src/net/icmp6.c +++ b/kern/src/net/icmp6.c @@ -500,7 +500,7 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc, p = (struct ip6hdr *)bp->rp; if (isv6mcast(p->src)) - goto clean; + goto freebl; nbp = newIPICMP(sz); np = (struct IPICMP *)nbp->rp; @@ -510,11 +510,9 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc, netlog(f, Logicmp, "send icmphostunr -> s%I d%I\n", p->src, p->dst); } else { netlog(f, Logicmp, "icmphostunr fail -> s%I d%I\n", p->src, p->dst); + runlock(&ifc->rwlock); freeblist(nbp); - if (free) - goto clean; - else - return; + goto freebl; } memmove(np->dst, p->src, IPaddrlen); @@ -529,14 +527,12 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc, if (free) ipiput6(f, ifc, nbp); - else { + else ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, NULL); - return; - } - -clean: runlock(&ifc->rwlock); - freeblist(bp); +freebl: + if (free) + freeblist(bp); } extern void icmpttlexceeded6(struct Fs *f, struct Ipifc *ifc, struct block *bp) From 519cf0ed9f092add0cc25a99fcb22505a5792390 Mon Sep 17 00:00:00 2001 From: Geoff Collyer Date: Mon, 11 Jan 2016 17:05:19 -0800 Subject: [PATCH 2/3] Fix ipv6 icmp bugs in locking and freeing in icmphostunr() per current Plan 9. Signed-off-by: Geoff Collyer --- kern/src/net/icmp6.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/kern/src/net/icmp6.c b/kern/src/net/icmp6.c index fd316deab9..4bc2ed3750 100644 --- a/kern/src/net/icmp6.c +++ b/kern/src/net/icmp6.c @@ -500,7 +500,7 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc, p = (struct ip6hdr *)bp->rp; if (isv6mcast(p->src)) - goto clean; + goto freebl; nbp = newIPICMP(sz); np = (struct IPICMP *)nbp->rp; @@ -510,11 +510,9 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc, netlog(f, Logicmp, "send icmphostunr -> s%I d%I\n", p->src, p->dst); } else { netlog(f, Logicmp, "icmphostunr fail -> s%I d%I\n", p->src, p->dst); + runlock(&ifc->rwlock); freeblist(nbp); - if (free) - goto clean; - else - return; + goto freebl; } memmove(np->dst, p->src, IPaddrlen); @@ -529,14 +527,12 @@ icmphostunr(struct Fs *f, struct Ipifc *ifc, if (free) ipiput6(f, ifc, nbp); - else { + else ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, NULL); - return; - } - -clean: runlock(&ifc->rwlock); - freeblist(bp); +freebl: + if (free) + freeblist(bp); } extern void icmpttlexceeded6(struct Fs *f, struct Ipifc *ifc, struct block *bp) From 8181ec0802e4ee6090c878fca889739f8c1c2603 Mon Sep 17 00:00:00 2001 From: Geoff Collyer Date: Mon, 14 Mar 2016 13:52:55 -0700 Subject: [PATCH 3/3] Correct multicast code to cope with controllers that use only 10 bits of mac address for their hash (rather than 12). --- kern/drivers/net/ether82563.c | 75 +++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/kern/drivers/net/ether82563.c b/kern/drivers/net/ether82563.c index c75c0ccd16..4ca351ca8f 100644 --- a/kern/drivers/net/ether82563.c +++ b/kern/drivers/net/ether82563.c @@ -24,7 +24,7 @@ /* This code has been modified by UC Berkeley and Google to work in Akaros. */ /* * Intel Gigabit Ethernet PCI-Express Controllers. - * 8256[36], 8257[1-79], 21[078] + * 8256[367], 8257[1-79], 21[078] * Pretty basic, does not use many of the chip smarts. * The interrupt mitigation tuning for each chip variant * is probably different. The reset/initialisation @@ -902,40 +902,71 @@ static void i82563promiscuous(void *arg, int on) } /* - * Returns number of longs of ctlr->mta in use (a power of 2). + * Returns the number of bits of mac address used in multicast hash, + * thus the number of longs of ctlr->mta (2^(bits-5)). * This must be right for multicast (thus ipv6) to work reliably. + * + * The default multicast hash for mta is based on 12 bits of MAC address; + * the rightmost bit is a function of Rctl's Multicast Offset: 0=>36, + * 1=>35, 2=>34, 3=>32. Exceptions include the 578, 579, 217, 218, 219; + * they use only 10 bits, ignoring the rightmost 2 of the 12. */ -static int mcasttblsize(struct ctlr *ctlr) +static int mcastbits(struct ctlr *ctlr) { switch (ctlr->type) { - case i210: - return 16; - /* - * openbsd says all `ich8' versions (ich8, ich9, ich10, pch, pch2 - * and pch_lpt) have 32 longs. the 218 seems to be an exception. - */ + /* + * openbsd says all `ich8' versions (ich8, ich9, ich10, pch, + * pch2 and pch_lpt) have 32 longs (use 10 bits of mac address + * for hash). + */ case i82566: case i82567: + // case i82578: + case i82579: case i217: - return 32; case i218: - return 64; + // case i219: + return 10; /* 32 longs */ + case i82563: + case i82571: + case i82572: + case i82573: + case i82574: + // case i82575: + // case i82583: + case i210: /* includes i211 */ + return 12; /* 128 longs */ default: - return 128; - } + printk("82563: unsure of multicast bits in mac " + "addresses; enabling promiscuous multicast " + "reception\n"); + csr32w(ctlr, Rctl, csr32r(ctlr, Rctl) | Mpe); + return 10; /* be conservative (for mta size) */ + } +} + +static int mcbitstolongs(int nmcbits) +{ + return 1 << (nmcbits - 5); /* 2^5 = 32 */ } static void i82563multicast(void *arg, uint8_t *addr, int on) { - int bit, x; + uint32_t nbits, tblsz, hash, word, bit; struct ctlr *ctlr; struct ether *edev; edev = arg; ctlr = edev->ctlr; - x = (addr[5] >> 1) & (mcasttblsize(ctlr) - 1); - bit = (addr[5] & 1) << 4 | addr[4] >> 4; + nbits = mcastbits(ctlr); + tblsz = mcbitstolongs(nbits); + /* assume multicast offset in Rctl is 0 (we clear it above) */ + hash = addr[5] << 4 | addr[4] >> 4; /* bits 47:36 of mac */ + if (nbits == 10) + hash >>= 2; /* discard 37:36 of mac */ + word = (hash / 32) & (tblsz - 1); + bit = 1UL << (hash % 32); /* * multiple ether addresses can hash to the same filter bit, * so it's never safe to clear a filter bit. @@ -943,11 +974,11 @@ static void i82563multicast(void *arg, uint8_t *addr, int on) * all the multicast addresses in use, clear all the filter bits, * then set the ones corresponding to in-use addresses. */ - if (on) - ctlr->mta[x] |= 1 << bit; -// else -// ctlr->mta[x] &= ~(1<mta[x]); + if(on) + ctlr->mta[word] |= bit; +// else +// ctlr->mta[word] &= ~bit; + csr32w(ctlr, Mta+word*4, ctlr->mta[word]); } static void i82563im(struct ctlr *ctlr, int im) @@ -1955,7 +1986,7 @@ static int i82563reset(struct ctlr *ctlr) csr32w(ctlr, Rah, 0x80000000 | ctlr->ra[5] << 8 | ctlr->ra[4]); /* populate multicast table */ - for (i = 0; i < mcasttblsize(ctlr); i++) + for (i = 0; i < mcbitstolongs(mcastbits(ctlr)); i++) csr32w(ctlr, Mta + i * 4, ctlr->mta[i]); /*