aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_multicast.c101
-rw-r--r--net/bridge/br_private.h7
2 files changed, 95 insertions, 13 deletions
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 5ccac62b4005..b3f17c9b4d06 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -789,6 +789,18 @@ static void br_ip6_multicast_querier_expired(unsigned long data)
789} 789}
790#endif 790#endif
791 791
792static void br_multicast_select_own_querier(struct net_bridge *br,
793 struct br_ip *ip,
794 struct sk_buff *skb)
795{
796 if (ip->proto == htons(ETH_P_IP))
797 br->ip4_querier.addr.u.ip4 = ip_hdr(skb)->saddr;
798#if IS_ENABLED(CONFIG_IPV6)
799 else
800 br->ip6_querier.addr.u.ip6 = ipv6_hdr(skb)->saddr;
801#endif
802}
803
792static void __br_multicast_send_query(struct net_bridge *br, 804static void __br_multicast_send_query(struct net_bridge *br,
793 struct net_bridge_port *port, 805 struct net_bridge_port *port,
794 struct br_ip *ip) 806 struct br_ip *ip)
@@ -804,8 +816,10 @@ static void __br_multicast_send_query(struct net_bridge *br,
804 skb->dev = port->dev; 816 skb->dev = port->dev;
805 NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, 817 NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
806 dev_queue_xmit); 818 dev_queue_xmit);
807 } else 819 } else {
820 br_multicast_select_own_querier(br, ip, skb);
808 netif_rx(skb); 821 netif_rx(skb);
822 }
809} 823}
810 824
811static void br_multicast_send_query(struct net_bridge *br, 825static void br_multicast_send_query(struct net_bridge *br,
@@ -1065,6 +1079,62 @@ static int br_ip6_multicast_mld2_report(struct net_bridge *br,
1065} 1079}
1066#endif 1080#endif
1067 1081
1082static bool br_ip4_multicast_select_querier(struct net_bridge *br,
1083 __be32 saddr)
1084{
1085 if (!timer_pending(&br->ip4_own_query.timer) &&
1086 !timer_pending(&br->ip4_other_query.timer))
1087 goto update;
1088
1089 if (!br->ip4_querier.addr.u.ip4)
1090 goto update;
1091
1092 if (ntohl(saddr) <= ntohl(br->ip4_querier.addr.u.ip4))
1093 goto update;
1094
1095 return false;
1096
1097update:
1098 br->ip4_querier.addr.u.ip4 = saddr;
1099
1100 return true;
1101}
1102
1103#if IS_ENABLED(CONFIG_IPV6)
1104static bool br_ip6_multicast_select_querier(struct net_bridge *br,
1105 struct in6_addr *saddr)
1106{
1107 if (!timer_pending(&br->ip6_own_query.timer) &&
1108 !timer_pending(&br->ip6_other_query.timer))
1109 goto update;
1110
1111 if (ipv6_addr_cmp(saddr, &br->ip6_querier.addr.u.ip6) <= 0)
1112 goto update;
1113
1114 return false;
1115
1116update:
1117 br->ip6_querier.addr.u.ip6 = *saddr;
1118
1119 return true;
1120}
1121#endif
1122
1123static bool br_multicast_select_querier(struct net_bridge *br,
1124 struct br_ip *saddr)
1125{
1126 switch (saddr->proto) {
1127 case htons(ETH_P_IP):
1128 return br_ip4_multicast_select_querier(br, saddr->u.ip4);
1129#if IS_ENABLED(CONFIG_IPV6)
1130 case htons(ETH_P_IPV6):
1131 return br_ip6_multicast_select_querier(br, &saddr->u.ip6);
1132#endif
1133 }
1134
1135 return false;
1136}
1137
1068static void 1138static void
1069br_multicast_update_query_timer(struct net_bridge *br, 1139br_multicast_update_query_timer(struct net_bridge *br,
1070 struct bridge_mcast_other_query *query, 1140 struct bridge_mcast_other_query *query,
@@ -1127,15 +1197,13 @@ timer:
1127static void br_multicast_query_received(struct net_bridge *br, 1197static void br_multicast_query_received(struct net_bridge *br,
1128 struct net_bridge_port *port, 1198 struct net_bridge_port *port,
1129 struct bridge_mcast_other_query *query, 1199 struct bridge_mcast_other_query *query,
1130 int saddr, 1200 struct br_ip *saddr,
1131 bool is_general_query,
1132 unsigned long max_delay) 1201 unsigned long max_delay)
1133{ 1202{
1134 if (saddr && is_general_query) 1203 if (!br_multicast_select_querier(br, saddr))
1135 br_multicast_update_query_timer(br, query, max_delay);
1136 else if (timer_pending(&query->timer))
1137 return; 1204 return;
1138 1205
1206 br_multicast_update_query_timer(br, query, max_delay);
1139 br_multicast_mark_router(br, port); 1207 br_multicast_mark_router(br, port);
1140} 1208}
1141 1209
@@ -1150,6 +1218,7 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1150 struct igmpv3_query *ih3; 1218 struct igmpv3_query *ih3;
1151 struct net_bridge_port_group *p; 1219 struct net_bridge_port_group *p;
1152 struct net_bridge_port_group __rcu **pp; 1220 struct net_bridge_port_group __rcu **pp;
1221 struct br_ip saddr;
1153 unsigned long max_delay; 1222 unsigned long max_delay;
1154 unsigned long now = jiffies; 1223 unsigned long now = jiffies;
1155 __be32 group; 1224 __be32 group;
@@ -1191,11 +1260,14 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1191 goto out; 1260 goto out;
1192 } 1261 }
1193 1262
1194 br_multicast_query_received(br, port, &br->ip4_other_query, 1263 if (!group) {
1195 !!iph->saddr, !group, max_delay); 1264 saddr.proto = htons(ETH_P_IP);
1265 saddr.u.ip4 = iph->saddr;
1196 1266
1197 if (!group) 1267 br_multicast_query_received(br, port, &br->ip4_other_query,
1268 &saddr, max_delay);
1198 goto out; 1269 goto out;
1270 }
1199 1271
1200 mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid); 1272 mp = br_mdb_ip4_get(mlock_dereference(br->mdb, br), group, vid);
1201 if (!mp) 1273 if (!mp)
@@ -1235,6 +1307,7 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1235 struct mld2_query *mld2q; 1307 struct mld2_query *mld2q;
1236 struct net_bridge_port_group *p; 1308 struct net_bridge_port_group *p;
1237 struct net_bridge_port_group __rcu **pp; 1309 struct net_bridge_port_group __rcu **pp;
1310 struct br_ip saddr;
1238 unsigned long max_delay; 1311 unsigned long max_delay;
1239 unsigned long now = jiffies; 1312 unsigned long now = jiffies;
1240 const struct in6_addr *group = NULL; 1313 const struct in6_addr *group = NULL;
@@ -1283,12 +1356,14 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1283 goto out; 1356 goto out;
1284 } 1357 }
1285 1358
1286 br_multicast_query_received(br, port, &br->ip6_other_query, 1359 if (is_general_query) {
1287 !ipv6_addr_any(&ip6h->saddr), 1360 saddr.proto = htons(ETH_P_IPV6);
1288 is_general_query, max_delay); 1361 saddr.u.ip6 = ip6h->saddr;
1289 1362
1290 if (!group) 1363 br_multicast_query_received(br, port, &br->ip6_other_query,
1364 &saddr, max_delay);
1291 goto out; 1365 goto out;
1366 }
1292 1367
1293 mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid); 1368 mp = br_mdb_ip6_get(mlock_dereference(br->mdb, br), group, vid);
1294 if (!mp) 1369 if (!mp)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 2469aeeda1ec..97c5e46dde72 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -78,6 +78,11 @@ struct bridge_mcast_other_query {
78 struct timer_list timer; 78 struct timer_list timer;
79 unsigned long delay_time; 79 unsigned long delay_time;
80}; 80};
81
82/* selected querier */
83struct bridge_mcast_querier {
84 struct br_ip addr;
85};
81#endif 86#endif
82 87
83struct net_port_vlans { 88struct net_port_vlans {
@@ -284,9 +289,11 @@ struct net_bridge
284 struct timer_list multicast_router_timer; 289 struct timer_list multicast_router_timer;
285 struct bridge_mcast_other_query ip4_other_query; 290 struct bridge_mcast_other_query ip4_other_query;
286 struct bridge_mcast_own_query ip4_own_query; 291 struct bridge_mcast_own_query ip4_own_query;
292 struct bridge_mcast_querier ip4_querier;
287#if IS_ENABLED(CONFIG_IPV6) 293#if IS_ENABLED(CONFIG_IPV6)
288 struct bridge_mcast_other_query ip6_other_query; 294 struct bridge_mcast_other_query ip6_other_query;
289 struct bridge_mcast_own_query ip6_own_query; 295 struct bridge_mcast_own_query ip6_own_query;
296 struct bridge_mcast_querier ip6_querier;
290#endif /* IS_ENABLED(CONFIG_IPV6) */ 297#endif /* IS_ENABLED(CONFIG_IPV6) */
291#endif 298#endif
292 299