diff mbox

igmp: Staggered igmp report intervals for unsolicited igmp reports

Message ID alpine.DEB.2.00.1009221400010.32661@router.home (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Christoph Lameter (Ampere) Sept. 22, 2010, 7:01 p.m. UTC
None
diff mbox

Patch

Index: linux-2.6/net/ipv4/igmp.c
===================================================================
--- linux-2.6.orig/net/ipv4/igmp.c	2010-09-22 12:50:32.000000000 -0500
+++ linux-2.6/net/ipv4/igmp.c	2010-09-22 13:32:58.000000000 -0500
@@ -124,17 +124,40 @@ 

 /* Control of unsolilcited reports (after join) */

-#define IGMP_Unsolicited_Report_Count		2
+#define IGMP_Unsolicited_Report_Count		6
 #define IGMP_Initial_Report_Delay		(1)
 #define IGMP_Unsolicited_Report_Min_Delay	(HZ/25)
+#define IGMP_Unsolicited_Fuzz			(HZ/100)
+

 /* IGMP_Initial_Report_Delay is not from IGMP specs!
  * IGMP specs require to report membership immediately after
  * joining a group, but we delay the first report by a
  * small interval. It seems more natural and still does not
  * contradict to specs provided this delay is small enough.
+ *
+ * The spec does not say how the initial igmp reports
+ * need to be repeated (aside from suggesting to just do the
+ * randomization of the intervals as for igmp queries but then
+ * there is no centralized trigger and therefore no randomization
+ * needed). We provide an array of delays here that are likely
+ * to work in general avoiding the often too short or too long intervals
+ * that would be generated if we would follow the suggestion in the rfc.
+ *
+ * Note that the sending of unsolicited reports may stop at any point
+ * if we see an igmp query from a router or a neighbors ignmp report.
  */

+static int unsolicited_delay[IGMP_Unsolicited_Report_Count + 1] = {
+	IGMP_Initial_Report_Delay + IGMP_Mininum_Delay,	/* "Immediate" */
+	HZ / 25,			/* 40ms  */
+	HZ / 5,				/* 200ms */
+	HZ,
+	5 * HZ,
+	10 * HZ,
+	60 * HZ
+};
+
 #define IGMP_V1_SEEN(in_dev) \
 	(IPV4_DEVCONF_ALL(dev_net(in_dev->dev), FORCE_IGMP_VERSION) == 1 || \
 	 IN_DEV_CONF_GET((in_dev), FORCE_IGMP_VERSION) == 1 || \
@@ -199,6 +222,13 @@  static void igmp_start_timer(struct ip_m
 		atomic_inc(&im->refcnt);
 }

+static void igmp_start_initial_timer(struct ip_mc_list *im, int interval)
+{
+	int delay = unsolicited_delay[interval];
+
+	igmp_start_timer(im, delay, delay + IGMP_Unsolicited_Fuzz);
+}
+
 static void igmp_gq_start_timer(struct in_device *in_dev)
 {
 	in_dev->mr_gq_running = 1;
@@ -748,8 +778,8 @@  static void igmp_timer_expire(unsigned l

 	if (im->unsolicit_count) {
 		im->unsolicit_count--;
-		igmp_start_timer(im, IGMP_Unsolicited_Report_Min_Delay,
-				IGMP_Unsolicited_Report_Interval);
+		igmp_start_initial_timer(im,
+			IGMP_Unsolicited_Report_Count - im->unsolicit_count);
 	}
 	im->reporter = 1;
 	spin_unlock(&im->lock);
@@ -1185,7 +1215,7 @@  static void igmp_group_added(struct ip_m
 		return;
 	if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
 		spin_lock_bh(&im->lock);
-		igmp_start_timer(im, IGMP_Mininum_Delay, IGMP_Initial_Report_Delay);
+		igmp_start_initial_timer(im, 0);
 		spin_unlock_bh(&im->lock);
 		return;
 	}