diff options
-rw-r--r-- | net/bridge/br_device.c | 3 | ||||
-rw-r--r-- | net/bridge/br_input.c | 3 | ||||
-rw-r--r-- | net/bridge/br_multicast.c | 39 | ||||
-rw-r--r-- | net/bridge/br_private.h | 12 |
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 | ||
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 | |||
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 | ||
1065 | static void br_multicast_query_received(struct net_bridge *br, | 1075 | static 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 | ||
1832 | 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) |
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 | ||
1844 | unlock: | 1865 | unlock: |
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 | |||
506 | static 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 |
505 | static inline int br_multicast_rcv(struct net_bridge *br, | 513 | static 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 | } |
568 | static inline bool br_multicast_querier_exists(struct net_bridge *br) | ||
569 | { | ||
570 | return false; | ||
571 | } | ||
560 | static inline void br_mdb_init(void) | 572 | static inline void br_mdb_init(void) |
561 | { | 573 | { |
562 | } | 574 | } |