Merge pull request #624 from ecsv/batadv-for-18.06
[feed/routing.git] / batman-adv / patches / 0054-batman-adv-mcast-fix-duplicate-mcast-packets-from-BL.patch
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
4
5 Scenario:
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
9
10 Issue:
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
13 with another
14
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.
18
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.
22
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.
28
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>
32
33 Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/c5cb6a670cc3070d9d5c5562f95fa75faac767ba
34
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)
40 }
41
42 /**
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
51 *
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.
58 *
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)
62 *
63 * Return: true if a packet is in the duplicate list, false otherwise.
64 */
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,
69 + const u8 *orig)
70 {
71 - int i, curr;
72 - __be32 crc;
73 - struct batadv_bcast_packet *bcast_packet;
74 struct batadv_bcast_duplist_entry *entry;
75 bool ret = false;
76 -
77 - bcast_packet = (struct batadv_bcast_packet *)skb->data;
78 + int i, curr;
79 + __be32 crc;
80
81 /* calculate the crc ... */
82 - crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
83 + crc = batadv_skb_crc32(skb, payload_ptr);
84
85 spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
86
87 @@ -1640,8 +1641,21 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
88 if (entry->crc != crc)
89 continue;
90
91 - if (batadv_compare_eth(entry->orig, bcast_packet->orig))
92 - continue;
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.
104 + */
105 + if (batadv_compare_eth(entry->orig, orig))
106 + continue;
107 + }
108
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];
113 entry->crc = crc;
114 entry->entrytime = jiffies;
115 - ether_addr_copy(entry->orig, bcast_packet->orig);
116 +
117 + /* known originator */
118 + if (orig)
119 + ether_addr_copy(entry->orig, orig);
120 + /* anonymous originator */
121 + else
122 + eth_zero_addr(entry->orig);
123 +
124 bat_priv->bla.bcast_duplist_curr = curr;
125
126 out:
127 @@ -1666,6 +1687,48 @@ bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
128 return ret;
129 }
130
131 +/**
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
135 + * unicast_packet
136 + *
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.
140 + *
141 + * Return: true if a packet is in the duplicate list, false otherwise.
142 + */
143 +static bool batadv_bla_check_ucast_duplist(struct batadv_priv *bat_priv,
144 + struct sk_buff *skb)
145 +{
146 + return batadv_bla_check_duplist(bat_priv, skb, (u8 *)skb->data, NULL);
147 +}
148 +
149 +/**
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
153 + *
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.
157 + *
158 + * Return: true if a packet is in the duplicate list, false otherwise.
159 + */
160 +bool batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
161 + struct sk_buff *skb)
162 +{
163 + struct batadv_bcast_packet *bcast_packet;
164 + u8 *payload_ptr;
165 +
166 + bcast_packet = (struct batadv_bcast_packet *)skb->data;
167 + payload_ptr = (u8 *)(bcast_packet + 1);
168 +
169 + return batadv_bla_check_duplist(bat_priv, skb, payload_ptr,
170 + bcast_packet->orig);
171 +}
172 +
173 /**
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)
178 goto handled;
179
180 + /* potential duplicates from foreign BLA backbone gateways via
181 + * multicast-in-unicast packets
182 + */
183 + if (is_multicast_ether_addr(ethhdr->h_dest) &&
184 + packet_type == BATADV_UNICAST &&
185 + batadv_bla_check_ucast_duplist(bat_priv, skb))
186 + goto handled;
187 +
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);