aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/routing.c
diff options
context:
space:
mode:
authorSimon Wunderlich <simon@open-mesh.com>2013-11-13 13:14:45 -0500
committerAntonio Quartulli <antonio@meshcoding.com>2014-01-12 08:41:10 -0500
commitf6c8b71173ad50e48e6569a1ef5d7d4486268b4d (patch)
treeece15dadcb5973de5eb11c0f4f2b9031d90462f4 /net/batman-adv/routing.c
parentf9577a376e28d7b8367319e103d6511d41c1c5fa (diff)
batman-adv: remove bonding and interface alternating
Remove bonding and interface alternating code - it will be replaced by a new, network-wide multi interface optimization which enables both bonding and interface alternating in a better way. Keep the sysfs and find router function though, this will be needed later. Signed-off-by: Simon Wunderlich <simon@open-mesh.com> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>
Diffstat (limited to 'net/batman-adv/routing.c')
-rw-r--r--net/batman-adv/routing.c300
1 files changed, 9 insertions, 291 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 7e8aa177eb1d..4fd2687b88c2 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -96,115 +96,6 @@ out:
96 batadv_neigh_node_free_ref(router); 96 batadv_neigh_node_free_ref(router);
97} 97}
98 98
99/* caller must hold the neigh_list_lock */
100void batadv_bonding_candidate_del(struct batadv_orig_node *orig_node,
101 struct batadv_neigh_node *neigh_node)
102{
103 /* this neighbor is not part of our candidate list */
104 if (list_empty(&neigh_node->bonding_list))
105 goto out;
106
107 list_del_rcu(&neigh_node->bonding_list);
108 INIT_LIST_HEAD(&neigh_node->bonding_list);
109 batadv_neigh_node_free_ref(neigh_node);
110 atomic_dec(&orig_node->bond_candidates);
111
112out:
113 return;
114}
115
116/**
117 * batadv_bonding_candidate_add - consider a new link for bonding mode towards
118 * the given originator
119 * @bat_priv: the bat priv with all the soft interface information
120 * @orig_node: the target node
121 * @neigh_node: the neighbor representing the new link to consider for bonding
122 * mode
123 */
124void batadv_bonding_candidate_add(struct batadv_priv *bat_priv,
125 struct batadv_orig_node *orig_node,
126 struct batadv_neigh_node *neigh_node)
127{
128 struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
129 struct batadv_neigh_node *tmp_neigh_node, *router = NULL;
130 uint8_t interference_candidate = 0;
131
132 spin_lock_bh(&orig_node->neigh_list_lock);
133
134 /* only consider if it has the same primary address ... */
135 if (!batadv_compare_eth(orig_node->orig,
136 neigh_node->orig_node->primary_addr))
137 goto candidate_del;
138
139 router = batadv_orig_node_get_router(orig_node);
140 if (!router)
141 goto candidate_del;
142
143
144 /* ... and is good enough to be considered */
145 if (bao->bat_neigh_is_equiv_or_better(neigh_node, router))
146 goto candidate_del;
147
148 /* check if we have another candidate with the same mac address or
149 * interface. If we do, we won't select this candidate because of
150 * possible interference.
151 */
152 hlist_for_each_entry_rcu(tmp_neigh_node,
153 &orig_node->neigh_list, list) {
154 if (tmp_neigh_node == neigh_node)
155 continue;
156
157 /* we only care if the other candidate is even
158 * considered as candidate.
159 */
160 if (list_empty(&tmp_neigh_node->bonding_list))
161 continue;
162
163 if ((neigh_node->if_incoming == tmp_neigh_node->if_incoming) ||
164 (batadv_compare_eth(neigh_node->addr,
165 tmp_neigh_node->addr))) {
166 interference_candidate = 1;
167 break;
168 }
169 }
170
171 /* don't care further if it is an interference candidate */
172 if (interference_candidate)
173 goto candidate_del;
174
175 /* this neighbor already is part of our candidate list */
176 if (!list_empty(&neigh_node->bonding_list))
177 goto out;
178
179 if (!atomic_inc_not_zero(&neigh_node->refcount))
180 goto out;
181
182 list_add_rcu(&neigh_node->bonding_list, &orig_node->bond_list);
183 atomic_inc(&orig_node->bond_candidates);
184 goto out;
185
186candidate_del:
187 batadv_bonding_candidate_del(orig_node, neigh_node);
188
189out:
190 spin_unlock_bh(&orig_node->neigh_list_lock);
191
192 if (router)
193 batadv_neigh_node_free_ref(router);
194}
195
196/* copy primary address for bonding */
197void
198batadv_bonding_save_primary(const struct batadv_orig_node *orig_node,
199 struct batadv_orig_node *orig_neigh_node,
200 const struct batadv_ogm_packet *batman_ogm_packet)
201{
202 if (!(batman_ogm_packet->flags & BATADV_PRIMARIES_FIRST_HOP))
203 return;
204
205 memcpy(orig_neigh_node->primary_addr, orig_node->orig, ETH_ALEN);
206}
207
208/* checks whether the host restarted and is in the protection time. 99/* checks whether the host restarted and is in the protection time.
209 * returns: 100 * returns:
210 * 0 if the packet is to be accepted 101 * 0 if the packet is to be accepted
@@ -459,114 +350,6 @@ out:
459 return ret; 350 return ret;
460} 351}
461 352
462/* In the bonding case, send the packets in a round
463 * robin fashion over the remaining interfaces.
464 *
465 * This method rotates the bonding list and increases the
466 * returned router's refcount.
467 */
468static struct batadv_neigh_node *
469batadv_find_bond_router(struct batadv_orig_node *primary_orig,
470 const struct batadv_hard_iface *recv_if)
471{
472 struct batadv_neigh_node *tmp_neigh_node;
473 struct batadv_neigh_node *router = NULL, *first_candidate = NULL;
474
475 rcu_read_lock();
476 list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list,
477 bonding_list) {
478 if (!first_candidate)
479 first_candidate = tmp_neigh_node;
480
481 /* recv_if == NULL on the first node. */
482 if (tmp_neigh_node->if_incoming == recv_if)
483 continue;
484
485 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
486 continue;
487
488 router = tmp_neigh_node;
489 break;
490 }
491
492 /* use the first candidate if nothing was found. */
493 if (!router && first_candidate &&
494 atomic_inc_not_zero(&first_candidate->refcount))
495 router = first_candidate;
496
497 if (!router)
498 goto out;
499
500 /* selected should point to the next element
501 * after the current router
502 */
503 spin_lock_bh(&primary_orig->neigh_list_lock);
504 /* this is a list_move(), which unfortunately
505 * does not exist as rcu version
506 */
507 list_del_rcu(&primary_orig->bond_list);
508 list_add_rcu(&primary_orig->bond_list,
509 &router->bonding_list);
510 spin_unlock_bh(&primary_orig->neigh_list_lock);
511
512out:
513 rcu_read_unlock();
514 return router;
515}
516
517/**
518 * batadv_find_ifalter_router - find the best of the remaining candidates which
519 * are not using this interface
520 * @bat_priv: the bat priv with all the soft interface information
521 * @primary_orig: the destination
522 * @recv_if: the interface that the router returned by this function has to not
523 * use
524 *
525 * Returns the best candidate towards primary_orig that is not using recv_if.
526 * Increases the returned neighbor's refcount
527 */
528static struct batadv_neigh_node *
529batadv_find_ifalter_router(struct batadv_priv *bat_priv,
530 struct batadv_orig_node *primary_orig,
531 const struct batadv_hard_iface *recv_if)
532{
533 struct batadv_neigh_node *router = NULL, *first_candidate = NULL;
534 struct batadv_algo_ops *bao = bat_priv->bat_algo_ops;
535 struct batadv_neigh_node *tmp_neigh_node;
536
537 rcu_read_lock();
538 list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list,
539 bonding_list) {
540 if (!first_candidate)
541 first_candidate = tmp_neigh_node;
542
543 /* recv_if == NULL on the first node. */
544 if (tmp_neigh_node->if_incoming == recv_if)
545 continue;
546
547 if (router && bao->bat_neigh_cmp(tmp_neigh_node, router))
548 continue;
549
550 if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
551 continue;
552
553 /* decrement refcount of previously selected router */
554 if (router)
555 batadv_neigh_node_free_ref(router);
556
557 /* we found a better router (or at least one valid router) */
558 router = tmp_neigh_node;
559 }
560
561 /* use the first candidate if nothing was found. */
562 if (!router && first_candidate &&
563 atomic_inc_not_zero(&first_candidate->refcount))
564 router = first_candidate;
565
566 rcu_read_unlock();
567 return router;
568}
569
570/** 353/**
571 * batadv_check_unicast_packet - Check for malformed unicast packets 354 * batadv_check_unicast_packet - Check for malformed unicast packets
572 * @bat_priv: the bat priv with all the soft interface information 355 * @bat_priv: the bat priv with all the soft interface information
@@ -604,95 +387,30 @@ static int batadv_check_unicast_packet(struct batadv_priv *bat_priv,
604 return 0; 387 return 0;
605} 388}
606 389
607/* find a suitable router for this originator, and use 390/**
608 * bonding if possible. increases the found neighbors 391 * batadv_find_router - find a suitable router for this originator
609 * refcount. 392 * @bat_priv: the bat priv with all the soft interface information
393 * @orig_node: the destination node
394 * @recv_if: pointer to interface this packet was received on
395 *
396 * Returns the router which should be used for this orig_node on
397 * this interface, or NULL if not available.
610 */ 398 */
611struct batadv_neigh_node * 399struct batadv_neigh_node *
612batadv_find_router(struct batadv_priv *bat_priv, 400batadv_find_router(struct batadv_priv *bat_priv,
613 struct batadv_orig_node *orig_node, 401 struct batadv_orig_node *orig_node,
614 const struct batadv_hard_iface *recv_if) 402 const struct batadv_hard_iface *recv_if)
615{ 403{
616 struct batadv_orig_node *primary_orig_node;
617 struct batadv_orig_node *router_orig;
618 struct batadv_neigh_node *router; 404 struct batadv_neigh_node *router;
619 static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
620 int bonding_enabled;
621 uint8_t *primary_addr;
622 405
623 if (!orig_node) 406 if (!orig_node)
624 return NULL; 407 return NULL;
625 408
626 router = batadv_orig_node_get_router(orig_node); 409 router = batadv_orig_node_get_router(orig_node);
627 if (!router)
628 goto err;
629
630 /* without bonding, the first node should
631 * always choose the default router.
632 */
633 bonding_enabled = atomic_read(&bat_priv->bonding);
634
635 rcu_read_lock();
636 /* select default router to output */
637 router_orig = router->orig_node;
638 if (!router_orig)
639 goto err_unlock;
640
641 if ((!recv_if) && (!bonding_enabled))
642 goto return_router;
643
644 primary_addr = router_orig->primary_addr;
645
646 /* if we have something in the primary_addr, we can search
647 * for a potential bonding candidate.
648 */
649 if (batadv_compare_eth(primary_addr, zero_mac))
650 goto return_router;
651
652 /* find the orig_node which has the primary interface. might
653 * even be the same as our router_orig in many cases
654 */
655 if (batadv_compare_eth(primary_addr, router_orig->orig)) {
656 primary_orig_node = router_orig;
657 } else {
658 primary_orig_node = batadv_orig_hash_find(bat_priv,
659 primary_addr);
660 if (!primary_orig_node)
661 goto return_router;
662 410
663 batadv_orig_node_free_ref(primary_orig_node); 411 /* TODO: fill this later with new bonding mechanism */
664 }
665
666 /* with less than 2 candidates, we can't do any
667 * bonding and prefer the original router.
668 */
669 if (atomic_read(&primary_orig_node->bond_candidates) < 2)
670 goto return_router;
671 412
672 /* all nodes between should choose a candidate which
673 * is is not on the interface where the packet came
674 * in.
675 */
676 batadv_neigh_node_free_ref(router);
677
678 if (bonding_enabled)
679 router = batadv_find_bond_router(primary_orig_node, recv_if);
680 else
681 router = batadv_find_ifalter_router(bat_priv, primary_orig_node,
682 recv_if);
683
684return_router:
685 if (router && router->if_incoming->if_status != BATADV_IF_ACTIVE)
686 goto err_unlock;
687
688 rcu_read_unlock();
689 return router; 413 return router;
690err_unlock:
691 rcu_read_unlock();
692err:
693 if (router)
694 batadv_neigh_node_free_ref(router);
695 return NULL;
696} 414}
697 415
698static int batadv_route_unicast_packet(struct sk_buff *skb, 416static int batadv_route_unicast_packet(struct sk_buff *skb,