===================================================================
@@ -116,10 +116,17 @@
#define IGMP_V2_Router_Present_Timeout (400*HZ)
#define IGMP_Unsolicited_Report_Interval (10*HZ)
#define IGMP_Query_Response_Interval (10*HZ)
-#define IGMP_Unsolicited_Report_Count 2
+/* Parameters not specified in igmp rfc. */
+
+/* Mininum ticks to have a meaningful notion of delay */
+#define IGMP_Mininum_Delay (2)
+
+/* Control of unsolilcited reports (after join) */
+#define IGMP_Unsolicited_Report_Count 2
#define IGMP_Initial_Report_Delay (1)
+#define IGMP_Unsolicited_Report_Min_Delay (HZ/25)
/* IGMP_Initial_Report_Delay is not from IGMP specs!
* IGMP specs require to report membership immediately after
@@ -174,22 +181,30 @@ static __inline__ void igmp_stop_timer(s
spin_unlock_bh(&im->lock);
}
-/* It must be called with locked im->lock */
-static void igmp_start_timer(struct ip_mc_list *im, int max_delay)
+static inline unsigned long jiffies_rand_delay(int min_delay, int max_delay)
{
- int tv = net_random() % max_delay;
+ int d = min_delay;
+
+ if (min_delay < max_delay)
+ d += net_random() % (max_delay - min_delay);
+ return jiffies + d;
+}
+
+/* It must be called with locked im->lock */
+static void igmp_start_timer(struct ip_mc_list *im, int min_delay, int max_delay)
+{
im->tm_running = 1;
- if (!mod_timer(&im->timer, jiffies+tv+2))
+ if (!mod_timer(&im->timer, jiffies_rand_delay(min_delay, max_delay)))
atomic_inc(&im->refcnt);
}
static void igmp_gq_start_timer(struct in_device *in_dev)
{
- int tv = net_random() % in_dev->mr_maxdelay;
-
in_dev->mr_gq_running = 1;
- if (!mod_timer(&in_dev->mr_gq_timer, jiffies+tv+2))
+ if (!mod_timer(&in_dev->mr_gq_timer,
+ jiffies_rand_delay(IGMP_Mininum_Delay,
+ in_dev->mr_maxdelay)))
in_dev_hold(in_dev);
}
@@ -201,7 +216,7 @@ static void igmp_ifc_start_timer(struct
in_dev_hold(in_dev);
}
-static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
+static void igmp_mod_timer(struct ip_mc_list *im, int min_delay, int max_delay)
{
spin_lock_bh(&im->lock);
im->unsolicit_count = 0;
@@ -214,7 +229,7 @@ static void igmp_mod_timer(struct ip_mc_
}
atomic_dec(&im->refcnt);
}
- igmp_start_timer(im, max_delay);
+ igmp_start_timer(im, min_delay, max_delay);
spin_unlock_bh(&im->lock);
}
@@ -733,7 +748,8 @@ static void igmp_timer_expire(unsigned l
if (im->unsolicit_count) {
im->unsolicit_count--;
- igmp_start_timer(im, IGMP_Unsolicited_Report_Interval);
+ igmp_start_timer(im, IGMP_Unsolicited_Report_Min_Delay,
+ IGMP_Unsolicited_Report_Interval);
}
im->reporter = 1;
spin_unlock(&im->lock);
@@ -911,7 +927,7 @@ static void igmp_heard_query(struct in_d
igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
spin_unlock_bh(&im->lock);
if (changed)
- igmp_mod_timer(im, max_delay);
+ igmp_mod_timer(im, IGMP_Mininum_Delay, max_delay);
}
read_unlock(&in_dev->mc_list_lock);
}
@@ -1169,7 +1185,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_Initial_Report_Delay);
+ igmp_start_timer(im, IGMP_Mininum_Delay, IGMP_Initial_Report_Delay);
spin_unlock_bh(&im->lock);
return;
}
@@ -1258,7 +1274,8 @@ void ip_mc_rejoin_group(struct ip_mc_lis
return;
if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
- igmp_mod_timer(im, IGMP_Initial_Report_Delay);
+ igmp_mod_timer(im, IGMP_Mininum_Delay,
+ IGMP_Initial_Report_Delay);
return;
}
/* else, v3 */