Messages in this thread Patch in this message | | | Date | Fri, 14 Jan 2000 09:59:09 -0500 | From | Mike Phillips <> | Subject | [PATCH] IPv6 over token ring updated and bug fixes for 2.3.39 |
| |
Attached is the patch for IPv6 over token ring now including the necessary changes to the olympic driver as well. (The olympic changes do not conflict with the recent smp changes to olympic - both patches should apply clean with each other).
The previous patch contained a couple of subtle bugs, everything worked fine if you were using only token ring and ip, but things got a little interesting once ethernet and/or different protocols were thrown into the mix.
Mike Phillips Linux Token Ring Project http://www.linxutr.net
diff -ur linux-2.3.39.orig/drivers/net/tokenring/ibmtr.c linux-2.3.39.ipv6/drivers/net/tokenring/ibmtr.c --- linux-2.3.39.orig/drivers/net/tokenring/ibmtr.c Tue Jan 11 13:48:55 2000 +++ linux-2.3.39.ipv6/drivers/net/tokenring/ibmtr.c Thu Jan 13 15:29:07 2000 @@ -1651,7 +1651,7 @@ ti->tr_stats.rx_packets++; skb->protocol = tr_type_trans(skb,dev); - if (IPv4_p){ + if (IPv4_p && (skb->protocol == ETH_P_IP)) { skb->csum = chksum; skb->ip_summed = 1; } diff -ur linux-2.3.39.orig/drivers/net/tokenring/olympic.c linux-2.3.39.ipv6/drivers/net/tokenring/olympic.c --- linux-2.3.39.orig/drivers/net/tokenring/olympic.c Tue Jan 11 13:48:55 2000 +++ linux-2.3.39.ipv6/drivers/net/tokenring/olympic.c Fri Jan 14 09:08:03 2000 @@ -202,7 +202,6 @@ olympic_priv->olympic_ring_speed = ringspeed[card_no] ; olympic_priv->olympic_message_level = message_level[card_no] ; - olympic_priv->olympic_multicast_set = 0 ; if(olympic_init(dev)==-1) { unregister_netdevice(dev); @@ -936,9 +935,11 @@ { struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; __u8 *olympic_mmio = olympic_priv->olympic_mmio ; - __u8 options = 0, set_mc_list = 0 ; - __u8 *srb, *ata ; + __u8 options = 0; + __u8 *srb; struct dev_mc_list *dmi ; + unsigned char dev_mc_address[4] ; + int i ; writel(olympic_priv->srb,olympic_mmio+LAPA); srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800)); @@ -949,10 +950,6 @@ else options &= ~(3<<5) ; - if (dev->mc_count) { - set_mc_list = 1 ; - } - /* Only issue the srb if there is a change in options */ if ((options ^ olympic_priv->olympic_copy_all_options)) { @@ -975,60 +972,30 @@ return ; } - if (set_mc_list ^ olympic_priv->olympic_multicast_set) { /* Multicast options have changed */ + /* Set the functional addresses we need for multicast */ - dmi = dev->mc_list ; - - if (set_mc_list) { /* Turn multicast on */ - - /* RFC 1469 Says we must support using the functional address C0 00 00 04 00 00 - * We do this with a set functional address mask. - */ - - ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ; - if (!(readb(ata+11) & 0x04)) { /* Hmmm, need to set the functional mask */ - writeb(SRB_SET_FUNC_ADDRESS,srb+0); - writeb(0,srb+1); - writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); - writeb(0,srb+3); - writeb(0,srb+4); - writeb(0,srb+5); - writeb(readb(ata+10),srb+6); - writeb(readb(ata+11)|4,srb+7); - writeb(readb(ata+12),srb+8); - writeb(readb(ata+13),srb+9); - - olympic_priv->srb_queued = 2 ; - writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); - - olympic_priv->olympic_multicast_set = 1 ; - } - - - } else { /* Turn multicast off */ - - ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ; - if ((readb(ata+11) & 0x04)) { /* Hmmm, need to reset the functional mask */ - writeb(SRB_SET_FUNC_ADDRESS,srb+0); - writeb(0,srb+1); - writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); - writeb(0,srb+3); - writeb(0,srb+4); - writeb(0,srb+5); - writeb(readb(ata+10),srb+6); - writeb(readb(ata+11) & ~4,srb+7); - writeb(readb(ata+12),srb+8); - writeb(readb(ata+13),srb+9); - - olympic_priv->srb_queued = 2 ; - writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); - - olympic_priv->olympic_multicast_set = 0 ; - } - } + dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; + for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { + dev_mc_address[0] |= dmi->dmi_addr[2] ; + dev_mc_address[1] |= dmi->dmi_addr[3] ; + dev_mc_address[2] |= dmi->dmi_addr[4] ; + dev_mc_address[3] |= dmi->dmi_addr[5] ; } + writeb(SRB_SET_FUNC_ADDRESS,srb+0); + writeb(0,srb+1); + writeb(OLYMPIC_CLEAR_RET_CODE,srb+2); + writeb(0,srb+3); + writeb(0,srb+4); + writeb(0,srb+5); + writeb(dev_mc_address[0],srb+6); + writeb(dev_mc_address[1],srb+7); + writeb(dev_mc_address[2],srb+8); + writeb(dev_mc_address[3],srb+9); + + olympic_priv->srb_queued = 2 ; + writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM); } @@ -1069,7 +1036,6 @@ case SRB_SET_GROUP_ADDRESS: switch (readb(srb+2)) { case 0x00: - olympic_priv->olympic_multicast_set = 1 ; break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; @@ -1097,7 +1063,6 @@ case SRB_RESET_GROUP_ADDRESS: switch (readb(srb+2)) { case 0x00: - olympic_priv->olympic_multicast_set = 0 ; break ; case 0x01: printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; diff -ur linux-2.3.39.orig/drivers/net/tokenring/olympic.h linux-2.3.39.ipv6/drivers/net/tokenring/olympic.h --- linux-2.3.39.orig/drivers/net/tokenring/olympic.h Tue Jan 11 13:48:55 2000 +++ linux-2.3.39.ipv6/drivers/net/tokenring/olympic.h Thu Jan 13 15:22:04 2000 @@ -265,7 +265,6 @@ __u8 olympic_ring_speed ; __u16 pkt_buf_sz ; __u8 olympic_receive_options, olympic_copy_all_options, olympic_message_level; - __u8 olympic_multicast_set ; __u16 olympic_addr_table_addr, olympic_parms_addr ; __u8 olympic_laa[6] ; }; diff -ur linux-2.3.39.orig/drivers/net/tokenring/tms380tr.c linux-2.3.39.ipv6/drivers/net/tokenring/tms380tr.c --- linux-2.3.39.orig/drivers/net/tokenring/tms380tr.c Tue Jan 11 13:48:55 2000 +++ linux-2.3.39.ipv6/drivers/net/tokenring/tms380tr.c Thu Jan 13 15:30:45 2000 @@ -2470,7 +2470,8 @@ tp->RplHead = SaveHead; break; /* Return to tms380tr_interrupt */ } - +#if 0 /* This might happen for multicast or broadcast packets. + The upper layers are expected to handle this, not here */ /* Drop frames sent by myself */ if(tms380tr_chk_frame(dev, rpl->MData)) { @@ -2480,6 +2481,7 @@ dev_kfree_skb(rpl->Skb); } else +#endif { tms380tr_update_rcv_stats(tp,ReceiveDataPtr,Length); diff -ur linux-2.3.39.orig/include/net/if_inet6.h linux-2.3.39.ipv6/include/net/if_inet6.h --- linux-2.3.39.orig/include/net/if_inet6.h Tue Jan 11 13:48:46 2000 +++ linux-2.3.39.ipv6/include/net/if_inet6.h Fri Jan 14 09:18:28 2000 @@ -119,5 +119,59 @@ memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32)); } + +extern __inline__ void ipv6_tr_mc_map(struct in6_addr *addr, char *buf) +{ + /* All nodes FF01::1, FF02::1, FF02::1:FFxx:xxxx */ + + if (((addr->s6_addr[0] == 0xFF) && + ((addr->s6_addr[1] == 0x01) || (addr->s6_addr[1] == 0x02)) && + (addr->s6_addr16[1] == 0) && + (addr->s6_addr32[1] == 0) && + (addr->s6_addr32[2] == 0) && + (addr->s6_addr16[6] == 0) && + (addr->s6_addr[15] == 1)) || + ((addr->s6_addr[0] == 0xFF) && + (addr->s6_addr[1] == 0x02) && + (addr->s6_addr16[1] == 0) && + (addr->s6_addr32[1] == 0) && + (addr->s6_addr16[4] == 0) && + (addr->s6_addr[10] == 0) && + (addr->s6_addr[11] == 1) && + (addr->s6_addr[12] == 0xff))) + { + buf[0]=0xC0; + buf[1]=0x00; + buf[2]=0x01; + buf[3]=0x00; + buf[4]=0x00; + buf[5]=0x00; + /* All routers FF0x::2 */ + } else if ((addr->s6_addr[0] ==0xff) && + ((addr->s6_addr[1] & 0xF0) == 0) && + (addr->s6_addr16[1] == 0) && + (addr->s6_addr32[1] == 0) && + (addr->s6_addr32[2] == 0) && + (addr->s6_addr16[6] == 0) && + (addr->s6_addr[15] == 2)) + { + buf[0]=0xC0; + buf[1]=0x00; + buf[2]=0x02; + buf[3]=0x00; + buf[4]=0x00; + buf[5]=0x00; + } else { + unsigned char i ; + + i = addr->s6_addr[15] & 7 ; + buf[0]=0xC0; + buf[1]=0x00; + buf[2]=0x00; + buf[3]=0x01 << i ; + buf[4]=0x00; + buf[5]=0x00; + } +} #endif #endif diff -ur linux-2.3.39.orig/net/ipv6/addrconf.c linux-2.3.39.ipv6/net/ipv6/addrconf.c --- linux-2.3.39.orig/net/ipv6/addrconf.c Tue Jan 11 13:48:51 2000 +++ linux-2.3.39.ipv6/net/ipv6/addrconf.c Thu Jan 13 15:41:55 2000 @@ -670,6 +670,7 @@ { switch (dev->type) { case ARPHRD_ETHER: + case ARPHRD_IEEE802_TR: if (dev->addr_len != ETH_ALEN) return -1; memcpy(eui, dev->dev_addr, 3); @@ -1191,7 +1192,8 @@ ASSERT_RTNL(); - if (dev->type != ARPHRD_ETHER) { + if ((dev->type != ARPHRD_ETHER) && + (dev->type != ARPHRD_IEEE802_TR)) { /* Alas, we support only Ethernet autoconfiguration. */ return; } @@ -1990,7 +1992,8 @@ case ARPHRD_LOOPBACK: init_loopback(dev); break; - case ARPHRD_ETHER: + case ARPHRD_ETHER: + case ARPHRD_IEEE802_TR: addrconf_dev_config(dev); break; default: diff -ur linux-2.3.39.orig/net/ipv6/ndisc.c linux-2.3.39.ipv6/net/ipv6/ndisc.c --- linux-2.3.39.orig/net/ipv6/ndisc.c Tue Jan 11 13:48:51 2000 +++ linux-2.3.39.ipv6/net/ipv6/ndisc.c Fri Jan 14 09:21:56 2000 @@ -161,6 +161,9 @@ case ARPHRD_FDDI: ipv6_eth_mc_map(addr, buf); return 0; + case ARPHRD_IEEE802_TR: + ipv6_tr_mc_map(addr,buf); + return 0; default: if (dir) { memcpy(buf, dev->broadcast, dev->addr_len); @@ -968,9 +971,22 @@ does DAD, otherwise we ignore solicitations until DAD timer expires. */ - if (addr_type == IPV6_ADDR_ANY) - addrconf_dad_failure(ifp); - else + if (addr_type == IPV6_ADDR_ANY) { + if (dev->type == ARPHRD_IEEE802_TR) { + unsigned char *sadr = skb->mac.raw ; + if (((sadr[8] &0x7f) != (dev->dev_addr[0] & 0x7f)) || + (sadr[9] != dev->dev_addr[1]) || + (sadr[10] != dev->dev_addr[2]) || + (sadr[11] != dev->dev_addr[3]) || + (sadr[12] != dev->dev_addr[4]) || + (sadr[13] != dev->dev_addr[5])) + { + addrconf_dad_failure(ifp) ; + } + } else { + addrconf_dad_failure(ifp); + } + } else in6_ifa_put(ifp); return 0; } | |