Bug 9440 - Problem in joinning a socket to ipv6 multicast address in specific scenario
Summary: Problem in joinning a socket to ipv6 multicast address in specific scenario
Status: CLOSED CODE_FIX
Alias: None
Product: Networking
Classification: Unclassified
Component: IPV6 (show other bugs)
Hardware: All Linux
: P1 high
Assignee: Hideaki YOSHIFUJI
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-11-22 11:02 UTC by Aviad Yehezkel
Modified: 2008-09-23 14:30 UTC (History)
1 user (show)

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


Attachments
application (3.85 KB, text/plain)
2007-11-25 06:50 UTC, Aviad Yehezkel
Details

Description Aviad Yehezkel 2007-11-22 11:02:02 UTC
Hi,
I have a problem in joinning a socket to multicast address in the following scenario (maybe kernel bug):
 
1. I am changing the mtu size of the eth device to a small size - "ifconfig eth1 mtu 100"
 
2. After that i am resizing the mtu for it's orginal size - "ifconfig eth1 mtu 1500"
 
3. Now i am running a program i wrote in c that opens a dgram socket (sock_fd[i] = socket(test_data->protocol, SOCK_DGRAM, 0);)  and join it to multicast ipv6 address. 
if i am running this program after steps 1+2 i get the following error: "Resource temporarily unavailable" when trying to join the socket to the multicast ipv6 address by the
system call : 
 
struct ipv6_mreq maddr6_group; 
...
setsockopt(sock_fd,
       IPPROTO_IPV6,
       IPV6_JOIN_GROUP,
       (char *)&maddr6_group,
       sizeof(maddr6_group));
 
but if i am running my program after reset of the driver (before steps 1+2) it is working fine.
if i am trying to run the program and join a socket to ipv4 multicast address (instead of ipv6) i get no errors - this doesn't work only when trying to join to ipv6 multicast address. 
 
I got this error in broadcom device ("Broadcom Corporation NetXtreme BCM5721 Gigabit Ethernet PCI Express (rev 21)") but i don't think this is a bug in broadcom driver,
because i tried it on differnt devices, in some devices i got the following error instead: "Invalid argument" with the same multicast address.
As i said before if i am trying to join a socket to multicast ipv6 address before resizing the mtu size it is working fine, all the problems are after step 1+2.
 
All my tries were OS:
1. SLES10.0 - 2.6.16.21-0.8-smp 
2. REDHAT5.0 - 2.6.18-8.el5 #1 SMP.
 
 
I am waiting for an answer,
thanks a lot,
Aviad Yehezkel.
Comment 1 Anonymous Emailer 2007-11-22 17:24:00 UTC
Reply-To: akpm@linux-foundation.org

On Thu, 22 Nov 2007 11:02:04 -0800 (PST) bugme-daemon@bugzilla.kernel.org wrote:

> http://bugzilla.kernel.org/show_bug.cgi?id=9440
> 
>            Summary: Problem in joinning a socket to ipv6 multicast address
>                     in specific scenario
>            Product: Networking
>            Version: 2.5
>      KernelVersion: 2.6
>           Platform: All
>         OS/Version: Linux
>               Tree: Mainline
>             Status: NEW
>           Severity: high
>           Priority: P1
>          Component: IPV6
>         AssignedTo: yoshfuji@linux-ipv6.org
>         ReportedBy: aviad.yehezkel5@gmail.com
> 
> 
> Hi,
> I have a problem in joinning a socket to multicast address in the following
> scenario (maybe kernel bug):
> 
> 1. I am changing the mtu size of the eth device to a small size - "ifconfig
> eth1 mtu 100"
> 
> 2. After that i am resizing the mtu for it's orginal size - "ifconfig eth1
> mtu
> 1500"
> 
> 3. Now i am running a program i wrote in c that opens a dgram socket
> (sock_fd[i] = socket(test_data->protocol, SOCK_DGRAM, 0);)  and join it to
> multicast ipv6 address. 
> if i am running this program after steps 1+2 i get the following error:
> "Resource temporarily unavailable" when trying to join the socket to the
> multicast ipv6 address by the
> system call : 
> 
> struct ipv6_mreq maddr6_group; 
> ...
> setsockopt(sock_fd,
>        IPPROTO_IPV6,
>        IPV6_JOIN_GROUP,
>        (char *)&maddr6_group,
>        sizeof(maddr6_group));
> 
> but if i am running my program after reset of the driver (before steps 1+2)
> it
> is working fine.
> if i am trying to run the program and join a socket to ipv4 multicast address
> (instead of ipv6) i get no errors - this doesn't work only when trying to
> join
> to ipv6 multicast address. 
> 
> I got this error in broadcom device ("Broadcom Corporation NetXtreme BCM5721
> Gigabit Ethernet PCI Express (rev 21)") but i don't think this is a bug in
> broadcom driver,
> because i tried it on differnt devices, in some devices i got the following
> error instead: "Invalid argument" with the same multicast address.
> As i said before if i am trying to join a socket to multicast ipv6 address
> before resizing the mtu size it is working fine, all the problems are after
> step 1+2.
> 
> All my tries were OS:
> 1. SLES10.0 - 2.6.16.21-0.8-smp 
> 2. REDHAT5.0 - 2.6.18-8.el5 #1 SMP.
> 
> 
> I am waiting for an answer,
> thanks a lot,
> Aviad Yehezkel.
> 
> 
> -- 
> Configure bugmail: http://bugzilla.kernel.org/userprefs.cgi?tab=email
> ------- You are receiving this mail because: -------
> You are on the CC list for the bug, or are watching someone who is.
Comment 2 Evgeniy Polyakov 2007-11-23 02:59:38 UTC
On Thu, Nov 22, 2007 at 05:23:42PM -0800, Andrew Morton (akpm@linux-foundation.org) wrote:
> > 3. Now i am running a program i wrote in c that opens a dgram socket
> > (sock_fd[i] = socket(test_data->protocol, SOCK_DGRAM, 0);)  and join it to
> > multicast ipv6 address. 
> > if i am running this program after steps 1+2 i get the following error:
> > "Resource temporarily unavailable" when trying to join the socket to the
> > multicast ipv6 address by the
> > system call : 

Could you provide a test application?
Given it is small and can be ran without external dependencies, it will
be fixed way much faster.

Thanks.
Comment 3 Aviad Yehezkel 2007-11-25 06:50:51 UTC
Created attachment 13743 [details]
application

this is a small application that repudce the bug.
the application join a sock to mcast addr. if you will do step 1 + 2 and after that you will run this application, setsockopt() system call will fail. 
importent:
change the hard coded parameters. pick an ipv6 mcast to join to and enter the if_name. the if_ipv4_addr arg is neccery only when joining an ipv4 mcast addr.
Comment 4 Evgeniy Polyakov 2007-11-28 03:18:23 UTC
Hi.

Avaid provided test application, so bug got fixed.

IPv6 addrconf removes ipv6 inner device from netdev each time cmu
changes and new value is less than IPV6_MIN_MTU (1280 bytes).
When mtu is changed and new value is greater than IPV6_MIN_MTU,
it does not add ipv6 addresses and inner device bac.

This patch fixes that.

Tested with Avaid's application, which works ok now.

Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 567664e..4f7e46c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2357,12 +2358,18 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 		break;
 
 	case NETDEV_CHANGEMTU:
-		if ( idev && dev->mtu >= IPV6_MIN_MTU) {
+		if (idev && dev->mtu >= IPV6_MIN_MTU) {
 			rt6_mtu_change(dev, dev->mtu);
 			idev->cnf.mtu6 = dev->mtu;
 			break;
 		}
 
+		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
+			idev = ipv6_add_dev(dev);
+			if (idev)
+				break;
+		}
+
 		/* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */
 
 	case NETDEV_DOWN:
Comment 5 Herbert Xu 2007-11-30 04:02:44 UTC
On Wed, Nov 28, 2007 at 02:18:14PM +0300, Evgeniy Polyakov wrote:
> Hi.
> 
> Avaid provided test application, so bug got fixed.
> 
> IPv6 addrconf removes ipv6 inner device from netdev each time cmu
> changes and new value is less than IPV6_MIN_MTU (1280 bytes).
> When mtu is changed and new value is greater than IPV6_MIN_MTU,
> it does not add ipv6 addresses and inner device bac.
> 
> This patch fixes that.
> 
> Tested with Avaid's application, which works ok now.
> 
> Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>

OK, this looks like a good change.  However, we should also
change NETDEV_UP as well to recreate idev if it isn't there
and the MTU is big enough.

Thanks,
Comment 6 Evgeniy Polyakov 2007-11-30 04:25:24 UTC
On Fri, Nov 30, 2007 at 11:02:19PM +1100, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> OK, this looks like a good change.  However, we should also
> change NETDEV_UP as well to recreate idev if it isn't there
> and the MTU is big enough.

Ok, added netdev_up too.

Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 567664e..e8c3475 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2293,6 +2293,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 				break;
 			}
 
+			if (!idev && dev->mtu >= IPV6_MIN_MTU)
+				idev = ipv6_add_dev(dev);
+
 			if (idev)
 				idev->if_flags |= IF_READY;
 		} else {
@@ -2357,12 +2360,18 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 		break;
 
 	case NETDEV_CHANGEMTU:
-		if ( idev && dev->mtu >= IPV6_MIN_MTU) {
+		if (idev && dev->mtu >= IPV6_MIN_MTU) {
 			rt6_mtu_change(dev, dev->mtu);
 			idev->cnf.mtu6 = dev->mtu;
 			break;
 		}
 
+		if (!idev && dev->mtu >= IPV6_MIN_MTU) {
+			idev = ipv6_add_dev(dev);
+			if (idev)
+				break;
+		}
+
 		/* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */
 
 	case NETDEV_DOWN:
Comment 7 Herbert Xu 2007-11-30 04:37:14 UTC
On Fri, Nov 30, 2007 at 03:25:16PM +0300, Evgeniy Polyakov wrote:
>
> Ok, added netdev_up too.
> 
> Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>

Applied to net-2.6.  Thanks Evgeniy!

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