Skip to content

Commit

Permalink
bridge: separate querier and query timer into IGMP/IPv4 and MLD/IPv6 …
Browse files Browse the repository at this point in the history
…ones

Currently we would still potentially suffer multicast packet loss if there
is just either an IGMP or an MLD querier: For the former case, we would
possibly drop IPv6 multicast packets, for the latter IPv4 ones. This is
because we are currently assuming that if either an IGMP or MLD querier
is present that the other one is present, too.

This patch makes the behaviour and fix added in
"bridge: disable snooping if there is no querier" (b00589a)
to also work if there is either just an IGMP or an MLD querier on the
link: It refines the deactivation of the snooping to be protocol
specific by using separate timers for the snooped IGMP and MLD queries
as well as separate timers for our internal IGMP and MLD queriers.

Signed-off-by: Linus Lüssing <linus.luessing@web.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
T-X authored and davem330 committed Aug 30, 2013
1 parent 79f9ab7 commit cc0fdd8
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 93 deletions.
2 changes: 1 addition & 1 deletion net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)

mdst = br_mdb_get(br, skb, vid);
if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
br_multicast_querier_exists(br))
br_multicast_querier_exists(br, eth_hdr(skb)))
br_multicast_deliver(mdst, skb);
else
br_flood_deliver(br, skb, false);
Expand Down
2 changes: 1 addition & 1 deletion net/bridge/br_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
} else if (is_multicast_ether_addr(dest)) {
mdst = br_mdb_get(br, skb, vid);
if ((mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) &&
br_multicast_querier_exists(br)) {
br_multicast_querier_exists(br, eth_hdr(skb))) {
if ((mdst && mdst->mglist) ||
br_multicast_is_router(br))
skb2 = skb;
Expand Down
14 changes: 9 additions & 5 deletions net/bridge/br_mdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,16 +414,20 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
if (!netif_running(br->dev) || br->multicast_disabled)
return -EINVAL;

if (timer_pending(&br->multicast_querier_timer))
return -EBUSY;

ip.proto = entry->addr.proto;
if (ip.proto == htons(ETH_P_IP))
if (ip.proto == htons(ETH_P_IP)) {
if (timer_pending(&br->ip4_querier.timer))
return -EBUSY;

ip.u.ip4 = entry->addr.u.ip4;
#if IS_ENABLED(CONFIG_IPV6)
else
} else {
if (timer_pending(&br->ip6_querier.timer))
return -EBUSY;

ip.u.ip6 = entry->addr.u.ip6;
#endif
}

spin_lock_bh(&br->multicast_lock);
mdb = mlock_dereference(br->mdb, br);
Expand Down
Loading

0 comments on commit cc0fdd8

Please sign in to comment.