Skip to content

Commit

Permalink
net: igmp: Reduce Unsolicited report interval to 1s when using IGMPv3
Browse files Browse the repository at this point in the history
If an IGMP join packet is lost you will not receive data sent to the
multicast group so if no data arrives from that multicast group in a
period of time after the IGMP join a second IGMP join will be sent.  The
delay between joins is the "IGMP Unsolicited Report Interval".

Previously this value was hard coded to be chosen randomly between 0-10s.
This can be too long for some use-cases, such as IPTV as it can cause
channel change to be slow in the presence of packet loss.

The value 10s has come from IGMPv2 RFC2236, which was reduced to 1s in
IGMPv3 RFC3376.  This patch makes the kernel use the 1s value from the
later RFC if we are operating in IGMPv3 mode.  IGMPv2 behaviour is
unaffected.

Tested with Wireshark and a simple program to join a (non-existent)
multicast group.  The distribution of timings for the second join differ
based upon setting /proc/sys/net/ipv4/conf/eth0/force_igmp_version.

Signed-off-by: William Manley <william.manley@youview.com>
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Acked-by: Benjamin LaHaise <bcrl@kvack.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
William Manley authored and David S. Miller committed Aug 9, 2013
1 parent b20903f commit cab7004
Showing 1 changed file with 13 additions and 3 deletions.
16 changes: 13 additions & 3 deletions net/ipv4/igmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@

#define IGMP_V1_Router_Present_Timeout (400*HZ)
#define IGMP_V2_Router_Present_Timeout (400*HZ)
#define IGMP_Unsolicited_Report_Interval (10*HZ)
#define IGMP_V2_Unsolicited_Report_Interval (10*HZ)
#define IGMP_V3_Unsolicited_Report_Interval (1*HZ)
#define IGMP_Query_Response_Interval (10*HZ)
#define IGMP_Unsolicited_Report_Count 2

Expand All @@ -139,6 +140,14 @@
((in_dev)->mr_v2_seen && \
time_before(jiffies, (in_dev)->mr_v2_seen)))

static int unsolicited_report_interval(struct in_device *in_dev)
{
if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev))
return IGMP_V2_Unsolicited_Report_Interval;
else /* v3 */
return IGMP_V3_Unsolicited_Report_Interval;
}

static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
static void igmpv3_clear_delrec(struct in_device *in_dev);
Expand Down Expand Up @@ -722,7 +731,8 @@ static void igmp_ifc_timer_expire(unsigned long data)
igmpv3_send_cr(in_dev);
if (in_dev->mr_ifc_count) {
in_dev->mr_ifc_count--;
igmp_ifc_start_timer(in_dev, IGMP_Unsolicited_Report_Interval);
igmp_ifc_start_timer(in_dev,
unsolicited_report_interval(in_dev));
}
__in_dev_put(in_dev);
}
Expand All @@ -747,7 +757,7 @@ static void igmp_timer_expire(unsigned long data)

if (im->unsolicit_count) {
im->unsolicit_count--;
igmp_start_timer(im, IGMP_Unsolicited_Report_Interval);
igmp_start_timer(im, unsolicited_report_interval(in_dev));
}
im->reporter = 1;
spin_unlock(&im->lock);
Expand Down

0 comments on commit cab7004

Please sign in to comment.