aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorLinus Lüssing <linus.luessing@web.de>2013-07-31 19:06:20 -0400
committerDavid S. Miller <davem@davemloft.net>2013-07-31 20:40:21 -0400
commitb00589af3b04736376f24625ab0b394642e89e29 (patch)
tree1661811588dd237d229e8bb9f33f8b81d5b98a9f /net/bridge
parentcf3c4c03060b688cbc389ebc5065ebcce5653e96 (diff)
bridge: disable snooping if there is no querier
If there is no querier on a link then we won't get periodic reports and therefore won't be able to learn about multicast listeners behind ports, potentially leading to lost multicast packets, especially for multicast listeners that joined before the creation of the bridge. These lost multicast packets can appear since c5c23260594 ("bridge: Add multicast_querier toggle and disable queries by default") in particular. With this patch we are flooding multicast packets if our querier is disabled and if we didn't detect any other querier. A grace period of the Maximum Response Delay of the querier is added to give multicast responses enough time to arrive and to be learned from before disabling the flooding behaviour again. Signed-off-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_device.c3
-rw-r--r--net/bridge/br_input.c3
-rw-r--r--net/bridge/br_multicast.c39
-rw-r--r--net/bridge/br_private.h12
4 files changed, 46 insertions, 11 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 2ef66781fedb..69363bd37f64 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -70,7 +70,8 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
70 } 70 }
71 71
72 mdst = br_mdb_get(br, skb, vid); 72 mdst = br_mdb_get(br, skb, vid);
73 if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) 73 if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
74 br_multicast_querier_exists(br))
74 br_multicast_deliver(mdst, skb); 75 br_multicast_deliver(mdst, skb);
75 else 76 else
76 br_flood_deliver(br, skb, false); 77 br_flood_deliver(br, skb, false);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 1b8b8b824cd7..8c561c0aa636 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -101,7 +101,8 @@ int br_handle_frame_finish(struct sk_buff *skb)
101 unicast = false; 101 unicast = false;
102 } else if (is_multicast_ether_addr(dest)) { 102 } else if (is_multicast_ether_addr(dest)) {
103 mdst = br_mdb_get(br, skb, vid); 103 mdst = br_mdb_get(br, skb, vid);
104 if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) { 104 if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
105 br_multicast_querier_exists(br)) {
105 if ((mdst && mdst->mglist) || 106 if ((mdst && mdst->mglist) ||
106 br_multicast_is_router(br)) 107 br_multicast_is_router(br))
107 skb2 = skb; 108 skb2 = skb;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 4b99c9a27044..61c5e819380e 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -1014,6 +1014,16 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
1014} 1014}
1015#endif 1015#endif
1016 1016
1017static void br_multicast_update_querier_timer(struct net_bridge *br,
1018 unsigned long max_delay)
1019{
1020 if (!timer_pending(&br->multicast_querier_timer))
1021 br->multicast_querier_delay_time = jiffies + max_delay;
1022
1023 mod_timer(&br->multicast_querier_timer,
1024 jiffies + br->multicast_querier_interval);
1025}
1026
1017/* 1027/*
1018 * Add port to router_list 1028 * Add port to router_list
1019 * list is maintained ordered by pointer value 1029 * list is maintained ordered by pointer value
@@ -1064,11 +1074,11 @@ timer:
1064 1074
1065static void br_multicast_query_received(struct net_bridge *br, 1075static void br_multicast_query_received(struct net_bridge *br,
1066 struct net_bridge_port *port, 1076 struct net_bridge_port *port,
1067 int saddr) 1077 int saddr,
1078 unsigned long max_delay)
1068{ 1079{
1069 if (saddr) 1080 if (saddr)
1070 mod_timer(&br->multicast_querier_timer, 1081 br_multicast_update_querier_timer(br, max_delay);
1071 jiffies + br->multicast_querier_interval);
1072 else if (timer_pending(&br->multicast_querier_timer)) 1082 else if (timer_pending(&br->multicast_querier_timer))
1073 return; 1083 return;
1074 1084
@@ -1096,8 +1106,6 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1096 (port && port->state == BR_STATE_DISABLED)) 1106 (port && port->state == BR_STATE_DISABLED))
1097 goto out; 1107 goto out;
1098 1108
1099 br_multicast_query_received(br, port, !!iph->saddr);
1100
1101 group = ih->group; 1109 group = ih->group;
1102 1110
1103 if (skb->len == sizeof(*ih)) { 1111 if (skb->len == sizeof(*ih)) {
@@ -1121,6 +1129,8 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1121 IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; 1129 IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
1122 } 1130 }
1123 1131
1132 br_multicast_query_received(br, port, !!iph->saddr, max_delay);
1133
1124 if (!group) 1134 if (!group)
1125 goto out; 1135 goto out;
1126 1136
@@ -1176,8 +1186,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1176 (port && port->state == BR_STATE_DISABLED)) 1186 (port && port->state == BR_STATE_DISABLED))
1177 goto out; 1187 goto out;
1178 1188
1179 br_multicast_query_received(br, port, !ipv6_addr_any(&ip6h->saddr));
1180
1181 if (skb->len == sizeof(*mld)) { 1189 if (skb->len == sizeof(*mld)) {
1182 if (!pskb_may_pull(skb, sizeof(*mld))) { 1190 if (!pskb_may_pull(skb, sizeof(*mld))) {
1183 err = -EINVAL; 1191 err = -EINVAL;
@@ -1198,6 +1206,9 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1198 max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(ntohs(mld2q->mld2q_mrc)) : 1; 1206 max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(ntohs(mld2q->mld2q_mrc)) : 1;
1199 } 1207 }
1200 1208
1209 br_multicast_query_received(br, port, !ipv6_addr_any(&ip6h->saddr),
1210 max_delay);
1211
1201 if (!group) 1212 if (!group)
1202 goto out; 1213 goto out;
1203 1214
@@ -1643,6 +1654,8 @@ void br_multicast_init(struct net_bridge *br)
1643 br->multicast_querier_interval = 255 * HZ; 1654 br->multicast_querier_interval = 255 * HZ;
1644 br->multicast_membership_interval = 260 * HZ; 1655 br->multicast_membership_interval = 260 * HZ;
1645 1656
1657 br->multicast_querier_delay_time = 0;
1658
1646 spin_lock_init(&br->multicast_lock); 1659 spin_lock_init(&br->multicast_lock);
1647 setup_timer(&br->multicast_router_timer, 1660 setup_timer(&br->multicast_router_timer,
1648 br_multicast_local_router_expired, 0); 1661 br_multicast_local_router_expired, 0);
@@ -1831,6 +1844,8 @@ unlock:
1831 1844
1832int br_multicast_set_querier(struct net_bridge *br, unsigned long val) 1845int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
1833{ 1846{
1847 unsigned long max_delay;
1848
1834 val = !!val; 1849 val = !!val;
1835 1850
1836 spin_lock_bh(&br->multicast_lock); 1851 spin_lock_bh(&br->multicast_lock);
@@ -1838,8 +1853,14 @@ int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
1838 goto unlock; 1853 goto unlock;
1839 1854
1840 br->multicast_querier = val; 1855 br->multicast_querier = val;
1841 if (val) 1856 if (!val)
1842 br_multicast_start_querier(br); 1857 goto unlock;
1858
1859 max_delay = br->multicast_query_response_interval;
1860 if (!timer_pending(&br->multicast_querier_timer))
1861 br->multicast_querier_delay_time = jiffies + max_delay;
1862
1863 br_multicast_start_querier(br);
1843 1864
1844unlock: 1865unlock:
1845 spin_unlock_bh(&br->multicast_lock); 1866 spin_unlock_bh(&br->multicast_lock);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 3be89b3ce17b..2f7da41851bf 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -267,6 +267,7 @@ struct net_bridge
267 unsigned long multicast_query_interval; 267 unsigned long multicast_query_interval;
268 unsigned long multicast_query_response_interval; 268 unsigned long multicast_query_response_interval;
269 unsigned long multicast_startup_query_interval; 269 unsigned long multicast_startup_query_interval;
270 unsigned long multicast_querier_delay_time;
270 271
271 spinlock_t multicast_lock; 272 spinlock_t multicast_lock;
272 struct net_bridge_mdb_htable __rcu *mdb; 273 struct net_bridge_mdb_htable __rcu *mdb;
@@ -501,6 +502,13 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
501 (br->multicast_router == 1 && 502 (br->multicast_router == 1 &&
502 timer_pending(&br->multicast_router_timer)); 503 timer_pending(&br->multicast_router_timer));
503} 504}
505
506static inline bool br_multicast_querier_exists(struct net_bridge *br)
507{
508 return time_is_before_jiffies(br->multicast_querier_delay_time) &&
509 (br->multicast_querier ||
510 timer_pending(&br->multicast_querier_timer));
511}
504#else 512#else
505static inline int br_multicast_rcv(struct net_bridge *br, 513static inline int br_multicast_rcv(struct net_bridge *br,
506 struct net_bridge_port *port, 514 struct net_bridge_port *port,
@@ -557,6 +565,10 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
557{ 565{
558 return 0; 566 return 0;
559} 567}
568static inline bool br_multicast_querier_exists(struct net_bridge *br)
569{
570 return false;
571}
560static inline void br_mdb_init(void) 572static inline void br_mdb_init(void)
561{ 573{
562} 574}