diff options
Diffstat (limited to 'target/linux/generic/patches-4.1/645-bridge_multicast_to_unicast.patch')
-rw-r--r-- | target/linux/generic/patches-4.1/645-bridge_multicast_to_unicast.patch | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/target/linux/generic/patches-4.1/645-bridge_multicast_to_unicast.patch b/target/linux/generic/patches-4.1/645-bridge_multicast_to_unicast.patch index 6915599c6c..bbd8e25447 100644 --- a/target/linux/generic/patches-4.1/645-bridge_multicast_to_unicast.patch +++ b/target/linux/generic/patches-4.1/645-bridge_multicast_to_unicast.patch @@ -305,7 +305,7 @@ rcu_assign_pointer(*pp, p); --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c -@@ -169,6 +169,29 @@ out: +@@ -169,6 +169,34 @@ out: return p; } @@ -316,10 +316,15 @@ + struct sk_buff *skb)) +{ + struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev; ++ const unsigned char *src = eth_hdr(skb)->h_source; + + if (!should_deliver(p, skb)) + return prev; + ++ /* Even with hairpin, no soliloquies - prevent breaking IPv6 DAD */ ++ if (skb->dev == p->dev && ether_addr_equal(src, addr)) ++ return prev; ++ + skb = skb_copy(skb, GFP_ATOMIC); + if (!skb) { + dev->stats.tx_dropped++; @@ -335,7 +340,7 @@ /* called under bridge lock */ static void br_flood(struct net_bridge *br, struct sk_buff *skb, struct sk_buff *skb0, -@@ -241,6 +264,7 @@ static void br_multicast_flood(struct ne +@@ -241,6 +269,7 @@ static void br_multicast_flood(struct ne struct net_bridge_port *prev = NULL; struct net_bridge_port_group *p; struct hlist_node *rp; @@ -343,7 +348,7 @@ rp = rcu_dereference(hlist_first_rcu(&br->router_list)); p = mdst ? rcu_dereference(mdst->ports) : NULL; -@@ -251,10 +275,19 @@ static void br_multicast_flood(struct ne +@@ -251,10 +280,19 @@ static void br_multicast_flood(struct ne rport = rp ? hlist_entry(rp, struct net_bridge_port, rlist) : NULL; |