|
@@ -402,12 +402,6 @@ static void mark_bonding_address(struct bat_priv *bat_priv,
|
|
|
struct batman_packet *batman_packet)
|
|
|
|
|
|
{
|
|
|
- /* don't care if bonding is not enabled */
|
|
|
- if (!atomic_read(&bat_priv->bonding_enabled)) {
|
|
|
- orig_node->bond.candidates = 0;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
if (batman_packet->flags & PRIMARIES_FIRST_HOP)
|
|
|
memcpy(orig_neigh_node->primary_addr,
|
|
|
orig_node->orig, ETH_ALEN);
|
|
@@ -425,12 +419,6 @@ void update_bonding_candidates(struct bat_priv *bat_priv,
|
|
|
struct neigh_node *tmp_neigh_node, *tmp_neigh_node2;
|
|
|
struct neigh_node *first_candidate, *last_candidate;
|
|
|
|
|
|
- /* don't care if bonding is not enabled */
|
|
|
- if (!atomic_read(&bat_priv->bonding_enabled)) {
|
|
|
- orig_node->bond.candidates = 0;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
/* update the candidates for this originator */
|
|
|
if (!orig_node->router) {
|
|
|
orig_node->bond.candidates = 0;
|
|
@@ -986,14 +974,16 @@ int recv_icmp_packet(struct sk_buff *skb)
|
|
|
|
|
|
/* find a suitable router for this originator, and use
|
|
|
* bonding if possible. */
|
|
|
-struct neigh_node *find_router(struct orig_node *orig_node)
|
|
|
+struct neigh_node *find_router(struct orig_node *orig_node,
|
|
|
+ struct batman_if *recv_if)
|
|
|
{
|
|
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
|
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
|
|
struct orig_node *primary_orig_node;
|
|
|
struct orig_node *router_orig;
|
|
|
- struct neigh_node *router;
|
|
|
+ struct neigh_node *router, *first_candidate, *best_router;
|
|
|
static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
|
|
|
+ int bonding_enabled;
|
|
|
|
|
|
if (!orig_node)
|
|
|
return NULL;
|
|
@@ -1001,9 +991,12 @@ struct neigh_node *find_router(struct orig_node *orig_node)
|
|
|
if (!orig_node->router)
|
|
|
return NULL;
|
|
|
|
|
|
- /* don't care if bonding is not enabled */
|
|
|
- if (!atomic_read(&bat_priv->bonding_enabled))
|
|
|
- return orig_node->router;
|
|
|
+ /* without bonding, the first node should
|
|
|
+ * always choose the default router. */
|
|
|
+
|
|
|
+ bonding_enabled = atomic_read(&bat_priv->bonding_enabled);
|
|
|
+ if (!bonding_enabled && (recv_if == NULL))
|
|
|
+ return orig_node->router;
|
|
|
|
|
|
router_orig = orig_node->router->orig_node;
|
|
|
|
|
@@ -1031,19 +1024,48 @@ struct neigh_node *find_router(struct orig_node *orig_node)
|
|
|
if (primary_orig_node->bond.candidates < 2)
|
|
|
return orig_node->router;
|
|
|
|
|
|
- router = primary_orig_node->bond.selected;
|
|
|
|
|
|
- /* sanity check - this should never happen. */
|
|
|
- if (!router)
|
|
|
- return orig_node->router;
|
|
|
+ /* all nodes between should choose a candidate which
|
|
|
+ * is is not on the interface where the packet came
|
|
|
+ * in. */
|
|
|
+ first_candidate = primary_orig_node->bond.selected;
|
|
|
+ router = first_candidate;
|
|
|
+
|
|
|
+ if (bonding_enabled) {
|
|
|
+ /* in the bonding case, send the packets in a round
|
|
|
+ * robin fashion over the remaining interfaces. */
|
|
|
+ do {
|
|
|
+ /* recv_if == NULL on the first node. */
|
|
|
+ if (router->if_incoming != recv_if)
|
|
|
+ break;
|
|
|
+
|
|
|
+ router = router->next_bond_candidate;
|
|
|
+ } while (router != first_candidate);
|
|
|
+
|
|
|
+ primary_orig_node->bond.selected = router->next_bond_candidate;
|
|
|
|
|
|
- /* select the next bonding partner ... */
|
|
|
- primary_orig_node->bond.selected = router->next_bond_candidate;
|
|
|
+ } else {
|
|
|
+ /* if bonding is disabled, use the best of the
|
|
|
+ * remaining candidates which are not using
|
|
|
+ * this interface. */
|
|
|
+ best_router = first_candidate;
|
|
|
+
|
|
|
+ do {
|
|
|
+ /* recv_if == NULL on the first node. */
|
|
|
+ if ((router->if_incoming != recv_if) &&
|
|
|
+ (router->tq_avg > best_router->tq_avg))
|
|
|
+ best_router = router;
|
|
|
+
|
|
|
+ router = router->next_bond_candidate;
|
|
|
+ } while (router != first_candidate);
|
|
|
+
|
|
|
+ router = best_router;
|
|
|
+ }
|
|
|
|
|
|
return router;
|
|
|
}
|
|
|
|
|
|
-int recv_unicast_packet(struct sk_buff *skb)
|
|
|
+int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
|
|
|
{
|
|
|
struct unicast_packet *unicast_packet;
|
|
|
struct orig_node *orig_node;
|
|
@@ -1095,7 +1117,7 @@ int recv_unicast_packet(struct sk_buff *skb)
|
|
|
orig_node = ((struct orig_node *)
|
|
|
hash_find(orig_hash, unicast_packet->dest));
|
|
|
|
|
|
- router = find_router(orig_node);
|
|
|
+ router = find_router(orig_node, recv_if);
|
|
|
|
|
|
if (!router) {
|
|
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|