hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/net/batman-adv/bat_iv_ogm.c
....@@ -1,19 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0
2
-/* Copyright (C) 2007-2018 B.A.T.M.A.N. contributors:
2
+/* Copyright (C) 2007-2020 B.A.T.M.A.N. contributors:
33 *
44 * Marek Lindner, Simon Wunderlich
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of version 2 of the GNU General Public
8
- * License as published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope that it will be useful, but
11
- * WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
- * General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
175 */
186
197 #include "bat_iv_ogm.h"
....@@ -39,6 +27,7 @@
3927 #include <linux/netdevice.h>
4028 #include <linux/netlink.h>
4129 #include <linux/pkt_sched.h>
30
+#include <linux/prandom.h>
4231 #include <linux/printk.h>
4332 #include <linux/random.h>
4433 #include <linux/rculist.h>
....@@ -139,169 +128,6 @@
139128 }
140129
141130 /**
142
- * batadv_iv_ogm_orig_free() - free the private resources allocated for this
143
- * orig_node
144
- * @orig_node: the orig_node for which the resources have to be free'd
145
- */
146
-static void batadv_iv_ogm_orig_free(struct batadv_orig_node *orig_node)
147
-{
148
- kfree(orig_node->bat_iv.bcast_own);
149
- kfree(orig_node->bat_iv.bcast_own_sum);
150
-}
151
-
152
-/**
153
- * batadv_iv_ogm_orig_add_if() - change the private structures of the orig_node
154
- * to include the new hard-interface
155
- * @orig_node: the orig_node that has to be changed
156
- * @max_if_num: the current amount of interfaces
157
- *
158
- * Return: 0 on success, a negative error code otherwise.
159
- */
160
-static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node,
161
- unsigned int max_if_num)
162
-{
163
- void *data_ptr;
164
- size_t old_size;
165
- int ret = -ENOMEM;
166
-
167
- spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
168
-
169
- old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS;
170
- data_ptr = kmalloc_array(max_if_num,
171
- BATADV_NUM_WORDS * sizeof(unsigned long),
172
- GFP_ATOMIC);
173
- if (!data_ptr)
174
- goto unlock;
175
-
176
- memcpy(data_ptr, orig_node->bat_iv.bcast_own, old_size);
177
- kfree(orig_node->bat_iv.bcast_own);
178
- orig_node->bat_iv.bcast_own = data_ptr;
179
-
180
- data_ptr = kmalloc_array(max_if_num, sizeof(u8), GFP_ATOMIC);
181
- if (!data_ptr)
182
- goto unlock;
183
-
184
- memcpy(data_ptr, orig_node->bat_iv.bcast_own_sum,
185
- (max_if_num - 1) * sizeof(u8));
186
- kfree(orig_node->bat_iv.bcast_own_sum);
187
- orig_node->bat_iv.bcast_own_sum = data_ptr;
188
-
189
- ret = 0;
190
-
191
-unlock:
192
- spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
193
-
194
- return ret;
195
-}
196
-
197
-/**
198
- * batadv_iv_ogm_drop_bcast_own_entry() - drop section of bcast_own
199
- * @orig_node: the orig_node that has to be changed
200
- * @max_if_num: the current amount of interfaces
201
- * @del_if_num: the index of the interface being removed
202
- */
203
-static void
204
-batadv_iv_ogm_drop_bcast_own_entry(struct batadv_orig_node *orig_node,
205
- unsigned int max_if_num,
206
- unsigned int del_if_num)
207
-{
208
- size_t chunk_size;
209
- size_t if_offset;
210
- void *data_ptr;
211
-
212
- lockdep_assert_held(&orig_node->bat_iv.ogm_cnt_lock);
213
-
214
- chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS;
215
- data_ptr = kmalloc_array(max_if_num, chunk_size, GFP_ATOMIC);
216
- if (!data_ptr)
217
- /* use old buffer when new one could not be allocated */
218
- data_ptr = orig_node->bat_iv.bcast_own;
219
-
220
- /* copy first part */
221
- memmove(data_ptr, orig_node->bat_iv.bcast_own, del_if_num * chunk_size);
222
-
223
- /* copy second part */
224
- if_offset = (del_if_num + 1) * chunk_size;
225
- memmove((char *)data_ptr + del_if_num * chunk_size,
226
- (uint8_t *)orig_node->bat_iv.bcast_own + if_offset,
227
- (max_if_num - del_if_num) * chunk_size);
228
-
229
- /* bcast_own was shrunk down in new buffer; free old one */
230
- if (orig_node->bat_iv.bcast_own != data_ptr) {
231
- kfree(orig_node->bat_iv.bcast_own);
232
- orig_node->bat_iv.bcast_own = data_ptr;
233
- }
234
-}
235
-
236
-/**
237
- * batadv_iv_ogm_drop_bcast_own_sum_entry() - drop section of bcast_own_sum
238
- * @orig_node: the orig_node that has to be changed
239
- * @max_if_num: the current amount of interfaces
240
- * @del_if_num: the index of the interface being removed
241
- */
242
-static void
243
-batadv_iv_ogm_drop_bcast_own_sum_entry(struct batadv_orig_node *orig_node,
244
- unsigned int max_if_num,
245
- unsigned int del_if_num)
246
-{
247
- size_t if_offset;
248
- void *data_ptr;
249
-
250
- lockdep_assert_held(&orig_node->bat_iv.ogm_cnt_lock);
251
-
252
- data_ptr = kmalloc_array(max_if_num, sizeof(u8), GFP_ATOMIC);
253
- if (!data_ptr)
254
- /* use old buffer when new one could not be allocated */
255
- data_ptr = orig_node->bat_iv.bcast_own_sum;
256
-
257
- memmove(data_ptr, orig_node->bat_iv.bcast_own_sum,
258
- del_if_num * sizeof(u8));
259
-
260
- if_offset = (del_if_num + 1) * sizeof(u8);
261
- memmove((char *)data_ptr + del_if_num * sizeof(u8),
262
- orig_node->bat_iv.bcast_own_sum + if_offset,
263
- (max_if_num - del_if_num) * sizeof(u8));
264
-
265
- /* bcast_own_sum was shrunk down in new buffer; free old one */
266
- if (orig_node->bat_iv.bcast_own_sum != data_ptr) {
267
- kfree(orig_node->bat_iv.bcast_own_sum);
268
- orig_node->bat_iv.bcast_own_sum = data_ptr;
269
- }
270
-}
271
-
272
-/**
273
- * batadv_iv_ogm_orig_del_if() - change the private structures of the orig_node
274
- * to exclude the removed interface
275
- * @orig_node: the orig_node that has to be changed
276
- * @max_if_num: the current amount of interfaces
277
- * @del_if_num: the index of the interface being removed
278
- *
279
- * Return: 0 on success, a negative error code otherwise.
280
- */
281
-static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node,
282
- unsigned int max_if_num,
283
- unsigned int del_if_num)
284
-{
285
- spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
286
-
287
- if (max_if_num == 0) {
288
- kfree(orig_node->bat_iv.bcast_own);
289
- kfree(orig_node->bat_iv.bcast_own_sum);
290
- orig_node->bat_iv.bcast_own = NULL;
291
- orig_node->bat_iv.bcast_own_sum = NULL;
292
- } else {
293
- batadv_iv_ogm_drop_bcast_own_entry(orig_node, max_if_num,
294
- del_if_num);
295
- batadv_iv_ogm_drop_bcast_own_sum_entry(orig_node, max_if_num,
296
- del_if_num);
297
- }
298
-
299
- spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
300
-
301
- return 0;
302
-}
303
-
304
-/**
305131 * batadv_iv_ogm_orig_get() - retrieve or create (if does not exist) an
306132 * originator
307133 * @bat_priv: the bat priv with all the soft interface information
....@@ -309,14 +135,13 @@
309135 *
310136 * Return: the originator object corresponding to the passed mac address or NULL
311137 * on failure.
312
- * If the object does not exists it is created an initialised.
138
+ * If the object does not exist, it is created and initialised.
313139 */
314140 static struct batadv_orig_node *
315141 batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr)
316142 {
317143 struct batadv_orig_node *orig_node;
318144 int hash_added;
319
- size_t size;
320145
321146 orig_node = batadv_orig_hash_find(bat_priv, addr);
322147 if (orig_node)
....@@ -328,16 +153,6 @@
328153
329154 spin_lock_init(&orig_node->bat_iv.ogm_cnt_lock);
330155
331
- size = bat_priv->num_ifaces * sizeof(unsigned long) * BATADV_NUM_WORDS;
332
- orig_node->bat_iv.bcast_own = kzalloc(size, GFP_ATOMIC);
333
- if (!orig_node->bat_iv.bcast_own)
334
- goto free_orig_node;
335
-
336
- size = bat_priv->num_ifaces * sizeof(u8);
337
- orig_node->bat_iv.bcast_own_sum = kzalloc(size, GFP_ATOMIC);
338
- if (!orig_node->bat_iv.bcast_own_sum)
339
- goto free_orig_node;
340
-
341156 kref_get(&orig_node->refcount);
342157 hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
343158 batadv_choose_orig, orig_node,
....@@ -348,8 +163,9 @@
348163 return orig_node;
349164
350165 free_orig_node_hash:
166
+ /* reference for batadv_hash_add */
351167 batadv_orig_node_put(orig_node);
352
-free_orig_node:
168
+ /* reference from batadv_orig_node_new */
353169 batadv_orig_node_put(orig_node);
354170
355171 return NULL;
....@@ -465,7 +281,7 @@
465281 unsigned int msecs;
466282
467283 msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
468
- msecs += prandom_u32() % (2 * BATADV_JITTER);
284
+ msecs += prandom_u32_max(2 * BATADV_JITTER);
469285
470286 return jiffies + msecs_to_jiffies(msecs);
471287 }
....@@ -473,7 +289,7 @@
473289 /* when do we schedule a ogm packet to be sent */
474290 static unsigned long batadv_iv_ogm_fwd_send_time(void)
475291 {
476
- return jiffies + msecs_to_jiffies(prandom_u32() % (BATADV_JITTER / 2));
292
+ return jiffies + msecs_to_jiffies(prandom_u32_max(BATADV_JITTER / 2));
477293 }
478294
479295 /* apply hop penalty for a normal link */
....@@ -930,26 +746,30 @@
930746 struct batadv_hashtable *hash = bat_priv->orig_hash;
931747 struct hlist_head *head;
932748 struct batadv_orig_node *orig_node;
749
+ struct batadv_orig_ifinfo *orig_ifinfo;
933750 unsigned long *word;
934751 u32 i;
935
- size_t word_index;
936752 u8 *w;
937
- unsigned int if_num;
938753
939754 for (i = 0; i < hash->size; i++) {
940755 head = &hash->table[i];
941756
942757 rcu_read_lock();
943758 hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
944
- spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
945
- word_index = hard_iface->if_num * BATADV_NUM_WORDS;
946
- word = &orig_node->bat_iv.bcast_own[word_index];
759
+ hlist_for_each_entry_rcu(orig_ifinfo,
760
+ &orig_node->ifinfo_list,
761
+ list) {
762
+ if (orig_ifinfo->if_outgoing != hard_iface)
763
+ continue;
947764
948
- batadv_bit_get_packet(bat_priv, word, 1, 0);
949
- if_num = hard_iface->if_num;
950
- w = &orig_node->bat_iv.bcast_own_sum[if_num];
951
- *w = bitmap_weight(word, BATADV_TQ_LOCAL_WINDOW_SIZE);
952
- spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
765
+ spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
766
+ word = orig_ifinfo->bat_iv.bcast_own;
767
+ batadv_bit_get_packet(bat_priv, word, 1, 0);
768
+ w = &orig_ifinfo->bat_iv.bcast_own_sum;
769
+ *w = bitmap_weight(word,
770
+ BATADV_TQ_LOCAL_WINDOW_SIZE);
771
+ spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
772
+ }
953773 }
954774 rcu_read_unlock();
955775 }
....@@ -1054,6 +874,35 @@
1054874 }
1055875
1056876 /**
877
+ * batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over interface
878
+ * @orig_node: originator which reproadcasted the OGMs directly
879
+ * @if_outgoing: interface which transmitted the original OGM and received the
880
+ * direct rebroadcast
881
+ *
882
+ * Return: Number of replied (rebroadcasted) OGMs which were transmitted by
883
+ * an originator and directly (without intermediate hop) received by a specific
884
+ * interface
885
+ */
886
+static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node,
887
+ struct batadv_hard_iface *if_outgoing)
888
+{
889
+ struct batadv_orig_ifinfo *orig_ifinfo;
890
+ u8 sum;
891
+
892
+ orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_outgoing);
893
+ if (!orig_ifinfo)
894
+ return 0;
895
+
896
+ spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
897
+ sum = orig_ifinfo->bat_iv.bcast_own_sum;
898
+ spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
899
+
900
+ batadv_orig_ifinfo_put(orig_ifinfo);
901
+
902
+ return sum;
903
+}
904
+
905
+/**
1057906 * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an
1058907 * originator
1059908 * @bat_priv: the bat priv with all the soft interface information
....@@ -1080,8 +929,6 @@
1080929 struct batadv_neigh_node *neigh_node = NULL;
1081930 struct batadv_neigh_node *tmp_neigh_node = NULL;
1082931 struct batadv_neigh_node *router = NULL;
1083
- struct batadv_orig_node *orig_node_tmp;
1084
- unsigned int if_num;
1085932 u8 sum_orig, sum_neigh;
1086933 u8 *neigh_addr;
1087934 u8 tq_avg;
....@@ -1186,18 +1033,10 @@
11861033 */
11871034 if (router_ifinfo &&
11881035 neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) {
1189
- orig_node_tmp = router->orig_node;
1190
- spin_lock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock);
1191
- if_num = router->if_incoming->if_num;
1192
- sum_orig = orig_node_tmp->bat_iv.bcast_own_sum[if_num];
1193
- spin_unlock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock);
1194
-
1195
- orig_node_tmp = neigh_node->orig_node;
1196
- spin_lock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock);
1197
- if_num = neigh_node->if_incoming->if_num;
1198
- sum_neigh = orig_node_tmp->bat_iv.bcast_own_sum[if_num];
1199
- spin_unlock_bh(&orig_node_tmp->bat_iv.ogm_cnt_lock);
1200
-
1036
+ sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node,
1037
+ router->if_incoming);
1038
+ sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node,
1039
+ neigh_node->if_incoming);
12011040 if (sum_orig >= sum_neigh)
12021041 goto out;
12031042 }
....@@ -1239,11 +1078,10 @@
12391078 struct batadv_neigh_ifinfo *neigh_ifinfo;
12401079 u8 total_count;
12411080 u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own;
1081
+ unsigned int tq_iface_hop_penalty = BATADV_TQ_MAX_VALUE;
12421082 unsigned int neigh_rq_inv_cube, neigh_rq_max_cube;
1243
- unsigned int if_num;
12441083 unsigned int tq_asym_penalty, inv_asym_penalty;
12451084 unsigned int combined_tq;
1246
- unsigned int tq_iface_penalty;
12471085 bool ret = false;
12481086
12491087 /* find corresponding one hop neighbor */
....@@ -1281,9 +1119,7 @@
12811119 orig_node->last_seen = jiffies;
12821120
12831121 /* find packet count of corresponding one hop neighbor */
1284
- spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
1285
- if_num = if_incoming->if_num;
1286
- orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num];
1122
+ orig_eq_count = batadv_iv_orig_ifinfo_sum(orig_neigh_node, if_incoming);
12871123 neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing);
12881124 if (neigh_ifinfo) {
12891125 neigh_rq_count = neigh_ifinfo->bat_iv.real_packet_count;
....@@ -1291,7 +1127,6 @@
12911127 } else {
12921128 neigh_rq_count = 0;
12931129 }
1294
- spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
12951130
12961131 /* pay attention to not get a value bigger than 100 % */
12971132 if (orig_eq_count > neigh_rq_count)
....@@ -1325,31 +1160,32 @@
13251160 inv_asym_penalty = BATADV_TQ_MAX_VALUE * neigh_rq_inv_cube;
13261161 inv_asym_penalty /= neigh_rq_max_cube;
13271162 tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty;
1163
+ tq_iface_hop_penalty -= atomic_read(&if_incoming->hop_penalty);
13281164
13291165 /* penalize if the OGM is forwarded on the same interface. WiFi
13301166 * interfaces and other half duplex devices suffer from throughput
13311167 * drops as they can't send and receive at the same time.
13321168 */
1333
- tq_iface_penalty = BATADV_TQ_MAX_VALUE;
13341169 if (if_outgoing && if_incoming == if_outgoing &&
13351170 batadv_is_wifi_hardif(if_outgoing))
1336
- tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE,
1337
- bat_priv);
1171
+ tq_iface_hop_penalty = batadv_hop_penalty(tq_iface_hop_penalty,
1172
+ bat_priv);
13381173
13391174 combined_tq = batadv_ogm_packet->tq *
13401175 tq_own *
13411176 tq_asym_penalty *
1342
- tq_iface_penalty;
1177
+ tq_iface_hop_penalty;
13431178 combined_tq /= BATADV_TQ_MAX_VALUE *
13441179 BATADV_TQ_MAX_VALUE *
13451180 BATADV_TQ_MAX_VALUE;
13461181 batadv_ogm_packet->tq = combined_tq;
13471182
13481183 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
1349
- "bidirectional: orig = %pM neigh = %pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, iface_penalty: %3i, total tq: %3i, if_incoming = %s, if_outgoing = %s\n",
1184
+ "bidirectional: orig = %pM neigh = %pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, iface_hop_penalty: %3i, total tq: %3i, if_incoming = %s, if_outgoing = %s\n",
13501185 orig_node->orig, orig_neigh_node->orig, total_count,
1351
- neigh_rq_count, tq_own, tq_asym_penalty, tq_iface_penalty,
1352
- batadv_ogm_packet->tq, if_incoming->net_dev->name,
1186
+ neigh_rq_count, tq_own, tq_asym_penalty,
1187
+ tq_iface_hop_penalty, batadv_ogm_packet->tq,
1188
+ if_incoming->net_dev->name,
13531189 if_outgoing ? if_outgoing->net_dev->name : "DEFAULT");
13541190
13551191 /* if link has the minimum required transmission quality
....@@ -1676,10 +1512,53 @@
16761512 }
16771513
16781514 /**
1515
+ * batadv_iv_ogm_process_reply() - Check OGM for direct reply and process it
1516
+ * @ogm_packet: rebroadcast OGM packet to process
1517
+ * @if_incoming: the interface where this packet was received
1518
+ * @orig_node: originator which reproadcasted the OGMs
1519
+ * @if_incoming_seqno: OGM sequence number when rebroadcast was received
1520
+ */
1521
+static void batadv_iv_ogm_process_reply(struct batadv_ogm_packet *ogm_packet,
1522
+ struct batadv_hard_iface *if_incoming,
1523
+ struct batadv_orig_node *orig_node,
1524
+ u32 if_incoming_seqno)
1525
+{
1526
+ struct batadv_orig_ifinfo *orig_ifinfo;
1527
+ s32 bit_pos;
1528
+ u8 *weight;
1529
+
1530
+ /* neighbor has to indicate direct link and it has to
1531
+ * come via the corresponding interface
1532
+ */
1533
+ if (!(ogm_packet->flags & BATADV_DIRECTLINK))
1534
+ return;
1535
+
1536
+ if (!batadv_compare_eth(if_incoming->net_dev->dev_addr,
1537
+ ogm_packet->orig))
1538
+ return;
1539
+
1540
+ orig_ifinfo = batadv_orig_ifinfo_get(orig_node, if_incoming);
1541
+ if (!orig_ifinfo)
1542
+ return;
1543
+
1544
+ /* save packet seqno for bidirectional check */
1545
+ spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
1546
+ bit_pos = if_incoming_seqno - 2;
1547
+ bit_pos -= ntohl(ogm_packet->seqno);
1548
+ batadv_set_bit(orig_ifinfo->bat_iv.bcast_own, bit_pos);
1549
+ weight = &orig_ifinfo->bat_iv.bcast_own_sum;
1550
+ *weight = bitmap_weight(orig_ifinfo->bat_iv.bcast_own,
1551
+ BATADV_TQ_LOCAL_WINDOW_SIZE);
1552
+ spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
1553
+
1554
+ batadv_orig_ifinfo_put(orig_ifinfo);
1555
+}
1556
+
1557
+/**
16791558 * batadv_iv_ogm_process() - process an incoming batman iv OGM
16801559 * @skb: the skb containing the OGM
16811560 * @ogm_offset: offset to the OGM which should be processed (for aggregates)
1682
- * @if_incoming: the interface where this packet was receved
1561
+ * @if_incoming: the interface where this packet was received
16831562 */
16841563 static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset,
16851564 struct batadv_hard_iface *if_incoming)
....@@ -1759,37 +1638,13 @@
17591638 }
17601639
17611640 if (is_my_orig) {
1762
- unsigned long *word;
1763
- size_t offset;
1764
- s32 bit_pos;
1765
- unsigned int if_num;
1766
- u8 *weight;
1767
-
17681641 orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv,
17691642 ethhdr->h_source);
17701643 if (!orig_neigh_node)
17711644 return;
17721645
1773
- /* neighbor has to indicate direct link and it has to
1774
- * come via the corresponding interface
1775
- * save packet seqno for bidirectional check
1776
- */
1777
- if (has_directlink_flag &&
1778
- batadv_compare_eth(if_incoming->net_dev->dev_addr,
1779
- ogm_packet->orig)) {
1780
- if_num = if_incoming->if_num;
1781
- offset = if_num * BATADV_NUM_WORDS;
1782
-
1783
- spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
1784
- word = &orig_neigh_node->bat_iv.bcast_own[offset];
1785
- bit_pos = if_incoming_seqno - 2;
1786
- bit_pos -= ntohl(ogm_packet->seqno);
1787
- batadv_set_bit(word, bit_pos);
1788
- weight = &orig_neigh_node->bat_iv.bcast_own_sum[if_num];
1789
- *weight = bitmap_weight(word,
1790
- BATADV_TQ_LOCAL_WINDOW_SIZE);
1791
- spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
1792
- }
1646
+ batadv_iv_ogm_process_reply(ogm_packet, if_incoming,
1647
+ orig_neigh_node, if_incoming_seqno);
17931648
17941649 batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
17951650 "Drop packet: originator packet from myself (via neighbor)\n");
....@@ -2437,7 +2292,7 @@
24372292 * @msg: Netlink message to dump into
24382293 * @cb: Control block containing additional options
24392294 * @bat_priv: The bat priv with all the soft interface information
2440
- * @single_hardif: Limit dump to this hard interfaace
2295
+ * @single_hardif: Limit dump to this hard interface
24412296 */
24422297 static void
24432298 batadv_iv_ogm_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb,
....@@ -2774,13 +2629,14 @@
27742629 * batadv_iv_gw_dump_entry() - Dump a gateway into a message
27752630 * @msg: Netlink message to dump into
27762631 * @portid: Port making netlink request
2777
- * @seq: Sequence number of netlink message
2632
+ * @cb: Control block containing additional options
27782633 * @bat_priv: The bat priv with all the soft interface information
27792634 * @gw_node: Gateway to be dumped
27802635 *
27812636 * Return: Error code, or 0 on success
27822637 */
2783
-static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
2638
+static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid,
2639
+ struct netlink_callback *cb,
27842640 struct batadv_priv *bat_priv,
27852641 struct batadv_gw_node *gw_node)
27862642 {
....@@ -2800,12 +2656,15 @@
28002656
28012657 curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
28022658
2803
- hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
2804
- NLM_F_MULTI, BATADV_CMD_GET_GATEWAYS);
2659
+ hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
2660
+ &batadv_netlink_family, NLM_F_MULTI,
2661
+ BATADV_CMD_GET_GATEWAYS);
28052662 if (!hdr) {
28062663 ret = -ENOBUFS;
28072664 goto out;
28082665 }
2666
+
2667
+ genl_dump_check_consistent(cb, hdr);
28092668
28102669 ret = -EMSGSIZE;
28112670
....@@ -2857,13 +2716,15 @@
28572716 int idx_skip = cb->args[0];
28582717 int idx = 0;
28592718
2860
- rcu_read_lock();
2861
- hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
2719
+ spin_lock_bh(&bat_priv->gw.list_lock);
2720
+ cb->seq = bat_priv->gw.generation << 1 | 1;
2721
+
2722
+ hlist_for_each_entry(gw_node, &bat_priv->gw.gateway_list, list) {
28622723 if (idx++ < idx_skip)
28632724 continue;
28642725
2865
- if (batadv_iv_gw_dump_entry(msg, portid, cb->nlh->nlmsg_seq,
2866
- bat_priv, gw_node)) {
2726
+ if (batadv_iv_gw_dump_entry(msg, portid, cb, bat_priv,
2727
+ gw_node)) {
28672728 idx_skip = idx - 1;
28682729 goto unlock;
28692730 }
....@@ -2871,7 +2732,7 @@
28712732
28722733 idx_skip = idx;
28732734 unlock:
2874
- rcu_read_unlock();
2735
+ spin_unlock_bh(&bat_priv->gw.list_lock);
28752736
28762737 cb->args[0] = idx_skip;
28772738 }
....@@ -2898,9 +2759,6 @@
28982759 .print = batadv_iv_ogm_orig_print,
28992760 #endif
29002761 .dump = batadv_iv_ogm_orig_dump,
2901
- .free = batadv_iv_ogm_orig_free,
2902
- .add_if = batadv_iv_ogm_orig_add_if,
2903
- .del_if = batadv_iv_ogm_orig_del_if,
29042762 },
29052763 .gw = {
29062764 .init_sel_class = batadv_iv_init_sel_class,