lkml.org 
[lkml]   [2000]   [Jan]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
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;
}
\
 
 \ /
  Last update: 2005-03-22 13:55    [W:2.627 / U:0.572 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site