b.a.t.m.a.n.lists.open-mesh.org archive mirror
 help / color / mirror / Atom feed
From: Sven Eckelmann <sven.eckelmann@gmx.de>
To: greg@kroah.com
Cc: b.a.t.m.a.n@lists.open-mesh.org, Marek Lindner <lindner_marek@yahoo.de>
Subject: [B.A.T.M.A.N.] [PATCH 13/29] Staging: batman-adv: softif bridge loop avoidance
Date: Mon, 22 Nov 2010 00:55:51 +0100	[thread overview]
Message-ID: <1290383767-32602-14-git-send-email-sven.eckelmann@gmx.de> (raw)
In-Reply-To: <1290383767-32602-1-git-send-email-sven.eckelmann@gmx.de>

From: Marek Lindner <lindner_marek@yahoo.de>

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>
---
 drivers/staging/batman-adv/bat_debugfs.c    |    9 +
 drivers/staging/batman-adv/main.c           |    4 +
 drivers/staging/batman-adv/main.h           |    2 +
 drivers/staging/batman-adv/originator.c     |    2 +
 drivers/staging/batman-adv/routing.c        |   12 +-
 drivers/staging/batman-adv/routing.h        |    2 +
 drivers/staging/batman-adv/soft-interface.c |  296 ++++++++++++++++++++++++++-
 drivers/staging/batman-adv/soft-interface.h |    5 +-
 drivers/staging/batman-adv/types.h          |   12 +
 9 files changed, 331 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/batman-adv/bat_debugfs.c b/drivers/staging/batman-adv/bat_debugfs.c
index 57f84a9..22f3eb9 100644
--- a/drivers/staging/batman-adv/bat_debugfs.c
+++ b/drivers/staging/batman-adv/bat_debugfs.c
@@ -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"
 
@@ -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;
@@ -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,
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c
index 0587940..f7d6733 100644
--- a/drivers/staging/batman-adv/main.c
+++ b/drivers/staging/batman-adv/main.c
@@ -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;
@@ -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);
 }
 
diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h
index 5e3f516..ec35ef8 100644
--- a/drivers/staging/batman-adv/main.h
+++ b/drivers/staging/batman-adv/main.h
@@ -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 */
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c
index 5527008..fc7fb31 100644
--- a/drivers/staging/batman-adv/originator.c
+++ b/drivers/staging/batman-adv/originator.c
@@ -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);
 
@@ -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)
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c
index 750cec7..3946c7c 100644
--- a/drivers/staging/batman-adv/routing.c
+++ b/drivers/staging/batman-adv/routing.c
@@ -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;
@@ -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 */
@@ -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;
 	}
 
@@ -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;
 	}
@@ -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;
 }
diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h
index 92674c8..f108f23 100644
--- a/drivers/staging/batman-adv/routing.h
+++ b/drivers/staging/batman-adv/routing.h
@@ -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);
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c
index 0e99618..c3313d0 100644
--- a/drivers/staging/batman-adv/soft-interface.c
+++ b/drivers/staging/batman-adv/soft-interface.c
@@ -33,7 +33,9 @@
 #include <linux/slab.h>
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
 #include "unicast.h"
+#include "routing.h"
 
 
 static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
@@ -75,6 +77,220 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len)
 	return 0;
 }
 
+static void softif_neigh_free_ref(struct kref *refcount)
+{
+	struct softif_neigh *softif_neigh;
+
+	softif_neigh = container_of(refcount, struct softif_neigh, refcount);
+	kfree(softif_neigh);
+}
+
+static void softif_neigh_free_rcu(struct rcu_head *rcu)
+{
+	struct softif_neigh *softif_neigh;
+
+	softif_neigh = container_of(rcu, struct softif_neigh, rcu);
+	kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
+}
+
+void softif_neigh_purge(struct bat_priv *bat_priv)
+{
+	struct softif_neigh *softif_neigh, *softif_neigh_tmp;
+	struct hlist_node *node, *node_tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bat_priv->softif_neigh_lock, flags);
+
+	hlist_for_each_entry_safe(softif_neigh, node, node_tmp,
+				  &bat_priv->softif_neigh_list, list) {
+
+		if ((!time_after(jiffies, softif_neigh->last_seen +
+				msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) &&
+		    (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE))
+			continue;
+
+		hlist_del_rcu(&softif_neigh->list);
+
+		if (bat_priv->softif_neigh == softif_neigh) {
+			bat_dbg(DBG_ROUTES, bat_priv,
+				 "Current mesh exit point '%pM' vanished "
+				 "(vid: %d).\n",
+				 softif_neigh->addr, softif_neigh->vid);
+			softif_neigh_tmp = bat_priv->softif_neigh;
+			bat_priv->softif_neigh = NULL;
+			kref_put(&softif_neigh_tmp->refcount,
+				 softif_neigh_free_ref);
+		}
+
+		call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
+	}
+
+	spin_unlock_irqrestore(&bat_priv->softif_neigh_lock, flags);
+}
+
+static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
+					     uint8_t *addr, short vid)
+{
+	struct softif_neigh *softif_neigh;
+	struct hlist_node *node;
+	unsigned long flags;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(softif_neigh, node,
+				 &bat_priv->softif_neigh_list, list) {
+		if (memcmp(softif_neigh->addr, addr, ETH_ALEN) != 0)
+			continue;
+
+		if (softif_neigh->vid != vid)
+			continue;
+
+		softif_neigh->last_seen = jiffies;
+		goto found;
+	}
+
+	softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
+	if (!softif_neigh)
+		goto out;
+
+	memcpy(softif_neigh->addr, addr, ETH_ALEN);
+	softif_neigh->vid = vid;
+	softif_neigh->last_seen = jiffies;
+	kref_init(&softif_neigh->refcount);
+
+	INIT_HLIST_NODE(&softif_neigh->list);
+	spin_lock_irqsave(&bat_priv->softif_neigh_lock, flags);
+	hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list);
+	spin_unlock_irqrestore(&bat_priv->softif_neigh_lock, flags);
+
+found:
+	kref_get(&softif_neigh->refcount);
+out:
+	rcu_read_unlock();
+	return softif_neigh;
+}
+
+int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
+{
+	struct net_device *net_dev = (struct net_device *)seq->private;
+	struct bat_priv *bat_priv = netdev_priv(net_dev);
+	struct softif_neigh *softif_neigh;
+	struct hlist_node *node;
+	size_t buf_size, pos;
+	char *buff;
+
+	if (!bat_priv->primary_if) {
+		return seq_printf(seq, "BATMAN mesh %s disabled - "
+			       "please specify interfaces to enable it\n",
+			       net_dev->name);
+	}
+
+	seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name);
+
+	buf_size = 1;
+	/* Estimate length for: "   xx:xx:xx:xx:xx:xx\n" */
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(softif_neigh, node,
+				 &bat_priv->softif_neigh_list, list)
+		buf_size += 30;
+	rcu_read_unlock();
+
+	buff = kmalloc(buf_size, GFP_ATOMIC);
+	if (!buff)
+		return -ENOMEM;
+
+	buff[0] = '\0';
+	pos = 0;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(softif_neigh, node,
+				 &bat_priv->softif_neigh_list, list) {
+		pos += snprintf(buff + pos, 31, "%s %pM (vid: %d)\n",
+				bat_priv->softif_neigh == softif_neigh
+				? "=>" : "  ", softif_neigh->addr,
+				softif_neigh->vid);
+	}
+	rcu_read_unlock();
+
+	seq_printf(seq, "%s", buff);
+	kfree(buff);
+	return 0;
+}
+
+static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
+			       short vid)
+{
+	struct bat_priv *bat_priv = netdev_priv(dev);
+	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
+	struct batman_packet *batman_packet;
+	struct softif_neigh *softif_neigh, *softif_neigh_tmp;
+
+	if (ntohs(ethhdr->h_proto) == ETH_P_8021Q)
+		batman_packet = (struct batman_packet *)
+					(skb->data + ETH_HLEN + VLAN_HLEN);
+	else
+		batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN);
+
+	if (batman_packet->version != COMPAT_VERSION)
+		goto err;
+
+	if (batman_packet->packet_type != BAT_PACKET)
+		goto err;
+
+	if (!(batman_packet->flags & PRIMARIES_FIRST_HOP))
+		goto err;
+
+	if (is_my_mac(batman_packet->orig))
+		goto err;
+
+	softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid);
+
+	if (!softif_neigh)
+		goto err;
+
+	if (bat_priv->softif_neigh == softif_neigh)
+		goto out;
+
+	/* we got a neighbor but its mac is 'bigger' than ours  */
+	if (memcmp(bat_priv->primary_if->net_dev->dev_addr,
+		   softif_neigh->addr, ETH_ALEN) < 0)
+		goto out;
+
+	/* switch to new 'smallest neighbor' */
+	if ((bat_priv->softif_neigh) &&
+	    (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr,
+							ETH_ALEN) < 0)) {
+		bat_dbg(DBG_ROUTES, bat_priv,
+			"Changing mesh exit point from %pM (vid: %d) "
+			"to %pM (vid: %d).\n",
+			 bat_priv->softif_neigh->addr,
+			 bat_priv->softif_neigh->vid,
+			 softif_neigh->addr, softif_neigh->vid);
+		softif_neigh_tmp = bat_priv->softif_neigh;
+		bat_priv->softif_neigh = softif_neigh;
+		kref_put(&softif_neigh_tmp->refcount, softif_neigh_free_ref);
+		/* we need to hold the additional reference */
+		goto err;
+	}
+
+	/* close own batX device and use softif_neigh as exit node */
+	if ((!bat_priv->softif_neigh) &&
+	    (memcmp(softif_neigh->addr,
+		    bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) {
+		bat_dbg(DBG_ROUTES, bat_priv,
+			"Setting mesh exit point to %pM (vid: %d).\n",
+			softif_neigh->addr, softif_neigh->vid);
+		bat_priv->softif_neigh = softif_neigh;
+		/* we need to hold the additional reference */
+		goto err;
+	}
+
+out:
+	kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
+err:
+	kfree_skb(skb);
+	return;
+}
+
 static int interface_open(struct net_device *dev)
 {
 	netif_start_queue(dev);
@@ -109,7 +325,6 @@ static int interface_set_mac_addr(struct net_device *dev, void *p)
 	}
 
 	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
-
 	return 0;
 }
 
@@ -129,13 +344,36 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface)
 	struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
 	struct bat_priv *bat_priv = netdev_priv(soft_iface);
 	struct bcast_packet *bcast_packet;
+	struct vlan_ethhdr *vhdr;
 	int data_len = skb->len, ret;
+	short vid = -1;
 
 	if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE)
 		goto dropped;
 
 	soft_iface->trans_start = jiffies;
 
+	switch (ntohs(ethhdr->h_proto)) {
+	case ETH_P_8021Q:
+		vhdr = (struct vlan_ethhdr *)skb->data;
+		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
+
+		if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
+			break;
+
+		/* fall through */
+	case ETH_P_BATMAN:
+		softif_batman_recv(skb, soft_iface, vid);
+		goto end;
+	}
+
+	/**
+	 * if we have a another chosen mesh exit node in range
+	 * it will transport the packets to the mesh
+	 */
+	if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid))
+		goto dropped;
+
 	/* TODO: check this for locks */
 	hna_local_add(soft_iface, ethhdr->h_source);
 
@@ -189,16 +427,60 @@ end:
 }
 
 void interface_rx(struct net_device *soft_iface,
-		  struct sk_buff *skb, int hdr_size)
+		  struct sk_buff *skb, struct batman_if *recv_if,
+		  int hdr_size)
 {
-	struct bat_priv *priv = netdev_priv(soft_iface);
+	struct bat_priv *bat_priv = netdev_priv(soft_iface);
+	struct unicast_packet *unicast_packet;
+	struct ethhdr *ethhdr;
+	struct vlan_ethhdr *vhdr;
+	short vid = -1;
+	int ret;
 
 	/* check if enough space is available for pulling, and pull */
 	if (!pskb_may_pull(skb, hdr_size))
 		goto dropped;
 
 	skb_pull_rcsum(skb, hdr_size);
-/*	skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
+	skb_reset_mac_header(skb);
+
+	ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+	switch (ntohs(ethhdr->h_proto)) {
+	case ETH_P_8021Q:
+		vhdr = (struct vlan_ethhdr *)skb->data;
+		vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK;
+
+		if (ntohs(vhdr->h_vlan_encapsulated_proto) != ETH_P_BATMAN)
+			break;
+
+		/* fall through */
+	case ETH_P_BATMAN:
+		goto dropped;
+	}
+
+	/**
+	 * if we have a another chosen mesh exit node in range
+	 * it will transport the packets to the non-mesh network
+	 */
+	if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) {
+		skb_push(skb, hdr_size);
+		unicast_packet = (struct unicast_packet *)skb->data;
+
+		if ((unicast_packet->packet_type != BAT_UNICAST) &&
+		    (unicast_packet->packet_type != BAT_UNICAST_FRAG))
+			goto dropped;
+
+		skb_reset_mac_header(skb);
+
+		memcpy(unicast_packet->dest,
+		       bat_priv->softif_neigh->addr, ETH_ALEN);
+		ret = route_unicast_packet(skb, recv_if, hdr_size);
+		if (ret == NET_RX_DROP)
+			goto dropped;
+
+		goto out;
+	}
 
 	/* skb->dev & skb->pkt_type are set here */
 	if (unlikely(!pskb_may_pull(skb, ETH_HLEN)))
@@ -211,8 +493,8 @@ void interface_rx(struct net_device *soft_iface,
 
 /*	skb->ip_summed = CHECKSUM_UNNECESSARY;*/
 
-	priv->stats.rx_packets++;
-	priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
+	bat_priv->stats.rx_packets++;
+	bat_priv->stats.rx_bytes += skb->len + sizeof(struct ethhdr);
 
 	soft_iface->last_rx = jiffies;
 
@@ -221,6 +503,7 @@ void interface_rx(struct net_device *soft_iface,
 
 dropped:
 	kfree_skb(skb);
+out:
 	return;
 }
 
@@ -310,6 +593,7 @@ struct net_device *softif_create(char *name)
 
 	bat_priv->primary_if = NULL;
 	bat_priv->num_ifaces = 0;
+	bat_priv->softif_neigh = NULL;
 
 	ret = sysfs_add_meshif(soft_iface);
 	if (ret < 0)
diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h
index 843a7ec..02b7733 100644
--- a/drivers/staging/batman-adv/soft-interface.h
+++ b/drivers/staging/batman-adv/soft-interface.h
@@ -23,9 +23,12 @@
 #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
 
 int my_skb_head_push(struct sk_buff *skb, unsigned int len);
+int softif_neigh_seq_print_text(struct seq_file *seq, void *offset);
+void softif_neigh_purge(struct bat_priv *bat_priv);
 int interface_tx(struct sk_buff *skb, struct net_device *soft_iface);
 void interface_rx(struct net_device *soft_iface,
-		  struct sk_buff *skb, int hdr_size);
+		  struct sk_buff *skb, struct batman_if *recv_if,
+		  int hdr_size);
 struct net_device *softif_create(char *name);
 void softif_destroy(struct net_device *soft_iface);
 
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h
index 8f6ba1c..835d51f 100644
--- a/drivers/staging/batman-adv/types.h
+++ b/drivers/staging/batman-adv/types.h
@@ -123,6 +123,8 @@ struct bat_priv {
 	atomic_t bcast_queue_left;
 	atomic_t batman_queue_left;
 	char num_ifaces;
+	struct hlist_head softif_neigh_list;
+	struct softif_neigh *softif_neigh;
 	struct debug_log *debug_log;
 	struct batman_if *primary_if;
 	struct kobject *mesh_obj;
@@ -141,6 +143,7 @@ struct bat_priv {
 	spinlock_t hna_ghash_lock; /* protects hna_global_hash */
 	spinlock_t vis_hash_lock; /* protects vis_hash */
 	spinlock_t vis_list_lock; /* protects vis_info::recv_list */
+	spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */
 	int16_t num_local_hna;
 	atomic_t hna_local_changed;
 	struct delayed_work hna_work;
@@ -239,4 +242,13 @@ struct recvlist_node {
 	uint8_t mac[ETH_ALEN];
 };
 
+struct softif_neigh {
+	struct hlist_node list;
+	uint8_t addr[ETH_ALEN];
+	unsigned long last_seen;
+	short vid;
+	struct kref refcount;
+	struct rcu_head rcu;
+};
+
 #endif /* _NET_BATMAN_ADV_TYPES_H_ */
-- 
1.7.2.3


  parent reply	other threads:[~2010-11-21 23:55 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-21 23:55 [B.A.T.M.A.N.] batman-adv for 2.6.38 (1) Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 01/29] Staging: batman-adv: Replace Andrew Lunn as Staging maintainer Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 02/29] Staging: batman-adv: ensure that eth_type_trans gets linear memory Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 03/29] Staging: batman-adv: Add new sysfs files to README Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 04/29] Staging: batman-adv: Don't remove interface with spinlock held Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 05/29] Staging: batman-adv: convert batman_if custom refcounting to kref functions Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 06/29] Staging: batman-adv: use rcu callbacks when freeing batman_if Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 07/29] Staging: batman-adv: restructure fragmentation to handle batman unicast packets Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 08/29] Staging: batman-adv: add frag_ prefix to all fragmentation related functions Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 09/29] Staging: batman-adv: move skb reassembly of fragmented packets into dedicated function Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 10/29] Staging: batman-adv: remove redundant is_my_mac() check in route_unicast_packet Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 11/29] Staging: batman-adv: fragment forwarded packets Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 12/29] Staging: batman-adv: reassemble fragmented skb if mtu allows it Sven Eckelmann
2010-11-21 23:55 ` Sven Eckelmann [this message]
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 14/29] Staging: batman-adv: Unify sysfs file names with their bat_priv atomics Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 15/29] Staging: batman-adv: Wrapper functions for sysfs storing Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 16/29] Staging: batman-adv: Ommit storing struct device in sysfs functions Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 17/29] Staging: batman-adv: Make hop_penalty configurable via sysfs Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 18/29] Staging: batman-adv: Remove hashdata_compare_cb from hash Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 19/29] Staging: batman-adv: Remove hashdata_choose_cb " Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 20/29] Staging: batman-adv: Move hash callback related function to header Sven Eckelmann
2010-11-21 23:55 ` [B.A.T.M.A.N.] [PATCH 21/29] Staging: batman-adv: Make hash_iterate inlineable Sven Eckelmann
2010-11-21 23:56 ` [B.A.T.M.A.N.] [PATCH 22/29] Staging: batman-adv: Rewrite hash using hlist_* Sven Eckelmann
2010-11-21 23:56 ` [B.A.T.M.A.N.] [PATCH 23/29] Staging: batman-adv: Limit spin_locks to spin_lock_bh Sven Eckelmann
2010-11-21 23:56 ` [B.A.T.M.A.N.] [PATCH 24/29] Staging: batman-adv: adding gateway functionality Sven Eckelmann
2010-11-21 23:56 ` [B.A.T.M.A.N.] [PATCH 25/29] Staging: batman-adv: send DHCP requests directly to the chosen gw Sven Eckelmann
2010-11-21 23:56 ` [B.A.T.M.A.N.] [PATCH 26/29] Staging: batman-adv: best gw DHCP filter 802.1Q support Sven Eckelmann
2010-11-21 23:56 ` [B.A.T.M.A.N.] [PATCH 27/29] Staging: batman-adv: add gateway IPv6 support by filtering DHCPv6 messages Sven Eckelmann
2010-11-21 23:56 ` [B.A.T.M.A.N.] [PATCH 28/29] Staging: batman-adv: Use kernel version min macro Sven Eckelmann
2010-11-21 23:56 ` [B.A.T.M.A.N.] [PATCH 29/29] Staging: batman-adv: Use kernel functions to identify broadcasts Sven Eckelmann
2010-11-22  1:06 ` [B.A.T.M.A.N.] batman-adv for 2.6.38 (1) Marek Lindner
2010-11-22 10:28   ` Sven Eckelmann
2010-11-22 11:34     ` [B.A.T.M.A.N.] Staging: batman-adv for 2.6.37 (6) Sven Eckelmann
2010-11-29 18:55       ` Greg KH
2010-11-22 11:34     ` [B.A.T.M.A.N.] [PATCH-stable] Staging: batman-adv: ensure that eth_type_trans gets linear memory Sven Eckelmann
2010-11-22 11:34     ` [B.A.T.M.A.N.] [PATCH 1/2] " Sven Eckelmann
2010-11-22 11:34     ` [B.A.T.M.A.N.] [PATCH 2/2] Staging: batman-adv: Don't remove interface with spinlock held Sven Eckelmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1290383767-32602-14-git-send-email-sven.eckelmann@gmx.de \
    --to=sven.eckelmann@gmx.de \
    --cc=b.a.t.m.a.n@lists.open-mesh.org \
    --cc=greg@kroah.com \
    --cc=lindner_marek@yahoo.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).