aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/patches-4.1/645-bridge_multicast_to_unicast.patch
diff options
context:
space:
mode:
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.patch11
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;