145 lines
5.5 KiB
Diff
145 lines
5.5 KiB
Diff
From: Linus Lüssing <linus.luessing@c0d3.blue>
|
|
Date: Tue, 15 Sep 2020 09:54:08 +0200
|
|
Subject: batman-adv: mcast: fix duplicate mcast packets in BLA backbone from LAN
|
|
|
|
Scenario:
|
|
* Multicast frame send from a BLA backbone (multiple nodes with
|
|
their bat0 bridged together, with BLA enabled)
|
|
|
|
Issue:
|
|
* BLA backbone nodes receive the frame multiple times on bat0
|
|
|
|
For multicast frames received via batman-adv broadcast packets the
|
|
originator of the broadcast packet is checked before decapsulating and
|
|
forwarding the frame to bat0 (batadv_bla_is_backbone_gw()->
|
|
batadv_recv_bcast_packet()). If it came from a node which shares the
|
|
same BLA backbone with us then it is not forwarded to bat0 to avoid a
|
|
loop.
|
|
|
|
When sending a multicast frame in a non-4-address batman-adv unicast
|
|
packet we are currently missing this check - and cannot do so because
|
|
the batman-adv unicast packet has no originator address field.
|
|
|
|
However, we can simply fix this on the sender side by only sending the
|
|
multicast frame via unicasts to interested nodes which do not share the
|
|
same BLA backbone with us. This also nicely avoids some unnecessary
|
|
transmissions on mesh side.
|
|
|
|
Note that no infinite loop was observed, probably because of dropping
|
|
via batadv_interface_tx()->batadv_bla_tx(). However the duplicates still
|
|
utterly confuse switches/bridges, ICMPv6 duplicate address detection and
|
|
neighbor discovery and therefore leads to long delays before being able
|
|
to establish TCP connections, for instance. And it also leads to the Linux
|
|
bridge printing messages like:
|
|
"br-lan: received packet on eth1 with own address as source address ..."
|
|
|
|
Fixes: 405cc1e5a81e ("batman-adv: Modified forwarding behaviour for multicast packets")
|
|
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
|
|
Acked-by: Simon Wunderlich <sw@simonwunderlich.de>
|
|
Signed-off-by: Sven Eckelmann <sven@narfation.org>
|
|
|
|
Origin: backport, https://git.open-mesh.org/batman-adv.git/commit/3c39a2455a5be02ecceeaf1a15976bddd611392e
|
|
|
|
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
|
|
index 39640d3d6fbdf8244344db6e79f2d769eb0972d9..764c304ffa5f6dc976050fa6b6f6e0891981c4f4 100644
|
|
--- a/net/batman-adv/multicast.c
|
|
+++ b/net/batman-adv/multicast.c
|
|
@@ -62,10 +62,12 @@
|
|
#include <uapi/linux/batadv_packet.h>
|
|
#include <uapi/linux/batman_adv.h>
|
|
|
|
+#include "bridge_loop_avoidance.h"
|
|
#include "hard-interface.h"
|
|
#include "hash.h"
|
|
#include "log.h"
|
|
#include "netlink.h"
|
|
+#include "send.h"
|
|
#include "soft-interface.h"
|
|
#include "translation-table.h"
|
|
#include "tvlv.h"
|
|
@@ -1027,6 +1029,35 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
|
}
|
|
}
|
|
|
|
+/**
|
|
+ * batadv_mcast_forw_send_orig() - send a multicast packet to an originator
|
|
+ * @bat_priv: the bat priv with all the soft interface information
|
|
+ * @skb: the multicast packet to send
|
|
+ * @vid: the vlan identifier
|
|
+ * @orig_node: the originator to send the packet to
|
|
+ *
|
|
+ * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
|
|
+ */
|
|
+int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
|
|
+ struct sk_buff *skb,
|
|
+ unsigned short vid,
|
|
+ struct batadv_orig_node *orig_node)
|
|
+{
|
|
+ /* Avoid sending multicast-in-unicast packets to other BLA
|
|
+ * gateways - they already got the frame from the LAN side
|
|
+ * we share with them.
|
|
+ * TODO: Refactor to take BLA into account earlier, to avoid
|
|
+ * reducing the mcast_fanout count.
|
|
+ */
|
|
+ if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid)) {
|
|
+ dev_kfree_skb(skb);
|
|
+ return NET_XMIT_SUCCESS;
|
|
+ }
|
|
+
|
|
+ return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST, 0,
|
|
+ orig_node, vid);
|
|
+}
|
|
+
|
|
/**
|
|
* batadv_mcast_want_unsnoop_update() - update unsnoop counter and list
|
|
* @bat_priv: the bat priv with all the soft interface information
|
|
diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h
|
|
index 3b04ab13f0eb1044454315c04e75a22ce4351afd..6f9f3813fc59a8e8798b71297c8d8f9ef50b5e72 100644
|
|
--- a/net/batman-adv/multicast.h
|
|
+++ b/net/batman-adv/multicast.h
|
|
@@ -51,6 +51,11 @@ enum batadv_forw_mode
|
|
batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
|
|
struct batadv_orig_node **mcast_single_orig);
|
|
|
|
+int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
|
|
+ struct sk_buff *skb,
|
|
+ unsigned short vid,
|
|
+ struct batadv_orig_node *orig_node);
|
|
+
|
|
void batadv_mcast_init(struct batadv_priv *bat_priv);
|
|
|
|
int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset);
|
|
@@ -78,6 +83,16 @@ static inline int batadv_mcast_init(struct batadv_priv *bat_priv)
|
|
return 0;
|
|
}
|
|
|
|
+static inline int
|
|
+batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
|
|
+ struct sk_buff *skb,
|
|
+ unsigned short vid,
|
|
+ struct batadv_orig_node *orig_node)
|
|
+{
|
|
+ kfree_skb(skb);
|
|
+ return NET_XMIT_DROP;
|
|
+}
|
|
+
|
|
static inline int
|
|
batadv_mcast_mesh_info_put(struct sk_buff *msg, struct batadv_priv *bat_priv)
|
|
{
|
|
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
|
|
index 97e28907a0acbb3d64d8ceebf7b1df13dc396300..267f6e6c802f1a7d3eb41a0f3aa2142ca3b21414 100644
|
|
--- a/net/batman-adv/soft-interface.c
|
|
+++ b/net/batman-adv/soft-interface.c
|
|
@@ -367,9 +367,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
|
|
goto dropped;
|
|
ret = batadv_send_skb_via_gw(bat_priv, skb, vid);
|
|
} else if (mcast_single_orig) {
|
|
- ret = batadv_send_skb_unicast(bat_priv, skb,
|
|
- BATADV_UNICAST, 0,
|
|
- mcast_single_orig, vid);
|
|
+ ret = batadv_mcast_forw_send_orig(bat_priv, skb, vid,
|
|
+ mcast_single_orig);
|
|
} else {
|
|
if (batadv_dat_snoop_outgoing_arp_request(bat_priv,
|
|
skb))
|