aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-06-11 02:51:00 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-11 02:51:00 -0400
commit7b0dcbd879101e829755d1288c1b440ba1f59460 (patch)
treee9690ec1d858835250edaa4cb5943bdd8e04d19e
parentc4d4c255d85310dc720c5535c164ca0f6d5b3b81 (diff)
parent2cd4143192e8c60f66cb32c3a30c76d0470a372d (diff)
Merge branch 'bridge_multicast_exports'
Linus Lüssing says: ==================== bridge: multicast snooping patches / exports The first patch is simply a cosmetic patch. So far I (and maybe others too?) have been regularly confusing these two structs, therefore I'd suggest renaming them and therefore making the follow-up patches easier to understand and nicer to fit in. The second patch fixes a minor issue, but probably not worth for stable. On the other hand the first two patches are also preparations for the third and fourth patch: These two patches are exporting functionality needed to marry the bridge multicast snooping with the batman-adv multicast optimizations recently added for the 3.15 kernel, allowing to use these optimzations in common setups having a bridge on top of e.g. bat0, too. So far these bridged setups would fall back to simple flooding through the batman-adv mesh network for any multicast packet entering bat0. More information about the batman-adv multicast optimizations currently implemented can be found here: http://www.open-mesh.org/projects/batman-adv/wiki/Basic-multicast-optimizations The integration on the batman-adv side could afterwards look like this, for instance: http://git.open-mesh.org/batman-adv.git/commitdiff/576b59dd3e34737c702e548b21fa72059262f796?hp=f95ce7131746c65fbcdffcf2089cab59e2c2f7ac ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/if_bridge.h19
-rw-r--r--net/bridge/br_mdb.c4
-rw-r--r--net/bridge/br_multicast.c378
-rw-r--r--net/bridge/br_private.h38
4 files changed, 326 insertions, 113 deletions
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 1085ffeef956..fd22789d7b2e 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -16,9 +16,28 @@
16#include <linux/netdevice.h> 16#include <linux/netdevice.h>
17#include <uapi/linux/if_bridge.h> 17#include <uapi/linux/if_bridge.h>
18 18
19struct br_ip {
20 union {
21 __be32 ip4;
22#if IS_ENABLED(CONFIG_IPV6)
23 struct in6_addr ip6;
24#endif
25 } u;
26 __be16 proto;
27 __u16 vid;
28};
29
30struct br_ip_list {
31 struct list_head list;
32 struct br_ip addr;
33};
34
19extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); 35extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
20 36
21typedef int br_should_route_hook_t(struct sk_buff *skb); 37typedef int br_should_route_hook_t(struct sk_buff *skb);
22extern br_should_route_hook_t __rcu *br_should_route_hook; 38extern br_should_route_hook_t __rcu *br_should_route_hook;
39int br_multicast_list_adjacent(struct net_device *dev,
40 struct list_head *br_ip_list);
41bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto);
23 42
24#endif 43#endif
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index b7b1914dfa25..5df05269d17a 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -418,13 +418,13 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
418 418
419 ip.proto = entry->addr.proto; 419 ip.proto = entry->addr.proto;
420 if (ip.proto == htons(ETH_P_IP)) { 420 if (ip.proto == htons(ETH_P_IP)) {
421 if (timer_pending(&br->ip4_querier.timer)) 421 if (timer_pending(&br->ip4_other_query.timer))
422 return -EBUSY; 422 return -EBUSY;
423 423
424 ip.u.ip4 = entry->addr.u.ip4; 424 ip.u.ip4 = entry->addr.u.ip4;
425#if IS_ENABLED(CONFIG_IPV6) 425#if IS_ENABLED(CONFIG_IPV6)
426 } else { 426 } else {
427 if (timer_pending(&br->ip6_querier.timer)) 427 if (timer_pending(&br->ip6_other_query.timer))
428 return -EBUSY; 428 return -EBUSY;
429 429
430 ip.u.ip6 = entry->addr.u.ip6; 430 ip.u.ip6 = entry->addr.u.ip6;
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 7b757b5dc773..cd3cf394c477 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -11,6 +11,7 @@
11 */ 11 */
12 12
13#include <linux/err.h> 13#include <linux/err.h>
14#include <linux/export.h>
14#include <linux/if_ether.h> 15#include <linux/if_ether.h>
15#include <linux/igmp.h> 16#include <linux/igmp.h>
16#include <linux/jhash.h> 17#include <linux/jhash.h>
@@ -35,7 +36,7 @@
35#include "br_private.h" 36#include "br_private.h"
36 37
37static void br_multicast_start_querier(struct net_bridge *br, 38static void br_multicast_start_querier(struct net_bridge *br,
38 struct bridge_mcast_query *query); 39 struct bridge_mcast_own_query *query);
39unsigned int br_mdb_rehash_seq; 40unsigned int br_mdb_rehash_seq;
40 41
41static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b) 42static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
@@ -761,7 +762,7 @@ static void br_multicast_local_router_expired(unsigned long data)
761} 762}
762 763
763static void br_multicast_querier_expired(struct net_bridge *br, 764static void br_multicast_querier_expired(struct net_bridge *br,
764 struct bridge_mcast_query *query) 765 struct bridge_mcast_own_query *query)
765{ 766{
766 spin_lock(&br->multicast_lock); 767 spin_lock(&br->multicast_lock);
767 if (!netif_running(br->dev) || br->multicast_disabled) 768 if (!netif_running(br->dev) || br->multicast_disabled)
@@ -777,7 +778,7 @@ static void br_ip4_multicast_querier_expired(unsigned long data)
777{ 778{
778 struct net_bridge *br = (void *)data; 779 struct net_bridge *br = (void *)data;
779 780
780 br_multicast_querier_expired(br, &br->ip4_query); 781 br_multicast_querier_expired(br, &br->ip4_own_query);
781} 782}
782 783
783#if IS_ENABLED(CONFIG_IPV6) 784#if IS_ENABLED(CONFIG_IPV6)
@@ -785,10 +786,22 @@ static void br_ip6_multicast_querier_expired(unsigned long data)
785{ 786{
786 struct net_bridge *br = (void *)data; 787 struct net_bridge *br = (void *)data;
787 788
788 br_multicast_querier_expired(br, &br->ip6_query); 789 br_multicast_querier_expired(br, &br->ip6_own_query);
789} 790}
790#endif 791#endif
791 792
793static void br_multicast_select_own_querier(struct net_bridge *br,
794 struct br_ip *ip,
795 struct sk_buff *skb)
796{
797 if (ip->proto == htons(ETH_P_IP))
798 br->ip4_querier.addr.u.ip4 = ip_hdr(skb)->saddr;
799#if IS_ENABLED(CONFIG_IPV6)
800 else
801 br->ip6_querier.addr.u.ip6 = ipv6_hdr(skb)->saddr;
802#endif
803}
804
792static void __br_multicast_send_query(struct net_bridge *br, 805static void __br_multicast_send_query(struct net_bridge *br,
793 struct net_bridge_port *port, 806 struct net_bridge_port *port,
794 struct br_ip *ip) 807 struct br_ip *ip)
@@ -804,17 +817,19 @@ static void __br_multicast_send_query(struct net_bridge *br,
804 skb->dev = port->dev; 817 skb->dev = port->dev;
805 NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, 818 NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
806 dev_queue_xmit); 819 dev_queue_xmit);
807 } else 820 } else {
821 br_multicast_select_own_querier(br, ip, skb);
808 netif_rx(skb); 822 netif_rx(skb);
823 }
809} 824}
810 825
811static void br_multicast_send_query(struct net_bridge *br, 826static void br_multicast_send_query(struct net_bridge *br,
812 struct net_bridge_port *port, 827 struct net_bridge_port *port,
813 struct bridge_mcast_query *query) 828 struct bridge_mcast_own_query *own_query)
814{ 829{
815 unsigned long time; 830 unsigned long time;
816 struct br_ip br_group; 831 struct br_ip br_group;
817 struct bridge_mcast_querier *querier = NULL; 832 struct bridge_mcast_other_query *other_query = NULL;
818 833
819 if (!netif_running(br->dev) || br->multicast_disabled || 834 if (!netif_running(br->dev) || br->multicast_disabled ||
820 !br->multicast_querier) 835 !br->multicast_querier)
@@ -822,31 +837,32 @@ static void br_multicast_send_query(struct net_bridge *br,
822 837
823 memset(&br_group.u, 0, sizeof(br_group.u)); 838 memset(&br_group.u, 0, sizeof(br_group.u));
824 839
825 if (port ? (query == &port->ip4_query) : 840 if (port ? (own_query == &port->ip4_own_query) :
826 (query == &br->ip4_query)) { 841 (own_query == &br->ip4_own_query)) {
827 querier = &br->ip4_querier; 842 other_query = &br->ip4_other_query;
828 br_group.proto = htons(ETH_P_IP); 843 br_group.proto = htons(ETH_P_IP);
829#if IS_ENABLED(CONFIG_IPV6) 844#if IS_ENABLED(CONFIG_IPV6)
830 } else { 845 } else {
831 querier = &br->ip6_querier; 846 other_query = &br->ip6_other_query;
832 br_group.proto = htons(ETH_P_IPV6); 847 br_group.proto = htons(ETH_P_IPV6);
833#endif 848#endif
834 } 849 }
835 850
836 if (!querier || timer_pending(&querier->timer)) 851 if (!other_query || timer_pending(&other_query->timer))
837 return; 852 return;
838 853
839 __br_multicast_send_query(br, port, &br_group); 854 __br_multicast_send_query(br, port, &br_group);
840 855
841 time = jiffies; 856 time = jiffies;
842 time += query->startup_sent < br->multicast_startup_query_count ? 857 time += own_query->startup_sent < br->multicast_startup_query_count ?
843 br->multicast_startup_query_interval : 858 br->multicast_startup_query_interval :
844 br->multicast_query_interval; 859 br->multicast_query_interval;
845 mod_timer(&query->timer, time); 860 mod_timer(&own_query->timer, time);
846} 861}
847 862
848static void br_multicast_port_query_expired(struct net_bridge_port *port, 863static void
849 struct bridge_mcast_query *query) 864br_multicast_port_query_expired(struct net_bridge_port *port,
865 struct bridge_mcast_own_query *query)
850{ 866{
851 struct net_bridge *br = port->br; 867 struct net_bridge *br = port->br;
852 868
@@ -868,7 +884,7 @@ static void br_ip4_multicast_port_query_expired(unsigned long data)
868{ 884{
869 struct net_bridge_port *port = (void *)data; 885 struct net_bridge_port *port = (void *)data;
870 886
871 br_multicast_port_query_expired(port, &port->ip4_query); 887 br_multicast_port_query_expired(port, &port->ip4_own_query);
872} 888}
873 889
874#if IS_ENABLED(CONFIG_IPV6) 890#if IS_ENABLED(CONFIG_IPV6)
@@ -876,7 +892,7 @@ static void br_ip6_multicast_port_query_expired(unsigned long data)
876{ 892{
877 struct net_bridge_port *port = (void *)data; 893 struct net_bridge_port *port = (void *)data;
878 894
879 br_multicast_port_query_expired(port, &port->ip6_query); 895 br_multicast_port_query_expired(port, &port->ip6_own_query);
880} 896}
881#endif 897#endif
882 898
@@ -886,11 +902,11 @@ void br_multicast_add_port(struct net_bridge_port *port)
886 902
887 setup_timer(&port->multicast_router_timer, br_multicast_router_expired, 903 setup_timer(&port->multicast_router_timer, br_multicast_router_expired,
888 (unsigned long)port); 904 (unsigned long)port);
889 setup_timer(&port->ip4_query.timer, br_ip4_multicast_port_query_expired, 905 setup_timer(&port->ip4_own_query.timer,
890 (unsigned long)port); 906 br_ip4_multicast_port_query_expired, (unsigned long)port);
891#if IS_ENABLED(CONFIG_IPV6) 907#if IS_ENABLED(CONFIG_IPV6)
892 setup_timer(&port->ip6_query.timer, br_ip6_multicast_port_query_expired, 908 setup_timer(&port->ip6_own_query.timer,
893 (unsigned long)port); 909 br_ip6_multicast_port_query_expired, (unsigned long)port);
894#endif 910#endif
895} 911}
896 912
@@ -899,7 +915,7 @@ void br_multicast_del_port(struct net_bridge_port *port)
899 del_timer_sync(&port->multicast_router_timer); 915 del_timer_sync(&port->multicast_router_timer);
900} 916}
901 917
902static void br_multicast_enable(struct bridge_mcast_query *query) 918static void br_multicast_enable(struct bridge_mcast_own_query *query)
903{ 919{
904 query->startup_sent = 0; 920 query->startup_sent = 0;
905 921
@@ -916,9 +932,9 @@ void br_multicast_enable_port(struct net_bridge_port *port)
916 if (br->multicast_disabled || !netif_running(br->dev)) 932 if (br->multicast_disabled || !netif_running(br->dev))
917 goto out; 933 goto out;
918 934
919 br_multicast_enable(&port->ip4_query); 935 br_multicast_enable(&port->ip4_own_query);
920#if IS_ENABLED(CONFIG_IPV6) 936#if IS_ENABLED(CONFIG_IPV6)
921 br_multicast_enable(&port->ip6_query); 937 br_multicast_enable(&port->ip6_own_query);
922#endif 938#endif
923 939
924out: 940out:
@@ -938,9 +954,9 @@ void br_multicast_disable_port(struct net_bridge_port *port)
938 if (!hlist_unhashed(&port->rlist)) 954 if (!hlist_unhashed(&port->rlist))
939 hlist_del_init_rcu(&port->rlist); 955 hlist_del_init_rcu(&port->rlist);
940 del_timer(&port->multicast_router_timer); 956 del_timer(&port->multicast_router_timer);
941 del_timer(&port->ip4_query.timer); 957 del_timer(&port->ip4_own_query.timer);
942#if IS_ENABLED(CONFIG_IPV6) 958#if IS_ENABLED(CONFIG_IPV6)
943 del_timer(&port->ip6_query.timer); 959 del_timer(&port->ip6_own_query.timer);
944#endif 960#endif
945 spin_unlock(&br->multicast_lock); 961 spin_unlock(&br->multicast_lock);
946} 962}
@@ -1064,15 +1080,80 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
1064} 1080}
1065#endif 1081#endif
1066 1082
1083static bool br_ip4_multicast_select_querier(struct net_bridge *br,
1084 struct net_bridge_port *port,
1085 __be32 saddr)
1086{
1087 if (!timer_pending(&br->ip4_own_query.timer) &&
1088 !timer_pending(&br->ip4_other_query.timer))
1089 goto update;
1090
1091 if (!br->ip4_querier.addr.u.ip4)
1092 goto update;
1093
1094 if (ntohl(saddr) <= ntohl(br->ip4_querier.addr.u.ip4))
1095 goto update;
1096
1097 return false;
1098
1099update:
1100 br->ip4_querier.addr.u.ip4 = saddr;
1101
1102 /* update protected by general multicast_lock by caller */
1103 rcu_assign_pointer(br->ip4_querier.port, port);
1104
1105 return true;
1106}
1107
1108#if IS_ENABLED(CONFIG_IPV6)
1109static bool br_ip6_multicast_select_querier(struct net_bridge *br,
1110 struct net_bridge_port *port,
1111 struct in6_addr *saddr)
1112{
1113 if (!timer_pending(&br->ip6_own_query.timer) &&
1114 !timer_pending(&br->ip6_other_query.timer))
1115 goto update;
1116
1117 if (ipv6_addr_cmp(saddr, &br->ip6_querier.addr.u.ip6) <= 0)
1118 goto update;
1119
1120 return false;
1121
1122update:
1123 br->ip6_querier.addr.u.ip6 = *saddr;
1124
1125 /* update protected by general multicast_lock by caller */
1126 rcu_assign_pointer(br->ip6_querier.port, port);
1127
1128 return true;
1129}
1130#endif
1131
1132static bool br_multicast_select_querier(struct net_bridge *br,
1133 struct net_bridge_port *port,
1134 struct br_ip *saddr)
1135{
1136 switch (saddr->proto) {
1137 case htons(ETH_P_IP):
1138 return br_ip4_multicast_select_querier(br, port, saddr->u.ip4);
1139#if IS_ENABLED(CONFIG_IPV6)
1140 case htons(ETH_P_IPV6):
1141 return br_ip6_multicast_select_querier(br, port, &saddr->u.ip6);
1142#endif
1143 }
1144
1145 return false;
1146}
1147
1067static void 1148static void
1068br_multicast_update_querier_timer(struct net_bridge *br, 1149br_multicast_update_query_timer(struct net_bridge *br,
1069 struct bridge_mcast_querier *querier, 1150 struct bridge_mcast_other_query *query,
1070 unsigned long max_delay) 1151 unsigned long max_delay)
1071{ 1152{
1072 if (!timer_pending(&querier->timer)) 1153 if (!timer_pending(&query->timer))
1073 querier->delay_time = jiffies + max_delay; 1154 query->delay_time = jiffies + max_delay;
1074 1155
1075 mod_timer(&querier->timer, jiffies + br->multicast_querier_interval); 1156 mod_timer(&query->timer, jiffies + br->multicast_querier_interval);
1076} 1157}
1077 1158
1078/* 1159/*
@@ -1125,16 +1206,14 @@ timer:
1125 1206
1126static void br_multicast_query_received(struct net_bridge *br, 1207static void br_multicast_query_received(struct net_bridge *br,
1127 struct net_bridge_port *port, 1208 struct net_bridge_port *port,
1128 struct bridge_mcast_querier *querier, 1209 struct bridge_mcast_other_query *query,
1129 int saddr, 1210 struct br_ip *saddr,
1130 bool is_general_query,
1131 unsigned long max_delay) 1211 unsigned long max_delay)
1132{ 1212{
1133 if (saddr && is_general_query) 1213 if (!br_multicast_select_querier(br, port, saddr))
1134 br_multicast_update_querier_timer(br, querier, max_delay);
1135 else if (timer_pending(&querier->timer))
1136 return; 1214 return;
1137 1215
1216 br_multicast_update_query_timer(br, query, max_delay);
1138 br_multicast_mark_router(br, port); 1217 br_multicast_mark_router(br, port);
1139} 1218}
1140 1219
@@ -1149,6 +1228,7 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1149 struct igmpv3_query *ih3; 1228 struct igmpv3_query *ih3;
1150 struct net_bridge_port_group *p; 1229 struct net_bridge_port_group *p;
1151 struct net_bridge_port_group __rcu **pp; 1230 struct net_bridge_port_group __rcu **pp;
1231 struct br_ip saddr;
1152 unsigned long max_delay; 1232 unsigned long max_delay;
1153 unsigned long now = jiffies; 1233 unsigned long now = jiffies;
1154 __be32 group; 1234 __be32 group;
@@ -1190,11 +1270,14 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1190 goto out; 1270 goto out;
1191 } 1271 }
1192 1272
1193 br_multicast_query_received(br, port, &br->ip4_querier, !!iph->saddr, 1273 if (!group) {
1194 !group, max_delay); 1274 saddr.proto = htons(ETH_P_IP);
1275 saddr.u.ip4 = iph->saddr;
1195 1276
1196 if (!group) 1277 br_multicast_query_received(br, port, &br->ip4_other_query,
1278 &saddr, max_delay);
1197 goto out; 1279 goto out;
1280 }
1198 1281
1199 mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid); 1282 mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid);
1200 if (!mp) 1283 if (!mp)
@@ -1234,6 +1317,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1234 struct mld2_query *mld2q; 1317 struct mld2_query *mld2q;
1235 struct net_bridge_port_group *p; 1318 struct net_bridge_port_group *p;
1236 struct net_bridge_port_group __rcu **pp; 1319 struct net_bridge_port_group __rcu **pp;
1320 struct br_ip saddr;
1237 unsigned long max_delay; 1321 unsigned long max_delay;
1238 unsigned long now = jiffies; 1322 unsigned long now = jiffies;
1239 const struct in6_addr *group = NULL; 1323 const struct in6_addr *group = NULL;
@@ -1282,12 +1366,14 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1282 goto out; 1366 goto out;
1283 } 1367 }
1284 1368
1285 br_multicast_query_received(br, port, &br->ip6_querier, 1369 if (is_general_query) {
1286 !ipv6_addr_any(&ip6h->saddr), 1370 saddr.proto = htons(ETH_P_IPV6);
1287 is_general_query, max_delay); 1371 saddr.u.ip6 = ip6h->saddr;
1288 1372
1289 if (!group) 1373 br_multicast_query_received(br, port, &br->ip6_other_query,
1374 &saddr, max_delay);
1290 goto out; 1375 goto out;
1376 }
1291 1377
1292 mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid); 1378 mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid);
1293 if (!mp) 1379 if (!mp)
@@ -1315,11 +1401,12 @@ out:
1315} 1401}
1316#endif 1402#endif
1317 1403
1318static void br_multicast_leave_group(struct net_bridge *br, 1404static void
1319 struct net_bridge_port *port, 1405br_multicast_leave_group(struct net_bridge *br,
1320 struct br_ip *group, 1406 struct net_bridge_port *port,
1321 struct bridge_mcast_querier *querier, 1407 struct br_ip *group,
1322 struct bridge_mcast_query *query) 1408 struct bridge_mcast_other_query *other_query,
1409 struct bridge_mcast_own_query *own_query)
1323{ 1410{
1324 struct net_bridge_mdb_htable *mdb; 1411 struct net_bridge_mdb_htable *mdb;
1325 struct net_bridge_mdb_entry *mp; 1412 struct net_bridge_mdb_entry *mp;
@@ -1330,7 +1417,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
1330 spin_lock(&br->multicast_lock); 1417 spin_lock(&br->multicast_lock);
1331 if (!netif_running(br->dev) || 1418 if (!netif_running(br->dev) ||
1332 (port && port->state == BR_STATE_DISABLED) || 1419 (port && port->state == BR_STATE_DISABLED) ||
1333 timer_pending(&querier->timer)) 1420 timer_pending(&other_query->timer))
1334 goto out; 1421 goto out;
1335 1422
1336 mdb = mlock_dereference(br->mdb, br); 1423 mdb = mlock_dereference(br->mdb, br);
@@ -1344,7 +1431,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
1344 time = jiffies + br->multicast_last_member_count * 1431 time = jiffies + br->multicast_last_member_count *
1345 br->multicast_last_member_interval; 1432 br->multicast_last_member_interval;
1346 1433
1347 mod_timer(&query->timer, time); 1434 mod_timer(&own_query->timer, time);
1348 1435
1349 for (p = mlock_dereference(mp->ports, br); 1436 for (p = mlock_dereference(mp->ports, br);
1350 p != NULL; 1437 p != NULL;
@@ -1425,17 +1512,19 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
1425 __u16 vid) 1512 __u16 vid)
1426{ 1513{
1427 struct br_ip br_group; 1514 struct br_ip br_group;
1428 struct bridge_mcast_query *query = port ? &port->ip4_query : 1515 struct bridge_mcast_own_query *own_query;
1429 &br->ip4_query;
1430 1516
1431 if (ipv4_is_local_multicast(group)) 1517 if (ipv4_is_local_multicast(group))
1432 return; 1518 return;
1433 1519
1520 own_query = port ? &port->ip4_own_query : &br->ip4_own_query;
1521
1434 br_group.u.ip4 = group; 1522 br_group.u.ip4 = group;
1435 br_group.proto = htons(ETH_P_IP); 1523 br_group.proto = htons(ETH_P_IP);
1436 br_group.vid = vid; 1524 br_group.vid = vid;
1437 1525
1438 br_multicast_leave_group(br, port, &br_group, &br->ip4_querier, query); 1526 br_multicast_leave_group(br, port, &br_group, &br->ip4_other_query,
1527 own_query);
1439} 1528}
1440 1529
1441#if IS_ENABLED(CONFIG_IPV6) 1530#if IS_ENABLED(CONFIG_IPV6)
@@ -1445,18 +1534,19 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
1445 __u16 vid) 1534 __u16 vid)
1446{ 1535{
1447 struct br_ip br_group; 1536 struct br_ip br_group;
1448 struct bridge_mcast_query *query = port ? &port->ip6_query : 1537 struct bridge_mcast_own_query *own_query;
1449 &br->ip6_query;
1450
1451 1538
1452 if (ipv6_addr_is_ll_all_nodes(group)) 1539 if (ipv6_addr_is_ll_all_nodes(group))
1453 return; 1540 return;
1454 1541
1542 own_query = port ? &port->ip6_own_query : &br->ip6_own_query;
1543
1455 br_group.u.ip6 = *group; 1544 br_group.u.ip6 = *group;
1456 br_group.proto = htons(ETH_P_IPV6); 1545 br_group.proto = htons(ETH_P_IPV6);
1457 br_group.vid = vid; 1546 br_group.vid = vid;
1458 1547
1459 br_multicast_leave_group(br, port, &br_group, &br->ip6_querier, query); 1548 br_multicast_leave_group(br, port, &br_group, &br->ip6_other_query,
1549 own_query);
1460} 1550}
1461#endif 1551#endif
1462 1552
@@ -1723,12 +1813,14 @@ int br_multicast_rcv(struct net_bridge *br, struct net_bridge_port *port,
1723} 1813}
1724 1814
1725static void br_multicast_query_expired(struct net_bridge *br, 1815static void br_multicast_query_expired(struct net_bridge *br,
1726 struct bridge_mcast_query *query) 1816 struct bridge_mcast_own_query *query,
1817 struct bridge_mcast_querier *querier)
1727{ 1818{
1728 spin_lock(&br->multicast_lock); 1819 spin_lock(&br->multicast_lock);
1729 if (query->startup_sent < br->multicast_startup_query_count) 1820 if (query->startup_sent < br->multicast_startup_query_count)
1730 query->startup_sent++; 1821 query->startup_sent++;
1731 1822
1823 rcu_assign_pointer(querier, NULL);
1732 br_multicast_send_query(br, NULL, query); 1824 br_multicast_send_query(br, NULL, query);
1733 spin_unlock(&br->multicast_lock); 1825 spin_unlock(&br->multicast_lock);
1734} 1826}
@@ -1737,7 +1829,7 @@ static void br_ip4_multicast_query_expired(unsigned long data)
1737{ 1829{
1738 struct net_bridge *br = (void *)data; 1830 struct net_bridge *br = (void *)data;
1739 1831
1740 br_multicast_query_expired(br, &br->ip4_query); 1832 br_multicast_query_expired(br, &br->ip4_own_query, &br->ip4_querier);
1741} 1833}
1742 1834
1743#if IS_ENABLED(CONFIG_IPV6) 1835#if IS_ENABLED(CONFIG_IPV6)
@@ -1745,7 +1837,7 @@ static void br_ip6_multicast_query_expired(unsigned long data)
1745{ 1837{
1746 struct net_bridge *br = (void *)data; 1838 struct net_bridge *br = (void *)data;
1747 1839
1748 br_multicast_query_expired(br, &br->ip6_query); 1840 br_multicast_query_expired(br, &br->ip6_own_query, &br->ip6_querier);
1749} 1841}
1750#endif 1842#endif
1751 1843
@@ -1767,28 +1859,30 @@ void br_multicast_init(struct net_bridge *br)
1767 br->multicast_querier_interval = 255 * HZ; 1859 br->multicast_querier_interval = 255 * HZ;
1768 br->multicast_membership_interval = 260 * HZ; 1860 br->multicast_membership_interval = 260 * HZ;
1769 1861
1770 br->ip4_querier.delay_time = 0; 1862 br->ip4_other_query.delay_time = 0;
1863 br->ip4_querier.port = NULL;
1771#if IS_ENABLED(CONFIG_IPV6) 1864#if IS_ENABLED(CONFIG_IPV6)
1772 br->ip6_querier.delay_time = 0; 1865 br->ip6_other_query.delay_time = 0;
1866 br->ip6_querier.port = NULL;
1773#endif 1867#endif
1774 1868
1775 spin_lock_init(&br->multicast_lock); 1869 spin_lock_init(&br->multicast_lock);
1776 setup_timer(&br->multicast_router_timer, 1870 setup_timer(&br->multicast_router_timer,
1777 br_multicast_local_router_expired, 0); 1871 br_multicast_local_router_expired, 0);
1778 setup_timer(&br->ip4_querier.timer, br_ip4_multicast_querier_expired, 1872 setup_timer(&br->ip4_other_query.timer,
1779 (unsigned long)br); 1873 br_ip4_multicast_querier_expired, (unsigned long)br);
1780 setup_timer(&br->ip4_query.timer, br_ip4_multicast_query_expired, 1874 setup_timer(&br->ip4_own_query.timer, br_ip4_multicast_query_expired,
1781 (unsigned long)br); 1875 (unsigned long)br);
1782#if IS_ENABLED(CONFIG_IPV6) 1876#if IS_ENABLED(CONFIG_IPV6)
1783 setup_timer(&br->ip6_querier.timer, br_ip6_multicast_querier_expired, 1877 setup_timer(&br->ip6_other_query.timer,
1784 (unsigned long)br); 1878 br_ip6_multicast_querier_expired, (unsigned long)br);
1785 setup_timer(&br->ip6_query.timer, br_ip6_multicast_query_expired, 1879 setup_timer(&br->ip6_own_query.timer, br_ip6_multicast_query_expired,
1786 (unsigned long)br); 1880 (unsigned long)br);
1787#endif 1881#endif
1788} 1882}
1789 1883
1790static void __br_multicast_open(struct net_bridge *br, 1884static void __br_multicast_open(struct net_bridge *br,
1791 struct bridge_mcast_query *query) 1885 struct bridge_mcast_own_query *query)
1792{ 1886{
1793 query->startup_sent = 0; 1887 query->startup_sent = 0;
1794 1888
@@ -1800,9 +1894,9 @@ static void __br_multicast_open(struct net_bridge *br,
1800 1894
1801void br_multicast_open(struct net_bridge *br) 1895void br_multicast_open(struct net_bridge *br)
1802{ 1896{
1803 __br_multicast_open(br, &br->ip4_query); 1897 __br_multicast_open(br, &br->ip4_own_query);
1804#if IS_ENABLED(CONFIG_IPV6) 1898#if IS_ENABLED(CONFIG_IPV6)
1805 __br_multicast_open(br, &br->ip6_query); 1899 __br_multicast_open(br, &br->ip6_own_query);
1806#endif 1900#endif
1807} 1901}
1808 1902
@@ -1815,11 +1909,11 @@ void br_multicast_stop(struct net_bridge *br)
1815 int i; 1909 int i;
1816 1910
1817 del_timer_sync(&br->multicast_router_timer); 1911 del_timer_sync(&br->multicast_router_timer);
1818 del_timer_sync(&br->ip4_querier.timer); 1912 del_timer_sync(&br->ip4_other_query.timer);
1819 del_timer_sync(&br->ip4_query.timer); 1913 del_timer_sync(&br->ip4_own_query.timer);
1820#if IS_ENABLED(CONFIG_IPV6) 1914#if IS_ENABLED(CONFIG_IPV6)
1821 del_timer_sync(&br->ip6_querier.timer); 1915 del_timer_sync(&br->ip6_other_query.timer);
1822 del_timer_sync(&br->ip6_query.timer); 1916 del_timer_sync(&br->ip6_own_query.timer);
1823#endif 1917#endif
1824 1918
1825 spin_lock_bh(&br->multicast_lock); 1919 spin_lock_bh(&br->multicast_lock);
@@ -1923,7 +2017,7 @@ unlock:
1923} 2017}
1924 2018
1925static void br_multicast_start_querier(struct net_bridge *br, 2019static void br_multicast_start_querier(struct net_bridge *br,
1926 struct bridge_mcast_query *query) 2020 struct bridge_mcast_own_query *query)
1927{ 2021{
1928 struct net_bridge_port *port; 2022 struct net_bridge_port *port;
1929 2023
@@ -1934,11 +2028,11 @@ static void br_multicast_start_querier(struct net_bridge *br,
1934 port->state == BR_STATE_BLOCKING) 2028 port->state == BR_STATE_BLOCKING)
1935 continue; 2029 continue;
1936 2030
1937 if (query == &br->ip4_query) 2031 if (query == &br->ip4_own_query)
1938 br_multicast_enable(&port->ip4_query); 2032 br_multicast_enable(&port->ip4_own_query);
1939#if IS_ENABLED(CONFIG_IPV6) 2033#if IS_ENABLED(CONFIG_IPV6)
1940 else 2034 else
1941 br_multicast_enable(&port->ip6_query); 2035 br_multicast_enable(&port->ip6_own_query);
1942#endif 2036#endif
1943 } 2037 }
1944} 2038}
@@ -1974,9 +2068,9 @@ rollback:
1974 goto rollback; 2068 goto rollback;
1975 } 2069 }
1976 2070
1977 br_multicast_start_querier(br, &br->ip4_query); 2071 br_multicast_start_querier(br, &br->ip4_own_query);
1978#if IS_ENABLED(CONFIG_IPV6) 2072#if IS_ENABLED(CONFIG_IPV6)
1979 br_multicast_start_querier(br, &br->ip6_query); 2073 br_multicast_start_querier(br, &br->ip6_own_query);
1980#endif 2074#endif
1981 2075
1982unlock: 2076unlock:
@@ -2001,16 +2095,16 @@ int br_multicast_set_querier(struct net_bridge *br, unsigned long val)
2001 2095
2002 max_delay = br->multicast_query_response_interval; 2096 max_delay = br->multicast_query_response_interval;
2003 2097
2004 if (!timer_pending(&br->ip4_querier.timer)) 2098 if (!timer_pending(&br->ip4_other_query.timer))
2005 br->ip4_querier.delay_time = jiffies + max_delay; 2099 br->ip4_other_query.delay_time = jiffies + max_delay;
2006 2100
2007 br_multicast_start_querier(br, &br->ip4_query); 2101 br_multicast_start_querier(br, &br->ip4_own_query);
2008 2102
2009#if IS_ENABLED(CONFIG_IPV6) 2103#if IS_ENABLED(CONFIG_IPV6)
2010 if (!timer_pending(&br->ip6_querier.timer)) 2104 if (!timer_pending(&br->ip6_other_query.timer))
2011 br->ip6_querier.delay_time = jiffies + max_delay; 2105 br->ip6_other_query.delay_time = jiffies + max_delay;
2012 2106
2013 br_multicast_start_querier(br, &br->ip6_query); 2107 br_multicast_start_querier(br, &br->ip6_own_query);
2014#endif 2108#endif
2015 2109
2016unlock: 2110unlock:
@@ -2061,3 +2155,107 @@ unlock:
2061 2155
2062 return err; 2156 return err;
2063} 2157}
2158
2159/**
2160 * br_multicast_list_adjacent - Returns snooped multicast addresses
2161 * @dev: The bridge port adjacent to which to retrieve addresses
2162 * @br_ip_list: The list to store found, snooped multicast IP addresses in
2163 *
2164 * Creates a list of IP addresses (struct br_ip_list) sensed by the multicast
2165 * snooping feature on all bridge ports of dev's bridge device, excluding
2166 * the addresses from dev itself.
2167 *
2168 * Returns the number of items added to br_ip_list.
2169 *
2170 * Notes:
2171 * - br_ip_list needs to be initialized by caller
2172 * - br_ip_list might contain duplicates in the end
2173 * (needs to be taken care of by caller)
2174 * - br_ip_list needs to be freed by caller
2175 */
2176int br_multicast_list_adjacent(struct net_device *dev,
2177 struct list_head *br_ip_list)
2178{
2179 struct net_bridge *br;
2180 struct net_bridge_port *port;
2181 struct net_bridge_port_group *group;
2182 struct br_ip_list *entry;
2183 int count = 0;
2184
2185 rcu_read_lock();
2186 if (!br_ip_list || !br_port_exists(dev))
2187 goto unlock;
2188
2189 port = br_port_get_rcu(dev);
2190 if (!port || !port->br)
2191 goto unlock;
2192
2193 br = port->br;
2194
2195 list_for_each_entry_rcu(port, &br->port_list, list) {
2196 if (!port->dev || port->dev == dev)
2197 continue;
2198
2199 hlist_for_each_entry_rcu(group, &port->mglist, mglist) {
2200 entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
2201 if (!entry)
2202 goto unlock;
2203
2204 entry->addr = group->addr;
2205 list_add(&entry->list, br_ip_list);
2206 count++;
2207 }
2208 }
2209
2210unlock:
2211 rcu_read_unlock();
2212 return count;
2213}
2214EXPORT_SYMBOL_GPL(br_multicast_list_adjacent);
2215
2216/**
2217 * br_multicast_has_querier_adjacent - Checks for a querier behind a bridge port
2218 * @dev: The bridge port adjacent to which to check for a querier
2219 * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6
2220 *
2221 * Checks whether the given interface has a bridge on top and if so returns
2222 * true if a selected querier is behind one of the other ports of this
2223 * bridge. Otherwise returns false.
2224 */
2225bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto)
2226{
2227 struct net_bridge *br;
2228 struct net_bridge_port *port;
2229 bool ret = false;
2230
2231 rcu_read_lock();
2232 if (!br_port_exists(dev))
2233 goto unlock;
2234
2235 port = br_port_get_rcu(dev);
2236 if (!port || !port->br)
2237 goto unlock;
2238
2239 br = port->br;
2240
2241 switch (proto) {
2242 case ETH_P_IP:
2243 if (!timer_pending(&br->ip4_other_query.timer) ||
2244 rcu_dereference(br->ip4_querier.port) == port)
2245 goto unlock;
2246 break;
2247 case ETH_P_IPV6:
2248 if (!timer_pending(&br->ip6_other_query.timer) ||
2249 rcu_dereference(br->ip6_querier.port) == port)
2250 goto unlock;
2251 break;
2252 default:
2253 goto unlock;
2254 }
2255
2256 ret = true;
2257unlock:
2258 rcu_read_unlock();
2259 return ret;
2260}
2261EXPORT_SYMBOL_GPL(br_multicast_has_querier_adjacent);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bc17210d4c52..8346e9504cdb 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -54,30 +54,24 @@ struct mac_addr
54 unsigned char addr[ETH_ALEN]; 54 unsigned char addr[ETH_ALEN];
55}; 55};
56 56
57struct br_ip
58{
59 union {
60 __be32 ip4;
61#if IS_ENABLED(CONFIG_IPV6)
62 struct in6_addr ip6;
63#endif
64 } u;
65 __be16 proto;
66 __u16 vid;
67};
68
69#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 57#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
70/* our own querier */ 58/* our own querier */
71struct bridge_mcast_query { 59struct bridge_mcast_own_query {
72 struct timer_list timer; 60 struct timer_list timer;
73 u32 startup_sent; 61 u32 startup_sent;
74}; 62};
75 63
76/* other querier */ 64/* other querier */
77struct bridge_mcast_querier { 65struct bridge_mcast_other_query {
78 struct timer_list timer; 66 struct timer_list timer;
79 unsigned long delay_time; 67 unsigned long delay_time;
80}; 68};
69
70/* selected querier */
71struct bridge_mcast_querier {
72 struct br_ip addr;
73 struct net_bridge_port __rcu *port;
74};
81#endif 75#endif
82 76
83struct net_port_vlans { 77struct net_port_vlans {
@@ -178,9 +172,9 @@ struct net_bridge_port
178#define BR_PROMISC 0x00000080 172#define BR_PROMISC 0x00000080
179 173
180#ifdef CONFIG_BRIDGE_IGMP_SNOOPING 174#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
181 struct bridge_mcast_query ip4_query; 175 struct bridge_mcast_own_query ip4_own_query;
182#if IS_ENABLED(CONFIG_IPV6) 176#if IS_ENABLED(CONFIG_IPV6)
183 struct bridge_mcast_query ip6_query; 177 struct bridge_mcast_own_query ip6_own_query;
184#endif /* IS_ENABLED(CONFIG_IPV6) */ 178#endif /* IS_ENABLED(CONFIG_IPV6) */
185 unsigned char multicast_router; 179 unsigned char multicast_router;
186 struct timer_list multicast_router_timer; 180 struct timer_list multicast_router_timer;
@@ -282,11 +276,13 @@ struct net_bridge
282 struct hlist_head router_list; 276 struct hlist_head router_list;
283 277
284 struct timer_list multicast_router_timer; 278 struct timer_list multicast_router_timer;
279 struct bridge_mcast_other_query ip4_other_query;
280 struct bridge_mcast_own_query ip4_own_query;
285 struct bridge_mcast_querier ip4_querier; 281 struct bridge_mcast_querier ip4_querier;
286 struct bridge_mcast_query ip4_query;
287#if IS_ENABLED(CONFIG_IPV6) 282#if IS_ENABLED(CONFIG_IPV6)
283 struct bridge_mcast_other_query ip6_other_query;
284 struct bridge_mcast_own_query ip6_own_query;
288 struct bridge_mcast_querier ip6_querier; 285 struct bridge_mcast_querier ip6_querier;
289 struct bridge_mcast_query ip6_query;
290#endif /* IS_ENABLED(CONFIG_IPV6) */ 286#endif /* IS_ENABLED(CONFIG_IPV6) */
291#endif 287#endif
292 288
@@ -493,7 +489,7 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
493 489
494static inline bool 490static inline bool
495__br_multicast_querier_exists(struct net_bridge *br, 491__br_multicast_querier_exists(struct net_bridge *br,
496 struct bridge_mcast_querier *querier) 492 struct bridge_mcast_other_query *querier)
497{ 493{
498 return time_is_before_jiffies(querier->delay_time) && 494 return time_is_before_jiffies(querier->delay_time) &&
499 (br->multicast_querier || timer_pending(&querier->timer)); 495 (br->multicast_querier || timer_pending(&querier->timer));
@@ -504,10 +500,10 @@ static inline bool br_multicast_querier_exists(struct net_bridge *br,
504{ 500{
505 switch (eth->h_proto) { 501 switch (eth->h_proto) {
506 case (htons(ETH_P_IP)): 502 case (htons(ETH_P_IP)):
507 return __br_multicast_querier_exists(br, &br->ip4_querier); 503 return __br_multicast_querier_exists(br, &br->ip4_other_query);
508#if IS_ENABLED(CONFIG_IPV6) 504#if IS_ENABLED(CONFIG_IPV6)
509 case (htons(ETH_P_IPV6)): 505 case (htons(ETH_P_IPV6)):
510 return __br_multicast_querier_exists(br, &br->ip6_querier); 506 return __br_multicast_querier_exists(br, &br->ip6_other_query);
511#endif 507#endif
512 default: 508 default:
513 return false; 509 return false;