Author: simon Date: 2010-06-04 15:50:59 +0200 (Fri, 04 Jun 2010) New Revision: 1686
Modified: trunk/batman-adv-kernelland/hard-interface.c trunk/batman-adv-kernelland/routing.c trunk/batman-adv-kernelland/routing.h trunk/batman-adv-kernelland/soft-interface.c Log: batman-adv: bonding and interface alternating
This patch adds interface alternating to the new bonding feature. By default, we now try to avoid forwarding packets on the receiving interface, instead choosing alternative interfaces. This feature works only on nodes which have multiple interfaces connected to the mesh. This approach should reduce problems of the half-duplex nature of WiFi Hardware and thus increase performance.
The patch also includes a bug fix for the interference detection. Neighbors which are not (yet) candidates should not be considered for the interference.
Signed-off-by: Simon Wunderlich siwu@hrz.tu-chemnitz.de Acked-by: Marek Lindner lindner_marek@yahoo.de --- Note that unlike the first bonding/alternating patch, the interface alternating is now activated by default. We have concluded at the WBMv3 that this is generally a good idea.
We also did tests on dual radio meshnodes, and the link appeared much more stable (steady 25 Mbit/s, instead of switching between 15 and 25 Mbit/s).
Modified: trunk/batman-adv-kernelland/hard-interface.c =================================================================== --- trunk/batman-adv-kernelland/hard-interface.c 2010-06-04 13:34:00 UTC (rev 1685) +++ trunk/batman-adv-kernelland/hard-interface.c 2010-06-04 13:50:59 UTC (rev 1686) @@ -514,7 +514,7 @@
/* unicast packet */ case BAT_UNICAST: - ret = recv_unicast_packet(skb); + ret = recv_unicast_packet(skb, batman_if); break;
/* broadcast packet */
Modified: trunk/batman-adv-kernelland/routing.c =================================================================== --- trunk/batman-adv-kernelland/routing.c 2010-06-04 13:34:00 UTC (rev 1685) +++ trunk/batman-adv-kernelland/routing.c 2010-06-04 13:50:59 UTC (rev 1686) @@ -416,12 +416,6 @@ 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); @@ -429,7 +423,7 @@ return; }
-/* mark possible bonding candidates in the neighbor list */ +/* mark possible bond.candidates in the neighbor list */ void update_bonding_candidates(struct bat_priv *bat_priv, struct orig_node *orig_node) { @@ -439,12 +433,6 @@ 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; @@ -453,7 +441,7 @@
best_tq = orig_node->router->tq_avg;
- /* update bonding candidates */ + /* update bond.candidates */
candidates = 0;
@@ -490,6 +478,12 @@ if (tmp_neigh_node2 == tmp_neigh_node) continue;
+ /* we only care if the other candidate is even + * considered as candidate. */ + if (tmp_neigh_node2->next_bond_candidate == NULL) + continue; + + if ((tmp_neigh_node->if_incoming == tmp_neigh_node2->if_incoming) || (memcmp(tmp_neigh_node->addr, @@ -1007,14 +1001,16 @@
/* 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; @@ -1022,10 +1018,13 @@ 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;
/* if we have something in the primary_addr, we can search @@ -1052,19 +1051,48 @@ 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;
- /* select the next bonding partner ... */ - primary_orig_node->bond.selected = router->next_bond_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; + + } 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; @@ -1116,7 +1144,7 @@ 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);
Modified: trunk/batman-adv-kernelland/routing.h =================================================================== --- trunk/batman-adv-kernelland/routing.h 2010-06-04 13:34:00 UTC (rev 1685) +++ trunk/batman-adv-kernelland/routing.h 2010-06-04 13:50:59 UTC (rev 1686) @@ -32,11 +32,12 @@ struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len); int recv_icmp_packet(struct sk_buff *skb); -int recv_unicast_packet(struct sk_buff *skb); +int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); int recv_bcast_packet(struct sk_buff *skb); int recv_vis_packet(struct sk_buff *skb); int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if); -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); void update_bonding_candidates(struct bat_priv *bat_priv, struct orig_node *orig_node);
Modified: trunk/batman-adv-kernelland/soft-interface.c =================================================================== --- trunk/batman-adv-kernelland/soft-interface.c 2010-06-04 13:34:00 UTC (rev 1685) +++ trunk/batman-adv-kernelland/soft-interface.c 2010-06-04 13:50:59 UTC (rev 1686) @@ -250,7 +250,7 @@ if (!orig_node) orig_node = transtable_search(ethhdr->h_dest);
- router = find_router(orig_node); + router = find_router(orig_node, NULL);
if (!router) goto unlock;