diff options
Diffstat (limited to 'net/bridge/br_multicast.c')
-rw-r--r-- | net/bridge/br_multicast.c | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 69af490cce44..08e576ada0b2 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 | ||
1017 | static 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 | ||
1062 | static void br_multicast_query_received(struct net_bridge *br, | 1075 | static 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; |
@@ -1185,7 +1195,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1185 | max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay)); | 1195 | max_delay = msecs_to_jiffies(ntohs(mld->mld_maxdelay)); |
1186 | if (max_delay) | 1196 | if (max_delay) |
1187 | group = &mld->mld_mca; | 1197 | group = &mld->mld_mca; |
1188 | } else if (skb->len >= sizeof(*mld2q)) { | 1198 | } else { |
1189 | if (!pskb_may_pull(skb, sizeof(*mld2q))) { | 1199 | if (!pskb_may_pull(skb, sizeof(*mld2q))) { |
1190 | err = -EINVAL; | 1200 | err = -EINVAL; |
1191 | goto out; | 1201 | goto out; |
@@ -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 | ||
1831 | int br_multicast_set_querier(struct net_bridge *br, unsigned long val) | 1845 | int 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 | ||
1843 | unlock: | 1865 | unlock: |
1844 | spin_unlock_bh(&br->multicast_lock); | 1866 | spin_unlock_bh(&br->multicast_lock); |