AnsweredAssumed Answered

i.MX Linux FEC Driver Drops IPV6 Multicasts & Promiscuous Setting

Question asked by TomE on Jul 16, 2015
Latest reply on Aug 12, 2015 by gusarambula
Branched to a new discussion

This applies at least to the i.MX28 and i.MX53. It may apply to the i.MX6 chips as well.

 

Our products have to use IPV6. The IPV6 Neighbour Discovery requires Ethernet Multicasting to work. Multicasting has been "standard" on Ethernet for over 20 years, so that should work on these chips.

 

Few of the Freescale Linux FEC drivers prior to Kernel 3.11 seem to handle receiving Multicasts properly. They don't work properly in "Promiscuous" mode either.

 

This has only recently been fixed on the "mainline", but I'm using Freescale's "imx_2.6.35_maintain" branch, and there are no patches fixing that.

 

That means that IPV6 (dates from 15 years ago) doesn't work reliably if at all. It also means IPV4 Multicasting (21 years ago) has the same problem. Also promiscuous bridging/monitoring.

 

Here's what happens

 

When the link comes up (initially or after the Ethernet cable is unplugged and plugged in again) the code calls "fec_restart()". That wipes out the Multicast filters. When the link comes up, calls to "set_multicast_list()" are made to fill in the filter again. After that has finished, the MII polling code notices the link has come up, calls "fec_enet_adjust_link()" and that calls "fec_restart()" and wipes them out again. So it now can't receive the multicasts. If you're really lucky with exactly the right timing in the /etc/init.d scripts, it might come up in the right order. When it is in the bad state you can type "ifconfig eth0 up", that puts the multicast filters back without restarting it and it now works until the next time the Ethernet cable is unplugged. If you "ifconfig eth0 down"you then have to bring it "up" twice to get multicast reception working again.

 

Here's the 2.6.35 "fec.c" and (pretty much identical in this function) 3.10 "fec_main.c":

 

http://lxr.free-electrons.com/source/drivers/net/fec.c?v=2.6.35

http://lxr.free-electrons.com/source/drivers/net/ethernet/freescale/fec_main.c?v=3.10

 

Apologies for the next line. It looked perfect when I pasted the code in when originally creating this page. The Site only mangled it all into one line after I'd posted it. I've had to have three goes at fixing it up to make it readable since then.

1145 /* This function is called to start or restart the FEC during a link1146  * change.  This only happens when switching between half and full1147  * duplex.1148  */1149 static void1150 fec_restart(struct net_device *dev, int duplex)1151 { ...1161 1162         /* Reset all multicast. */1163         writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);1164         writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);


1145 /* This function is called to start or restart the FEC during a link
1146  * change.  This only happens when switching between half and full
1147  * duplex.
1148  */
1149 static void
1150 fec_restart(struct net_device *dev, int duplex)
1151 {
 ...
1161 
1162         /* Reset all multicast. */
1163         writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
1164         writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);


First of all, the comment on that function is wrong. It may have been called for that originally, but by this version it is also called on link timeout and link state change.

 

Here's the fixed 3.14 version, still with the bad comment:

 

491 /* This function is called to start or restart the FEC during a link
492  * change.  This only happens when switching between half and full
493  * duplex.
494  */
495 static void
496 fec_restart(struct net_device *ndev, int duplex)
497 {
...
651         /* Setup multicast filter. */
652         set_multicast_list(ndev);



The driver isn't all that "stable" as there have been at least 102 patches to this source code
file alone since then. One of them (in 3.17 I think) at least fixed the comment:

914 /*
915  * This function is called to start or restart the FEC during a link
916  * change, transmit timeout, or to reconfigure the FEC.  The network
917  * packet processing for this device must be stopped before this call.
918  */
919 static void
920 fec_restart(struct net_device *ndev)
921 {


This problem was documented and patched here:

 

http://kernel.opensuse.org/cgit/kernel/commit/?id=772e42b07fbdc650206746e00cb2914e362594a3

 

That fix was buggy, as complained about here (wiping out the Promiscuous setting for bridges and packet monitoring):

 

http://permalink.gmane.org/gmane.linux.network/307446

 

Then patched again here:

 

http://kernel.opensuse.org/cgit/kernel/commit/?id=84fe61821e4ebab6322eeae3f3c27f77f0031978

 

Update. I've found a patch, but only on Freescale's "imx_3.0.35_4.1.0" branch. This one fixes the "Multicast" problem without fixing the "Promiscuous" problem:

 

Author: Fugang Duan <B38611@freescale.com>  2013-11-26 17:18:36
Committer: Jason Liu <r64343@freescale.com>  2014-01-24 13:33:26
Parent: 76f9b385fe7d4602f3157d309f4ba793ac13bb36 (ENGR00291667-02 net:fec_ptp: fix the potential issue for storing timestamp)
Branch: remotes/origin/remote/freescale/imx_3.0.35_4.1.0

 

    ENGR00291667-01 net:fec: reinit multicast address when fec restart
   
    Ptp multicast packet receive does not work after Ethernet link is lost
    for a short time and then reconnected again. Because fec call restart()
    to reset all multicast when cable hotplug.
    (cherry picked from commit adfa64f0c2bf35f8b902ae5700f97e7e11ae1794)

 

 

Tom

Outcomes