Staging: 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.

Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Acked-by: Marek Lindner <lindner_marek@yahoo.de>
[sven.eckelmann@gmx.de: Rework on top of current version]
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Simon Wunderlich 2010-06-22 01:25:53 +02:00 committed by Greg Kroah-Hartman
parent e35fd5ecde
commit 11f79decfd
4 changed files with 52 additions and 29 deletions

View File

@ -512,7 +512,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
/* unicast packet */
case BAT_UNICAST:
ret = recv_unicast_packet(skb);
ret = recv_unicast_packet(skb, batman_if);
break;
/* broadcast packet */

View File

@ -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;
/* 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;
@ -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);

View File

@ -30,11 +30,12 @@ void update_routes(struct orig_node *orig_node,
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);

View File

@ -188,7 +188,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
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;