summaryrefslogtreecommitdiff
path: root/net/batman-adv/soft-interface.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/batman-adv/soft-interface.c')
-rw-r--r--net/batman-adv/soft-interface.c77
1 files changed, 33 insertions, 44 deletions
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index e89ede192ed0..9ed26140a269 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
+ * Copyright (C) 2007-2011 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@@ -26,18 +26,15 @@
#include "send.h"
#include "bat_debugfs.h"
#include "translation-table.h"
-#include "types.h"
#include "hash.h"
#include "gateway_common.h"
#include "gateway_client.h"
-#include "send.h"
#include "bat_sysfs.h"
#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);
@@ -79,20 +76,18 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len)
return 0;
}
-static void softif_neigh_free_ref(struct kref *refcount)
+static void softif_neigh_free_rcu(struct rcu_head *rcu)
{
struct softif_neigh *softif_neigh;
- softif_neigh = container_of(refcount, struct softif_neigh, refcount);
+ softif_neigh = container_of(rcu, struct softif_neigh, rcu);
kfree(softif_neigh);
}
-static void softif_neigh_free_rcu(struct rcu_head *rcu)
+static void softif_neigh_free_ref(struct softif_neigh *softif_neigh)
{
- struct softif_neigh *softif_neigh;
-
- softif_neigh = container_of(rcu, struct softif_neigh, rcu);
- kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
+ if (atomic_dec_and_test(&softif_neigh->refcount))
+ call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
}
void softif_neigh_purge(struct bat_priv *bat_priv)
@@ -119,11 +114,10 @@ void softif_neigh_purge(struct bat_priv *bat_priv)
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);
+ softif_neigh_free_ref(softif_neigh_tmp);
}
- call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu);
+ softif_neigh_free_ref(softif_neigh);
}
spin_unlock_bh(&bat_priv->softif_neigh_lock);
@@ -138,14 +132,17 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
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)
+ if (!compare_eth(softif_neigh->addr, addr))
continue;
if (softif_neigh->vid != vid)
continue;
+ if (!atomic_inc_not_zero(&softif_neigh->refcount))
+ continue;
+
softif_neigh->last_seen = jiffies;
- goto found;
+ goto out;
}
softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC);
@@ -155,15 +152,14 @@ static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv,
memcpy(softif_neigh->addr, addr, ETH_ALEN);
softif_neigh->vid = vid;
softif_neigh->last_seen = jiffies;
- kref_init(&softif_neigh->refcount);
+ /* initialize with 2 - caller decrements counter by one */
+ atomic_set(&softif_neigh->refcount, 2);
INIT_HLIST_NODE(&softif_neigh->list);
spin_lock_bh(&bat_priv->softif_neigh_lock);
hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list);
spin_unlock_bh(&bat_priv->softif_neigh_lock);
-found:
- kref_get(&softif_neigh->refcount);
out:
rcu_read_unlock();
return softif_neigh;
@@ -175,8 +171,6 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
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 - "
@@ -186,33 +180,15 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset)
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",
+ seq_printf(seq, "%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;
}
@@ -267,7 +243,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
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);
+ softif_neigh_free_ref(softif_neigh_tmp);
/* we need to hold the additional reference */
goto err;
}
@@ -285,7 +261,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev,
}
out:
- kref_put(&softif_neigh->refcount, softif_neigh_free_ref);
+ softif_neigh_free_ref(softif_neigh);
err:
kfree_skb(skb);
return;
@@ -438,7 +414,7 @@ end:
}
void interface_rx(struct net_device *soft_iface,
- struct sk_buff *skb, struct batman_if *recv_if,
+ struct sk_buff *skb, struct hard_iface *recv_if,
int hdr_size)
{
struct bat_priv *bat_priv = netdev_priv(soft_iface);
@@ -486,7 +462,7 @@ void interface_rx(struct net_device *soft_iface,
memcpy(unicast_packet->dest,
bat_priv->softif_neigh->addr, ETH_ALEN);
- ret = route_unicast_packet(skb, recv_if, hdr_size);
+ ret = route_unicast_packet(skb, recv_if);
if (ret == NET_RX_DROP)
goto dropped;
@@ -646,6 +622,19 @@ void softif_destroy(struct net_device *soft_iface)
unregister_netdevice(soft_iface);
}
+int softif_is_valid(struct net_device *net_dev)
+{
+#ifdef HAVE_NET_DEVICE_OPS
+ if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
+ return 1;
+#else
+ if (net_dev->hard_start_xmit == interface_tx)
+ return 1;
+#endif
+
+ return 0;
+}
+
/* ethtool */
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{