[B.A.T.M.A.N.] [PATCH] batman-adv: remove useless newline
by Antonio Quartulli
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
network-coding.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/network-coding.c b/network-coding.c
index 4eb49fc..f7c5430 100644
--- a/network-coding.c
+++ b/network-coding.c
@@ -1504,8 +1504,7 @@ void batadv_nc_skb_store_sniffed_unicast(struct batadv_priv *bat_priv,
* in case of an error.
*/
static struct batadv_unicast_packet *
-batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv,
- struct sk_buff *skb,
+batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
struct batadv_nc_packet *nc_packet)
{
const int h_size = sizeof(struct batadv_unicast_packet);
--
1.8.1.5
9 years, 1 month
Re: [B.A.T.M.A.N.] linux-next: build failure after merge of the net-next tree
by Antonio Quartulli
Hi Stephen,
On Fri, Apr 19, 2013 at 01:21:27PM +1000, Stephen Rothwell wrote:
>
> Caused by commits 612d2b4fe0a1 ("batman-adv: network coding - save
> overheard and tx packets for decoding") and 2df5278b0267 ("batman-adv:
> network coding - receive coded packets and decode them") from the
> net-next tree interacting with commit fe8a93b95145 ("batman-adv: make
> is_my_mac() check for the current mesh only") from the net tree.
>
> I added the following merge fix patch and can carry it as necessary:
thank you very much for taking care of this.
However, as I wrote to David in the pull request which generated this noise
(http://patchwork.ozlabs.org/patch/237363/), I am now going to send a second
pull request which fixes this problem properly and adds the related kernel doc.
Your patch looks good, but I'd prefer to send my already prepared pull request.
Is it ok with you?
Cheers,
--
Antonio Quartulli
..each of us alone is worth nothing..
Ernesto "Che" Guevara
9 years, 1 month
[B.A.T.M.A.N.] pull request: batman-adv 2013-04-17
by Antonio Quartulli
Hi David,
here you have a patch intended for net/linux-3.9 (if it can still make it..).
It is fixing a MAC address check routine which does not behave
correctly in case of multiple mesh interfaces in the same node.
This patch will generate some conflicts the next time you will merge net in
net-next and will also break it (this happens because the function this patch is
changing is used by some patches existing in net-next only).
I will send some instruction on how to solve the merge conflicts and a patch to
fix net-next soon.
Please pull or let me know if there is any problem.
Thanks a lot,
Antonio
The following changes since commit 361cd29cf9363505c2a35bbf9a034a22feebfb07:
qlcnic: fix beaconing test for 82xx adapter (2013-04-17 01:15:29 -0400)
are available in the git repository at:
git://git.open-mesh.org/linux-merge.git tags/batman-adv-fix-for-davem
for you to fetch changes up to fe8a93b95145c66adf196eea4a919dfe0b7c57db:
batman-adv: make is_my_mac() check for the current mesh only (2013-04-17 22:31:22 +0200)
----------------------------------------------------------------
Included changes:
- fix MAC address check in case of multiple mesh interfaces
----------------------------------------------------------------
Antonio Quartulli (1):
batman-adv: make is_my_mac() check for the current mesh only
net/batman-adv/main.c | 5 ++++-
net/batman-adv/main.h | 2 +-
net/batman-adv/routing.c | 38 ++++++++++++++++++++------------------
net/batman-adv/translation-table.c | 2 +-
net/batman-adv/vis.c | 4 ++--
5 files changed, 28 insertions(+), 23 deletions(-)
9 years, 1 month
[B.A.T.M.A.N.] [PATCHv2 1/2] batman-adv: avoid race conditions on TT global table by counting references
by Antonio Quartulli
To avoid race conditions on TT global table clean up keep
track of the number of active contexts (each tt_global_entry
in the hash table is an active context) and destroy the
table only when the counter reaches zero.
In this way the TT global table internal hash cannot be
deleted until all the entries have been destroyed.
CC: Linus Lüssing <linus.luessing(a)web.de>
CC: Simon Wunderlich <siwu(a)hrz.tu-chemnitz.de>
CC: Marek Lindner <lindner_marek(a)yahoo.de>
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
v2:
- RCU callbacks reworking
- split the patch in 2 pieces
Cheers,
soft-interface.c | 7 +++
translation-table.c | 126 +++++++++++++++++++++++++++++++++-------------------
types.h | 4 ++
3 files changed, 92 insertions(+), 45 deletions(-)
diff --git a/soft-interface.c b/soft-interface.c
index 403b8c4..e2acf76 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -582,6 +582,13 @@ static void batadv_softif_free(struct net_device *dev)
{
batadv_debugfs_del_meshif(dev);
batadv_mesh_free(dev);
+
+ /* at this point there are some RCU tasks scheduled (TT free) which
+ * requires the bat_priv struct to exist. Wait for the tasks to be
+ * finished before freeing bat_priv
+ */
+ rcu_barrier();
+
free_netdev(dev);
}
diff --git a/translation-table.c b/translation-table.c
index 96dfb38..bf8b7fa 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -42,6 +42,9 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
const unsigned char *addr,
const char *message, bool roaming);
+static void
+batadv_tt_global_entry_free_ref(struct batadv_priv *bat_priv,
+ struct batadv_tt_global_entry *tt_global_entry);
/* returns 1 if they are the same mac addr */
static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
@@ -117,6 +120,41 @@ batadv_tt_local_entry_free_ref(struct batadv_tt_local_entry *tt_local_entry)
kfree_rcu(tt_local_entry, common.rcu);
}
+/**
+ * batadv_tt_global_table_free_rcu - purge the tt global table
+ * @rcu: RCU object handling the context of the callback
+ *
+ * Free the hash. This function is invoked only when the hash table is empty
+ * and this is guaranteed by the fact that its refcounter reached zero.
+ */
+static void
+batadv_tt_global_table_free_rcu(struct rcu_head *rcu)
+{
+ struct batadv_priv_tt *tt_priv;
+
+ tt_priv = container_of(rcu, struct batadv_priv_tt, global_rcu);
+
+ batadv_hash_destroy(tt_priv->global_hash);
+ tt_priv->global_hash = NULL;
+}
+
+/**
+ * batadv_tt_global_table_free_ref - decrement the global table refcounter and
+ * possibly schedule its clean up
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void
+batadv_tt_global_table_free_ref(struct batadv_priv *bat_priv)
+{
+ /* test if this was the last reference to the global table. If so,
+ * destroy the table as well
+ */
+ if (!atomic_dec_and_test(&bat_priv->tt.global_refcount))
+ return;
+
+ call_rcu(&bat_priv->tt.global_rcu, batadv_tt_global_table_free_rcu);
+}
+
static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
{
struct batadv_tt_common_entry *tt_common_entry;
@@ -129,14 +167,23 @@ static void batadv_tt_global_entry_free_rcu(struct rcu_head *rcu)
kfree(tt_global_entry);
}
+/**
+ * batadv_tt_global_entry_free_ref - decrement the global entry refcounter and
+ * possibly schedule its clean up
+ * @bat_priv: the bat priv with all the soft interface information
+ * @tt_global_entry: the entry which refcounter has to be decremented
+ */
static void
-batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry)
+batadv_tt_global_entry_free_ref(struct batadv_priv *bat_priv,
+ struct batadv_tt_global_entry *tt_global_entry)
{
- if (atomic_dec_and_test(&tt_global_entry->common.refcount)) {
- batadv_tt_global_del_orig_list(tt_global_entry);
- call_rcu(&tt_global_entry->common.rcu,
- batadv_tt_global_entry_free_rcu);
- }
+ if (!atomic_dec_and_test(&tt_global_entry->common.refcount))
+ return;
+
+ batadv_tt_global_del_orig_list(tt_global_entry);
+ batadv_tt_global_table_free_ref(bat_priv);
+
+ call_rcu(&tt_global_entry->common.rcu, batadv_tt_global_entry_free_rcu);
}
static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu)
@@ -251,7 +298,7 @@ static void batadv_tt_global_free(struct batadv_priv *bat_priv,
batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
batadv_choose_orig, tt_global->common.addr);
- batadv_tt_global_entry_free_ref(tt_global);
+ batadv_tt_global_entry_free_ref(bat_priv, tt_global);
}
void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
@@ -364,7 +411,7 @@ out:
if (tt_local)
batadv_tt_local_entry_free_ref(tt_local);
if (tt_global)
- batadv_tt_global_entry_free_ref(tt_global);
+ batadv_tt_global_entry_free_ref(bat_priv, tt_global);
}
static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff,
@@ -687,6 +734,12 @@ static int batadv_tt_global_init(struct batadv_priv *bat_priv)
if (!bat_priv->tt.global_hash)
return -ENOMEM;
+ /* initialise the refcount to 1 meaning that the global table is used by
+ * the TT component. This is balanced by tt_global_table_free_ref() in
+ * tt_global_table_free()
+ */
+ atomic_set(&bat_priv->tt.global_refcount, 1);
+
batadv_hash_set_lock_class(bat_priv->tt.global_hash,
&batadv_tt_global_hash_lock_class_key);
@@ -844,7 +897,17 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
if (unlikely(hash_added != 0)) {
/* remove the reference for the hash */
- batadv_tt_global_entry_free_ref(tt_global_entry);
+ batadv_tt_global_entry_free_ref(bat_priv,
+ tt_global_entry);
+ goto out_remove;
+ }
+
+ /* increase the refcounter for this new "reference to the global
+ * table represented by the global entry. If the increment
+ * fails remove the entry from the hash
+ */
+ if (!atomic_inc_not_zero(&bat_priv->tt.global_refcount)) {
+ hlist_del_rcu(&tt_global_entry->common.hash_entry);
goto out_remove;
}
} else {
@@ -918,7 +981,7 @@ out_remove:
out:
if (tt_global_entry)
- batadv_tt_global_entry_free_ref(tt_global_entry);
+ batadv_tt_global_entry_free_ref(bat_priv, tt_global_entry);
if (tt_local_entry)
batadv_tt_local_entry_free_ref(tt_local_entry);
return ret;
@@ -1180,7 +1243,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
out:
if (tt_global_entry)
- batadv_tt_global_entry_free_ref(tt_global_entry);
+ batadv_tt_global_entry_free_ref(bat_priv, tt_global_entry);
if (local_entry)
batadv_tt_local_entry_free_ref(local_entry);
}
@@ -1219,7 +1282,8 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
"Deleting global tt entry %pM: %s\n",
tt_global->common.addr, message);
hlist_del_rcu(&tt_common_entry->hash_entry);
- batadv_tt_global_entry_free_ref(tt_global);
+ batadv_tt_global_entry_free_ref(bat_priv,
+ tt_global);
}
}
spin_unlock_bh(list_lock);
@@ -1280,7 +1344,7 @@ static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
hlist_del_rcu(&tt_common->hash_entry);
- batadv_tt_global_entry_free_ref(tt_global);
+ batadv_tt_global_entry_free_ref(bat_priv, tt_global);
}
spin_unlock_bh(list_lock);
}
@@ -1288,38 +1352,10 @@ static void batadv_tt_global_purge(struct batadv_priv *bat_priv)
static void batadv_tt_global_table_free(struct batadv_priv *bat_priv)
{
- struct batadv_hashtable *hash;
- spinlock_t *list_lock; /* protects write access to the hash lists */
- struct batadv_tt_common_entry *tt_common_entry;
- struct batadv_tt_global_entry *tt_global;
- struct hlist_node *node_tmp;
- struct hlist_head *head;
- uint32_t i;
-
if (!bat_priv->tt.global_hash)
return;
- hash = bat_priv->tt.global_hash;
-
- for (i = 0; i < hash->size; i++) {
- head = &hash->table[i];
- list_lock = &hash->list_locks[i];
-
- spin_lock_bh(list_lock);
- hlist_for_each_entry_safe(tt_common_entry, node_tmp,
- head, hash_entry) {
- hlist_del_rcu(&tt_common_entry->hash_entry);
- tt_global = container_of(tt_common_entry,
- struct batadv_tt_global_entry,
- common);
- batadv_tt_global_entry_free_ref(tt_global);
- }
- spin_unlock_bh(list_lock);
- }
-
- batadv_hash_destroy(hash);
-
- bat_priv->tt.global_hash = NULL;
+ batadv_tt_global_table_free_ref(bat_priv);
}
static bool
@@ -1373,7 +1409,7 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
out:
if (tt_global_entry)
- batadv_tt_global_entry_free_ref(tt_global_entry);
+ batadv_tt_global_entry_free_ref(bat_priv, tt_global_entry);
if (tt_local_entry)
batadv_tt_local_entry_free_ref(tt_local_entry);
@@ -2433,7 +2469,7 @@ bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, uint8_t *src,
out:
if (tt_global_entry)
- batadv_tt_global_entry_free_ref(tt_global_entry);
+ batadv_tt_global_entry_free_ref(bat_priv, tt_global_entry);
if (tt_local_entry)
batadv_tt_local_entry_free_ref(tt_local_entry);
return ret;
@@ -2521,7 +2557,7 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
goto out;
ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
- batadv_tt_global_entry_free_ref(tt_global_entry);
+ batadv_tt_global_entry_free_ref(bat_priv, tt_global_entry);
out:
return ret;
}
diff --git a/types.h b/types.h
index 5f542bd..a293a9b 100644
--- a/types.h
+++ b/types.h
@@ -337,6 +337,8 @@ enum batadv_counters {
* @changes_list: tracks tt local changes within an originator interval
* @local_hash: local translation table hash table
* @global_hash: global translation table hash table
+ * @global_refcount: number of context where the global_hash table is used
+ * @global_rcu: object used to free the global table
* @req_list: list of pending & unanswered tt_requests
* @roam_list: list of the last roaming events of each client limiting the
* number of roaming events to avoid route flapping
@@ -357,6 +359,8 @@ struct batadv_priv_tt {
struct list_head changes_list;
struct batadv_hashtable *local_hash;
struct batadv_hashtable *global_hash;
+ atomic_t global_refcount;
+ struct rcu_head global_rcu;
struct list_head req_list;
struct list_head roam_list;
spinlock_t changes_list_lock; /* protects changes */
--
1.8.1.5
9 years, 1 month
[B.A.T.M.A.N.] [PATCHv2] batman-adv: pass a 16bit long flag argument to tt_global_add()
by Antonio Quartulli
it may be the case that we want to store some local TT client flags in a global
entry, therefore the tt_global_add needs to get a proper argument for this
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
v2:
- added kernel doc
translation-table.c | 19 +++++++++++++++++--
translation-table.h | 2 +-
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/translation-table.c b/translation-table.c
index 52808c4..bbda424 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -798,10 +798,25 @@ out:
batadv_tt_orig_list_entry_free_ref(orig_entry);
}
-/* caller must hold orig_node refcount */
+/**
+ * batadv_tt_global_add - add a new TT global entry or update it
+ * @bat_priv: the bat priv with all the soft interface information
+ * @orig_node: the originator announcing the client
+ * @tt_addr: the MAC address of the client
+ * @flags: TT flags that have to be set for this client
+ * @ttvn: the first originator's TT version number having this client
+ *
+ * Add a new TT global entry for the given originator. If the entry already
+ * exists add a new reference to the given originator (a global entry can have
+ * references to multiple originators) and adjust the flags attribute to reflect
+ * the function argument.
+ * If a TT local entry exists for this client remove it.
+ *
+ * The caller must hold orig_node refcount.
+ */
int batadv_tt_global_add(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
- const unsigned char *tt_addr, uint8_t flags,
+ const unsigned char *tt_addr, uint16_t flags,
uint8_t ttvn)
{
struct batadv_tt_global_entry *tt_global_entry;
diff --git a/translation-table.h b/translation-table.h
index ab8e683..659a3bb 100644
--- a/translation-table.h
+++ b/translation-table.h
@@ -33,7 +33,7 @@ void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
const unsigned char *tt_buff, int tt_buff_len);
int batadv_tt_global_add(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
- const unsigned char *addr, uint8_t flags,
+ const unsigned char *addr, uint16_t flags,
uint8_t ttvn);
int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
--
1.8.1.5
9 years, 1 month
[B.A.T.M.A.N.] [PATCH 1/2] batman-adv: pass a 16bit long flag argument to tt_global_add()
by Antonio Quartulli
it may be the case that we want to store some local TT client flags in a global
entry, therefore the tt_global_add needs to get a proper argument for this
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
Based on top of the TVLV patches sent by Marek (but they may apply on maser as
well)
Cheers,
translation-table.c | 2 +-
translation-table.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/translation-table.c b/translation-table.c
index 5d99c64..c1a8a10 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -786,7 +786,7 @@ out:
/* caller must hold orig_node refcount */
int batadv_tt_global_add(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
- const unsigned char *tt_addr, uint8_t flags,
+ const unsigned char *tt_addr, uint16_t flags,
uint8_t ttvn)
{
struct batadv_tt_global_entry *tt_global_entry;
diff --git a/translation-table.h b/translation-table.h
index 597a5d6..b4b6dea 100644
--- a/translation-table.h
+++ b/translation-table.h
@@ -32,7 +32,7 @@ void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
const unsigned char *tt_buff, int tt_buff_len);
int batadv_tt_global_add(struct batadv_priv *bat_priv,
struct batadv_orig_node *orig_node,
- const unsigned char *addr, uint8_t flags,
+ const unsigned char *addr, uint16_t flags,
uint8_t ttvn);
int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset);
void batadv_tt_global_del_orig(struct batadv_priv *bat_priv,
--
1.8.1.5
9 years, 1 month
[B.A.T.M.A.N.] [PATCH] batman-adv: don't deal with NET_IP_ALIGN manually
by Antonio Quartulli
Instead of dealing with NET_IP_ALIGN during allocation and
headroom reservation, it is possible to use
netdev_alloc_skb_ip_align() which transparently allocate
and reserve the correct amount of data
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
compat stuff: compiled tested only on 2.6.32
bat_iv_ogm.c | 6 +++---
compat.h | 10 ++++++++++
icmp_socket.c | 4 ++--
translation-table.c | 20 ++++++++++----------
vis.c | 12 ++++++------
5 files changed, 31 insertions(+), 21 deletions(-)
diff --git a/bat_iv_ogm.c b/bat_iv_ogm.c
index 071f288..197b1b0 100644
--- a/bat_iv_ogm.c
+++ b/bat_iv_ogm.c
@@ -413,16 +413,16 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
else
skb_size = packet_len;
- skb_size += ETH_HLEN + NET_IP_ALIGN;
+ skb_size += ETH_HLEN;
- forw_packet_aggr->skb = dev_alloc_skb(skb_size);
+ forw_packet_aggr->skb = netdev_alloc_skb_ip_align(NULL, skb_size);
if (!forw_packet_aggr->skb) {
if (!own_packet)
atomic_inc(&bat_priv->batman_queue_left);
kfree(forw_packet_aggr);
goto out;
}
- skb_reserve(forw_packet_aggr->skb, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(forw_packet_aggr->skb, ETH_HLEN);
INIT_HLIST_NODE(&forw_packet_aggr->list);
diff --git a/compat.h b/compat.h
index 0663df5..617ad71 100644
--- a/compat.h
+++ b/compat.h
@@ -74,6 +74,16 @@ static inline void batadv_this_cpu_add(uint64_t *count_ptr, size_t count)
#define batadv_softif_destroy_netlink(dev, head) batadv_softif_destroy_netlink(dev)
#define unregister_netdevice_queue(dev, head) unregister_netdevice(dev)
+static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev,
+ unsigned int length)
+{
+ struct sk_buff *skb = netdev_alloc_skb(dev, length + NET_IP_ALIGN);
+
+ if (NET_IP_ALIGN && skb)
+ skb_reserve(skb, NET_IP_ALIGN);
+ return skb;
+}
+
#endif /* < KERNEL_VERSION(2, 6, 33) */
diff --git a/icmp_socket.c b/icmp_socket.c
index 0ba6c89..b27508b 100644
--- a/icmp_socket.c
+++ b/icmp_socket.c
@@ -177,13 +177,13 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
if (len >= sizeof(struct batadv_icmp_packet_rr))
packet_len = sizeof(struct batadv_icmp_packet_rr);
- skb = dev_alloc_skb(packet_len + ETH_HLEN + NET_IP_ALIGN);
+ skb = netdev_alloc_skb_ip_align(NULL, packet_len + ETH_HLEN);
if (!skb) {
len = -ENOMEM;
goto out;
}
- skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(skb, ETH_HLEN);
icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len);
if (copy_from_user(icmp_packet, buff, packet_len)) {
diff --git a/translation-table.c b/translation-table.c
index 9322320..61e6ea8 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -1595,11 +1595,11 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = tt_query_size + tt_len;
- skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
+ skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!skb)
goto out;
- skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(skb, ETH_HLEN);
tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
tt_response->ttvn = ttvn;
@@ -1660,11 +1660,11 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
if (!tt_req_node)
goto out;
- skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
+ skb = netdev_alloc_skb_ip_align(NULL, sizeof(*tt_request) + ETH_HLEN);
if (!skb)
goto out;
- skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(skb, ETH_HLEN);
tt_req_len = sizeof(*tt_request);
tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
@@ -1757,11 +1757,11 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = sizeof(*tt_response) + tt_len;
- skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
+ skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!skb)
goto unlock;
- skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(skb, ETH_HLEN);
packet_pos = skb_put(skb, len);
tt_response = (struct batadv_tt_query_packet *)packet_pos;
tt_response->ttvn = req_ttvn;
@@ -1873,11 +1873,11 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
tt_tot = tt_len / sizeof(struct batadv_tt_change);
len = sizeof(*tt_response) + tt_len;
- skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
+ skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!skb)
goto unlock;
- skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(skb, ETH_HLEN);
packet_pos = skb_put(skb, len);
tt_response = (struct batadv_tt_query_packet *)packet_pos;
tt_response->ttvn = req_ttvn;
@@ -2207,11 +2207,11 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
if (!batadv_tt_check_roam_count(bat_priv, client))
goto out;
- skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN);
+ skb = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!skb)
goto out;
- skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(skb, ETH_HLEN);
roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
diff --git a/vis.c b/vis.c
index 962ccf3..2c60ecd 100644
--- a/vis.c
+++ b/vis.c
@@ -392,12 +392,12 @@ batadv_add_packet(struct batadv_priv *bat_priv,
return NULL;
len = sizeof(*packet) + vis_info_len;
- info->skb_packet = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
+ info->skb_packet = netdev_alloc_skb_ip_align(NULL, len + ETH_HLEN);
if (!info->skb_packet) {
kfree(info);
return NULL;
}
- skb_reserve(info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(info->skb_packet, ETH_HLEN);
packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);
kref_init(&info->refcount);
@@ -854,13 +854,13 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
if (!bat_priv->vis.my_info)
goto err;
- len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE;
- len += ETH_HLEN + NET_IP_ALIGN;
- bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len);
+ len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
+ bat_priv->vis.my_info->skb_packet = netdev_alloc_skb_ip_align(NULL,
+ len);
if (!bat_priv->vis.my_info->skb_packet)
goto free_info;
- skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
+ skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
tmp_skb = bat_priv->vis.my_info->skb_packet;
packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
--
1.8.1.5
9 years, 1 month
[B.A.T.M.A.N.] [PATCH next] batman-adv: fix global protection fault during soft_iface destruction
by Antonio Quartulli
batadv_mesh_free() schedules some RCU callbacks which need the bat_priv struct
to do their jobs, while free_netdev(), which is called immediately after, is
destroying the private data.
Put an rcu_barrier() in the middle so that free_netdev() is invoked only after
all the callbacks returned.
This bug has been introduced by ab8f433dd39be94e8617cff2dfe9f7eca162eb15
("batman-adv: Move deinitialization of soft-interface to destructor")
Signed-off-by: Antonio Quartulli <ordex(a)autistici.org>
---
soft-interface.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/soft-interface.c b/soft-interface.c
index 403b8c4..6f20d33 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -582,6 +582,13 @@ static void batadv_softif_free(struct net_device *dev)
{
batadv_debugfs_del_meshif(dev);
batadv_mesh_free(dev);
+
+ /* some scheduled RCU callbacks need the bat_priv struct to accomplish
+ * their tasks. Wait for them all to be finished before freeing the
+ * netdev and its private data (bat_priv)
+ */
+ rcu_barrier();
+
free_netdev(dev);
}
--
1.8.1.5
9 years, 1 month
[B.A.T.M.A.N.] [PATCH] batman-adv: Avoid double freeing of bat_counters
by Martin Hundebøll
On errors in batadv_mesh_init(), bat_counters will be freed in both
batadv_mesh_free() and batadv_softif_init_late(). This patch fixes this
by returning earlier from batadv_softif_init_late() in case of errors in
batadv_mesh_init().
Signed-off-by: Martin Hundebøll <martin(a)hundeboll.net>
---
soft-interface.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/soft-interface.c b/soft-interface.c
index c2a9c20..4de4d0f 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -503,6 +503,9 @@ static int batadv_softif_init_late(struct net_device *dev)
unreg_debugfs:
batadv_debugfs_del_meshif(dev);
+
+ return ret;
+
free_bat_counters:
free_percpu(bat_priv->bat_counters);
--
1.8.2.1
9 years, 1 month
[B.A.T.M.A.N.] [PATCH] batman-adv: refactor batadv_tt_local_event()
by Antonio Quartulli
From: Antonio Quartulli <antonio(a)open-mesh.com>
Instead of passing a generic combination of flags as
argument, it is easier to pass the entire tt_common
structure (containing the flags already set) plus a
bitfield of additional flags that will be unified with
the already existing ones before inserting the client
in the event queue.
In this way invocations of the modified function can be
simplified.
Signed-off-by: Antonio Quartulli <antonio(a)open-mesh.com>
---
translation-table.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/translation-table.c b/translation-table.c
index 9322320..3bebdcc 100644
--- a/translation-table.c
+++ b/translation-table.c
@@ -158,10 +158,19 @@ batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry)
call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu);
}
+/**
+ * batadv_tt_local_event - store a local TT event (ADD/DEL)
+ * @bat_priv: the bat priv with all the soft interface information
+ * @tt_local_entry: the TT entry involved in the event
+ * @additional_flags: other flag to store in the event structure
+ */
static void batadv_tt_local_event(struct batadv_priv *bat_priv,
- const uint8_t *addr, uint8_t flags)
+ struct batadv_tt_local_entry *tt_local_entry,
+ uint8_t additional_flags)
{
struct batadv_tt_change_node *tt_change_node, *entry, *safe;
+ struct batadv_tt_common_entry *common = &tt_local_entry->common;
+ uint8_t flags = common->flags | additional_flags;
bool event_removed = false;
bool del_op_requested, del_op_entry;
@@ -171,7 +180,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
return;
tt_change_node->change.flags = flags;
- memcpy(tt_change_node->change.addr, addr, ETH_ALEN);
+ memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN);
del_op_requested = flags & BATADV_TT_CLIENT_DEL;
@@ -179,7 +188,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv,
spin_lock_bh(&bat_priv->tt.changes_list_lock);
list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list,
list) {
- if (!batadv_compare_eth(entry->change.addr, addr))
+ if (!batadv_compare_eth(entry->change.addr, common->addr))
continue;
/* DEL+ADD in the same orig interval have no effect and can be
@@ -327,7 +336,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
}
add_event:
- batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
+ batadv_tt_local_event(bat_priv, tt_local, BATADV_NO_FLAGS);
check_roaming:
/* Check whether it is a roaming, but don't do anything if the roaming
@@ -524,8 +533,7 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
struct batadv_tt_local_entry *tt_local_entry,
uint16_t flags, const char *message)
{
- batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
- tt_local_entry->common.flags | flags);
+ batadv_tt_local_event(bat_priv, tt_local_entry, flags);
/* The local client has to be marked as "pending to be removed" but has
* to be kept in the table in order to send it in a full table
@@ -579,8 +587,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
/* if this client has been added right now, it is possible to
* immediately purge it
*/
- batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
- curr_flags | BATADV_TT_CLIENT_DEL);
+ batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
hlist_del_rcu(&tt_local_entry->common.hash_entry);
batadv_tt_local_entry_free_ref(tt_local_entry);
--
1.8.1.5
9 years, 1 month