.. | .. |
---|
1 | 1 | // 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: |
---|
3 | 3 | * |
---|
4 | 4 | * 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/>. |
---|
17 | 5 | */ |
---|
18 | 6 | |
---|
19 | 7 | #include "bat_iv_ogm.h" |
---|
.. | .. |
---|
39 | 27 | #include <linux/netdevice.h> |
---|
40 | 28 | #include <linux/netlink.h> |
---|
41 | 29 | #include <linux/pkt_sched.h> |
---|
| 30 | +#include <linux/prandom.h> |
---|
42 | 31 | #include <linux/printk.h> |
---|
43 | 32 | #include <linux/random.h> |
---|
44 | 33 | #include <linux/rculist.h> |
---|
.. | .. |
---|
139 | 128 | } |
---|
140 | 129 | |
---|
141 | 130 | /** |
---|
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 | | -/** |
---|
305 | 131 | * batadv_iv_ogm_orig_get() - retrieve or create (if does not exist) an |
---|
306 | 132 | * originator |
---|
307 | 133 | * @bat_priv: the bat priv with all the soft interface information |
---|
.. | .. |
---|
309 | 135 | * |
---|
310 | 136 | * Return: the originator object corresponding to the passed mac address or NULL |
---|
311 | 137 | * 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. |
---|
313 | 139 | */ |
---|
314 | 140 | static struct batadv_orig_node * |
---|
315 | 141 | batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr) |
---|
316 | 142 | { |
---|
317 | 143 | struct batadv_orig_node *orig_node; |
---|
318 | 144 | int hash_added; |
---|
319 | | - size_t size; |
---|
320 | 145 | |
---|
321 | 146 | orig_node = batadv_orig_hash_find(bat_priv, addr); |
---|
322 | 147 | if (orig_node) |
---|
.. | .. |
---|
328 | 153 | |
---|
329 | 154 | spin_lock_init(&orig_node->bat_iv.ogm_cnt_lock); |
---|
330 | 155 | |
---|
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 | | - |
---|
341 | 156 | kref_get(&orig_node->refcount); |
---|
342 | 157 | hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig, |
---|
343 | 158 | batadv_choose_orig, orig_node, |
---|
.. | .. |
---|
348 | 163 | return orig_node; |
---|
349 | 164 | |
---|
350 | 165 | free_orig_node_hash: |
---|
| 166 | + /* reference for batadv_hash_add */ |
---|
351 | 167 | batadv_orig_node_put(orig_node); |
---|
352 | | -free_orig_node: |
---|
| 168 | + /* reference from batadv_orig_node_new */ |
---|
353 | 169 | batadv_orig_node_put(orig_node); |
---|
354 | 170 | |
---|
355 | 171 | return NULL; |
---|
.. | .. |
---|
465 | 281 | unsigned int msecs; |
---|
466 | 282 | |
---|
467 | 283 | msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER; |
---|
468 | | - msecs += prandom_u32() % (2 * BATADV_JITTER); |
---|
| 284 | + msecs += prandom_u32_max(2 * BATADV_JITTER); |
---|
469 | 285 | |
---|
470 | 286 | return jiffies + msecs_to_jiffies(msecs); |
---|
471 | 287 | } |
---|
.. | .. |
---|
473 | 289 | /* when do we schedule a ogm packet to be sent */ |
---|
474 | 290 | static unsigned long batadv_iv_ogm_fwd_send_time(void) |
---|
475 | 291 | { |
---|
476 | | - return jiffies + msecs_to_jiffies(prandom_u32() % (BATADV_JITTER / 2)); |
---|
| 292 | + return jiffies + msecs_to_jiffies(prandom_u32_max(BATADV_JITTER / 2)); |
---|
477 | 293 | } |
---|
478 | 294 | |
---|
479 | 295 | /* apply hop penalty for a normal link */ |
---|
.. | .. |
---|
930 | 746 | struct batadv_hashtable *hash = bat_priv->orig_hash; |
---|
931 | 747 | struct hlist_head *head; |
---|
932 | 748 | struct batadv_orig_node *orig_node; |
---|
| 749 | + struct batadv_orig_ifinfo *orig_ifinfo; |
---|
933 | 750 | unsigned long *word; |
---|
934 | 751 | u32 i; |
---|
935 | | - size_t word_index; |
---|
936 | 752 | u8 *w; |
---|
937 | | - unsigned int if_num; |
---|
938 | 753 | |
---|
939 | 754 | for (i = 0; i < hash->size; i++) { |
---|
940 | 755 | head = &hash->table[i]; |
---|
941 | 756 | |
---|
942 | 757 | rcu_read_lock(); |
---|
943 | 758 | 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; |
---|
947 | 764 | |
---|
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 | + } |
---|
953 | 773 | } |
---|
954 | 774 | rcu_read_unlock(); |
---|
955 | 775 | } |
---|
.. | .. |
---|
1054 | 874 | } |
---|
1055 | 875 | |
---|
1056 | 876 | /** |
---|
| 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 | +/** |
---|
1057 | 906 | * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an |
---|
1058 | 907 | * originator |
---|
1059 | 908 | * @bat_priv: the bat priv with all the soft interface information |
---|
.. | .. |
---|
1080 | 929 | struct batadv_neigh_node *neigh_node = NULL; |
---|
1081 | 930 | struct batadv_neigh_node *tmp_neigh_node = NULL; |
---|
1082 | 931 | struct batadv_neigh_node *router = NULL; |
---|
1083 | | - struct batadv_orig_node *orig_node_tmp; |
---|
1084 | | - unsigned int if_num; |
---|
1085 | 932 | u8 sum_orig, sum_neigh; |
---|
1086 | 933 | u8 *neigh_addr; |
---|
1087 | 934 | u8 tq_avg; |
---|
.. | .. |
---|
1186 | 1033 | */ |
---|
1187 | 1034 | if (router_ifinfo && |
---|
1188 | 1035 | 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); |
---|
1201 | 1040 | if (sum_orig >= sum_neigh) |
---|
1202 | 1041 | goto out; |
---|
1203 | 1042 | } |
---|
.. | .. |
---|
1239 | 1078 | struct batadv_neigh_ifinfo *neigh_ifinfo; |
---|
1240 | 1079 | u8 total_count; |
---|
1241 | 1080 | u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own; |
---|
| 1081 | + unsigned int tq_iface_hop_penalty = BATADV_TQ_MAX_VALUE; |
---|
1242 | 1082 | unsigned int neigh_rq_inv_cube, neigh_rq_max_cube; |
---|
1243 | | - unsigned int if_num; |
---|
1244 | 1083 | unsigned int tq_asym_penalty, inv_asym_penalty; |
---|
1245 | 1084 | unsigned int combined_tq; |
---|
1246 | | - unsigned int tq_iface_penalty; |
---|
1247 | 1085 | bool ret = false; |
---|
1248 | 1086 | |
---|
1249 | 1087 | /* find corresponding one hop neighbor */ |
---|
.. | .. |
---|
1281 | 1119 | orig_node->last_seen = jiffies; |
---|
1282 | 1120 | |
---|
1283 | 1121 | /* 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); |
---|
1287 | 1123 | neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing); |
---|
1288 | 1124 | if (neigh_ifinfo) { |
---|
1289 | 1125 | neigh_rq_count = neigh_ifinfo->bat_iv.real_packet_count; |
---|
.. | .. |
---|
1291 | 1127 | } else { |
---|
1292 | 1128 | neigh_rq_count = 0; |
---|
1293 | 1129 | } |
---|
1294 | | - spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock); |
---|
1295 | 1130 | |
---|
1296 | 1131 | /* pay attention to not get a value bigger than 100 % */ |
---|
1297 | 1132 | if (orig_eq_count > neigh_rq_count) |
---|
.. | .. |
---|
1325 | 1160 | inv_asym_penalty = BATADV_TQ_MAX_VALUE * neigh_rq_inv_cube; |
---|
1326 | 1161 | inv_asym_penalty /= neigh_rq_max_cube; |
---|
1327 | 1162 | tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty; |
---|
| 1163 | + tq_iface_hop_penalty -= atomic_read(&if_incoming->hop_penalty); |
---|
1328 | 1164 | |
---|
1329 | 1165 | /* penalize if the OGM is forwarded on the same interface. WiFi |
---|
1330 | 1166 | * interfaces and other half duplex devices suffer from throughput |
---|
1331 | 1167 | * drops as they can't send and receive at the same time. |
---|
1332 | 1168 | */ |
---|
1333 | | - tq_iface_penalty = BATADV_TQ_MAX_VALUE; |
---|
1334 | 1169 | if (if_outgoing && if_incoming == if_outgoing && |
---|
1335 | 1170 | 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); |
---|
1338 | 1173 | |
---|
1339 | 1174 | combined_tq = batadv_ogm_packet->tq * |
---|
1340 | 1175 | tq_own * |
---|
1341 | 1176 | tq_asym_penalty * |
---|
1342 | | - tq_iface_penalty; |
---|
| 1177 | + tq_iface_hop_penalty; |
---|
1343 | 1178 | combined_tq /= BATADV_TQ_MAX_VALUE * |
---|
1344 | 1179 | BATADV_TQ_MAX_VALUE * |
---|
1345 | 1180 | BATADV_TQ_MAX_VALUE; |
---|
1346 | 1181 | batadv_ogm_packet->tq = combined_tq; |
---|
1347 | 1182 | |
---|
1348 | 1183 | 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", |
---|
1350 | 1185 | 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, |
---|
1353 | 1189 | if_outgoing ? if_outgoing->net_dev->name : "DEFAULT"); |
---|
1354 | 1190 | |
---|
1355 | 1191 | /* if link has the minimum required transmission quality |
---|
.. | .. |
---|
1676 | 1512 | } |
---|
1677 | 1513 | |
---|
1678 | 1514 | /** |
---|
| 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 | +/** |
---|
1679 | 1558 | * batadv_iv_ogm_process() - process an incoming batman iv OGM |
---|
1680 | 1559 | * @skb: the skb containing the OGM |
---|
1681 | 1560 | * @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 |
---|
1683 | 1562 | */ |
---|
1684 | 1563 | static void batadv_iv_ogm_process(const struct sk_buff *skb, int ogm_offset, |
---|
1685 | 1564 | struct batadv_hard_iface *if_incoming) |
---|
.. | .. |
---|
1759 | 1638 | } |
---|
1760 | 1639 | |
---|
1761 | 1640 | 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 | | - |
---|
1768 | 1641 | orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv, |
---|
1769 | 1642 | ethhdr->h_source); |
---|
1770 | 1643 | if (!orig_neigh_node) |
---|
1771 | 1644 | return; |
---|
1772 | 1645 | |
---|
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); |
---|
1793 | 1648 | |
---|
1794 | 1649 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
---|
1795 | 1650 | "Drop packet: originator packet from myself (via neighbor)\n"); |
---|
.. | .. |
---|
2437 | 2292 | * @msg: Netlink message to dump into |
---|
2438 | 2293 | * @cb: Control block containing additional options |
---|
2439 | 2294 | * @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 |
---|
2441 | 2296 | */ |
---|
2442 | 2297 | static void |
---|
2443 | 2298 | batadv_iv_ogm_neigh_dump(struct sk_buff *msg, struct netlink_callback *cb, |
---|
.. | .. |
---|
2774 | 2629 | * batadv_iv_gw_dump_entry() - Dump a gateway into a message |
---|
2775 | 2630 | * @msg: Netlink message to dump into |
---|
2776 | 2631 | * @portid: Port making netlink request |
---|
2777 | | - * @seq: Sequence number of netlink message |
---|
| 2632 | + * @cb: Control block containing additional options |
---|
2778 | 2633 | * @bat_priv: The bat priv with all the soft interface information |
---|
2779 | 2634 | * @gw_node: Gateway to be dumped |
---|
2780 | 2635 | * |
---|
2781 | 2636 | * Return: Error code, or 0 on success |
---|
2782 | 2637 | */ |
---|
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, |
---|
2784 | 2640 | struct batadv_priv *bat_priv, |
---|
2785 | 2641 | struct batadv_gw_node *gw_node) |
---|
2786 | 2642 | { |
---|
.. | .. |
---|
2800 | 2656 | |
---|
2801 | 2657 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
---|
2802 | 2658 | |
---|
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); |
---|
2805 | 2662 | if (!hdr) { |
---|
2806 | 2663 | ret = -ENOBUFS; |
---|
2807 | 2664 | goto out; |
---|
2808 | 2665 | } |
---|
| 2666 | + |
---|
| 2667 | + genl_dump_check_consistent(cb, hdr); |
---|
2809 | 2668 | |
---|
2810 | 2669 | ret = -EMSGSIZE; |
---|
2811 | 2670 | |
---|
.. | .. |
---|
2857 | 2716 | int idx_skip = cb->args[0]; |
---|
2858 | 2717 | int idx = 0; |
---|
2859 | 2718 | |
---|
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) { |
---|
2862 | 2723 | if (idx++ < idx_skip) |
---|
2863 | 2724 | continue; |
---|
2864 | 2725 | |
---|
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)) { |
---|
2867 | 2728 | idx_skip = idx - 1; |
---|
2868 | 2729 | goto unlock; |
---|
2869 | 2730 | } |
---|
.. | .. |
---|
2871 | 2732 | |
---|
2872 | 2733 | idx_skip = idx; |
---|
2873 | 2734 | unlock: |
---|
2874 | | - rcu_read_unlock(); |
---|
| 2735 | + spin_unlock_bh(&bat_priv->gw.list_lock); |
---|
2875 | 2736 | |
---|
2876 | 2737 | cb->args[0] = idx_skip; |
---|
2877 | 2738 | } |
---|
.. | .. |
---|
2898 | 2759 | .print = batadv_iv_ogm_orig_print, |
---|
2899 | 2760 | #endif |
---|
2900 | 2761 | .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, |
---|
2904 | 2762 | }, |
---|
2905 | 2763 | .gw = { |
---|
2906 | 2764 | .init_sel_class = batadv_iv_init_sel_class, |
---|