Merge pull request #624 from ecsv/batadv-for-18.06
[feed/routing.git] / batman-adv / patches / 0053-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:09 +0200
3 Subject: batman-adv: mcast: fix duplicate mcast packets in BLA backbone from mesh
4
5 Scenario:
6 * Multicast frame send from mesh to a BLA backbone (multiple nodes
7 with their bat0 bridged together, with BLA enabled)
8
9 Issue:
10 * BLA backbone nodes receive the frame multiple times on bat0,
11 once from mesh->bat0 and once from each backbone_gw from LAN
12
13 For unicast, a node will send only to the best backbone gateway
14 according to the TQ. However for multicast we currently cannot determine
15 if multiple destination nodes share the same backbone if they don't share
16 the same backbone with us. So we need to keep sending the unicasts to
17 all backbone gateways and let the backbone gateways decide which one
18 will forward the frame. We can use the CLAIM mechanism to make this
19 decision.
20
21 One catch: The batman-adv gateway feature for DHCP packets potentially
22 sends multicast packets in the same batman-adv unicast header as the
23 multicast optimizations code. And we are not allowed to drop those even
24 if we did not claim the source address of the sender, as for such
25 packets there is only this one multicast-in-unicast packet.
26
27 How can we distinguish the two cases?
28
29 The gateway feature uses a batman-adv unicast 4 address header. While
30 the multicast-to-unicasts feature uses a simple, 3 address batman-adv
31 unicast header. So let's use this to distinguish.
32
33 Fixes: e32470167379 ("batman-adv: check incoming packet type for bla")
34 Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
35 Acked-by: Simon Wunderlich <sw@simonwunderlich.de>
36 Signed-off-by: Sven Eckelmann <sven@narfation.org>
37
38 Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/d7665cf8a824c41c61c6e2110ab63d37eb7a8ef7
39
40 diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
41 index 26f590ba31d49a85143f67f1c002a25dc007b594..4dc67a0d081c06507aba87f7bec03488817791b2 100644
42 --- a/net/batman-adv/bridge_loop_avoidance.c
43 +++ b/net/batman-adv/bridge_loop_avoidance.c
44 @@ -1827,7 +1827,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
45 * @bat_priv: the bat priv with all the soft interface information
46 * @skb: the frame to be checked
47 * @vid: the VLAN ID of the frame
48 - * @is_bcast: the packet came in a broadcast packet type.
49 + * @packet_type: the batman packet type this frame came in
50 *
51 * batadv_bla_rx avoidance checks if:
52 * * we have to race for a claim
53 @@ -1839,7 +1839,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
54 * further process the skb.
55 */
56 bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
57 - unsigned short vid, bool is_bcast)
58 + unsigned short vid, int packet_type)
59 {
60 struct batadv_bla_backbone_gw *backbone_gw;
61 struct ethhdr *ethhdr;
62 @@ -1861,9 +1861,24 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
63 goto handled;
64
65 if (unlikely(atomic_read(&bat_priv->bla.num_requests)))
66 - /* don't allow broadcasts while requests are in flight */
67 - if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast)
68 - goto handled;
69 + /* don't allow multicast packets while requests are in flight */
70 + if (is_multicast_ether_addr(ethhdr->h_dest))
71 + /* Both broadcast flooding or multicast-via-unicasts
72 + * delivery might send to multiple backbone gateways
73 + * sharing the same LAN and therefore need to coordinate
74 + * which backbone gateway forwards into the LAN,
75 + * by claiming the payload source address.
76 + *
77 + * Broadcast flooding and multicast-via-unicasts
78 + * delivery use the following two batman packet types.
79 + * Note: explicitly exclude BATADV_UNICAST_4ADDR,
80 + * as the DHCP gateway feature will send explicitly
81 + * to only one BLA gateway, so the claiming process
82 + * should be avoided there.
83 + */
84 + if (packet_type == BATADV_BCAST ||
85 + packet_type == BATADV_UNICAST)
86 + goto handled;
87
88 ether_addr_copy(search_claim.addr, ethhdr->h_source);
89 search_claim.vid = vid;
90 @@ -1898,13 +1913,14 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
91 goto allow;
92 }
93
94 - /* if it is a broadcast ... */
95 - if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) {
96 + /* if it is a multicast ... */
97 + if (is_multicast_ether_addr(ethhdr->h_dest) &&
98 + (packet_type == BATADV_BCAST || packet_type == BATADV_UNICAST)) {
99 /* ... drop it. the responsible gateway is in charge.
100 *
101 - * We need to check is_bcast because with the gateway
102 + * We need to check packet type because with the gateway
103 * feature, broadcasts (like DHCP requests) may be sent
104 - * using a unicast packet type.
105 + * using a unicast 4 address packet type. See comment above.
106 */
107 goto handled;
108 } else {
109 diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
110 index 71f95a3e4d3f335890408685432f18e5d7411a76..af28fdb01467ce290c2a00d0741f01a6e4f347ee 100644
111 --- a/net/batman-adv/bridge_loop_avoidance.h
112 +++ b/net/batman-adv/bridge_loop_avoidance.h
113 @@ -48,7 +48,7 @@ static inline bool batadv_bla_is_loopdetect_mac(const uint8_t *mac)
114
115 #ifdef CONFIG_BATMAN_ADV_BLA
116 bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
117 - unsigned short vid, bool is_bcast);
118 + unsigned short vid, int packet_type);
119 bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
120 unsigned short vid);
121 bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
122 @@ -79,7 +79,7 @@ bool batadv_bla_check_claim(struct batadv_priv *bat_priv, u8 *addr,
123
124 static inline bool batadv_bla_rx(struct batadv_priv *bat_priv,
125 struct sk_buff *skb, unsigned short vid,
126 - bool is_bcast)
127 + int packet_type)
128 {
129 return false;
130 }
131 diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
132 index 267f6e6c802f1a7d3eb41a0f3aa2142ca3b21414..82582abd92485b68254789fb6e2108ae5e547dd6 100644
133 --- a/net/batman-adv/soft-interface.c
134 +++ b/net/batman-adv/soft-interface.c
135 @@ -425,10 +425,10 @@ void batadv_interface_rx(struct net_device *soft_iface,
136 struct vlan_ethhdr *vhdr;
137 struct ethhdr *ethhdr;
138 unsigned short vid;
139 - bool is_bcast;
140 + int packet_type;
141
142 batadv_bcast_packet = (struct batadv_bcast_packet *)skb->data;
143 - is_bcast = (batadv_bcast_packet->packet_type == BATADV_BCAST);
144 + packet_type = batadv_bcast_packet->packet_type;
145
146 skb_pull_rcsum(skb, hdr_size);
147 skb_reset_mac_header(skb);
148 @@ -471,7 +471,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
149 /* Let the bridge loop avoidance check the packet. If will
150 * not handle it, we can safely push it up.
151 */
152 - if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
153 + if (batadv_bla_rx(bat_priv, skb, vid, packet_type))
154 goto out;
155
156 if (orig_node)