Bug 10577 - IPv6 to Intel EtherExpress 16 fails - multicast problems
Summary: IPv6 to Intel EtherExpress 16 fails - multicast problems
Status: CLOSED CODE_FIX
Alias: None
Product: Drivers
Classification: Unclassified
Component: Network (show other bugs)
Hardware: All Linux
: P1 normal
Assignee: Jeff Garzik
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-04-30 04:02 UTC by Bruce Robson
Modified: 2008-07-08 03:37 UTC (History)
1 user (show)

See Also:
Kernel Version: 2.6.24
Subsystem:
Regression: ---
Bisected commit-id:


Attachments
patch to file eexpress.c (1.59 KB, patch)
2008-04-30 04:05 UTC, Bruce Robson
Details | Diff

Description Bruce Robson 2008-04-30 04:02:58 UTC
Latest working kernel version:
Earliest failing kernel version:
Distribution: Debian
Hardware Environment: Intel ClassicR+ with Intel EtherExpress 16
Software Environment: Debian testing (lenny)
Problem Description:

I was unable to access a computer containing an Intel EtherExpress
16 network card using IPv6.

I traced this to failure of neighbour discovery. When I used an
"ip -6 neigh add" command, on the computer attempting access, to
insert a binding between the IPv6 address of the computer with
the Intel EtherExpress 16 network card and the card's ethernet
address, I was able to access that computer using IPv6.

Neighbour discovery requires working multicast. The driver
sources file eexpress.c contains an approximately 30 line
function eexp_setup_filter used when loading multicast addresses.
I found 3 problems in this function
1)  It wrote the number of multicast addresses to the card instead
    of the number of bytes in the multicast addresses.
2)  When loading multiple multicast addresses it loaded the first
    one provided multiple times instead of loading each one once.
3)  The setting of pointer 'data' from 'dmi->dmi_addr' occured before
    the test for the error situation of 'dmi' being NULL.

Correcting these problems allows the computer with the Intel
EtherExpress 16 network card to found by IPv6 neighbour discovery.

p.s. There is some information on the Intel EtherExpress 16 at
http://www.intel.com/support/etherexpress/vintage/sb/cs-013500.htm
Datasheet for the Intel 82586 ethernet controller used by the card
http://www.datasheetcatalog.com/datasheets_pdf/8/2/5/8/82586.shtml



--- eexpress.c.000      2008-01-24 22:58:37.000000000 +0000
+++ eexpress.c  2008-04-30 00:17:51.000000000 +0100
@@ -201,9 +201,9 @@

        0x0000,Cmd_MCast,
        0x0076,                 /* link to next command */
 #define CONF_NR_MULTICAST 0x44
-       0x0000,                 /* number of multicast addresses */
+       0x0000,                 /* number of bytes in multicast address(es) */
 #define CONF_MULTICAST 0x46
        0x0000, 0x0000, 0x0000, /* some addresses */
        0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000,
@@ -1568,9 +1568,9 @@
 }

 static void eexp_setup_filter(struct net_device *dev)
 {
-       struct dev_mc_list *dmi = dev->mc_list;
+       struct dev_mc_list *dmi;
        unsigned short ioaddr = dev->base_addr;
        int count = dev->mc_count;
        int i;
        if (count > 8) {
@@ -1579,19 +1579,20 @@
                count = 8;
        }

        outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR);
-       outw(count, ioaddr+SHADOW(CONF_NR_MULTICAST));
-       for (i = 0; i < count; i++) {
-               unsigned short *data = (unsigned short *)dmi->dmi_addr;
+       outw(6*count, ioaddr+SHADOW(CONF_NR_MULTICAST));
+       for (i = 0, dmi = dev->mc_list; i < count; i++, dmi = dmi->next) {
+               unsigned short *data;
                if (!dmi) {
                        printk(KERN_INFO "%s: too few multicast addresses\n", de
v->name);
                        break;
                }
                if (dmi->dmi_addrlen != ETH_ALEN) {
                        printk(KERN_INFO "%s: invalid multicast address length g
iven.\n", dev->name);
                        continue;
                }
+               data = (unsigned short *)dmi->dmi_addr;
                outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR);
                outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i)));
                outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR);
                outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2));
Comment 1 Bruce Robson 2008-04-30 04:05:55 UTC
Created attachment 15985 [details]
patch to file eexpress.c

Here's the patch as an attached file
Comment 2 Anonymous Emailer 2008-04-30 05:16:45 UTC
Reply-To: akpm@linux-foundation.org

thanks.

Please do submit patches via mail in future - merging them from
bugzilla is a hassle.

Please email a signed-off-by: for this patch as per
Documentation/SubmittingPatches?
Comment 3 Bruce Robson 2008-07-08 03:37:39 UTC
The patch has been included in 2.6.26-rc2.
http://kernel.org/pub/linux/kernel/v2.6/testing/ChangeLog-2.6.26-rc2

Note You need to log in before you can comment on or make changes to this bug.