diff options
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r-- | net/batman-adv/routing.c | 572 |
1 files changed, 286 insertions, 286 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index c172f5d0e05a..bb1c3ec7e3ff 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -64,80 +64,97 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) | |||
64 | } | 64 | } |
65 | } | 65 | } |
66 | 66 | ||
67 | static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node, | 67 | static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node, |
68 | unsigned char *hna_buff, int hna_buff_len) | 68 | unsigned char *tt_buff, int tt_buff_len) |
69 | { | 69 | { |
70 | if ((hna_buff_len != orig_node->hna_buff_len) || | 70 | if ((tt_buff_len != orig_node->tt_buff_len) || |
71 | ((hna_buff_len > 0) && | 71 | ((tt_buff_len > 0) && |
72 | (orig_node->hna_buff_len > 0) && | 72 | (orig_node->tt_buff_len > 0) && |
73 | (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) { | 73 | (memcmp(orig_node->tt_buff, tt_buff, tt_buff_len) != 0))) { |
74 | 74 | ||
75 | if (orig_node->hna_buff_len > 0) | 75 | if (orig_node->tt_buff_len > 0) |
76 | hna_global_del_orig(bat_priv, orig_node, | 76 | tt_global_del_orig(bat_priv, orig_node, |
77 | "originator changed hna"); | 77 | "originator changed tt"); |
78 | 78 | ||
79 | if ((hna_buff_len > 0) && (hna_buff)) | 79 | if ((tt_buff_len > 0) && (tt_buff)) |
80 | hna_global_add_orig(bat_priv, orig_node, | 80 | tt_global_add_orig(bat_priv, orig_node, |
81 | hna_buff, hna_buff_len); | 81 | tt_buff, tt_buff_len); |
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | static void update_route(struct bat_priv *bat_priv, | 85 | static void update_route(struct bat_priv *bat_priv, |
86 | struct orig_node *orig_node, | 86 | struct orig_node *orig_node, |
87 | struct neigh_node *neigh_node, | 87 | struct neigh_node *neigh_node, |
88 | unsigned char *hna_buff, int hna_buff_len) | 88 | unsigned char *tt_buff, int tt_buff_len) |
89 | { | 89 | { |
90 | struct neigh_node *neigh_node_tmp; | 90 | struct neigh_node *curr_router; |
91 | |||
92 | curr_router = orig_node_get_router(orig_node); | ||
91 | 93 | ||
92 | /* route deleted */ | 94 | /* route deleted */ |
93 | if ((orig_node->router) && (!neigh_node)) { | 95 | if ((curr_router) && (!neigh_node)) { |
94 | 96 | ||
95 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", | 97 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", |
96 | orig_node->orig); | 98 | orig_node->orig); |
97 | hna_global_del_orig(bat_priv, orig_node, | 99 | tt_global_del_orig(bat_priv, orig_node, |
98 | "originator timed out"); | 100 | "originator timed out"); |
99 | 101 | ||
100 | /* route added */ | 102 | /* route added */ |
101 | } else if ((!orig_node->router) && (neigh_node)) { | 103 | } else if ((!curr_router) && (neigh_node)) { |
102 | 104 | ||
103 | bat_dbg(DBG_ROUTES, bat_priv, | 105 | bat_dbg(DBG_ROUTES, bat_priv, |
104 | "Adding route towards: %pM (via %pM)\n", | 106 | "Adding route towards: %pM (via %pM)\n", |
105 | orig_node->orig, neigh_node->addr); | 107 | orig_node->orig, neigh_node->addr); |
106 | hna_global_add_orig(bat_priv, orig_node, | 108 | tt_global_add_orig(bat_priv, orig_node, |
107 | hna_buff, hna_buff_len); | 109 | tt_buff, tt_buff_len); |
108 | 110 | ||
109 | /* route changed */ | 111 | /* route changed */ |
110 | } else { | 112 | } else { |
111 | bat_dbg(DBG_ROUTES, bat_priv, | 113 | bat_dbg(DBG_ROUTES, bat_priv, |
112 | "Changing route towards: %pM " | 114 | "Changing route towards: %pM " |
113 | "(now via %pM - was via %pM)\n", | 115 | "(now via %pM - was via %pM)\n", |
114 | orig_node->orig, neigh_node->addr, | 116 | orig_node->orig, neigh_node->addr, |
115 | orig_node->router->addr); | 117 | curr_router->addr); |
116 | } | 118 | } |
117 | 119 | ||
120 | if (curr_router) | ||
121 | neigh_node_free_ref(curr_router); | ||
122 | |||
123 | /* increase refcount of new best neighbor */ | ||
118 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) | 124 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) |
119 | neigh_node = NULL; | 125 | neigh_node = NULL; |
120 | neigh_node_tmp = orig_node->router; | 126 | |
121 | orig_node->router = neigh_node; | 127 | spin_lock_bh(&orig_node->neigh_list_lock); |
122 | if (neigh_node_tmp) | 128 | rcu_assign_pointer(orig_node->router, neigh_node); |
123 | neigh_node_free_ref(neigh_node_tmp); | 129 | spin_unlock_bh(&orig_node->neigh_list_lock); |
130 | |||
131 | /* decrease refcount of previous best neighbor */ | ||
132 | if (curr_router) | ||
133 | neigh_node_free_ref(curr_router); | ||
124 | } | 134 | } |
125 | 135 | ||
126 | 136 | ||
127 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | 137 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, |
128 | struct neigh_node *neigh_node, unsigned char *hna_buff, | 138 | struct neigh_node *neigh_node, unsigned char *tt_buff, |
129 | int hna_buff_len) | 139 | int tt_buff_len) |
130 | { | 140 | { |
141 | struct neigh_node *router = NULL; | ||
131 | 142 | ||
132 | if (!orig_node) | 143 | if (!orig_node) |
133 | return; | 144 | goto out; |
145 | |||
146 | router = orig_node_get_router(orig_node); | ||
134 | 147 | ||
135 | if (orig_node->router != neigh_node) | 148 | if (router != neigh_node) |
136 | update_route(bat_priv, orig_node, neigh_node, | 149 | update_route(bat_priv, orig_node, neigh_node, |
137 | hna_buff, hna_buff_len); | 150 | tt_buff, tt_buff_len); |
138 | /* may be just HNA changed */ | 151 | /* may be just TT changed */ |
139 | else | 152 | else |
140 | update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); | 153 | update_TT(bat_priv, orig_node, tt_buff, tt_buff_len); |
154 | |||
155 | out: | ||
156 | if (router) | ||
157 | neigh_node_free_ref(router); | ||
141 | } | 158 | } |
142 | 159 | ||
143 | static int is_bidirectional_neigh(struct orig_node *orig_node, | 160 | static int is_bidirectional_neigh(struct orig_node *orig_node, |
@@ -152,65 +169,41 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
152 | uint8_t orig_eq_count, neigh_rq_count, tq_own; | 169 | uint8_t orig_eq_count, neigh_rq_count, tq_own; |
153 | int tq_asym_penalty, ret = 0; | 170 | int tq_asym_penalty, ret = 0; |
154 | 171 | ||
155 | if (orig_node == orig_neigh_node) { | 172 | /* find corresponding one hop neighbor */ |
156 | rcu_read_lock(); | 173 | rcu_read_lock(); |
157 | hlist_for_each_entry_rcu(tmp_neigh_node, node, | 174 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
158 | &orig_node->neigh_list, list) { | 175 | &orig_neigh_node->neigh_list, list) { |
159 | |||
160 | if (!compare_eth(tmp_neigh_node->addr, | ||
161 | orig_neigh_node->orig)) | ||
162 | continue; | ||
163 | |||
164 | if (tmp_neigh_node->if_incoming != if_incoming) | ||
165 | continue; | ||
166 | |||
167 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
168 | continue; | ||
169 | |||
170 | neigh_node = tmp_neigh_node; | ||
171 | } | ||
172 | rcu_read_unlock(); | ||
173 | 176 | ||
174 | if (!neigh_node) | 177 | if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig)) |
175 | neigh_node = create_neighbor(orig_node, | 178 | continue; |
176 | orig_neigh_node, | ||
177 | orig_neigh_node->orig, | ||
178 | if_incoming); | ||
179 | if (!neigh_node) | ||
180 | goto out; | ||
181 | 179 | ||
182 | neigh_node->last_valid = jiffies; | 180 | if (tmp_neigh_node->if_incoming != if_incoming) |
183 | } else { | 181 | continue; |
184 | /* find packet count of corresponding one hop neighbor */ | ||
185 | rcu_read_lock(); | ||
186 | hlist_for_each_entry_rcu(tmp_neigh_node, node, | ||
187 | &orig_neigh_node->neigh_list, list) { | ||
188 | 182 | ||
189 | if (!compare_eth(tmp_neigh_node->addr, | 183 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) |
190 | orig_neigh_node->orig)) | 184 | continue; |
191 | continue; | ||
192 | 185 | ||
193 | if (tmp_neigh_node->if_incoming != if_incoming) | 186 | neigh_node = tmp_neigh_node; |
194 | continue; | 187 | break; |
188 | } | ||
189 | rcu_read_unlock(); | ||
195 | 190 | ||
196 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | 191 | if (!neigh_node) |
197 | continue; | 192 | neigh_node = create_neighbor(orig_neigh_node, |
193 | orig_neigh_node, | ||
194 | orig_neigh_node->orig, | ||
195 | if_incoming); | ||
198 | 196 | ||
199 | neigh_node = tmp_neigh_node; | 197 | if (!neigh_node) |
200 | } | 198 | goto out; |
201 | rcu_read_unlock(); | ||
202 | 199 | ||
203 | if (!neigh_node) | 200 | /* if orig_node is direct neighbour update neigh_node last_valid */ |
204 | neigh_node = create_neighbor(orig_neigh_node, | 201 | if (orig_node == orig_neigh_node) |
205 | orig_neigh_node, | 202 | neigh_node->last_valid = jiffies; |
206 | orig_neigh_node->orig, | ||
207 | if_incoming); | ||
208 | if (!neigh_node) | ||
209 | goto out; | ||
210 | } | ||
211 | 203 | ||
212 | orig_node->last_valid = jiffies; | 204 | orig_node->last_valid = jiffies; |
213 | 205 | ||
206 | /* find packet count of corresponding one hop neighbor */ | ||
214 | spin_lock_bh(&orig_node->ogm_cnt_lock); | 207 | spin_lock_bh(&orig_node->ogm_cnt_lock); |
215 | orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; | 208 | orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; |
216 | neigh_rq_count = neigh_node->real_packet_count; | 209 | neigh_rq_count = neigh_node->real_packet_count; |
@@ -288,8 +281,8 @@ static void bonding_candidate_add(struct orig_node *orig_node, | |||
288 | struct neigh_node *neigh_node) | 281 | struct neigh_node *neigh_node) |
289 | { | 282 | { |
290 | struct hlist_node *node; | 283 | struct hlist_node *node; |
291 | struct neigh_node *tmp_neigh_node; | 284 | struct neigh_node *tmp_neigh_node, *router = NULL; |
292 | uint8_t best_tq, interference_candidate = 0; | 285 | uint8_t interference_candidate = 0; |
293 | 286 | ||
294 | spin_lock_bh(&orig_node->neigh_list_lock); | 287 | spin_lock_bh(&orig_node->neigh_list_lock); |
295 | 288 | ||
@@ -298,13 +291,12 @@ static void bonding_candidate_add(struct orig_node *orig_node, | |||
298 | neigh_node->orig_node->primary_addr)) | 291 | neigh_node->orig_node->primary_addr)) |
299 | goto candidate_del; | 292 | goto candidate_del; |
300 | 293 | ||
301 | if (!orig_node->router) | 294 | router = orig_node_get_router(orig_node); |
295 | if (!router) | ||
302 | goto candidate_del; | 296 | goto candidate_del; |
303 | 297 | ||
304 | best_tq = orig_node->router->tq_avg; | ||
305 | |||
306 | /* ... and is good enough to be considered */ | 298 | /* ... and is good enough to be considered */ |
307 | if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD) | 299 | if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD) |
308 | goto candidate_del; | 300 | goto candidate_del; |
309 | 301 | ||
310 | /** | 302 | /** |
@@ -350,7 +342,9 @@ candidate_del: | |||
350 | 342 | ||
351 | out: | 343 | out: |
352 | spin_unlock_bh(&orig_node->neigh_list_lock); | 344 | spin_unlock_bh(&orig_node->neigh_list_lock); |
353 | return; | 345 | |
346 | if (router) | ||
347 | neigh_node_free_ref(router); | ||
354 | } | 348 | } |
355 | 349 | ||
356 | /* copy primary address for bonding */ | 350 | /* copy primary address for bonding */ |
@@ -369,13 +363,14 @@ static void update_orig(struct bat_priv *bat_priv, | |||
369 | struct ethhdr *ethhdr, | 363 | struct ethhdr *ethhdr, |
370 | struct batman_packet *batman_packet, | 364 | struct batman_packet *batman_packet, |
371 | struct hard_iface *if_incoming, | 365 | struct hard_iface *if_incoming, |
372 | unsigned char *hna_buff, int hna_buff_len, | 366 | unsigned char *tt_buff, int tt_buff_len, |
373 | char is_duplicate) | 367 | char is_duplicate) |
374 | { | 368 | { |
375 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 369 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
370 | struct neigh_node *router = NULL; | ||
376 | struct orig_node *orig_node_tmp; | 371 | struct orig_node *orig_node_tmp; |
377 | struct hlist_node *node; | 372 | struct hlist_node *node; |
378 | int tmp_hna_buff_len; | 373 | int tmp_tt_buff_len; |
379 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; | 374 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; |
380 | 375 | ||
381 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " | 376 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " |
@@ -396,10 +391,12 @@ static void update_orig(struct bat_priv *bat_priv, | |||
396 | if (is_duplicate) | 391 | if (is_duplicate) |
397 | continue; | 392 | continue; |
398 | 393 | ||
394 | spin_lock_bh(&tmp_neigh_node->tq_lock); | ||
399 | ring_buffer_set(tmp_neigh_node->tq_recv, | 395 | ring_buffer_set(tmp_neigh_node->tq_recv, |
400 | &tmp_neigh_node->tq_index, 0); | 396 | &tmp_neigh_node->tq_index, 0); |
401 | tmp_neigh_node->tq_avg = | 397 | tmp_neigh_node->tq_avg = |
402 | ring_buffer_avg(tmp_neigh_node->tq_recv); | 398 | ring_buffer_avg(tmp_neigh_node->tq_recv); |
399 | spin_unlock_bh(&tmp_neigh_node->tq_lock); | ||
403 | } | 400 | } |
404 | 401 | ||
405 | if (!neigh_node) { | 402 | if (!neigh_node) { |
@@ -424,10 +421,12 @@ static void update_orig(struct bat_priv *bat_priv, | |||
424 | orig_node->flags = batman_packet->flags; | 421 | orig_node->flags = batman_packet->flags; |
425 | neigh_node->last_valid = jiffies; | 422 | neigh_node->last_valid = jiffies; |
426 | 423 | ||
424 | spin_lock_bh(&neigh_node->tq_lock); | ||
427 | ring_buffer_set(neigh_node->tq_recv, | 425 | ring_buffer_set(neigh_node->tq_recv, |
428 | &neigh_node->tq_index, | 426 | &neigh_node->tq_index, |
429 | batman_packet->tq); | 427 | batman_packet->tq); |
430 | neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); | 428 | neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); |
429 | spin_unlock_bh(&neigh_node->tq_lock); | ||
431 | 430 | ||
432 | if (!is_duplicate) { | 431 | if (!is_duplicate) { |
433 | orig_node->last_ttl = batman_packet->ttl; | 432 | orig_node->last_ttl = batman_packet->ttl; |
@@ -436,24 +435,23 @@ static void update_orig(struct bat_priv *bat_priv, | |||
436 | 435 | ||
437 | bonding_candidate_add(orig_node, neigh_node); | 436 | bonding_candidate_add(orig_node, neigh_node); |
438 | 437 | ||
439 | tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? | 438 | tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ? |
440 | batman_packet->num_hna * ETH_ALEN : hna_buff_len); | 439 | batman_packet->num_tt * ETH_ALEN : tt_buff_len); |
441 | 440 | ||
442 | /* if this neighbor already is our next hop there is nothing | 441 | /* if this neighbor already is our next hop there is nothing |
443 | * to change */ | 442 | * to change */ |
444 | if (orig_node->router == neigh_node) | 443 | router = orig_node_get_router(orig_node); |
445 | goto update_hna; | 444 | if (router == neigh_node) |
445 | goto update_tt; | ||
446 | 446 | ||
447 | /* if this neighbor does not offer a better TQ we won't consider it */ | 447 | /* if this neighbor does not offer a better TQ we won't consider it */ |
448 | if ((orig_node->router) && | 448 | if (router && (router->tq_avg > neigh_node->tq_avg)) |
449 | (orig_node->router->tq_avg > neigh_node->tq_avg)) | 449 | goto update_tt; |
450 | goto update_hna; | ||
451 | 450 | ||
452 | /* if the TQ is the same and the link not more symetric we | 451 | /* if the TQ is the same and the link not more symetric we |
453 | * won't consider it either */ | 452 | * won't consider it either */ |
454 | if ((orig_node->router) && | 453 | if (router && (neigh_node->tq_avg == router->tq_avg)) { |
455 | (neigh_node->tq_avg == orig_node->router->tq_avg)) { | 454 | orig_node_tmp = router->orig_node; |
456 | orig_node_tmp = orig_node->router->orig_node; | ||
457 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); | 455 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); |
458 | bcast_own_sum_orig = | 456 | bcast_own_sum_orig = |
459 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; | 457 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; |
@@ -466,16 +464,16 @@ static void update_orig(struct bat_priv *bat_priv, | |||
466 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); | 464 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); |
467 | 465 | ||
468 | if (bcast_own_sum_orig >= bcast_own_sum_neigh) | 466 | if (bcast_own_sum_orig >= bcast_own_sum_neigh) |
469 | goto update_hna; | 467 | goto update_tt; |
470 | } | 468 | } |
471 | 469 | ||
472 | update_routes(bat_priv, orig_node, neigh_node, | 470 | update_routes(bat_priv, orig_node, neigh_node, |
473 | hna_buff, tmp_hna_buff_len); | 471 | tt_buff, tmp_tt_buff_len); |
474 | goto update_gw; | 472 | goto update_gw; |
475 | 473 | ||
476 | update_hna: | 474 | update_tt: |
477 | update_routes(bat_priv, orig_node, orig_node->router, | 475 | update_routes(bat_priv, orig_node, router, |
478 | hna_buff, tmp_hna_buff_len); | 476 | tt_buff, tmp_tt_buff_len); |
479 | 477 | ||
480 | update_gw: | 478 | update_gw: |
481 | if (orig_node->gw_flags != batman_packet->gw_flags) | 479 | if (orig_node->gw_flags != batman_packet->gw_flags) |
@@ -496,6 +494,8 @@ unlock: | |||
496 | out: | 494 | out: |
497 | if (neigh_node) | 495 | if (neigh_node) |
498 | neigh_node_free_ref(neigh_node); | 496 | neigh_node_free_ref(neigh_node); |
497 | if (router) | ||
498 | neigh_node_free_ref(router); | ||
499 | } | 499 | } |
500 | 500 | ||
501 | /* checks whether the host restarted and is in the protection time. | 501 | /* checks whether the host restarted and is in the protection time. |
@@ -597,12 +597,14 @@ out: | |||
597 | 597 | ||
598 | void receive_bat_packet(struct ethhdr *ethhdr, | 598 | void receive_bat_packet(struct ethhdr *ethhdr, |
599 | struct batman_packet *batman_packet, | 599 | struct batman_packet *batman_packet, |
600 | unsigned char *hna_buff, int hna_buff_len, | 600 | unsigned char *tt_buff, int tt_buff_len, |
601 | struct hard_iface *if_incoming) | 601 | struct hard_iface *if_incoming) |
602 | { | 602 | { |
603 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 603 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
604 | struct hard_iface *hard_iface; | 604 | struct hard_iface *hard_iface; |
605 | struct orig_node *orig_neigh_node, *orig_node; | 605 | struct orig_node *orig_neigh_node, *orig_node; |
606 | struct neigh_node *router = NULL, *router_router = NULL; | ||
607 | struct neigh_node *orig_neigh_router = NULL; | ||
606 | char has_directlink_flag; | 608 | char has_directlink_flag; |
607 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; | 609 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; |
608 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; | 610 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; |
@@ -747,14 +749,15 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
747 | goto out; | 749 | goto out; |
748 | } | 750 | } |
749 | 751 | ||
752 | router = orig_node_get_router(orig_node); | ||
753 | if (router) | ||
754 | router_router = orig_node_get_router(router->orig_node); | ||
755 | |||
750 | /* avoid temporary routing loops */ | 756 | /* avoid temporary routing loops */ |
751 | if ((orig_node->router) && | 757 | if (router && router_router && |
752 | (orig_node->router->orig_node->router) && | 758 | (compare_eth(router->addr, batman_packet->prev_sender)) && |
753 | (compare_eth(orig_node->router->addr, | ||
754 | batman_packet->prev_sender)) && | ||
755 | !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && | 759 | !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && |
756 | (compare_eth(orig_node->router->addr, | 760 | (compare_eth(router->addr, router_router->addr))) { |
757 | orig_node->router->orig_node->router->addr))) { | ||
758 | bat_dbg(DBG_BATMAN, bat_priv, | 761 | bat_dbg(DBG_BATMAN, bat_priv, |
759 | "Drop packet: ignoring all rebroadcast packets that " | 762 | "Drop packet: ignoring all rebroadcast packets that " |
760 | "may make me loop (sender: %pM)\n", ethhdr->h_source); | 763 | "may make me loop (sender: %pM)\n", ethhdr->h_source); |
@@ -769,9 +772,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
769 | if (!orig_neigh_node) | 772 | if (!orig_neigh_node) |
770 | goto out; | 773 | goto out; |
771 | 774 | ||
775 | orig_neigh_router = orig_node_get_router(orig_neigh_node); | ||
776 | |||
772 | /* drop packet if sender is not a direct neighbor and if we | 777 | /* drop packet if sender is not a direct neighbor and if we |
773 | * don't route towards it */ | 778 | * don't route towards it */ |
774 | if (!is_single_hop_neigh && (!orig_neigh_node->router)) { | 779 | if (!is_single_hop_neigh && (!orig_neigh_router)) { |
775 | bat_dbg(DBG_BATMAN, bat_priv, | 780 | bat_dbg(DBG_BATMAN, bat_priv, |
776 | "Drop packet: OGM via unknown neighbor!\n"); | 781 | "Drop packet: OGM via unknown neighbor!\n"); |
777 | goto out_neigh; | 782 | goto out_neigh; |
@@ -789,14 +794,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
789 | ((orig_node->last_real_seqno == batman_packet->seqno) && | 794 | ((orig_node->last_real_seqno == batman_packet->seqno) && |
790 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) | 795 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) |
791 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, | 796 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, |
792 | if_incoming, hna_buff, hna_buff_len, is_duplicate); | 797 | if_incoming, tt_buff, tt_buff_len, is_duplicate); |
793 | 798 | ||
794 | /* is single hop (direct) neighbor */ | 799 | /* is single hop (direct) neighbor */ |
795 | if (is_single_hop_neigh) { | 800 | if (is_single_hop_neigh) { |
796 | 801 | ||
797 | /* mark direct link on incoming interface */ | 802 | /* mark direct link on incoming interface */ |
798 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 803 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
799 | 1, hna_buff_len, if_incoming); | 804 | 1, tt_buff_len, if_incoming); |
800 | 805 | ||
801 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " | 806 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " |
802 | "rebroadcast neighbor packet with direct link flag\n"); | 807 | "rebroadcast neighbor packet with direct link flag\n"); |
@@ -819,12 +824,19 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
819 | bat_dbg(DBG_BATMAN, bat_priv, | 824 | bat_dbg(DBG_BATMAN, bat_priv, |
820 | "Forwarding packet: rebroadcast originator packet\n"); | 825 | "Forwarding packet: rebroadcast originator packet\n"); |
821 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 826 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
822 | 0, hna_buff_len, if_incoming); | 827 | 0, tt_buff_len, if_incoming); |
823 | 828 | ||
824 | out_neigh: | 829 | out_neigh: |
825 | if ((orig_neigh_node) && (!is_single_hop_neigh)) | 830 | if ((orig_neigh_node) && (!is_single_hop_neigh)) |
826 | orig_node_free_ref(orig_neigh_node); | 831 | orig_node_free_ref(orig_neigh_node); |
827 | out: | 832 | out: |
833 | if (router) | ||
834 | neigh_node_free_ref(router); | ||
835 | if (router_router) | ||
836 | neigh_node_free_ref(router_router); | ||
837 | if (orig_neigh_router) | ||
838 | neigh_node_free_ref(orig_neigh_router); | ||
839 | |||
828 | orig_node_free_ref(orig_node); | 840 | orig_node_free_ref(orig_node); |
829 | } | 841 | } |
830 | 842 | ||
@@ -868,8 +880,9 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface) | |||
868 | static int recv_my_icmp_packet(struct bat_priv *bat_priv, | 880 | static int recv_my_icmp_packet(struct bat_priv *bat_priv, |
869 | struct sk_buff *skb, size_t icmp_len) | 881 | struct sk_buff *skb, size_t icmp_len) |
870 | { | 882 | { |
883 | struct hard_iface *primary_if = NULL; | ||
871 | struct orig_node *orig_node = NULL; | 884 | struct orig_node *orig_node = NULL; |
872 | struct neigh_node *neigh_node = NULL; | 885 | struct neigh_node *router = NULL; |
873 | struct icmp_packet_rr *icmp_packet; | 886 | struct icmp_packet_rr *icmp_packet; |
874 | int ret = NET_RX_DROP; | 887 | int ret = NET_RX_DROP; |
875 | 888 | ||
@@ -881,28 +894,19 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
881 | goto out; | 894 | goto out; |
882 | } | 895 | } |
883 | 896 | ||
884 | if (!bat_priv->primary_if) | 897 | primary_if = primary_if_get_selected(bat_priv); |
898 | if (!primary_if) | ||
885 | goto out; | 899 | goto out; |
886 | 900 | ||
887 | /* answer echo request (ping) */ | 901 | /* answer echo request (ping) */ |
888 | /* get routing information */ | 902 | /* get routing information */ |
889 | rcu_read_lock(); | ||
890 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); | 903 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
891 | |||
892 | if (!orig_node) | 904 | if (!orig_node) |
893 | goto unlock; | 905 | goto out; |
894 | |||
895 | neigh_node = orig_node->router; | ||
896 | |||
897 | if (!neigh_node) | ||
898 | goto unlock; | ||
899 | |||
900 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
901 | neigh_node = NULL; | ||
902 | goto unlock; | ||
903 | } | ||
904 | 906 | ||
905 | rcu_read_unlock(); | 907 | router = orig_node_get_router(orig_node); |
908 | if (!router) | ||
909 | goto out; | ||
906 | 910 | ||
907 | /* create a copy of the skb, if needed, to modify it. */ | 911 | /* create a copy of the skb, if needed, to modify it. */ |
908 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 912 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -911,20 +915,18 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
911 | icmp_packet = (struct icmp_packet_rr *)skb->data; | 915 | icmp_packet = (struct icmp_packet_rr *)skb->data; |
912 | 916 | ||
913 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 917 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
914 | memcpy(icmp_packet->orig, | 918 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
915 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
916 | icmp_packet->msg_type = ECHO_REPLY; | 919 | icmp_packet->msg_type = ECHO_REPLY; |
917 | icmp_packet->ttl = TTL; | 920 | icmp_packet->ttl = TTL; |
918 | 921 | ||
919 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 922 | send_skb_packet(skb, router->if_incoming, router->addr); |
920 | ret = NET_RX_SUCCESS; | 923 | ret = NET_RX_SUCCESS; |
921 | goto out; | ||
922 | 924 | ||
923 | unlock: | ||
924 | rcu_read_unlock(); | ||
925 | out: | 925 | out: |
926 | if (neigh_node) | 926 | if (primary_if) |
927 | neigh_node_free_ref(neigh_node); | 927 | hardif_free_ref(primary_if); |
928 | if (router) | ||
929 | neigh_node_free_ref(router); | ||
928 | if (orig_node) | 930 | if (orig_node) |
929 | orig_node_free_ref(orig_node); | 931 | orig_node_free_ref(orig_node); |
930 | return ret; | 932 | return ret; |
@@ -933,8 +935,9 @@ out: | |||
933 | static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | 935 | static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, |
934 | struct sk_buff *skb) | 936 | struct sk_buff *skb) |
935 | { | 937 | { |
938 | struct hard_iface *primary_if = NULL; | ||
936 | struct orig_node *orig_node = NULL; | 939 | struct orig_node *orig_node = NULL; |
937 | struct neigh_node *neigh_node = NULL; | 940 | struct neigh_node *router = NULL; |
938 | struct icmp_packet *icmp_packet; | 941 | struct icmp_packet *icmp_packet; |
939 | int ret = NET_RX_DROP; | 942 | int ret = NET_RX_DROP; |
940 | 943 | ||
@@ -948,27 +951,18 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
948 | goto out; | 951 | goto out; |
949 | } | 952 | } |
950 | 953 | ||
951 | if (!bat_priv->primary_if) | 954 | primary_if = primary_if_get_selected(bat_priv); |
955 | if (!primary_if) | ||
952 | goto out; | 956 | goto out; |
953 | 957 | ||
954 | /* get routing information */ | 958 | /* get routing information */ |
955 | rcu_read_lock(); | ||
956 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); | 959 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
957 | |||
958 | if (!orig_node) | 960 | if (!orig_node) |
959 | goto unlock; | 961 | goto out; |
960 | |||
961 | neigh_node = orig_node->router; | ||
962 | |||
963 | if (!neigh_node) | ||
964 | goto unlock; | ||
965 | |||
966 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
967 | neigh_node = NULL; | ||
968 | goto unlock; | ||
969 | } | ||
970 | 962 | ||
971 | rcu_read_unlock(); | 963 | router = orig_node_get_router(orig_node); |
964 | if (!router) | ||
965 | goto out; | ||
972 | 966 | ||
973 | /* create a copy of the skb, if needed, to modify it. */ | 967 | /* create a copy of the skb, if needed, to modify it. */ |
974 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 968 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -977,20 +971,18 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
977 | icmp_packet = (struct icmp_packet *)skb->data; | 971 | icmp_packet = (struct icmp_packet *)skb->data; |
978 | 972 | ||
979 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 973 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
980 | memcpy(icmp_packet->orig, | 974 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
981 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
982 | icmp_packet->msg_type = TTL_EXCEEDED; | 975 | icmp_packet->msg_type = TTL_EXCEEDED; |
983 | icmp_packet->ttl = TTL; | 976 | icmp_packet->ttl = TTL; |
984 | 977 | ||
985 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 978 | send_skb_packet(skb, router->if_incoming, router->addr); |
986 | ret = NET_RX_SUCCESS; | 979 | ret = NET_RX_SUCCESS; |
987 | goto out; | ||
988 | 980 | ||
989 | unlock: | ||
990 | rcu_read_unlock(); | ||
991 | out: | 981 | out: |
992 | if (neigh_node) | 982 | if (primary_if) |
993 | neigh_node_free_ref(neigh_node); | 983 | hardif_free_ref(primary_if); |
984 | if (router) | ||
985 | neigh_node_free_ref(router); | ||
994 | if (orig_node) | 986 | if (orig_node) |
995 | orig_node_free_ref(orig_node); | 987 | orig_node_free_ref(orig_node); |
996 | return ret; | 988 | return ret; |
@@ -1003,7 +995,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1003 | struct icmp_packet_rr *icmp_packet; | 995 | struct icmp_packet_rr *icmp_packet; |
1004 | struct ethhdr *ethhdr; | 996 | struct ethhdr *ethhdr; |
1005 | struct orig_node *orig_node = NULL; | 997 | struct orig_node *orig_node = NULL; |
1006 | struct neigh_node *neigh_node = NULL; | 998 | struct neigh_node *router = NULL; |
1007 | int hdr_size = sizeof(struct icmp_packet); | 999 | int hdr_size = sizeof(struct icmp_packet); |
1008 | int ret = NET_RX_DROP; | 1000 | int ret = NET_RX_DROP; |
1009 | 1001 | ||
@@ -1050,23 +1042,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1050 | return recv_icmp_ttl_exceeded(bat_priv, skb); | 1042 | return recv_icmp_ttl_exceeded(bat_priv, skb); |
1051 | 1043 | ||
1052 | /* get routing information */ | 1044 | /* get routing information */ |
1053 | rcu_read_lock(); | ||
1054 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); | 1045 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); |
1055 | |||
1056 | if (!orig_node) | 1046 | if (!orig_node) |
1057 | goto unlock; | 1047 | goto out; |
1058 | |||
1059 | neigh_node = orig_node->router; | ||
1060 | |||
1061 | if (!neigh_node) | ||
1062 | goto unlock; | ||
1063 | |||
1064 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
1065 | neigh_node = NULL; | ||
1066 | goto unlock; | ||
1067 | } | ||
1068 | 1048 | ||
1069 | rcu_read_unlock(); | 1049 | router = orig_node_get_router(orig_node); |
1050 | if (!router) | ||
1051 | goto out; | ||
1070 | 1052 | ||
1071 | /* create a copy of the skb, if needed, to modify it. */ | 1053 | /* create a copy of the skb, if needed, to modify it. */ |
1072 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 1054 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -1078,20 +1060,117 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1078 | icmp_packet->ttl--; | 1060 | icmp_packet->ttl--; |
1079 | 1061 | ||
1080 | /* route it */ | 1062 | /* route it */ |
1081 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 1063 | send_skb_packet(skb, router->if_incoming, router->addr); |
1082 | ret = NET_RX_SUCCESS; | 1064 | ret = NET_RX_SUCCESS; |
1083 | goto out; | ||
1084 | 1065 | ||
1085 | unlock: | ||
1086 | rcu_read_unlock(); | ||
1087 | out: | 1066 | out: |
1088 | if (neigh_node) | 1067 | if (router) |
1089 | neigh_node_free_ref(neigh_node); | 1068 | neigh_node_free_ref(router); |
1090 | if (orig_node) | 1069 | if (orig_node) |
1091 | orig_node_free_ref(orig_node); | 1070 | orig_node_free_ref(orig_node); |
1092 | return ret; | 1071 | return ret; |
1093 | } | 1072 | } |
1094 | 1073 | ||
1074 | /* In the bonding case, send the packets in a round | ||
1075 | * robin fashion over the remaining interfaces. | ||
1076 | * | ||
1077 | * This method rotates the bonding list and increases the | ||
1078 | * returned router's refcount. */ | ||
1079 | static struct neigh_node *find_bond_router(struct orig_node *primary_orig, | ||
1080 | struct hard_iface *recv_if) | ||
1081 | { | ||
1082 | struct neigh_node *tmp_neigh_node; | ||
1083 | struct neigh_node *router = NULL, *first_candidate = NULL; | ||
1084 | |||
1085 | rcu_read_lock(); | ||
1086 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | ||
1087 | bonding_list) { | ||
1088 | if (!first_candidate) | ||
1089 | first_candidate = tmp_neigh_node; | ||
1090 | |||
1091 | /* recv_if == NULL on the first node. */ | ||
1092 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1093 | continue; | ||
1094 | |||
1095 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1096 | continue; | ||
1097 | |||
1098 | router = tmp_neigh_node; | ||
1099 | break; | ||
1100 | } | ||
1101 | |||
1102 | /* use the first candidate if nothing was found. */ | ||
1103 | if (!router && first_candidate && | ||
1104 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1105 | router = first_candidate; | ||
1106 | |||
1107 | if (!router) | ||
1108 | goto out; | ||
1109 | |||
1110 | /* selected should point to the next element | ||
1111 | * after the current router */ | ||
1112 | spin_lock_bh(&primary_orig->neigh_list_lock); | ||
1113 | /* this is a list_move(), which unfortunately | ||
1114 | * does not exist as rcu version */ | ||
1115 | list_del_rcu(&primary_orig->bond_list); | ||
1116 | list_add_rcu(&primary_orig->bond_list, | ||
1117 | &router->bonding_list); | ||
1118 | spin_unlock_bh(&primary_orig->neigh_list_lock); | ||
1119 | |||
1120 | out: | ||
1121 | rcu_read_unlock(); | ||
1122 | return router; | ||
1123 | } | ||
1124 | |||
1125 | /* Interface Alternating: Use the best of the | ||
1126 | * remaining candidates which are not using | ||
1127 | * this interface. | ||
1128 | * | ||
1129 | * Increases the returned router's refcount */ | ||
1130 | static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, | ||
1131 | struct hard_iface *recv_if) | ||
1132 | { | ||
1133 | struct neigh_node *tmp_neigh_node; | ||
1134 | struct neigh_node *router = NULL, *first_candidate = NULL; | ||
1135 | |||
1136 | rcu_read_lock(); | ||
1137 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | ||
1138 | bonding_list) { | ||
1139 | if (!first_candidate) | ||
1140 | first_candidate = tmp_neigh_node; | ||
1141 | |||
1142 | /* recv_if == NULL on the first node. */ | ||
1143 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1144 | continue; | ||
1145 | |||
1146 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1147 | continue; | ||
1148 | |||
1149 | /* if we don't have a router yet | ||
1150 | * or this one is better, choose it. */ | ||
1151 | if ((!router) || | ||
1152 | (tmp_neigh_node->tq_avg > router->tq_avg)) { | ||
1153 | /* decrement refcount of | ||
1154 | * previously selected router */ | ||
1155 | if (router) | ||
1156 | neigh_node_free_ref(router); | ||
1157 | |||
1158 | router = tmp_neigh_node; | ||
1159 | atomic_inc_not_zero(&router->refcount); | ||
1160 | } | ||
1161 | |||
1162 | neigh_node_free_ref(tmp_neigh_node); | ||
1163 | } | ||
1164 | |||
1165 | /* use the first candidate if nothing was found. */ | ||
1166 | if (!router && first_candidate && | ||
1167 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1168 | router = first_candidate; | ||
1169 | |||
1170 | rcu_read_unlock(); | ||
1171 | return router; | ||
1172 | } | ||
1173 | |||
1095 | /* find a suitable router for this originator, and use | 1174 | /* find a suitable router for this originator, and use |
1096 | * bonding if possible. increases the found neighbors | 1175 | * bonding if possible. increases the found neighbors |
1097 | * refcount.*/ | 1176 | * refcount.*/ |
@@ -1101,15 +1180,16 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1101 | { | 1180 | { |
1102 | struct orig_node *primary_orig_node; | 1181 | struct orig_node *primary_orig_node; |
1103 | struct orig_node *router_orig; | 1182 | struct orig_node *router_orig; |
1104 | struct neigh_node *router, *first_candidate, *tmp_neigh_node; | 1183 | struct neigh_node *router; |
1105 | static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; | 1184 | static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; |
1106 | int bonding_enabled; | 1185 | int bonding_enabled; |
1107 | 1186 | ||
1108 | if (!orig_node) | 1187 | if (!orig_node) |
1109 | return NULL; | 1188 | return NULL; |
1110 | 1189 | ||
1111 | if (!orig_node->router) | 1190 | router = orig_node_get_router(orig_node); |
1112 | return NULL; | 1191 | if (!router) |
1192 | goto err; | ||
1113 | 1193 | ||
1114 | /* without bonding, the first node should | 1194 | /* without bonding, the first node should |
1115 | * always choose the default router. */ | 1195 | * always choose the default router. */ |
@@ -1117,12 +1197,9 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1117 | 1197 | ||
1118 | rcu_read_lock(); | 1198 | rcu_read_lock(); |
1119 | /* select default router to output */ | 1199 | /* select default router to output */ |
1120 | router = orig_node->router; | 1200 | router_orig = router->orig_node; |
1121 | router_orig = orig_node->router->orig_node; | 1201 | if (!router_orig) |
1122 | if (!router_orig || !atomic_inc_not_zero(&router->refcount)) { | 1202 | goto err_unlock; |
1123 | rcu_read_unlock(); | ||
1124 | return NULL; | ||
1125 | } | ||
1126 | 1203 | ||
1127 | if ((!recv_if) && (!bonding_enabled)) | 1204 | if ((!recv_if) && (!bonding_enabled)) |
1128 | goto return_router; | 1205 | goto return_router; |
@@ -1151,91 +1228,26 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1151 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) | 1228 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) |
1152 | goto return_router; | 1229 | goto return_router; |
1153 | 1230 | ||
1154 | |||
1155 | /* all nodes between should choose a candidate which | 1231 | /* all nodes between should choose a candidate which |
1156 | * is is not on the interface where the packet came | 1232 | * is is not on the interface where the packet came |
1157 | * in. */ | 1233 | * in. */ |
1158 | 1234 | ||
1159 | neigh_node_free_ref(router); | 1235 | neigh_node_free_ref(router); |
1160 | first_candidate = NULL; | ||
1161 | router = NULL; | ||
1162 | |||
1163 | if (bonding_enabled) { | ||
1164 | /* in the bonding case, send the packets in a round | ||
1165 | * robin fashion over the remaining interfaces. */ | ||
1166 | |||
1167 | list_for_each_entry_rcu(tmp_neigh_node, | ||
1168 | &primary_orig_node->bond_list, bonding_list) { | ||
1169 | if (!first_candidate) | ||
1170 | first_candidate = tmp_neigh_node; | ||
1171 | /* recv_if == NULL on the first node. */ | ||
1172 | if (tmp_neigh_node->if_incoming != recv_if && | ||
1173 | atomic_inc_not_zero(&tmp_neigh_node->refcount)) { | ||
1174 | router = tmp_neigh_node; | ||
1175 | break; | ||
1176 | } | ||
1177 | } | ||
1178 | |||
1179 | /* use the first candidate if nothing was found. */ | ||
1180 | if (!router && first_candidate && | ||
1181 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1182 | router = first_candidate; | ||
1183 | 1236 | ||
1184 | if (!router) { | 1237 | if (bonding_enabled) |
1185 | rcu_read_unlock(); | 1238 | router = find_bond_router(primary_orig_node, recv_if); |
1186 | return NULL; | 1239 | else |
1187 | } | 1240 | router = find_ifalter_router(primary_orig_node, recv_if); |
1188 | |||
1189 | /* selected should point to the next element | ||
1190 | * after the current router */ | ||
1191 | spin_lock_bh(&primary_orig_node->neigh_list_lock); | ||
1192 | /* this is a list_move(), which unfortunately | ||
1193 | * does not exist as rcu version */ | ||
1194 | list_del_rcu(&primary_orig_node->bond_list); | ||
1195 | list_add_rcu(&primary_orig_node->bond_list, | ||
1196 | &router->bonding_list); | ||
1197 | spin_unlock_bh(&primary_orig_node->neigh_list_lock); | ||
1198 | |||
1199 | } else { | ||
1200 | /* if bonding is disabled, use the best of the | ||
1201 | * remaining candidates which are not using | ||
1202 | * this interface. */ | ||
1203 | list_for_each_entry_rcu(tmp_neigh_node, | ||
1204 | &primary_orig_node->bond_list, bonding_list) { | ||
1205 | if (!first_candidate) | ||
1206 | first_candidate = tmp_neigh_node; | ||
1207 | |||
1208 | /* recv_if == NULL on the first node. */ | ||
1209 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1210 | continue; | ||
1211 | |||
1212 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1213 | continue; | ||
1214 | |||
1215 | /* if we don't have a router yet | ||
1216 | * or this one is better, choose it. */ | ||
1217 | if ((!router) || | ||
1218 | (tmp_neigh_node->tq_avg > router->tq_avg)) { | ||
1219 | /* decrement refcount of | ||
1220 | * previously selected router */ | ||
1221 | if (router) | ||
1222 | neigh_node_free_ref(router); | ||
1223 | |||
1224 | router = tmp_neigh_node; | ||
1225 | atomic_inc_not_zero(&router->refcount); | ||
1226 | } | ||
1227 | |||
1228 | neigh_node_free_ref(tmp_neigh_node); | ||
1229 | } | ||
1230 | 1241 | ||
1231 | /* use the first candidate if nothing was found. */ | ||
1232 | if (!router && first_candidate && | ||
1233 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1234 | router = first_candidate; | ||
1235 | } | ||
1236 | return_router: | 1242 | return_router: |
1237 | rcu_read_unlock(); | 1243 | rcu_read_unlock(); |
1238 | return router; | 1244 | return router; |
1245 | err_unlock: | ||
1246 | rcu_read_unlock(); | ||
1247 | err: | ||
1248 | if (router) | ||
1249 | neigh_node_free_ref(router); | ||
1250 | return NULL; | ||
1239 | } | 1251 | } |
1240 | 1252 | ||
1241 | static int check_unicast_packet(struct sk_buff *skb, int hdr_size) | 1253 | static int check_unicast_packet(struct sk_buff *skb, int hdr_size) |
@@ -1284,13 +1296,10 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1284 | } | 1296 | } |
1285 | 1297 | ||
1286 | /* get routing information */ | 1298 | /* get routing information */ |
1287 | rcu_read_lock(); | ||
1288 | orig_node = orig_hash_find(bat_priv, unicast_packet->dest); | 1299 | orig_node = orig_hash_find(bat_priv, unicast_packet->dest); |
1289 | 1300 | ||
1290 | if (!orig_node) | 1301 | if (!orig_node) |
1291 | goto unlock; | 1302 | goto out; |
1292 | |||
1293 | rcu_read_unlock(); | ||
1294 | 1303 | ||
1295 | /* find_router() increases neigh_nodes refcount if found. */ | 1304 | /* find_router() increases neigh_nodes refcount if found. */ |
1296 | neigh_node = find_router(bat_priv, orig_node, recv_if); | 1305 | neigh_node = find_router(bat_priv, orig_node, recv_if); |
@@ -1336,10 +1345,7 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1336 | /* route it */ | 1345 | /* route it */ |
1337 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 1346 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
1338 | ret = NET_RX_SUCCESS; | 1347 | ret = NET_RX_SUCCESS; |
1339 | goto out; | ||
1340 | 1348 | ||
1341 | unlock: | ||
1342 | rcu_read_unlock(); | ||
1343 | out: | 1349 | out: |
1344 | if (neigh_node) | 1350 | if (neigh_node) |
1345 | neigh_node_free_ref(neigh_node); | 1351 | neigh_node_free_ref(neigh_node); |
@@ -1438,13 +1444,10 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1438 | if (bcast_packet->ttl < 2) | 1444 | if (bcast_packet->ttl < 2) |
1439 | goto out; | 1445 | goto out; |
1440 | 1446 | ||
1441 | rcu_read_lock(); | ||
1442 | orig_node = orig_hash_find(bat_priv, bcast_packet->orig); | 1447 | orig_node = orig_hash_find(bat_priv, bcast_packet->orig); |
1443 | 1448 | ||
1444 | if (!orig_node) | 1449 | if (!orig_node) |
1445 | goto rcu_unlock; | 1450 | goto out; |
1446 | |||
1447 | rcu_read_unlock(); | ||
1448 | 1451 | ||
1449 | spin_lock_bh(&orig_node->bcast_seqno_lock); | 1452 | spin_lock_bh(&orig_node->bcast_seqno_lock); |
1450 | 1453 | ||
@@ -1475,9 +1478,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1475 | ret = NET_RX_SUCCESS; | 1478 | ret = NET_RX_SUCCESS; |
1476 | goto out; | 1479 | goto out; |
1477 | 1480 | ||
1478 | rcu_unlock: | ||
1479 | rcu_read_unlock(); | ||
1480 | goto out; | ||
1481 | spin_unlock: | 1481 | spin_unlock: |
1482 | spin_unlock_bh(&orig_node->bcast_seqno_lock); | 1482 | spin_unlock_bh(&orig_node->bcast_seqno_lock); |
1483 | out: | 1483 | out: |