1 From: Linus Lüssing <linus.luessing@c0d3.blue>
2 Date: Tue, 15 Sep 2020 09:54:10 +0200
3 Subject: batman-adv: mcast: fix duplicate mcast packets from BLA backbone to mesh
6 * Multicast frame send from BLA backbone gateways (multiple nodes
7 with their bat0 bridged together, with BLA enabled) sharing the same
8 LAN to nodes in the mesh
11 * Nodes receive the frame multiple times on bat0 from the mesh,
12 once from each foreign BLA backbone gateway which shares the same LAN
15 For multicast frames via batman-adv broadcast packets coming from the
16 same BLA backbone but from different backbone gateways duplicates are
17 currently detected via a CRC history of previously received packets.
19 However this CRC so far was not performed for multicast frames received
20 via batman-adv unicast packets. Fixing this by appyling the same check
21 for such packets, too.
23 Room for improvements in the future: Ideally we would introduce the
24 possibility to not only claim a client, but a complete originator, too.
25 This would allow us to only send a multicast-in-unicast packet from a BLA
26 backbone gateway claiming the node and by that avoid potential redundant
27 transmissions in the first place.
29 Fixes: e5cf86d30a9b ("batman-adv: add broadcast duplicate check")
30 Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
31 Signed-off-by: Sven Eckelmann <sven@narfation.org>
33 Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/c5cb6a670cc3070d9d5c5562f95fa75faac767ba
35 diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
36 index 4dc67a0d081c06507aba87f7bec03488817791b2..4996bd7b8256557bddaf8ebe87cc606def588adf 100644
37 --- a/net/batman-adv/bridge_loop_avoidance.c
38 +++ b/net/batman-adv/bridge_loop_avoidance.c
39 @@ -1594,13 +1594,16 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
43 - * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup.
44 + * batadv_bla_check_duplist() - Check if a frame is in the broadcast dup.
45 * @bat_priv: the bat priv with all the soft interface information
46 - * @skb: contains the bcast_packet to be checked
47 + * @skb: contains the multicast packet to be checked
48 + * @payload_ptr: pointer to position inside the head buffer of the skb
49 + * marking the start of the data to be CRC'ed
50 + * @orig: originator mac address, NULL if unknown
52 - * check if it is on our broadcast list. Another gateway might
53 - * have sent the same packet because it is connected to the same backbone,
54 - * so we have to remove this duplicate.
55 + * Check if it is on our broadcast list. Another gateway might have sent the
56 + * same packet because it is connected to the same backbone, so we have to
57 + * remove this duplicate.
59 * This is performed by checking the CRC, which will tell us
60 * with a good chance that it is the same packet. If it is furthermore
61 @@ -1609,19 +1612,17 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
63 * Return: true if a packet is in the duplicate list, false otherwise.
65 -bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
66 - struct sk_buff *skb)
67 +static bool batadv_bla_check_duplist(struct batadv_priv *bat_priv,
68 + struct sk_buff *skb, u8 *payload_ptr,
73 - struct batadv_bcast_packet *bcast_packet;
74 struct batadv_bcast_duplist_entry *entry;
77 - bcast_packet = (struct batadv_bcast_packet *)skb->data;
81 /* calculate the crc ... */
82 - crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
83 + crc = batadv_skb_crc32(skb, payload_ptr);
85 spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
87 @@ -1640,8 +1641,21 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
88 if (entry->crc != crc)
91 - if (batadv_compare_eth(entry->orig, bcast_packet->orig))
93 + /* are the originators both known and not anonymous? */
94 + if (orig && !is_zero_ether_addr(orig) &&
95 + !is_zero_ether_addr(entry->orig)) {
96 + /* If known, check if the new frame came from
97 + * the same originator:
98 + * We are safe to take identical frames from the
99 + * same orig, if known, as multiplications in
100 + * the mesh are detected via the (orig, seqno) pair.
101 + * So we can be a bit more liberal here and allow
102 + * identical frames from the same orig which the source
103 + * host might have sent multiple times on purpose.
105 + if (batadv_compare_eth(entry->orig, orig))
109 /* this entry seems to match: same crc, not too old,
110 * and from another gw. therefore return true to forbid it.
111 @@ -1657,7 +1671,14 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
112 entry = &bat_priv->bla.bcast_duplist[curr];
114 entry->entrytime = jiffies;
115 - ether_addr_copy(entry->orig, bcast_packet->orig);
117 + /* known originator */
119 + ether_addr_copy(entry->orig, orig);
120 + /* anonymous originator */
122 + eth_zero_addr(entry->orig);
124 bat_priv->bla.bcast_duplist_curr = curr;
127 @@ -1666,6 +1687,48 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
132 + * batadv_bla_check_ucast_duplist() - Check if a frame is in the broadcast dup.
133 + * @bat_priv: the bat priv with all the soft interface information
134 + * @skb: contains the multicast packet to be checked, decapsulated from a
137 + * Check if it is on our broadcast list. Another gateway might have sent the
138 + * same packet because it is connected to the same backbone, so we have to
139 + * remove this duplicate.
141 + * Return: true if a packet is in the duplicate list, false otherwise.
143 +static bool batadv_bla_check_ucast_duplist(struct batadv_priv *bat_priv,
144 + struct sk_buff *skb)
146 + return batadv_bla_check_duplist(bat_priv, skb, (u8 *)skb->data, NULL);
150 + * batadv_bla_check_bcast_duplist() - Check if a frame is in the broadcast dup.
151 + * @bat_priv: the bat priv with all the soft interface information
152 + * @skb: contains the bcast_packet to be checked
154 + * Check if it is on our broadcast list. Another gateway might have sent the
155 + * same packet because it is connected to the same backbone, so we have to
156 + * remove this duplicate.
158 + * Return: true if a packet is in the duplicate list, false otherwise.
160 +bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
161 + struct sk_buff *skb)
163 + struct batadv_bcast_packet *bcast_packet;
166 + bcast_packet = (struct batadv_bcast_packet *)skb->data;
167 + payload_ptr = (u8 *)(bcast_packet + 1);
169 + return batadv_bla_check_duplist(bat_priv, skb, payload_ptr,
170 + bcast_packet->orig);
174 * batadv_bla_is_backbone_gw_orig() - Check if the originator is a gateway for
175 * the VLAN identified by vid.
176 @@ -1880,6 +1943,14 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
177 packet_type == BATADV_UNICAST)
180 + /* potential duplicates from foreign BLA backbone gateways via
181 + * multicast-in-unicast packets
183 + if (is_multicast_ether_addr(ethhdr->h_dest) &&
184 + packet_type == BATADV_UNICAST &&
185 + batadv_bla_check_ucast_duplist(bat_priv, skb))
188 ether_addr_copy(search_claim.addr, ethhdr->h_source);
189 search_claim.vid = vid;
190 claim = batadv_claim_hash_find(bat_priv, &search_claim);