From patchwork Tue May 25 22:54:11 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Wunderlich X-Patchwork-Id: 198 Return-Path: Received: from jessica.hrz.tu-chemnitz.de (jessica.hrz.tu-chemnitz.de [134.109.132.47]) by open-mesh.net (Postfix) with ESMTPS id A2C061542A7 for ; Wed, 26 May 2010 00:54:14 +0200 (CEST) Received: from p57aa0338.dip0.t-ipconnect.de ([87.170.3.56] helo=pandem0nium) by jessica.hrz.tu-chemnitz.de with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.69) (envelope-from ) id 1OH30m-0004NC-DV for b.a.t.m.a.n@lists.open-mesh.org; Wed, 26 May 2010 00:54:13 +0200 Received: from dotslash by pandem0nium with local (Exim 4.69) (envelope-from ) id 1OH30l-00063F-Dj for b.a.t.m.a.n@lists.open-mesh.org; Wed, 26 May 2010 00:54:11 +0200 Date: Wed, 26 May 2010 00:54:11 +0200 From: Simon Wunderlich To: The list for a Better Approach To Mobile Ad-hoc Networking Message-ID: <20100525225411.GA23108@pandem0nium> MIME-Version: 1.0 Content-Disposition: inline Precedence: first-class Priority: normal User-Agent: Mutt/1.5.18 (2008-05-17) X-Spam-Score: -1.0 (-) X-Spam-Report: --- Start der SpamAssassin 3.3.0 Textanalyse (-1.0 Punkte) Fragen an/questions to: Postmaster TU Chemnitz * -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP --- Ende der SpamAssassin Textanalyse X-Scan-Signature: 3687ae86873e952d2f4ab3febb78cf6d Subject: [B.A.T.M.A.N.] [PATCH] Staging: batman-adv: bonding and interface alternating X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.11 Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 May 2010 22:54:15 -0000 This patch adds interface alternating to the new bonding feature. Instead of only sending in a round robin fashion on the usable interfaces, we can also attempt to use a different interface for sending than for receiving (interface alternating). This should reduce problems of the half-duplex nature of WiFi Hardware and thus increase performance. The bonding modes are now enhanced from two modes (disabled/enabled) to the following 4 modes: * 0 - bonding off * 1 - round robin (as before) * 2 - interface alternating * 3 - smart bonding (round robin + interface alternating) This is an experimental patch and targeted for upcoming experiments at Wireless Battle Mesh v3 in Bracciano/Italy. Feedback, comments and reviews appreciated! Signed-off-by: Simon Wunderlich Index: a/batman-adv-kernelland/types.h =================================================================== --- a/batman-adv-kernelland/types.h (revision 1679) +++ a/batman-adv-kernelland/types.h (working copy) @@ -119,7 +119,7 @@ struct bat_priv { struct net_device_stats stats; atomic_t aggregation_enabled; - atomic_t bonding_enabled; + atomic_t bonding_mode; atomic_t vis_mode; atomic_t gw_mode; atomic_t gw_class; Index: a/batman-adv-kernelland/soft-interface.c =================================================================== --- a/batman-adv-kernelland/soft-interface.c (revision 1679) +++ a/batman-adv-kernelland/soft-interface.c (working copy) @@ -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; Index: a/batman-adv-kernelland/hard-interface.c =================================================================== --- a/batman-adv-kernelland/hard-interface.c (revision 1679) +++ a/batman-adv-kernelland/hard-interface.c (working copy) @@ -514,7 +514,7 @@ /* unicast packet */ case BAT_UNICAST: - ret = recv_unicast_packet(skb); + ret = recv_unicast_packet(skb, batman_if); break; /* broadcast packet */ Index: a/batman-adv-kernelland/routing.c =================================================================== --- a/batman-adv-kernelland/routing.c (revision 1679) +++ a/batman-adv-kernelland/routing.c (working copy) @@ -417,7 +417,7 @@ { /* don't care if bonding is not enabled */ - if (!atomic_read(&bat_priv->bonding_enabled)) { + if (!atomic_read(&bat_priv->bonding_mode)) { orig_node->bond.candidates = 0; return; } @@ -429,7 +429,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) { @@ -440,7 +440,7 @@ struct neigh_node *first_candidate, *last_candidate; /* don't care if bonding is not enabled */ - if (!atomic_read(&bat_priv->bonding_enabled)) { + if (!atomic_read(&bat_priv->bonding_mode)) { orig_node->bond.candidates = 0; return; } @@ -453,7 +453,7 @@ best_tq = orig_node->router->tq_avg; - /* update bonding candidates */ + /* update bond.candidates */ candidates = 0; @@ -1007,14 +1007,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; static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; + int bonding_mode; if (!orig_node) return NULL; @@ -1022,8 +1024,9 @@ if (!orig_node->router) return NULL; - /* don't care if bonding is not enabled */ - if (!atomic_read(&bat_priv->bonding_enabled)) + /* just return default router if bonding is not enabled */ + bonding_mode = atomic_read(&bat_priv->bonding_mode); + if (!bonding_mode) return orig_node->router; router_orig = orig_node->router->orig_node; @@ -1052,19 +1055,50 @@ if (primary_orig_node->bond.candidates < 2) return orig_node->router; - router = primary_orig_node->bond.selected; + switch (bonding_mode) { + case BONDING_ROUNDROBIN: + router = primary_orig_node->bond.selected; - /* sanity check - this should never happen. */ - if (!router) - return orig_node->router; + /* sanity check - this should never happen. */ + if (!router) + return orig_node->router; - /* select the next bonding partner ... */ - primary_orig_node->bond.selected = router->next_bond_candidate; + /* select the next bonding partner ... */ + primary_orig_node->bond.selected = router->next_bond_candidate; + break; + case BONDING_ALTERNATE: + /* in alternate mode, the first node should + * always choose the default router. */ + if (recv_if == NULL) + return orig_node->router; + /* all nodes between should choose a candidate which + * is is not on the interface where the packet came + * in. There might be more than one alternative + * interface, and we send the packet in a round robin + * fashion on these interfaces in this case. */ + case BONDING_SMART: + first_candidate = primary_orig_node->bond.selected; + router = first_candidate; + + do { + /* recv_if == NULL on the first node. */ + if (router->if_incoming != recv_if) + break; + router = router->next_bond_candidate; + } while (router != first_candidate); + + /* select the next to have some diversity here. */ + primary_orig_node->bond.selected = router->next_bond_candidate; + break; + default: + router = orig_node->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 +1150,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); Index: a/batman-adv-kernelland/main.h =================================================================== --- a/batman-adv-kernelland/main.h (revision 1679) +++ a/batman-adv-kernelland/main.h (working copy) @@ -63,6 +63,10 @@ * to be considered as bonding candidates */ #define BONDING_TQ_THRESHOLD 50 +#define BONDING_NONE 0 +#define BONDING_ROUNDROBIN 1 +#define BONDING_ALTERNATE 2 +#define BONDING_SMART 3 #define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or * change the size of Index: a/batman-adv-kernelland/routing.h =================================================================== --- a/batman-adv-kernelland/routing.h (revision 1679) +++ a/batman-adv-kernelland/routing.h (working copy) @@ -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); Index: a/batman-adv-kernelland/bat_sysfs.c =================================================================== --- a/batman-adv-kernelland/bat_sysfs.c (revision 1679) +++ a/batman-adv-kernelland/bat_sysfs.c (working copy) @@ -92,10 +92,9 @@ { struct device *dev = to_dev(kobj->parent); struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); - int bond_status = atomic_read(&bat_priv->bonding_enabled); + int bonding_mode = atomic_read(&bat_priv->bonding_mode); - return sprintf(buff, "%s\n", - bond_status == 0 ? "disabled" : "enabled"); + return sprintf(buff, "%d\n", bonding_mode); } static ssize_t store_bond(struct kobject *kobj, struct attribute *attr, @@ -104,17 +103,25 @@ struct device *dev = to_dev(kobj->parent); struct net_device *net_dev = to_net_dev(dev); struct bat_priv *bat_priv = netdev_priv(net_dev); - int bonding_enabled_tmp = -1; + int bonding_mode_tmp = -1; - if (((count == 2) && (buff[0] == '1')) || - (strncmp(buff, "enable", 6) == 0)) - bonding_enabled_tmp = 1; + if (count == 2) + switch (buff[0]) { + case '0': + bonding_mode_tmp = 0; + break; + case '1': + bonding_mode_tmp = BONDING_ROUNDROBIN; + break; + case '2': + bonding_mode_tmp = BONDING_ALTERNATE; + break; + case '3': + bonding_mode_tmp = BONDING_SMART; + break; + } - if (((count == 2) && (buff[0] == '0')) || - (strncmp(buff, "disable", 7) == 0)) - bonding_enabled_tmp = 0; - - if (bonding_enabled_tmp < 0) { + if (bonding_mode_tmp < 0) { if (buff[count - 1] == '\n') buff[count - 1] = '\0'; @@ -123,16 +130,14 @@ return -EINVAL; } - if (atomic_read(&bat_priv->bonding_enabled) == bonding_enabled_tmp) + if (atomic_read(&bat_priv->bonding_mode) == bonding_mode_tmp) return count; - printk(KERN_INFO "batman-adv:Changing bonding from: %s to: %s on mesh: %s\n", - atomic_read(&bat_priv->bonding_enabled) == 1 ? - "enabled" : "disabled", - bonding_enabled_tmp == 1 ? "enabled" : "disabled", + printk(KERN_INFO "batman-adv:Changing bonding from: %d to: %d on mesh: %s\n", + atomic_read(&bat_priv->bonding_mode), bonding_mode_tmp, net_dev->name); - atomic_set(&bat_priv->bonding_enabled, (unsigned)bonding_enabled_tmp); + atomic_set(&bat_priv->bonding_mode, (unsigned)bonding_mode_tmp); return count; } @@ -303,7 +308,7 @@ /* FIXME: should be done in the general mesh setup routine as soon as we have it */ atomic_set(&bat_priv->aggregation_enabled, 1); - atomic_set(&bat_priv->bonding_enabled, 0); + atomic_set(&bat_priv->bonding_mode, 0); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); atomic_set(&bat_priv->gw_class, 0);