Skip to content

Commit

Permalink
Staging: batman-adv: softif bridge loop avoidance
Browse files Browse the repository at this point in the history
By connecting multiple batman-adv mesh nodes to the same ethernet
segment a loop can be created when the soft-interface is bridged
into that ethernet segment. A simple visualization of the loop
involving the most common case - a LAN as ethernet segment:

node1  <-- LAN  -->  node2
   |                   |
 wifi  <-- mesh -->  wifi

Packets from the LAN (e.g. ARP broadcasts) will circle forever from
node1 or node2 over the mesh back into the LAN.

This patch adds the functionality to detect other batman-adv nodes
connected to the LAN and select a 'gateway' to talk to the
non-batman-adv devices on this LAN. All traffic from and to the mesh
will be handled by this gateway to avoid the loop. OGMs received via
the soft-interface are interpreted as 'port announcements' to locate
potential batman-adv nodes. The patch can also deal with vlans on
top of batX and offers a list of LAN neighbors via debugfs.

Signed-off-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>
  • Loading branch information
Marek Lindner authored and Greg Kroah-Hartman committed Nov 29, 2010
1 parent 225f7b0 commit 4201935
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 13 deletions.
9 changes: 9 additions & 0 deletions drivers/staging/batman-adv/bat_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "translation-table.h"
#include "originator.h"
#include "hard-interface.h"
#include "soft-interface.h"
#include "vis.h"
#include "icmp_socket.h"

Expand Down Expand Up @@ -227,6 +228,12 @@ static int originators_open(struct inode *inode, struct file *file)
return single_open(file, orig_seq_print_text, net_dev);
}

static int softif_neigh_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
return single_open(file, softif_neigh_seq_print_text, net_dev);
}

static int transtable_global_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
Expand Down Expand Up @@ -263,12 +270,14 @@ struct bat_debuginfo bat_debuginfo_##_name = { \
};

static BAT_DEBUGINFO(originators, S_IRUGO, originators_open);
static BAT_DEBUGINFO(softif_neigh, S_IRUGO, softif_neigh_open);
static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open);
static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open);
static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open);

static struct bat_debuginfo *mesh_debuginfos[] = {
&bat_debuginfo_originators,
&bat_debuginfo_softif_neigh,
&bat_debuginfo_transtable_global,
&bat_debuginfo_transtable_local,
&bat_debuginfo_vis_data,
Expand Down
4 changes: 4 additions & 0 deletions drivers/staging/batman-adv/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@ int mesh_init(struct net_device *soft_iface)
spin_lock_init(&bat_priv->hna_ghash_lock);
spin_lock_init(&bat_priv->vis_hash_lock);
spin_lock_init(&bat_priv->vis_list_lock);
spin_lock_init(&bat_priv->softif_neigh_lock);

INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
INIT_HLIST_HEAD(&bat_priv->softif_neigh_list);

if (originator_init(bat_priv) < 1)
goto err;
Expand Down Expand Up @@ -132,6 +134,8 @@ void mesh_free(struct net_device *soft_iface)
hna_local_free(bat_priv);
hna_global_free(bat_priv);

softif_neigh_purge(bat_priv);

atomic_set(&bat_priv->mesh_state, MESH_INACTIVE);
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/staging/batman-adv/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
* forw_packet->direct_link_flags */
#define MAX_AGGREGATION_MS 100

#define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */

#define RESET_PROTECTION_MS 30000
#define EXPECTED_SEQNO_RANGE 65536
/* don't reset again within 30 seconds */
Expand Down
2 changes: 2 additions & 0 deletions drivers/staging/batman-adv/originator.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "routing.h"
#include "hard-interface.h"
#include "unicast.h"
#include "soft-interface.h"

static void purge_orig(struct work_struct *work);

Expand Down Expand Up @@ -286,6 +287,7 @@ static void _purge_orig(struct bat_priv *bat_priv)

spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags);

softif_neigh_purge(bat_priv);
}

static void purge_orig(struct work_struct *work)
Expand Down
12 changes: 6 additions & 6 deletions drivers/staging/batman-adv/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,8 +1117,8 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size)
return 0;
}

static int route_unicast_packet(struct sk_buff *skb,
struct batman_if *recv_if, int hdr_size)
int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
int hdr_size)
{
struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
struct orig_node *orig_node;
Expand Down Expand Up @@ -1186,7 +1186,7 @@ static int route_unicast_packet(struct sk_buff *skb,
return NET_RX_SUCCESS;

skb = new_skb;
unicast_packet = (struct unicast_packet *) skb->data;
unicast_packet = (struct unicast_packet *)skb->data;
}

/* decrement ttl */
Expand All @@ -1210,7 +1210,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)

/* packet for me */
if (is_my_mac(unicast_packet->dest)) {
interface_rx(recv_if->soft_iface, skb, hdr_size);
interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
return NET_RX_SUCCESS;
}

Expand Down Expand Up @@ -1242,7 +1242,7 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if)
if (!new_skb)
return NET_RX_SUCCESS;

interface_rx(recv_if->soft_iface, new_skb,
interface_rx(recv_if->soft_iface, new_skb, recv_if,
sizeof(struct unicast_packet));
return NET_RX_SUCCESS;
}
Expand Down Expand Up @@ -1324,7 +1324,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
add_bcast_packet_to_list(bat_priv, skb);

/* broadcast for me */
interface_rx(recv_if->soft_iface, skb, hdr_size);
interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);

return NET_RX_SUCCESS;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/staging/batman-adv/routing.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node,
struct neigh_node *neigh_node, unsigned char *hna_buff,
int hna_buff_len);
int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if,
int hdr_size);
int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if);
int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if);
int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if);
Expand Down
Loading

0 comments on commit 4201935

Please sign in to comment.