| .. | .. |
|---|
| 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, |
|---|