[B.A.T.M.A.N.] [PATCH] batman-adv: Deinline batadv_orig_hash_find, save 9024 bytes
by Denys Vlasenko
This function compiles to 473 bytes of machine code.
21 callsites.
text data bss dec hex filename
95903266 20860288 35991552 152755106 91adba2 vmlinux_before
95894242 20860288 35991552 152746082 91ab862 vmlinux
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
CC: Marek Lindner <mareklindner(a)neomailbox.ch>
CC: Simon Wunderlich <sw(a)simonwunderlich.de>
CC: Antonio Quartulli <a(a)unstable.cc>
CC: Sven Eckelmann <sven(a)narfation.org>
CC: b.a.t.m.a.n(a)lists.open-mesh.org
CC: linux-kernel(a)vger.kernel.org
---
net/batman-adv/originator.c | 29 +++++++++++++++++++++++++++++
net/batman-adv/originator.h | 31 ++-----------------------------
2 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index e4cbb07..bcf78f1 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -47,6 +47,36 @@
/* hash class keys */
static struct lock_class_key batadv_orig_hash_lock_class_key;
+struct batadv_orig_node *
+batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data)
+{
+ struct batadv_hashtable *hash = bat_priv->orig_hash;
+ struct hlist_head *head;
+ struct batadv_orig_node *orig_node, *orig_node_tmp = NULL;
+ int index;
+
+ if (!hash)
+ return NULL;
+
+ index = batadv_choose_orig(data, hash->size);
+ head = &hash->table[index];
+
+ rcu_read_lock();
+ hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
+ if (!batadv_compare_eth(orig_node, data))
+ continue;
+
+ if (!kref_get_unless_zero(&orig_node->refcount))
+ continue;
+
+ orig_node_tmp = orig_node;
+ break;
+ }
+ rcu_read_unlock();
+
+ return orig_node_tmp;
+}
+
static void batadv_purge_orig(struct work_struct *work);
/**
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h
index 4e8b67f..db7a87d 100644
--- a/net/batman-adv/originator.h
+++ b/net/batman-adv/originator.h
@@ -96,34 +96,7 @@ static inline u32 batadv_choose_orig(const void *data, u32 size)
return hash % size;
}
-static inline struct batadv_orig_node *
-batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data)
-{
- struct batadv_hashtable *hash = bat_priv->orig_hash;
- struct hlist_head *head;
- struct batadv_orig_node *orig_node, *orig_node_tmp = NULL;
- int index;
-
- if (!hash)
- return NULL;
-
- index = batadv_choose_orig(data, hash->size);
- head = &hash->table[index];
-
- rcu_read_lock();
- hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
- if (!batadv_compare_eth(orig_node, data))
- continue;
-
- if (!kref_get_unless_zero(&orig_node->refcount))
- continue;
-
- orig_node_tmp = orig_node;
- break;
- }
- rcu_read_unlock();
-
- return orig_node_tmp;
-}
+struct batadv_orig_node *
+batadv_orig_hash_find(struct batadv_priv *bat_priv, const void *data);
#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */
--
1.8.1.4
5 years, 3 months
[B.A.T.M.A.N.] [PATCH 0/3] batman-adv: Deletion of a few unnecessary checks
by SF Markus Elfring
From: Markus Elfring <elfring(a)users.sourceforge.net>
Date: Tue, 3 Nov 2015 21:34:29 +0100
Further update suggestions were taken into account after a patch
was applied from static source code analysis.
Markus Elfring (3):
Delete an unnecessary check before the function call "batadv_softif_vlan_free_ref"
Split a condition check
Less function calls in batadv_is_ap_isolated() after error detection
net/batman-adv/translation-table.c | 29 ++++++++++++++---------------
1 file changed, 14 insertions(+), 15 deletions(-)
--
2.6.2
6 years, 3 months
[B.A.T.M.A.N.] Patch to add mesh_no_rebroadcast
by Ruben Wisniewski
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
hard-interface.c | 2 ++
send.c | 4 ++++
sysfs-class-net-batman-adv | 10 ++++++++
sysfs.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++
types.h | 1 +
5 files changed, 76 insertions(+)
diff --git a/hard-interface.c b/hard-interface.c
index fbda6b5..3997f9c 100644
--- a/hard-interface.c
+++ b/hard-interface.c
@@ -591,6 +591,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
/* extra reference for return */
atomic_set(&hard_iface->refcount, 2);
+ atomic_set(&hard_iface->no_rebroadcast, 0);
+
batadv_check_known_mac_addr(hard_iface->net_dev);
list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
diff --git a/send.c b/send.c
index d27161e..4383a66 100644
--- a/send.c
+++ b/send.c
@@ -513,6 +513,10 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
if (forw_packet->num_packets >= hard_iface->num_bcasts)
continue;
+ if (atomic_read(&hard_iface->no_rebroadcast) &&
+ forw_packet->skb->dev == hard_iface->net_dev)
+ continue;
+
/* send a copy of the saved skb */
skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC);
if (skb1)
diff --git a/sysfs-class-net-batman-adv b/sysfs-class-net-batman-adv
index 7f34a95..cf7fe00 100644
--- a/sysfs-class-net-batman-adv
+++ b/sysfs-class-net-batman-adv
@@ -13,3 +13,13 @@ Description:
displays the batman mesh interface this <iface>
currently is associated with.
+What: /sys/class/net/<iface>/batman-adv/no_rebroadcast
+Date: Sep 2013
+Contact: Linus Lüssing <linus.luessing(a)web.de>
+Description:
+ With this option set incoming multicast payload frames on
+ <iface> are not being rebroadcasted on <iface> again. This
+ option should be set on links which are known to be transitive
+ and symmetric only, for instance point-to-point wifi longshots
+ or wired links. Using this option wrongly is going to
+ break your mesh network, use at your own risk!
diff --git a/sysfs.c b/sysfs.c
index fc47baa..adaeca4 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -110,6 +110,17 @@ struct batadv_attribute batadv_attr_vlan_##_name = { \
.store = _store, \
}
+/* Use this, if you have customized show and store functions
+ * for hard interface attrs
+ */
+#define BATADV_ATTR_HIF(_name, _mode, _show, _store) \
+struct batadv_attribute batadv_attr_hif_##_name = { \
+ .attr = {.name = __stringify(_name), \
+ .mode = _mode }, \
+ .show = _show, \
+ .store = _store, \
+};
+
/* Use this, if you have customized show and store functions */
#define BATADV_ATTR(_name, _mode, _show, _store) \
struct batadv_attribute batadv_attr_##_name = { \
@@ -221,6 +232,52 @@ ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \
static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \
batadv_store_vlan_##_name)
+#define BATADV_ATTR_HIF_STORE_BOOL(_name, _post_func) \
+ssize_t batadv_store_hif_##_name(struct kobject *kobj, \
+ struct attribute *attr, char *buff, \
+ size_t count) \
+{ \
+ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
+ struct batadv_hard_iface *hard_iface; \
+ size_t res; \
+ \
+ hard_iface = batadv_hardif_get_by_netdev(net_dev); \
+ if (!hard_iface) \
+ return 0; \
+ \
+ res = __batadv_store_bool_attr(buff, count, _post_func, \
+ attr, &hard_iface->_name, \
+ hard_iface->soft_iface); \
+ batadv_hardif_free_ref(hard_iface); \
+ return res; \
+}
+
+#define BATADV_ATTR_HIF_SHOW_BOOL(_name) \
+ssize_t batadv_show_hif_##_name(struct kobject *kobj, \
+ struct attribute *attr, char *buff) \
+{ \
+ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \
+ struct batadv_hard_iface *hard_iface; \
+ size_t res; \
+ \
+ hard_iface = batadv_hardif_get_by_netdev(net_dev); \
+ if (!hard_iface) \
+ return 0; \
+ \
+ res = sprintf(buff, "%s\n", \
+ atomic_read(&hard_iface->_name) == 0 ? \
+ "disabled" : "enabled"); \
+ batadv_hardif_free_ref(hard_iface); \
+ return res; \
+}
+
+/* Use this, if you are going to turn a [name] in the vlan struct on or off */
+#define BATADV_ATTR_HIF_BOOL(_name, _mode, _post_func) \
+ static BATADV_ATTR_HIF_STORE_BOOL(_name, _post_func) \
+ static BATADV_ATTR_HIF_SHOW_BOOL(_name) \
+ static BATADV_ATTR_HIF(_name, _mode, batadv_show_hif_##_name, \
+ batadv_store_hif_##_name)
+
static int batadv_store_bool_attr(char *buff, size_t count,
struct net_device *net_dev,
const char *attr_name, atomic_t *attr)
@@ -844,10 +901,12 @@ static ssize_t batadv_show_iface_status(struct kobject *kobj,
static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface,
batadv_store_mesh_iface);
static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL);
+BATADV_ATTR_HIF_BOOL(no_rebroadcast, S_IRUGO | S_IWUSR, NULL);
static struct batadv_attribute *batadv_batman_attrs[] = {
&batadv_attr_mesh_iface,
&batadv_attr_iface_status,
+ &batadv_attr_hif_no_rebroadcast,
NULL,
};
diff --git a/types.h b/types.h
index 8854c05..39619fb 100644
--- a/types.h
+++ b/types.h
@@ -101,6 +101,7 @@ struct batadv_hard_iface {
struct batadv_hard_iface_bat_iv bat_iv;
struct work_struct cleanup_work;
struct dentry *debug_dir;
+ atomic_t no_rebroadcast;
};
/**
--
2.1.3
6 years, 6 months
[B.A.T.M.A.N.] [PATCH 1/2] batman-adv: Fix broadcast+ogm queue purging race condition
by Linus Lüssing
So far on purging broadcast and ogm queues we temporarily give up the
spin lock of these queues to be able to cancel any scheduled forwarding
work. However this is unsafe and can lead to a general protection error
in batadv_purge_outstanding_packets().
With this patch we split the queue purging into two steps: First
removing forward packets from those queues and signaling the
cancelation. Secondly, we are actively canceling any scheduled
forwarding, wait for any running forwarding to finish and only free a
forw_packet afterwards.
Signed-off-by: Linus Lüssing <linus.luessing(a)web.de>
---
Fixes issue #168
send.c | 117 ++++++++++++++++++++++++++++++++++++++-------------------------
types.h | 1 +
2 files changed, 71 insertions(+), 47 deletions(-)
diff --git a/send.c b/send.c
index 0a0bb45..f93476b 100644
--- a/send.c
+++ b/send.c
@@ -245,6 +245,10 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
bat_priv = netdev_priv(soft_iface);
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
+ if (hlist_unhashed(&forw_packet->list)) {
+ spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
+ return;
+ }
hlist_del(&forw_packet->list);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
@@ -293,6 +297,10 @@ void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work)
delayed_work);
bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface);
spin_lock_bh(&bat_priv->forw_bat_list_lock);
+ if (hlist_unhashed(&forw_packet->list)) {
+ spin_unlock_bh(&bat_priv->forw_bat_list_lock);
+ return;
+ }
hlist_del(&forw_packet->list);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
@@ -316,13 +324,68 @@ out:
batadv_forw_packet_free(forw_packet);
}
+/**
+ * batadv_cancel_packets - Cancels a list of forward packets
+ * @forw_list: The to be canceled forward packets
+ * @canceled_list: The backup list.
+ *
+ * This canceles any scheduled forwarding packet tasks in the provided
+ * forw_list. The packets are being moved from the forw_list to the
+ * canceled_list afterwards to unhash the forward packet list pointer,
+ * allowing any already running task to notice the cancelation.
+ */
+static void batadv_cancel_packets(struct hlist_head *forw_list,
+ struct hlist_head *canceled_list,
+ const struct batadv_hard_iface *hard_iface)
+{
+ struct batadv_forw_packet *forw_packet;
+ struct hlist_node *tmp_node, *safe_tmp_node;
+
+ hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
+ forw_list, list) {
+ /* if purge_outstanding_packets() was called with an argument
+ * we delete only packets belonging to the given interface
+ */
+ if ((hard_iface) &&
+ (forw_packet->if_incoming != hard_iface))
+ continue;
+
+ hlist_del_init(&forw_packet->list);
+ hlist_add_head(&forw_packet->canceled_list, canceled_list);
+ }
+}
+
+/**
+ * batadv_canceled_packets_free - Frees canceled forward packets
+ * @head: A list of to be freed forw_packets
+ *
+ * This function canceles the scheduling of any packet in the provided list,
+ * waits for any possibly running packet forwarding thread to finish and
+ * finally, safely frees this forward packet.
+ *
+ * This function might sleep.
+ */
+static void batadv_canceled_packets_free(struct hlist_head *head)
+{
+ struct batadv_forw_packet *forw_packet;
+ struct hlist_node *tmp_node, *safe_tmp_node;
+
+ hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node, head,
+ canceled_list) {
+ cancel_delayed_work_sync(&forw_packet->delayed_work);
+
+ hlist_del(&forw_packet->canceled_list);
+ batadv_forw_packet_free(forw_packet);
+ }
+}
+
void
batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
const struct batadv_hard_iface *hard_iface)
{
- struct batadv_forw_packet *forw_packet;
- struct hlist_node *tmp_node, *safe_tmp_node;
- bool pending;
+ struct hlist_head head;
+
+ INIT_HLIST_HEAD(&head);
if (hard_iface)
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -334,53 +397,13 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv,
/* free bcast list */
spin_lock_bh(&bat_priv->forw_bcast_list_lock);
- hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
- &bat_priv->forw_bcast_list, list) {
- /* if purge_outstanding_packets() was called with an argument
- * we delete only packets belonging to the given interface
- */
- if ((hard_iface) &&
- (forw_packet->if_incoming != hard_iface))
- continue;
-
- spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
-
- /* batadv_send_outstanding_bcast_packet() will lock the list to
- * delete the item from the list
- */
- pending = cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock_bh(&bat_priv->forw_bcast_list_lock);
-
- if (pending) {
- hlist_del(&forw_packet->list);
- batadv_forw_packet_free(forw_packet);
- }
- }
+ batadv_cancel_packets(&bat_priv->forw_bcast_list, &head, hard_iface);
spin_unlock_bh(&bat_priv->forw_bcast_list_lock);
/* free batman packet list */
spin_lock_bh(&bat_priv->forw_bat_list_lock);
- hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
- &bat_priv->forw_bat_list, list) {
- /* if purge_outstanding_packets() was called with an argument
- * we delete only packets belonging to the given interface
- */
- if ((hard_iface) &&
- (forw_packet->if_incoming != hard_iface))
- continue;
-
- spin_unlock_bh(&bat_priv->forw_bat_list_lock);
-
- /* send_outstanding_bat_packet() will lock the list to
- * delete the item from the list
- */
- pending = cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock_bh(&bat_priv->forw_bat_list_lock);
-
- if (pending) {
- hlist_del(&forw_packet->list);
- batadv_forw_packet_free(forw_packet);
- }
- }
+ batadv_cancel_packets(&bat_priv->forw_bat_list, &head, hard_iface);
spin_unlock_bh(&bat_priv->forw_bat_list_lock);
+
+ batadv_canceled_packets_free(&head);
}
diff --git a/types.h b/types.h
index aba8364..f62a35f 100644
--- a/types.h
+++ b/types.h
@@ -853,6 +853,7 @@ struct batadv_skb_cb {
*/
struct batadv_forw_packet {
struct hlist_node list;
+ struct hlist_node canceled_list;
unsigned long send_time;
uint8_t own;
struct sk_buff *skb;
--
1.7.10.4
6 years, 6 months
[B.A.T.M.A.N.] [RFC] batman-adv: use kmem_cache for translation table
by Sven Eckelmann
The two translation tables (global, local) contain equally sized objects.
The global translation table changes often when a client is
connected/removed from the mesh. So it makes sense to keep a cache of the
equally sized objects.
TODO statistics, batadv_tt_roam_node?, batadv_tt_change_node?,
batadv_tt_req_node?, ....
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
net/batman-adv/main.c | 16 +++++-
net/batman-adv/translation-table.c | 115 ++++++++++++++++++++++++++++++++++---
net/batman-adv/translation-table.h | 3 +
3 files changed, 125 insertions(+), 9 deletions(-)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 275604b..1c546d9 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -81,6 +81,12 @@ static void batadv_recv_handler_init(void);
static int __init batadv_init(void)
{
+ int ret;
+
+ ret = batadv_tt_cache_init();
+ if (ret < 0)
+ return ret;
+
INIT_LIST_HEAD(&batadv_hardif_list);
batadv_algo_init();
@@ -91,9 +97,8 @@ static int __init batadv_init(void)
batadv_nc_init();
batadv_event_workqueue = create_singlethread_workqueue("bat_events");
-
if (!batadv_event_workqueue)
- return -ENOMEM;
+ goto err_create_wq;
batadv_socket_init();
batadv_debugfs_init();
@@ -106,6 +111,11 @@ static int __init batadv_init(void)
BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION);
return 0;
+
+err_create_wq:
+ batadv_tt_cache_destroy();
+
+ return -ENOMEM;
}
static void __exit batadv_exit(void)
@@ -121,6 +131,8 @@ static void __exit batadv_exit(void)
batadv_event_workqueue = NULL;
rcu_barrier();
+
+ batadv_tt_cache_destroy();
}
int batadv_mesh_init(struct net_device *soft_iface)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 13cae72..f9b865b 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -22,12 +22,14 @@
#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
+#include <linux/cache.h>
#include <linux/compiler.h>
#include <linux/crc32c.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
#include <linux/fs.h>
#include <linux/if_ether.h>
+#include <linux/init.h>
#include <linux/jhash.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
@@ -54,6 +56,10 @@
#include "soft-interface.h"
#include "tvlv.h"
+static struct kmem_cache *batadv_tl_cache __read_mostly;
+static struct kmem_cache *batadv_tg_cache __read_mostly;
+static struct kmem_cache *batadv_tt_orig_cache __read_mostly;
+
/* hash class keys */
static struct lock_class_key batadv_tt_local_hash_lock_class_key;
static struct lock_class_key batadv_tt_global_hash_lock_class_key;
@@ -205,6 +211,20 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const u8 *addr,
}
/**
+ * batadv_tt_local_entry_free_rcu - free the tt_local_entry
+ * @rcu: rcu pointer of the tt_local_entry
+ */
+static void batadv_tt_local_entry_free_rcu(struct rcu_head *rcu)
+{
+ struct batadv_tt_local_entry *tt_local_entry;
+
+ tt_local_entry = container_of(rcu, struct batadv_tt_local_entry,
+ common.rcu);
+
+ kmem_cache_free(batadv_tl_cache, tt_local_entry);
+}
+
+/**
* batadv_tt_local_entry_release - release tt_local_entry from lists and queue
* for free after rcu grace period
* @ref: kref pointer of the nc_node
@@ -218,7 +238,7 @@ static void batadv_tt_local_entry_release(struct kref *ref)
batadv_softif_vlan_put(tt_local_entry->vlan);
- kfree_rcu(tt_local_entry, common.rcu);
+ call_rcu(&tt_local_entry->common.rcu, batadv_tt_local_entry_free_rcu);
}
/**
@@ -234,6 +254,20 @@ batadv_tt_local_entry_put(struct batadv_tt_local_entry *tt_local_entry)
}
/**
+ * batadv_tt_global_entry_free_rcu - free the tt_global_entry
+ * @rcu: rcu pointer of the tt_global_entry
+ */
+static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
+{
+ struct batadv_tt_global_entry *tt_global_entry;
+
+ tt_global_entry = container_of(rcu, struct batadv_tt_global_entry,
+ common.rcu);
+
+ kmem_cache_free(batadv_tg_cache, tt_global_entry);
+}
+
+/**
* batadv_tt_global_entry_release - release tt_global_entry from lists and queue
* for free after rcu grace period
* @ref: kref pointer of the nc_node
@@ -246,7 +280,8 @@ static void batadv_tt_global_entry_release(struct kref *ref)
common.refcount);
batadv_tt_global_del_orig_list(tt_global_entry);
- kfree_rcu(tt_global_entry, common.rcu);
+
+ call_rcu(&tt_global_entry->common.rcu, batadv_tt_global_entry_free_rcu);
}
/**
@@ -384,6 +419,19 @@ static void batadv_tt_global_size_dec(struct batadv_orig_node *orig_node,
}
/**
+ * batadv_tt_orig_list_entry_free_rcu - free the orig_entry
+ * @rcu: rcu pointer of the orig_entry
+ */
+static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
+{
+ struct batadv_tt_orig_list_entry *orig_entry;
+
+ orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu);
+
+ kmem_cache_free(batadv_tt_orig_cache, orig_entry);
+}
+
+/**
* batadv_tt_orig_list_entry_release - release tt orig entry from lists and
* queue for free after rcu grace period
* @ref: kref pointer of the tt orig entry
@@ -396,7 +444,7 @@ static void batadv_tt_orig_list_entry_release(struct kref *ref)
refcount);
batadv_orig_node_put(orig_entry->orig_node);
- kfree_rcu(orig_entry, rcu);
+ call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
}
/**
@@ -646,7 +694,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
goto out;
}
- tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
+ tt_local = kmem_cache_alloc(batadv_tl_cache, GFP_ATOMIC);
if (!tt_local)
goto out;
@@ -654,7 +702,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
vlan = batadv_softif_vlan_get(bat_priv, vid);
if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d",
addr, BATADV_PRINT_VID(vid))) {
- kfree(tt_local);
+ kmem_cache_free(batadv_tl_cache, tt_local);
tt_local = NULL;
goto out;
}
@@ -1342,10 +1390,12 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
goto out;
}
- orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC);
+ orig_entry = kmem_cache_alloc(batadv_tt_orig_cache, GFP_ATOMIC);
if (!orig_entry)
goto out;
+ memset(orig_entry, 0, sizeof(*orig_entry));
+
INIT_HLIST_NODE(&orig_entry->list);
kref_get(&orig_node->refcount);
batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
@@ -1412,10 +1462,12 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
goto out;
if (!tt_global_entry) {
- tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
+ tt_global_entry = kmem_cache_alloc(batadv_tg_cache, GFP_ATOMIC);
if (!tt_global_entry)
goto out;
+ memset(tt_global_entry, 0, sizeof(*tt_global_entry));
+
common = &tt_global_entry->common;
ether_addr_copy(common->addr, tt_addr);
common->vid = vid;
@@ -3835,3 +3887,52 @@ bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
return ret;
}
+
+/**
+ * batadv_tt_cache_init - Initialize tt memory object cache
+ *
+ * Return: 0 on success or negative error number in case of failure.
+ */
+int __init batadv_tt_cache_init(void)
+{
+ size_t tl_size = sizeof(struct batadv_tt_local_entry);
+ size_t tg_size = sizeof(struct batadv_tt_global_entry);
+ size_t tt_orig_size = sizeof(struct batadv_tt_orig_list_entry);
+
+ batadv_tl_cache = kmem_cache_create("batadv_tl_cache", tl_size, 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!batadv_tl_cache)
+ return -ENOMEM;
+
+ batadv_tg_cache = kmem_cache_create("batadv_tg_cache", tg_size, 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!batadv_tg_cache)
+ goto err_tg_alloc;
+
+ batadv_tt_orig_cache = kmem_cache_create("batadv_tt_orig_cache",
+ tt_orig_size, 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!batadv_tt_orig_cache)
+ goto err_tt_orig_alloc;
+
+ return 0;
+
+err_tt_orig_alloc:
+ kmem_cache_destroy(batadv_tg_cache);
+ batadv_tg_cache = NULL;
+err_tg_alloc:
+ kmem_cache_destroy(batadv_tl_cache);
+ batadv_tl_cache = NULL;
+
+ return -ENOMEM;
+}
+
+/**
+ * batadv_tt_cache_destroy - Destroy tt memory object cache
+ */
+void batadv_tt_cache_destroy(void)
+{
+ kmem_cache_destroy(batadv_tl_cache);
+ kmem_cache_destroy(batadv_tg_cache);
+ kmem_cache_destroy(batadv_tt_orig_cache);
+}
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h
index 7c7e2c0..02b0f85 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -59,4 +59,7 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
bool batadv_tt_global_is_isolated(struct batadv_priv *bat_priv,
const u8 *addr, unsigned short vid);
+int batadv_tt_cache_init(void);
+void batadv_tt_cache_destroy(void);
+
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
--
2.8.1
6 years, 7 months
[B.A.T.M.A.N.] [PATCHv3 0/6] batman-adv: Optimizations for setups running dat and bla
by Andreas Pape
This patchset introduces optimizations for batman-adv in setups having several
gateways into a common (switched) Ethernet backbone network especially if dat
is additionally enabled.
Using the current implementation with bla and dat enabled, several problems
can be observed in a real setup:
1. Multiplication of ARP replies from dat enabled gateways and dat enabled
mesh nodes leading to an "ARP reply storm" in the common backbone network.
2. In rare corner cases bla does not fully prevent looping of unicast frames
in the direction Backbone --> mesh --> backbone and looping of multicast
frames in the direction mesh --> backbone --> mesh.
The latter can lead to temporary confusion in the switched backbone resulting
in packet loss and communication timeouts.
The observed problems are solved by introduction of additional rules for the
dat handling, bla packet forwarding and bla claiming/unclaiming of clients.
v3:
- rebased patchset
- moved snooping of ip addresses for dat speed up into separate function
- removed "patch of a patch"
- removed automatic claiming during check of a claim
- fixed issues of the patchset not being compiled due to chosen batman
options
Kind regards,
Andreas
..................................................................
PHOENIX CONTACT ELECTRONICS GmbH
Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont
USt-Id-Nr.: DE811742156
Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
___________________________________________________________________
Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren, jegliche anderweitige Verwendung sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
----------------------------------------------------------------------------------------------------
This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure, distribution or other use of the material or parts thereof is strictly forbidden.
___________________________________________________________________
6 years, 7 months
[B.A.T.M.A.N.] Non-batman Clients
by Jonathan Haws
I've followed the quick start guide, but apparently I'm missing
something when it comes to non-batman clients.
I've set all this up using vagrant and VirtualBox. The mesh seems to
work perfectly, however when I put in non-batman clients they cannot
communicate one with another. I would expect that they would be able to
ping one another.
I've given IP addresses to the bridge adapters on the 192.168.1.0/24
subnet. The clients I've given IP addresses on that same subnet
(192.168.1.121 and 192.168.1.142). When I tried pinging, I don't get
anything back. Sniffing packets in tcpdump shows that it is never
getting anything back, though I did get an ARP back once with the
correct MAC address, but still couldn't ping. Never got an ARP back
again...
I can ping from each client to the IP address of the bridge they are
connecting to, but cannot ping anything else on the network.
Any thoughts? Hopefully someone has seen this before and can point me
in the right direction!
Also, is there a separate list for alfred, or should I use this list for
alfred questions?
Thanks!
Jon
Here are the commands I used to setup:
batctl if add eth0 (eth0 already up)
ip link add name br0 type bridge
ip link set dev eth1 master br0
ip link set dev bat0 master br0
ip link set up dev eth1
ip link set up dev bat0
ip addr replace dev br0 192.168.1.102/24 (and 104 on the other node)
Here is what batadv-vis shows for my setup (I changed the labels "TT"
for the two clients to "CLI<IP>").
digraph {
subgraph "cluster_08:00:27:2c:10:05" {
"08:00:27:2c:10:05"
}
"08:00:27:2c:10:05" -> "08:00:27:6b:86:2e" [label="1.016"]
"08:00:27:2c:10:05" -> "0a:00:27:00:00:06" [label="TT"]
"08:00:27:2c:10:05" -> "1e:8d:d3:23:ab:d4" [label="TT"]
"08:00:27:2c:10:05" -> "08:00:27:b1:38:03" [label="CLI142"]
"08:00:27:2c:10:05" -> "1e:8d:d3:23:ab:d4" [label="TT"]
"08:00:27:2c:10:05" -> "08:00:27:1c:9b:14" [label="TT"]
subgraph "cluster_08:00:27:a2:8c:62" {
"08:00:27:a2:8c:62"
}
"08:00:27:a2:8c:62" -> "08:00:27:83:dd:41" [label="1.000"]
"08:00:27:a2:8c:62" -> "08:00:27:38:31:55" [label="1.000"]
"08:00:27:a2:8c:62" -> "08:00:27:f6:78:1a" [label="TT"]
"08:00:27:a2:8c:62" -> "d6:f4:e6:bd:22:fb" [label="TT"]
"08:00:27:a2:8c:62" -> "d6:f4:e6:bd:22:fb" [label="TT"]
"08:00:27:a2:8c:62" -> "0a:00:27:00:00:05" [label="TT"]
subgraph "cluster_08:00:27:38:31:55" {
"08:00:27:38:31:55"
}
"08:00:27:38:31:55" -> "08:00:27:83:dd:41" [label="1.000"]
"08:00:27:38:31:55" -> "08:00:27:a2:8c:62" [label="1.000"]
"08:00:27:38:31:55" -> "52:98:12:67:6b:06" [label="TT"]
"08:00:27:38:31:55" -> "0a:00:27:00:00:04" [label="TT"]
"08:00:27:38:31:55" -> "08:00:27:08:ee:90" [label="CLI121"]
"08:00:27:38:31:55" -> "52:98:12:67:6b:06" [label="TT"]
"08:00:27:38:31:55" -> "08:00:27:17:21:9d" [label="TT"]
subgraph "cluster_08:00:27:6b:86:2e" {
"08:00:27:6b:86:2e"
"08:00:27:83:dd:41" [peripheries=2]
}
"08:00:27:6b:86:2e" -> "08:00:27:2c:10:05" [label="1.000"]
"08:00:27:83:dd:41" -> "08:00:27:38:31:55" [label="1.000"]
"08:00:27:83:dd:41" -> "08:00:27:a2:8c:62" [label="1.016"]
"08:00:27:6b:86:2e" -> "a6:f4:5c:fa:06:cd" [label="TT"]
"08:00:27:6b:86:2e" -> "0a:00:27:00:00:03" [label="TT"]
"08:00:27:6b:86:2e" -> "08:00:27:9c:bb:a3" [label="TT"]
"08:00:27:6b:86:2e" -> "a6:f4:5c:fa:06:cd" [label="TT"]
}
6 years, 7 months
[B.A.T.M.A.N.] [PATCH] batctl: Fix format string for raw tp_meter output
by Sven Eckelmann
The tp_meter output for raw bytes is not casting the values to float.
It must therefore use PRIu64 to print the results.
Reported-by: Simon Wunderlich <sw(a)simonwunderlich.de>
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
tp_meter.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tp_meter.c b/tp_meter.c
index d980ebd..43c19da 100644
--- a/tp_meter.c
+++ b/tp_meter.c
@@ -524,8 +524,8 @@ int tp_meter(char *mesh_iface, int argc, char **argv)
(float)throughput / (1<<10),
(float)throughput * 8 / 1000);
else
- printf("%lu Bytes/s (%lu Bps)\n",
- throughput, throughput * 8);
+ printf("%" PRIu64 " Bytes/s (%" PRIu64 " Bps)\n",
+ throughput, throughput * 8);
ret = 0;
break;
--
2.8.1
6 years, 7 months
[B.A.T.M.A.N.] [PATCH] batman-adv: Fix hardif remove/add race
by Andrew Lunn
A hard interface can be removed and then added back in quick
succession. This is particularly true for hdlc interface when changing
the protocol.
It is not possible it synchronously remove the sysfs and debugfs
entries for the hard interface when it is removed because the files
may be open. Thus removal is deferred. The files may thus already
exist in sysfs and debugfs when the hard interface is re-added, and
the operations fail.
To fix this race, synchronously rename the debugfs and sysfs files to
a unique temporary name, thus making the name available when the
interface comes back, yet keeps open files still available.
Signed-off-by: Andrew Lunn <andrew(a)lunn.ch>
---
net/batman-adv/debugfs.c | 23 +++++++++++++++++++++++
net/batman-adv/debugfs.h | 1 +
net/batman-adv/hard-interface.c | 19 +++++++++++++++++++
net/batman-adv/sysfs.c | 17 +++++++++++++++++
net/batman-adv/sysfs.h | 2 ++
5 files changed, 62 insertions(+)
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
index 50545b0..8b852aa 100644
--- a/net/batman-adv/debugfs.c
+++ b/net/batman-adv/debugfs.c
@@ -55,6 +55,7 @@
#include "translation-table.h"
static struct dentry *batadv_debugfs;
+static atomic_t batadv_rename = ATOMIC_INIT(0);
#ifdef CONFIG_BATMAN_ADV_DEBUG
#define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1)
@@ -570,6 +571,28 @@ void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface)
}
}
+/**
+ * batadv_debugfs_rename_hardif - rename the base directory
+ * @hard_iface: hard interface which is renamed.
+ *
+ * The interface may be removed and then quickly added back
+ * again. Rename the old instance to something temporary and unique,
+ * so avoiding a name space clash if it does reappear before the deferred
+ * work completes the removal.
+ */
+void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface)
+{
+ char new_name[32];
+
+ snprintf(new_name, sizeof(*new_name) - 1, "tmp-%d",
+ atomic_inc_return(&batadv_rename));
+
+ if (batadv_debugfs && hard_iface->debug_dir) {
+ debugfs_rename(batadv_debugfs, hard_iface->debug_dir,
+ batadv_debugfs, new_name);
+ }
+}
+
int batadv_debugfs_add_meshif(struct net_device *dev)
{
struct batadv_priv *bat_priv = netdev_priv(dev);
diff --git a/net/batman-adv/debugfs.h b/net/batman-adv/debugfs.h
index 1ab4e2e..e7d19c1 100644
--- a/net/batman-adv/debugfs.h
+++ b/net/batman-adv/debugfs.h
@@ -34,6 +34,7 @@ int batadv_debugfs_add_meshif(struct net_device *dev);
void batadv_debugfs_del_meshif(struct net_device *dev);
int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface);
void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface);
+void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface);
#else
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index bf4ee24..08b62d9 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -747,6 +747,23 @@ out:
return NULL;
}
+/**
+ * batadv_hardif_rename - rename the sysfs and debugfs
+ * @hard_iface: The hard interface to rename
+ *
+ * The sysfs and debugfs files cannot be removed until all users close
+ * them. So the removal is differed into a work queue. This however
+ * means if the interface comes back before the work queue runs, the
+ * files are still there, and so the create gives an EEXISTS error. To
+ * avoid this, rename them to a tempory name.
+ */
+static void batadv_hardif_rename(struct batadv_hard_iface *hard_iface)
+{
+ batadv_sysfs_rename_hardif(&hard_iface->hardif_obj,
+ hard_iface->net_dev);
+ batadv_debugfs_rename_hardif(hard_iface);
+}
+
static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface)
{
ASSERT_RTNL();
@@ -760,6 +777,8 @@ static void batadv_hardif_remove_interface(struct batadv_hard_iface *hard_iface)
return;
hard_iface->if_status = BATADV_IF_TO_BE_REMOVED;
+ batadv_hardif_rename(hard_iface);
+
queue_work(batadv_event_workqueue, &hard_iface->cleanup_work);
}
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
index 233abcf..37b0aae 100644
--- a/net/batman-adv/sysfs.c
+++ b/net/batman-adv/sysfs.c
@@ -47,6 +47,8 @@
#include "packet.h"
#include "soft-interface.h"
+static atomic_t batadv_rename = ATOMIC_INIT(0);
+
static struct net_device *batadv_kobj_to_netdev(struct kobject *obj)
{
struct device *dev = container_of(obj->parent, struct device, kobj);
@@ -1045,6 +1047,21 @@ out:
return -ENOMEM;
}
+void batadv_sysfs_rename_hardif(struct kobject **hardif_obj,
+ struct net_device *dev)
+{
+ char new_name[32];
+ int err;
+
+ snprintf(new_name, sizeof(*new_name) - 1, "tmp-%d",
+ atomic_inc_return(&batadv_rename));
+
+ err = kobject_rename(*hardif_obj, new_name);
+ if (err)
+ batadv_err(dev, "Can't rename sysfs dir: %s/%s: %d\n",
+ dev->name, new_name, err);
+}
+
void batadv_sysfs_del_hardif(struct kobject **hardif_obj)
{
kobject_put(*hardif_obj);
diff --git a/net/batman-adv/sysfs.h b/net/batman-adv/sysfs.h
index c76021b..64d3722 100644
--- a/net/batman-adv/sysfs.h
+++ b/net/batman-adv/sysfs.h
@@ -48,6 +48,8 @@ void batadv_sysfs_del_meshif(struct net_device *dev);
int batadv_sysfs_add_hardif(struct kobject **hardif_obj,
struct net_device *dev);
void batadv_sysfs_del_hardif(struct kobject **hardif_obj);
+void batadv_sysfs_rename_hardif(struct kobject **hardif_obj,
+ struct net_device *dev);
int batadv_sysfs_add_vlan(struct net_device *dev,
struct batadv_softif_vlan *vlan);
void batadv_sysfs_del_vlan(struct batadv_priv *bat_priv,
--
2.8.0.rc3
6 years, 7 months