Merge pull request #624 from ecsv/batadv-for-18.06
[feed/routing.git] / batman-adv / patches / 0052-batman-adv-mcast-fix-duplicate-mcast-packets-in-BLA-.patch
1 From: Linus Lüssing <linus.luessing@c0d3.blue>
2 Date: Tue, 15 Sep 2020 09:54:08 +0200
3 Subject: batman-adv: mcast: fix duplicate mcast packets in BLA backbone from LAN
4
5 Scenario:
6 * Multicast frame send from a BLA backbone (multiple nodes with
7 their bat0 bridged together, with BLA enabled)
8
9 Issue:
10 * BLA backbone nodes receive the frame multiple times on bat0
11
12 For multicast frames received via batman-adv broadcast packets the
13 originator of the broadcast packet is checked before decapsulating and
14 forwarding the frame to bat0 (batadv_bla_is_backbone_gw()->
15 batadv_recv_bcast_packet()). If it came from a node which shares the
16 same BLA backbone with us then it is not forwarded to bat0 to avoid a
17 loop.
18
19 When sending a multicast frame in a non-4-address batman-adv unicast
20 packet we are currently missing this check - and cannot do so because
21 the batman-adv unicast packet has no originator address field.
22
23 However, we can simply fix this on the sender side by only sending the
24 multicast frame via unicasts to interested nodes which do not share the
25 same BLA backbone with us. This also nicely avoids some unnecessary
26 transmissions on mesh side.
27
28 Note that no infinite loop was observed, probably because of dropping
29 via batadv_interface_tx()->batadv_bla_tx(). However the duplicates still
30 utterly confuse switches/bridges, ICMPv6 duplicate address detection and
31 neighbor discovery and therefore leads to long delays before being able
32 to establish TCP connections, for instance. And it also leads to the Linux
33 bridge printing messages like:
34 "br-lan: received packet on eth1 with own address as source address ..."
35
36 Fixes: 405cc1e5a81e ("batman-adv: Modified forwarding behaviour for multicast packets")
37 Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
38 Acked-by: Simon Wunderlich <sw@simonwunderlich.de>
39 Signed-off-by: Sven Eckelmann <sven@narfation.org>
40
41 Origin: backport, https://git.open-mesh.org/batman-adv.git/commit/3c39a2455a5be02ecceeaf1a15976bddd611392e
42
43 diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
44 index 39640d3d6fbdf8244344db6e79f2d769eb0972d9..764c304ffa5f6dc976050fa6b6f6e0891981c4f4 100644
45 --- a/net/batman-adv/multicast.c
46 +++ b/net/batman-adv/multicast.c
47 @@ -62,10 +62,12 @@
48 #include <uapi/linux/batadv_packet.h>
49 #include <uapi/linux/batman_adv.h>
50
51 +#include "bridge_loop_avoidance.h"
52 #include "hard-interface.h"
53 #include "hash.h"
54 #include "log.h"
55 #include "netlink.h"
56 +#include "send.h"
57 #include "soft-interface.h"
58 #include "translation-table.h"
59 #include "tvlv.h"
60 @@ -1027,6 +1029,35 @@ batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
61 }
62 }
63
64 +/**
65 + * batadv_mcast_forw_send_orig() - send a multicast packet to an originator
66 + * @bat_priv: the bat priv with all the soft interface information
67 + * @skb: the multicast packet to send
68 + * @vid: the vlan identifier
69 + * @orig_node: the originator to send the packet to
70 + *
71 + * Return: NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise.
72 + */
73 +int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
74 + struct sk_buff *skb,
75 + unsigned short vid,
76 + struct batadv_orig_node *orig_node)
77 +{
78 + /* Avoid sending multicast-in-unicast packets to other BLA
79 + * gateways - they already got the frame from the LAN side
80 + * we share with them.
81 + * TODO: Refactor to take BLA into account earlier, to avoid
82 + * reducing the mcast_fanout count.
83 + */
84 + if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig, vid)) {
85 + dev_kfree_skb(skb);
86 + return NET_XMIT_SUCCESS;
87 + }
88 +
89 + return batadv_send_skb_unicast(bat_priv, skb, BATADV_UNICAST, 0,
90 + orig_node, vid);
91 +}
92 +
93 /**
94 * batadv_mcast_want_unsnoop_update() - update unsnoop counter and list
95 * @bat_priv: the bat priv with all the soft interface information
96 diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h
97 index 3b04ab13f0eb1044454315c04e75a22ce4351afd..6f9f3813fc59a8e8798b71297c8d8f9ef50b5e72 100644
98 --- a/net/batman-adv/multicast.h
99 +++ b/net/batman-adv/multicast.h
100 @@ -51,6 +51,11 @@ enum batadv_forw_mode
101 batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb,
102 struct batadv_orig_node **mcast_single_orig);
103
104 +int batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
105 + struct sk_buff *skb,
106 + unsigned short vid,
107 + struct batadv_orig_node *orig_node);
108 +
109 void batadv_mcast_init(struct batadv_priv *bat_priv);
110
111 int batadv_mcast_flags_seq_print_text(struct seq_file *seq, void *offset);
112 @@ -78,6 +83,16 @@ static inline int batadv_mcast_init(struct batadv_priv *bat_priv)
113 return 0;
114 }
115
116 +static inline int
117 +batadv_mcast_forw_send_orig(struct batadv_priv *bat_priv,
118 + struct sk_buff *skb,
119 + unsigned short vid,
120 + struct batadv_orig_node *orig_node)
121 +{
122 + kfree_skb(skb);
123 + return NET_XMIT_DROP;
124 +}
125 +
126 static inline int
127 batadv_mcast_mesh_info_put(struct sk_buff *msg, struct batadv_priv *bat_priv)
128 {
129 diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
130 index 97e28907a0acbb3d64d8ceebf7b1df13dc396300..267f6e6c802f1a7d3eb41a0f3aa2142ca3b21414 100644
131 --- a/net/batman-adv/soft-interface.c
132 +++ b/net/batman-adv/soft-interface.c
133 @@ -367,9 +367,8 @@ static int batadv_interface_tx(struct sk_buff *skb,
134 goto dropped;
135 ret = batadv_send_skb_via_gw(bat_priv, skb, vid);
136 } else if (mcast_single_orig) {
137 - ret = batadv_send_skb_unicast(bat_priv, skb,
138 - BATADV_UNICAST, 0,
139 - mcast_single_orig, vid);
140 + ret = batadv_mcast_forw_send_orig(bat_priv, skb, vid,
141 + mcast_single_orig);
142 } else {
143 if (batadv_dat_snoop_outgoing_arp_request(bat_priv,
144 skb))