aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/routing.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r--net/batman-adv/routing.c572
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
67static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node, 67static 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
85static void update_route(struct bat_priv *bat_priv, 85static 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
127void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, 137void 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
155out:
156 if (router)
157 neigh_node_free_ref(router);
141} 158}
142 159
143static int is_bidirectional_neigh(struct orig_node *orig_node, 160static 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
351out: 343out:
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
476update_hna: 474update_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
480update_gw: 478update_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:
496out: 494out:
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
598void receive_bat_packet(struct ethhdr *ethhdr, 598void 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
824out_neigh: 829out_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);
827out: 832out:
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)
868static int recv_my_icmp_packet(struct bat_priv *bat_priv, 880static 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
923unlock:
924 rcu_read_unlock();
925out: 925out:
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:
933static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, 935static 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
989unlock:
990 rcu_read_unlock();
991out: 981out:
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
1085unlock:
1086 rcu_read_unlock();
1087out: 1066out:
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. */
1079static 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
1120out:
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 */
1130static 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 }
1236return_router: 1242return_router:
1237 rcu_read_unlock(); 1243 rcu_read_unlock();
1238 return router; 1244 return router;
1245err_unlock:
1246 rcu_read_unlock();
1247err:
1248 if (router)
1249 neigh_node_free_ref(router);
1250 return NULL;
1239} 1251}
1240 1252
1241static int check_unicast_packet(struct sk_buff *skb, int hdr_size) 1253static 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
1341unlock:
1342 rcu_read_unlock();
1343out: 1349out:
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
1478rcu_unlock:
1479 rcu_read_unlock();
1480 goto out;
1481spin_unlock: 1481spin_unlock:
1482 spin_unlock_bh(&orig_node->bcast_seqno_lock); 1482 spin_unlock_bh(&orig_node->bcast_seqno_lock);
1483out: 1483out: