netdev
[Top] [All Lists]

[PATCH] fix IGMPv3 timer initialization when device not "upped"

To: davem@xxxxxxxxxx, netdev@xxxxxxxxxxx
Subject: [PATCH] fix IGMPv3 timer initialization when device not "upped"
From: David Stevens <dlstevens@xxxxxxxxxx>
Date: Tue, 30 Mar 2004 17:13:44 -0700
Sender: netdev-bounce@xxxxxxxxxxx

The patch below creates a new "ip_mc_init_dev()" that has complementary
function to "ip_mc_destroy_dev()", and moves timer and lock initialization to
it rather than trying to determine when a device is up, coming up, down or
going down based on idev->dead (not set before device up, but set on
device going down) or IFF_UP (not set on mc_down).

With this patch, multicast initialization is always done at device initialization
and has nothing to do with up/down state. This should eliminate the timer
queue corruption and (I think) make the code easier to understand. This
patch also removes the "mc_initted" flag, which is no longer needed. Patch
is relative to 2.6.5-rc3 ; 2.4.x version to follow.

Thanks to Karlis Peisenieks, who original reported the problem and pointed
out flaws in the original fix.

+-DLS

diff -ruN linux-2.6.5-rc3/include/linux/inetdevice.h linux-2.6.5-rc3F1/include/linux/inetdevice.h
--- linux-2.6.5-rc3/include/linux/inetdevice.h 2004-03-30 12:27:29.000000000 -0800
+++ linux-2.6.5-rc3F1/include/linux/inetdevice.h 2004-03-30 14:08:50.000000000 -0800
@@ -36,8 +36,6 @@
rwlock_t lock;
int dead;
struct in_ifaddr *ifa_list; /* IP ifaddr chain */
- int mc_initted;
-
struct ip_mc_list *mc_list; /* IP multicast filter chain */
rwlock_t mc_lock; /* for mc_tomb */
struct ip_mc_list *mc_tomb;
diff -ruN linux-2.6.5-rc3/net/ipv4/devinet.c linux-2.6.5-rc3F1/net/ipv4/devinet.c
--- linux-2.6.5-rc3/net/ipv4/devinet.c 2004-03-10 18:55:23.000000000 -0800
+++ linux-2.6.5-rc3F1/net/ipv4/devinet.c 2004-03-30 14:09:46.000000000 -0800
@@ -165,6 +165,7 @@
#ifdef CONFIG_SYSCTL
devinet_sysctl_register(in_dev, &in_dev->cnf);
#endif
+ ip_mc_init_dev(in_dev);
if (dev->flags & IFF_UP)
ip_mc_up(in_dev);
out:
diff -ruN linux-2.6.5-rc3/net/ipv4/igmp.c linux-2.6.5-rc3F1/net/ipv4/igmp.c
--- linux-2.6.5-rc3/net/ipv4/igmp.c 2004-03-30 12:27:30.000000000 -0800
+++ linux-2.6.5-rc3F1/net/ipv4/igmp.c 2004-03-30 15:53:28.000000000 -0800
@@ -1217,8 +1217,8 @@

ASSERT_RTNL();

- if (!in_dev->mc_initted)
- return;
+ for (i=in_dev->mc_list; i; i=i->next)
+ igmp_group_dropped(i);

#ifdef CONFIG_IP_MULTICAST
in_dev->mr_ifc_count = 0;
@@ -1227,24 +1227,14 @@
in_dev->mr_gq_running = 0;
if (del_timer(&in_dev->mr_gq_timer))
__in_dev_put(in_dev);
-#endif
-
- for (i=in_dev->mc_list; i; i=i->next)
- igmp_group_dropped(i);
-
-#ifdef CONFIG_IP_MULTICAST
igmpv3_clear_delrec(in_dev);
#endif

ip_mc_dec_group(in_dev, IGMP_ALL_HOSTS);
}

-/* Device going up */
-
-void ip_mc_up(struct in_device *in_dev)
+void ip_mc_init_dev(struct in_device *in_dev)
{
- struct ip_mc_list *i;
-
ASSERT_RTNL();

in_dev->mc_tomb = 0;
@@ -1261,12 +1251,20 @@
#endif

in_dev->mc_lock = RW_LOCK_UNLOCKED;
+}
+
+/* Device going up */
+
+void ip_mc_up(struct in_device *in_dev)
+{
+ struct ip_mc_list *i;
+
+ ASSERT_RTNL();
+
ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);

for (i=in_dev->mc_list; i; i=i->next)
igmp_group_added(i);
-
- in_dev->mc_initted = 1;
}

/*

(See attached file: igmpinit.patch)

Attachment: igmpinit.patch
Description: Binary data

<Prev in Thread] Current Thread [Next in Thread>