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);
