aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge/br_multicast.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r--net/bridge/br_multicast.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 69af490cce44..61c5e819380e 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -619,6 +619,9 @@ rehash:
619 mp->br = br; 619 mp->br = br;
620 mp->addr = *group; 620 mp->addr = *group;
621 621
622 setup_timer(&mp->timer, br_multicast_group_expired,
623 (unsigned long)mp);
624
622 hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]); 625 hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);
623 mdb->size++; 626 mdb->size++;
624 627
@@ -1011,6 +1014,16 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
1011} 1014}
1012#endif 1015#endif
1013 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
1014/* 1027/*
1015 * Add port to router_list 1028 * Add port to router_list
1016 * list is maintained ordered by pointer value 1029 * list is maintained ordered by pointer value
@@ -1061,11 +1074,11 @@ timer:
1061 1074
1062static void br_multicast_query_received(struct net_bridge *br, 1075static void br_multicast_query_received(struct net_bridge *br,
1063 struct net_bridge_port *port, 1076 struct net_bridge_port *port,
1064 int saddr) 1077 int saddr,
1078 unsigned long max_delay)
1065{ 1079{
1066 if (saddr) 1080 if (saddr)
1067 mod_timer(&br->multicast_querier_timer, 1081 br_multicast_update_querier_timer(br, max_delay);
1068 jiffies + br->multicast_querier_interval);
1069 else if (timer_pending(&br->multicast_querier_timer)) 1082 else if (timer_pending(&br->multicast_querier_timer))
1070 return; 1083 return;
1071 1084
@@ -1093,8 +1106,6 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1093 (port && port->state == BR_STATE_DISABLED)) 1106 (port && port->state == BR_STATE_DISABLED))
1094 goto out; 1107 goto out;
1095 1108
1096 br_multicast_query_received(br, port, !!iph->saddr);
1097
1098 group = ih->group; 1109 group = ih->group;
1099 1110
1100 if (skb->len == sizeof(*ih)) { 1111 if (skb->len == sizeof(*ih)) {
@@ -1118,6 +1129,8 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1118 IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; 1129 IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1;
1119 } 1130 }
1120 1131
1132 br_multicast_query_received(br, port, !!iph->saddr, max_delay);
1133
1121 if (!group) 1134 if (!group)
1122 goto out; 1135 goto out;
1123 1136
@@ -1126,7 +1139,6 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1126 if (!mp) 1139 if (!mp)
1127 goto out; 1140 goto out;
1128 1141
1129 setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp);
1130 mod_timer(&mp->timer, now + br->multicast_membership_interval); 1142 mod_timer(&mp->timer, now + br->multicast_membership_interval);
1131 mp->timer_armed = true; 1143 mp->timer_armed = true;
1132 1144
@@ -1174,8 +1186,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1174 (port && port->state == BR_STATE_DISABLED)) 1186 (port && port->state == BR_STATE_DISABLED))
1175 goto out; 1187 goto out;
1176 1188
1177 br_multicast_query_received(br, port, !ipv6_addr_any(&ip6h->saddr));
1178
1179 if (skb->len == sizeof(*mld)) { 1189 if (skb->len == sizeof(*mld)) {
1180 if (!pskb_may_pull(skb, sizeof(*mld))) { 1190 if (!pskb_may_pull(skb, sizeof(*mld))) {
1181 err = -EINVAL; 1191 err = -EINVAL;
@@ -1196,6 +1206,9 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1196 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;
1197 } 1207 }
1198 1208
1209 br_multicast_query_received(br, port, !ipv6_addr_any(&ip6h->saddr),
1210 max_delay);
1211
1199 if (!group) 1212 if (!group)
1200 goto out; 1213 goto out;
1201 1214
@@ -1204,7 +1217,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1204 if (!mp) 1217 if (!mp)
1205 goto out; 1218 goto out;
1206 1219
1207 setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp);
1208 mod_timer(&mp->timer, now + br->multicast_membership_interval); 1220 mod_timer(&mp->timer, now + br->multicast_membership_interval);
1209 mp->timer_armed = true; 1221 mp->timer_armed = true;
1210 1222
@@ -1642,6 +1654,8 @@ void br_multicast_init(struct net_bridge *br)
1642 br->multicast_querier_interval = 255 * HZ; 1654 br->multicast_querier_interval = 255 * HZ;
1643 br->multicast_membership_interval = 260 * HZ; 1655 br->multicast_membership_interval = 260 * HZ;
1644 1656
1657 br->multicast_querier_delay_time = 0;
1658
1645 spin_lock_init(&br->multicast_lock); 1659 spin_lock_init(&br->multicast_lock);
1646 setup_timer(&br->multicast_router_timer, 1660 setup_timer(&br->multicast_router_timer,
1647 br_multicast_local_router_expired, 0); 1661 br_multicast_local_router_expired, 0);
@@ -1830,6 +1844,8 @@ unlock:
1830 1844
1831int br_multicast_set_querier(struct net_bridge *br, unsigned long val) 1845int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
1832{ 1846{
1847 unsigned long max_delay;
1848
1833 val = !!val; 1849 val = !!val;
1834 1850
1835 spin_lock_bh(&br->multicast_lock); 1851 spin_lock_bh(&br->multicast_lock);
@@ -1837,8 +1853,14 @@ int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
1837 goto unlock; 1853 goto unlock;
1838 1854
1839 br->multicast_querier = val; 1855 br->multicast_querier = val;
1840 if (val) 1856 if (!val)
1841 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);
1842 1864
1843unlock: 1865unlock:
1844 spin_unlock_bh(&br->multicast_lock); 1866 spin_unlock_bh(&br->multicast_lock);