Commit 5aa25c05 authored by David S. Miller's avatar David S. Miller

Merge tag 'batadv-next-for-davem-20181114' of git://git.open-mesh.org/linux-merge

Simon Wunderlich says:

====================
This feature/cleanup patchset includes the following patches:

 - Bump version strings, by Simon Wunderlich

 - Fixup includes, by Sven Eckelmann (3 patches)

 - Separate BATMAN_ADV_DEBUG from DEBUGFS, by Sven Eckelmann

 - Fixup tracing log documentation, by Sven Eckelmann

 - Use exclusive locks to secure netlink information dump transfers,
   by Sven Eckelmann (8 patches)

 - Move CRC16 dependency, by Sven Eckelmann

 - Enable MCAST by default, by Linus Luessing
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 45cf7959 016fd285
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
config BATMAN_ADV config BATMAN_ADV
tristate "B.A.T.M.A.N. Advanced Meshing Protocol" tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
depends on NET depends on NET
select CRC16
select LIBCRC32C select LIBCRC32C
help help
B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
...@@ -48,6 +47,7 @@ config BATMAN_ADV_BATMAN_V ...@@ -48,6 +47,7 @@ config BATMAN_ADV_BATMAN_V
config BATMAN_ADV_BLA config BATMAN_ADV_BLA
bool "Bridge Loop Avoidance" bool "Bridge Loop Avoidance"
depends on BATMAN_ADV && INET depends on BATMAN_ADV && INET
select CRC16
default y default y
help help
This option enables BLA (Bridge Loop Avoidance), a mechanism This option enables BLA (Bridge Loop Avoidance), a mechanism
...@@ -82,6 +82,7 @@ config BATMAN_ADV_NC ...@@ -82,6 +82,7 @@ config BATMAN_ADV_NC
config BATMAN_ADV_MCAST config BATMAN_ADV_MCAST
bool "Multicast optimisation" bool "Multicast optimisation"
depends on BATMAN_ADV && INET && !(BRIDGE=m && BATMAN_ADV=y) depends on BATMAN_ADV && INET && !(BRIDGE=m && BATMAN_ADV=y)
default y
help help
This option enables the multicast optimisation which aims to This option enables the multicast optimisation which aims to
reduce the air overhead while improving the reliability of reduce the air overhead while improving the reliability of
...@@ -100,12 +101,13 @@ config BATMAN_ADV_DEBUGFS ...@@ -100,12 +101,13 @@ config BATMAN_ADV_DEBUGFS
config BATMAN_ADV_DEBUG config BATMAN_ADV_DEBUG
bool "B.A.T.M.A.N. debugging" bool "B.A.T.M.A.N. debugging"
depends on BATMAN_ADV_DEBUGFS depends on BATMAN_ADV
help help
This is an option for use by developers; most people should This is an option for use by developers; most people should
say N here. This enables compilation of support for say N here. This enables compilation of support for
outputting debugging information to the kernel log. The outputting debugging information to the debugfs log or tracing
output is controlled via the module parameter debug. buffer. The output is controlled via the batadv netdev specific
log_level setting.
config BATMAN_ADV_TRACING config BATMAN_ADV_TRACING
bool "B.A.T.M.A.N. tracing support" bool "B.A.T.M.A.N. tracing support"
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/pkt_sched.h> #include <linux/pkt_sched.h>
...@@ -2585,13 +2584,14 @@ static void batadv_iv_gw_print(struct batadv_priv *bat_priv, ...@@ -2585,13 +2584,14 @@ static void batadv_iv_gw_print(struct batadv_priv *bat_priv,
* batadv_iv_gw_dump_entry() - Dump a gateway into a message * batadv_iv_gw_dump_entry() - Dump a gateway into a message
* @msg: Netlink message to dump into * @msg: Netlink message to dump into
* @portid: Port making netlink request * @portid: Port making netlink request
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @bat_priv: The bat priv with all the soft interface information * @bat_priv: The bat priv with all the soft interface information
* @gw_node: Gateway to be dumped * @gw_node: Gateway to be dumped
* *
* Return: Error code, or 0 on success * Return: Error code, or 0 on success
*/ */
static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_priv *bat_priv, struct batadv_priv *bat_priv,
struct batadv_gw_node *gw_node) struct batadv_gw_node *gw_node)
{ {
...@@ -2611,13 +2611,16 @@ static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -2611,13 +2611,16 @@ static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
curr_gw = batadv_gw_get_selected_gw_node(bat_priv); curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
NLM_F_MULTI, BATADV_CMD_GET_GATEWAYS); &batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_GATEWAYS);
if (!hdr) { if (!hdr) {
ret = -ENOBUFS; ret = -ENOBUFS;
goto out; goto out;
} }
genl_dump_check_consistent(cb, hdr);
ret = -EMSGSIZE; ret = -EMSGSIZE;
if (curr_gw == gw_node) if (curr_gw == gw_node)
...@@ -2668,13 +2671,15 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb, ...@@ -2668,13 +2671,15 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
int idx_skip = cb->args[0]; int idx_skip = cb->args[0];
int idx = 0; int idx = 0;
rcu_read_lock(); spin_lock_bh(&bat_priv->gw.list_lock);
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) { cb->seq = bat_priv->gw.generation << 1 | 1;
hlist_for_each_entry(gw_node, &bat_priv->gw.gateway_list, list) {
if (idx++ < idx_skip) if (idx++ < idx_skip)
continue; continue;
if (batadv_iv_gw_dump_entry(msg, portid, cb->nlh->nlmsg_seq, if (batadv_iv_gw_dump_entry(msg, portid, cb, bat_priv,
bat_priv, gw_node)) { gw_node)) {
idx_skip = idx - 1; idx_skip = idx - 1;
goto unlock; goto unlock;
} }
...@@ -2682,7 +2687,7 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb, ...@@ -2682,7 +2687,7 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
idx_skip = idx; idx_skip = idx;
unlock: unlock:
rcu_read_unlock(); spin_unlock_bh(&bat_priv->gw.list_lock);
cb->args[0] = idx_skip; cb->args[0] = idx_skip;
} }
......
...@@ -27,11 +27,13 @@ ...@@ -27,11 +27,13 @@
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kref.h> #include <linux/kref.h>
#include <linux/list.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/rculist.h> #include <linux/rculist.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
...@@ -915,13 +917,14 @@ static void batadv_v_gw_print(struct batadv_priv *bat_priv, ...@@ -915,13 +917,14 @@ static void batadv_v_gw_print(struct batadv_priv *bat_priv,
* batadv_v_gw_dump_entry() - Dump a gateway into a message * batadv_v_gw_dump_entry() - Dump a gateway into a message
* @msg: Netlink message to dump into * @msg: Netlink message to dump into
* @portid: Port making netlink request * @portid: Port making netlink request
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @bat_priv: The bat priv with all the soft interface information * @bat_priv: The bat priv with all the soft interface information
* @gw_node: Gateway to be dumped * @gw_node: Gateway to be dumped
* *
* Return: Error code, or 0 on success * Return: Error code, or 0 on success
*/ */
static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_priv *bat_priv, struct batadv_priv *bat_priv,
struct batadv_gw_node *gw_node) struct batadv_gw_node *gw_node)
{ {
...@@ -941,13 +944,16 @@ static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -941,13 +944,16 @@ static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
curr_gw = batadv_gw_get_selected_gw_node(bat_priv); curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
NLM_F_MULTI, BATADV_CMD_GET_GATEWAYS); &batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_GATEWAYS);
if (!hdr) { if (!hdr) {
ret = -ENOBUFS; ret = -ENOBUFS;
goto out; goto out;
} }
genl_dump_check_consistent(cb, hdr);
ret = -EMSGSIZE; ret = -EMSGSIZE;
if (curr_gw == gw_node) { if (curr_gw == gw_node) {
...@@ -1018,13 +1024,15 @@ static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb, ...@@ -1018,13 +1024,15 @@ static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
int idx_skip = cb->args[0]; int idx_skip = cb->args[0];
int idx = 0; int idx = 0;
rcu_read_lock(); spin_lock_bh(&bat_priv->gw.list_lock);
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) { cb->seq = bat_priv->gw.generation << 1 | 1;
hlist_for_each_entry(gw_node, &bat_priv->gw.gateway_list, list) {
if (idx++ < idx_skip) if (idx++ < idx_skip)
continue; continue;
if (batadv_v_gw_dump_entry(msg, portid, cb->nlh->nlmsg_seq, if (batadv_v_gw_dump_entry(msg, portid, cb, bat_priv,
bat_priv, gw_node)) { gw_node)) {
idx_skip = idx - 1; idx_skip = idx - 1;
goto unlock; goto unlock;
} }
...@@ -1032,7 +1040,7 @@ static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb, ...@@ -1032,7 +1040,7 @@ static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
idx_skip = idx; idx_skip = idx;
unlock: unlock:
rcu_read_unlock(); spin_unlock_bh(&bat_priv->gw.list_lock);
cb->args[0] = idx_skip; cb->args[0] = idx_skip;
} }
......
...@@ -2094,14 +2094,15 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) ...@@ -2094,14 +2094,15 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
* to a netlink socket * to a netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @primary_if: primary interface * @primary_if: primary interface
* @claim: entry to dump * @claim: entry to dump
* *
* Return: 0 or error code. * Return: 0 or error code.
*/ */
static int static int
batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_hard_iface *primary_if, struct batadv_hard_iface *primary_if,
struct batadv_bla_claim *claim) struct batadv_bla_claim *claim)
{ {
...@@ -2111,13 +2112,16 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -2111,13 +2112,16 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
void *hdr; void *hdr;
int ret = -EINVAL; int ret = -EINVAL;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
NLM_F_MULTI, BATADV_CMD_GET_BLA_CLAIM); &batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_BLA_CLAIM);
if (!hdr) { if (!hdr) {
ret = -ENOBUFS; ret = -ENOBUFS;
goto out; goto out;
} }
genl_dump_check_consistent(cb, hdr);
is_own = batadv_compare_eth(claim->backbone_gw->orig, is_own = batadv_compare_eth(claim->backbone_gw->orig,
primary_addr); primary_addr);
...@@ -2153,28 +2157,33 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -2153,28 +2157,33 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
* to a netlink socket * to a netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @primary_if: primary interface * @primary_if: primary interface
* @head: bucket to dump * @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip * @idx_skip: How many entries to skip
* *
* Return: always 0. * Return: always 0.
*/ */
static int static int
batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_hard_iface *primary_if, struct batadv_hard_iface *primary_if,
struct hlist_head *head, int *idx_skip) struct batadv_hashtable *hash, unsigned int bucket,
int *idx_skip)
{ {
struct batadv_bla_claim *claim; struct batadv_bla_claim *claim;
int idx = 0; int idx = 0;
int ret = 0; int ret = 0;
rcu_read_lock(); spin_lock_bh(&hash->list_locks[bucket]);
hlist_for_each_entry_rcu(claim, head, hash_entry) { cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(claim, &hash->table[bucket], hash_entry) {
if (idx++ < *idx_skip) if (idx++ < *idx_skip)
continue; continue;
ret = batadv_bla_claim_dump_entry(msg, portid, seq, ret = batadv_bla_claim_dump_entry(msg, portid, cb,
primary_if, claim); primary_if, claim);
if (ret) { if (ret) {
*idx_skip = idx - 1; *idx_skip = idx - 1;
...@@ -2184,7 +2193,7 @@ batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -2184,7 +2193,7 @@ batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
*idx_skip = 0; *idx_skip = 0;
unlock: unlock:
rcu_read_unlock(); spin_unlock_bh(&hash->list_locks[bucket]);
return ret; return ret;
} }
...@@ -2204,7 +2213,6 @@ int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -2204,7 +2213,6 @@ int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_hashtable *hash; struct batadv_hashtable *hash;
struct batadv_priv *bat_priv; struct batadv_priv *bat_priv;
int bucket = cb->args[0]; int bucket = cb->args[0];
struct hlist_head *head;
int idx = cb->args[1]; int idx = cb->args[1];
int ifindex; int ifindex;
int ret = 0; int ret = 0;
...@@ -2230,11 +2238,8 @@ int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -2230,11 +2238,8 @@ int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb)
} }
while (bucket < hash->size) { while (bucket < hash->size) {
head = &hash->table[bucket]; if (batadv_bla_claim_dump_bucket(msg, portid, cb, primary_if,
hash, bucket, &idx))
if (batadv_bla_claim_dump_bucket(msg, portid,
cb->nlh->nlmsg_seq,
primary_if, head, &idx))
break; break;
bucket++; bucket++;
} }
...@@ -2325,14 +2330,15 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) ...@@ -2325,14 +2330,15 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
* netlink socket * netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @primary_if: primary interface * @primary_if: primary interface
* @backbone_gw: entry to dump * @backbone_gw: entry to dump
* *
* Return: 0 or error code. * Return: 0 or error code.
*/ */
static int static int
batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_hard_iface *primary_if, struct batadv_hard_iface *primary_if,
struct batadv_bla_backbone_gw *backbone_gw) struct batadv_bla_backbone_gw *backbone_gw)
{ {
...@@ -2343,13 +2349,16 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -2343,13 +2349,16 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
void *hdr; void *hdr;
int ret = -EINVAL; int ret = -EINVAL;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
NLM_F_MULTI, BATADV_CMD_GET_BLA_BACKBONE); &batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_BLA_BACKBONE);
if (!hdr) { if (!hdr) {
ret = -ENOBUFS; ret = -ENOBUFS;
goto out; goto out;
} }
genl_dump_check_consistent(cb, hdr);
is_own = batadv_compare_eth(backbone_gw->orig, primary_addr); is_own = batadv_compare_eth(backbone_gw->orig, primary_addr);
spin_lock_bh(&backbone_gw->crc_lock); spin_lock_bh(&backbone_gw->crc_lock);
...@@ -2386,28 +2395,33 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -2386,28 +2395,33 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
* a netlink socket * a netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @primary_if: primary interface * @primary_if: primary interface
* @head: bucket to dump * @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip * @idx_skip: How many entries to skip
* *
* Return: always 0. * Return: always 0.
*/ */
static int static int
batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_hard_iface *primary_if, struct batadv_hard_iface *primary_if,
struct hlist_head *head, int *idx_skip) struct batadv_hashtable *hash,
unsigned int bucket, int *idx_skip)
{ {
struct batadv_bla_backbone_gw *backbone_gw; struct batadv_bla_backbone_gw *backbone_gw;
int idx = 0; int idx = 0;
int ret = 0; int ret = 0;
rcu_read_lock(); spin_lock_bh(&hash->list_locks[bucket]);
hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) { cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(backbone_gw, &hash->table[bucket], hash_entry) {
if (idx++ < *idx_skip) if (idx++ < *idx_skip)
continue; continue;
ret = batadv_bla_backbone_dump_entry(msg, portid, seq, ret = batadv_bla_backbone_dump_entry(msg, portid, cb,
primary_if, backbone_gw); primary_if, backbone_gw);
if (ret) { if (ret) {
*idx_skip = idx - 1; *idx_skip = idx - 1;
...@@ -2417,7 +2431,7 @@ batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -2417,7 +2431,7 @@ batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
*idx_skip = 0; *idx_skip = 0;
unlock: unlock:
rcu_read_unlock(); spin_unlock_bh(&hash->list_locks[bucket]);
return ret; return ret;
} }
...@@ -2437,7 +2451,6 @@ int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -2437,7 +2451,6 @@ int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_hashtable *hash; struct batadv_hashtable *hash;
struct batadv_priv *bat_priv; struct batadv_priv *bat_priv;
int bucket = cb->args[0]; int bucket = cb->args[0];
struct hlist_head *head;
int idx = cb->args[1]; int idx = cb->args[1];
int ifindex; int ifindex;
int ret = 0; int ret = 0;
...@@ -2463,11 +2476,8 @@ int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -2463,11 +2476,8 @@ int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
} }
while (bucket < hash->size) { while (bucket < hash->size) {
head = &hash->table[bucket]; if (batadv_bla_backbone_dump_bucket(msg, portid, cb, primary_if,
hash, bucket, &idx))
if (batadv_bla_backbone_dump_bucket(msg, portid,
cb->nlh->nlmsg_seq,
primary_if, head, &idx))
break; break;
bucket++; bucket++;
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "debugfs.h" #include "debugfs.h"
#include "main.h" #include "main.h"
#include <asm/current.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/sched.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/stddef.h> #include <linux/stddef.h>
......
...@@ -863,23 +863,27 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset) ...@@ -863,23 +863,27 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
* netlink socket * netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @dat_entry: entry to dump * @dat_entry: entry to dump
* *
* Return: 0 or error code. * Return: 0 or error code.
*/ */
static int static int
batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_dat_entry *dat_entry) struct batadv_dat_entry *dat_entry)
{ {
int msecs; int msecs;
void *hdr; void *hdr;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
NLM_F_MULTI, BATADV_CMD_GET_DAT_CACHE); &batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_DAT_CACHE);
if (!hdr) if (!hdr)
return -ENOBUFS; return -ENOBUFS;
genl_dump_check_consistent(cb, hdr);
msecs = jiffies_to_msecs(jiffies - dat_entry->last_update); msecs = jiffies_to_msecs(jiffies - dat_entry->last_update);
if (nla_put_in_addr(msg, BATADV_ATTR_DAT_CACHE_IP4ADDRESS, if (nla_put_in_addr(msg, BATADV_ATTR_DAT_CACHE_IP4ADDRESS,
...@@ -901,27 +905,31 @@ batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -901,27 +905,31 @@ batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
* a netlink socket * a netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @head: bucket to dump * @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip * @idx_skip: How many entries to skip
* *
* Return: 0 or error code. * Return: 0 or error code.
*/ */
static int static int
batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid,
struct hlist_head *head, int *idx_skip) struct netlink_callback *cb,
struct batadv_hashtable *hash, unsigned int bucket,
int *idx_skip)
{ {
struct batadv_dat_entry *dat_entry; struct batadv_dat_entry *dat_entry;
int idx = 0; int idx = 0;
rcu_read_lock(); spin_lock_bh(&hash->list_locks[bucket]);
hlist_for_each_entry_rcu(dat_entry, head, hash_entry) { cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(dat_entry, &hash->table[bucket], hash_entry) {
if (idx < *idx_skip) if (idx < *idx_skip)
goto skip; goto skip;
if (batadv_dat_cache_dump_entry(msg, portid, seq, if (batadv_dat_cache_dump_entry(msg, portid, cb, dat_entry)) {
dat_entry)) { spin_unlock_bh(&hash->list_locks[bucket]);
rcu_read_unlock();
*idx_skip = idx; *idx_skip = idx;
return -EMSGSIZE; return -EMSGSIZE;
...@@ -930,7 +938,7 @@ batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -930,7 +938,7 @@ batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
skip: skip:
idx++; idx++;
} }
rcu_read_unlock(); spin_unlock_bh(&hash->list_locks[bucket]);
return 0; return 0;
} }
...@@ -951,7 +959,6 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -951,7 +959,6 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_hashtable *hash; struct batadv_hashtable *hash;
struct batadv_priv *bat_priv; struct batadv_priv *bat_priv;
int bucket = cb->args[0]; int bucket = cb->args[0];
struct hlist_head *head;
int idx = cb->args[1]; int idx = cb->args[1];
int ifindex; int ifindex;
int ret = 0; int ret = 0;
...@@ -977,10 +984,7 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -977,10 +984,7 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
} }
while (bucket < hash->size) { while (bucket < hash->size) {
head = &hash->table[bucket]; if (batadv_dat_cache_dump_bucket(msg, portid, cb, hash, bucket,
if (batadv_dat_cache_dump_bucket(msg, portid,
cb->nlh->nlmsg_seq, head,
&idx)) &idx))
break; break;
......
...@@ -377,6 +377,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, ...@@ -377,6 +377,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
kref_get(&gw_node->refcount); kref_get(&gw_node->refcount);
hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list); hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list);
bat_priv->gw.generation++;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv, batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n", "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n",
...@@ -472,6 +473,7 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv, ...@@ -472,6 +473,7 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
if (!hlist_unhashed(&gw_node->list)) { if (!hlist_unhashed(&gw_node->list)) {
hlist_del_init_rcu(&gw_node->list); hlist_del_init_rcu(&gw_node->list);
batadv_gw_node_put(gw_node); batadv_gw_node_put(gw_node);
bat_priv->gw.generation++;
} }
spin_unlock_bh(&bat_priv->gw.list_lock); spin_unlock_bh(&bat_priv->gw.list_lock);
...@@ -518,6 +520,7 @@ void batadv_gw_node_free(struct batadv_priv *bat_priv) ...@@ -518,6 +520,7 @@ void batadv_gw_node_free(struct batadv_priv *bat_priv)
&bat_priv->gw.gateway_list, list) { &bat_priv->gw.gateway_list, list) {
hlist_del_init_rcu(&gw_node->list); hlist_del_init_rcu(&gw_node->list);
batadv_gw_node_put(gw_node); batadv_gw_node_put(gw_node);
bat_priv->gw.generation++;
} }
spin_unlock_bh(&bat_priv->gw.list_lock); spin_unlock_bh(&bat_priv->gw.list_lock);
} }
......
...@@ -951,6 +951,7 @@ batadv_hardif_add_interface(struct net_device *net_dev) ...@@ -951,6 +951,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
batadv_check_known_mac_addr(hard_iface->net_dev); batadv_check_known_mac_addr(hard_iface->net_dev);
kref_get(&hard_iface->refcount); kref_get(&hard_iface->refcount);
list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
batadv_hardif_generation++;
return hard_iface; return hard_iface;
...@@ -993,6 +994,7 @@ void batadv_hardif_remove_interfaces(void) ...@@ -993,6 +994,7 @@ void batadv_hardif_remove_interfaces(void)
list_for_each_entry_safe(hard_iface, hard_iface_tmp, list_for_each_entry_safe(hard_iface, hard_iface_tmp,
&batadv_hardif_list, list) { &batadv_hardif_list, list) {
list_del_rcu(&hard_iface->list); list_del_rcu(&hard_iface->list);
batadv_hardif_generation++;
batadv_hardif_remove_interface(hard_iface); batadv_hardif_remove_interface(hard_iface);
} }
rtnl_unlock(); rtnl_unlock();
...@@ -1054,6 +1056,7 @@ static int batadv_hard_if_event(struct notifier_block *this, ...@@ -1054,6 +1056,7 @@ static int batadv_hard_if_event(struct notifier_block *this,
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
case NETDEV_PRE_TYPE_CHANGE: case NETDEV_PRE_TYPE_CHANGE:
list_del_rcu(&hard_iface->list); list_del_rcu(&hard_iface->list);
batadv_hardif_generation++;
batadv_hardif_remove_interface(hard_iface); batadv_hardif_remove_interface(hard_iface);
break; break;
......
...@@ -32,6 +32,8 @@ static void batadv_hash_init(struct batadv_hashtable *hash) ...@@ -32,6 +32,8 @@ static void batadv_hash_init(struct batadv_hashtable *hash)
INIT_HLIST_HEAD(&hash->table[i]); INIT_HLIST_HEAD(&hash->table[i]);
spin_lock_init(&hash->list_locks[i]); spin_lock_init(&hash->list_locks[i]);
} }
atomic_set(&hash->generation, 0);
} }
/** /**
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "main.h" #include "main.h"
#include <linux/atomic.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/rculist.h> #include <linux/rculist.h>
...@@ -58,6 +59,9 @@ struct batadv_hashtable { ...@@ -58,6 +59,9 @@ struct batadv_hashtable {
/** @size: size of hashtable */ /** @size: size of hashtable */
u32 size; u32 size;
/** @generation: current (generation) sequence number */
atomic_t generation;
}; };
/* allocates and clears the hash */ /* allocates and clears the hash */
...@@ -112,6 +116,7 @@ static inline int batadv_hash_add(struct batadv_hashtable *hash, ...@@ -112,6 +116,7 @@ static inline int batadv_hash_add(struct batadv_hashtable *hash,
/* no duplicate found in list, add new element */ /* no duplicate found in list, add new element */
hlist_add_head_rcu(data_node, head); hlist_add_head_rcu(data_node, head);
atomic_inc(&hash->generation);
ret = 0; ret = 0;
...@@ -154,6 +159,7 @@ static inline void *batadv_hash_remove(struct batadv_hashtable *hash, ...@@ -154,6 +159,7 @@ static inline void *batadv_hash_remove(struct batadv_hashtable *hash,
data_save = node; data_save = node;
hlist_del_rcu(node); hlist_del_rcu(node);
atomic_inc(&hash->generation);
break; break;
} }
spin_unlock_bh(&hash->list_locks[index]); spin_unlock_bh(&hash->list_locks[index]);
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
#include "debugfs.h" #include "debugfs.h"
#include "trace.h" #include "trace.h"
#ifdef CONFIG_BATMAN_ADV_DEBUGFS
#define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1) #define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1)
static const int batadv_log_buff_len = BATADV_LOG_BUF_LEN; static const int batadv_log_buff_len = BATADV_LOG_BUF_LEN;
...@@ -92,33 +94,6 @@ static int batadv_fdebug_log(struct batadv_priv_debug_log *debug_log, ...@@ -92,33 +94,6 @@ static int batadv_fdebug_log(struct batadv_priv_debug_log *debug_log,
return 0; return 0;
} }
/**
* batadv_debug_log() - Add debug log entry
* @bat_priv: the bat priv with all the soft interface information
* @fmt: format string
*
* Return: 0 on success or negative error number in case of failure
*/
int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
batadv_fdebug_log(bat_priv->debug_log, "[%10u] %pV",
jiffies_to_msecs(jiffies), &vaf);
trace_batadv_dbg(bat_priv, &vaf);
va_end(args);
return 0;
}
static int batadv_log_open(struct inode *inode, struct file *file) static int batadv_log_open(struct inode *inode, struct file *file)
{ {
if (!try_module_get(THIS_MODULE)) if (!try_module_get(THIS_MODULE))
...@@ -259,3 +234,34 @@ void batadv_debug_log_cleanup(struct batadv_priv *bat_priv) ...@@ -259,3 +234,34 @@ void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
kfree(bat_priv->debug_log); kfree(bat_priv->debug_log);
bat_priv->debug_log = NULL; bat_priv->debug_log = NULL;
} }
#endif /* CONFIG_BATMAN_ADV_DEBUGFS */
/**
* batadv_debug_log() - Add debug log entry
* @bat_priv: the bat priv with all the soft interface information
* @fmt: format string
*
* Return: 0 on success or negative error number in case of failure
*/
int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
#ifdef CONFIG_BATMAN_ADV_DEBUGFS
batadv_fdebug_log(bat_priv->debug_log, "[%10u] %pV",
jiffies_to_msecs(jiffies), &vaf);
#endif
trace_batadv_dbg(bat_priv, &vaf);
va_end(args);
return 0;
}
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
* list traversals just rcu-locked * list traversals just rcu-locked
*/ */
struct list_head batadv_hardif_list; struct list_head batadv_hardif_list;
unsigned int batadv_hardif_generation;
static int (*batadv_rx_handler[256])(struct sk_buff *skb, static int (*batadv_rx_handler[256])(struct sk_buff *skb,
struct batadv_hard_iface *recv_if); struct batadv_hard_iface *recv_if);
...@@ -186,6 +187,8 @@ int batadv_mesh_init(struct net_device *soft_iface) ...@@ -186,6 +187,8 @@ int batadv_mesh_init(struct net_device *soft_iface)
INIT_HLIST_HEAD(&bat_priv->softif_vlan_list); INIT_HLIST_HEAD(&bat_priv->softif_vlan_list);
INIT_HLIST_HEAD(&bat_priv->tp_list); INIT_HLIST_HEAD(&bat_priv->tp_list);
bat_priv->gw.generation = 0;
ret = batadv_v_mesh_init(bat_priv); ret = batadv_v_mesh_init(bat_priv);
if (ret < 0) if (ret < 0)
goto err; goto err;
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define BATADV_DRIVER_DEVICE "batman-adv" #define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION #ifndef BATADV_SOURCE_VERSION
#define BATADV_SOURCE_VERSION "2018.4" #define BATADV_SOURCE_VERSION "2019.0"
#endif #endif
/* B.A.T.M.A.N. parameters */ /* B.A.T.M.A.N. parameters */
...@@ -247,6 +247,7 @@ static inline int batadv_print_vid(unsigned short vid) ...@@ -247,6 +247,7 @@ static inline int batadv_print_vid(unsigned short vid)
} }
extern struct list_head batadv_hardif_list; extern struct list_head batadv_hardif_list;
extern unsigned int batadv_hardif_generation;
extern unsigned char batadv_broadcast_addr[]; extern unsigned char batadv_broadcast_addr[];
extern struct workqueue_struct *batadv_event_workqueue; extern struct workqueue_struct *batadv_event_workqueue;
......
...@@ -1365,22 +1365,26 @@ int batadv_mcast_mesh_info_put(struct sk_buff *msg, ...@@ -1365,22 +1365,26 @@ int batadv_mcast_mesh_info_put(struct sk_buff *msg,
* to a netlink socket * to a netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @orig_node: originator to dump the multicast flags of * @orig_node: originator to dump the multicast flags of
* *
* Return: 0 or error code. * Return: 0 or error code.
*/ */
static int static int
batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_orig_node *orig_node) struct batadv_orig_node *orig_node)
{ {
void *hdr; void *hdr;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
NLM_F_MULTI, BATADV_CMD_GET_MCAST_FLAGS); &batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_MCAST_FLAGS);
if (!hdr) if (!hdr)
return -ENOBUFS; return -ENOBUFS;
genl_dump_check_consistent(cb, hdr);
if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN, if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
orig_node->orig)) { orig_node->orig)) {
genlmsg_cancel(msg, hdr); genlmsg_cancel(msg, hdr);
...@@ -1405,21 +1409,26 @@ batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1405,21 +1409,26 @@ batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
* table to a netlink socket * table to a netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @head: bucket to dump * @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip * @idx_skip: How many entries to skip
* *
* Return: 0 or error code. * Return: 0 or error code.
*/ */
static int static int
batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid,
struct hlist_head *head, long *idx_skip) struct netlink_callback *cb,
struct batadv_hashtable *hash,
unsigned int bucket, long *idx_skip)
{ {
struct batadv_orig_node *orig_node; struct batadv_orig_node *orig_node;
long idx = 0; long idx = 0;
rcu_read_lock(); spin_lock_bh(&hash->list_locks[bucket]);
hlist_for_each_entry_rcu(orig_node, head, hash_entry) { cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(orig_node, &hash->table[bucket], hash_entry) {
if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST, if (!test_bit(BATADV_ORIG_CAPA_HAS_MCAST,
&orig_node->capa_initialized)) &orig_node->capa_initialized))
continue; continue;
...@@ -1427,9 +1436,8 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1427,9 +1436,8 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
if (idx < *idx_skip) if (idx < *idx_skip)
goto skip; goto skip;
if (batadv_mcast_flags_dump_entry(msg, portid, seq, if (batadv_mcast_flags_dump_entry(msg, portid, cb, orig_node)) {
orig_node)) { spin_unlock_bh(&hash->list_locks[bucket]);
rcu_read_unlock();
*idx_skip = idx; *idx_skip = idx;
return -EMSGSIZE; return -EMSGSIZE;
...@@ -1438,7 +1446,7 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1438,7 +1446,7 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
skip: skip:
idx++; idx++;
} }
rcu_read_unlock(); spin_unlock_bh(&hash->list_locks[bucket]);
return 0; return 0;
} }
...@@ -1447,7 +1455,7 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1447,7 +1455,7 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
* __batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket * __batadv_mcast_flags_dump() - dump multicast flags table to a netlink socket
* @msg: buffer for the message * @msg: buffer for the message
* @portid: netlink port * @portid: netlink port
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @bat_priv: the bat priv with all the soft interface information * @bat_priv: the bat priv with all the soft interface information
* @bucket: current bucket to dump * @bucket: current bucket to dump
* @idx: index in current bucket to the next entry to dump * @idx: index in current bucket to the next entry to dump
...@@ -1455,19 +1463,17 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1455,19 +1463,17 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
* Return: 0 or error code. * Return: 0 or error code.
*/ */
static int static int
__batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid, u32 seq, __batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_priv *bat_priv, long *bucket, long *idx) struct batadv_priv *bat_priv, long *bucket, long *idx)
{ {
struct batadv_hashtable *hash = bat_priv->orig_hash; struct batadv_hashtable *hash = bat_priv->orig_hash;
long bucket_tmp = *bucket; long bucket_tmp = *bucket;
struct hlist_head *head;
long idx_tmp = *idx; long idx_tmp = *idx;
while (bucket_tmp < hash->size) { while (bucket_tmp < hash->size) {
head = &hash->table[bucket_tmp]; if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash,
*bucket, &idx_tmp))
if (batadv_mcast_flags_dump_bucket(msg, portid, seq, head,
&idx_tmp))
break; break;
bucket_tmp++; bucket_tmp++;
...@@ -1550,8 +1556,7 @@ int batadv_mcast_flags_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -1550,8 +1556,7 @@ int batadv_mcast_flags_dump(struct sk_buff *msg, struct netlink_callback *cb)
return ret; return ret;
bat_priv = netdev_priv(primary_if->soft_iface); bat_priv = netdev_priv(primary_if->soft_iface);
ret = __batadv_mcast_flags_dump(msg, portid, cb->nlh->nlmsg_seq, ret = __batadv_mcast_flags_dump(msg, portid, cb, bat_priv, bucket, idx);
bat_priv, bucket, idx);
batadv_hardif_put(primary_if); batadv_hardif_put(primary_if);
return ret; return ret;
......
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/rculist.h> #include <linux/rtnetlink.h>
#include <linux/rcupdate.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -445,23 +445,27 @@ batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info) ...@@ -445,23 +445,27 @@ batadv_netlink_tp_meter_cancel(struct sk_buff *skb, struct genl_info *info)
* batadv_netlink_dump_hardif_entry() - Dump one hard interface into a message * batadv_netlink_dump_hardif_entry() - Dump one hard interface into a message
* @msg: Netlink message to dump into * @msg: Netlink message to dump into
* @portid: Port making netlink request * @portid: Port making netlink request
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @hard_iface: Hard interface to dump * @hard_iface: Hard interface to dump
* *
* Return: error code, or 0 on success * Return: error code, or 0 on success
*/ */
static int static int
batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid, u32 seq, batadv_netlink_dump_hardif_entry(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_hard_iface *hard_iface) struct batadv_hard_iface *hard_iface)
{ {
struct net_device *net_dev = hard_iface->net_dev; struct net_device *net_dev = hard_iface->net_dev;
void *hdr; void *hdr;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, NLM_F_MULTI, hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
&batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_HARDIFS); BATADV_CMD_GET_HARDIFS);
if (!hdr) if (!hdr)
return -EMSGSIZE; return -EMSGSIZE;
genl_dump_check_consistent(cb, hdr);
if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX, if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
net_dev->ifindex) || net_dev->ifindex) ||
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME, nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
...@@ -498,7 +502,6 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -498,7 +502,6 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_hard_iface *hard_iface; struct batadv_hard_iface *hard_iface;
int ifindex; int ifindex;
int portid = NETLINK_CB(cb->skb).portid; int portid = NETLINK_CB(cb->skb).portid;
int seq = cb->nlh->nlmsg_seq;
int skip = cb->args[0]; int skip = cb->args[0];
int i = 0; int i = 0;
...@@ -516,23 +519,24 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -516,23 +519,24 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb)
return -ENODEV; return -ENODEV;
} }
rcu_read_lock(); rtnl_lock();
cb->seq = batadv_hardif_generation << 1 | 1;
list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) { list_for_each_entry(hard_iface, &batadv_hardif_list, list) {
if (hard_iface->soft_iface != soft_iface) if (hard_iface->soft_iface != soft_iface)
continue; continue;
if (i++ < skip) if (i++ < skip)
continue; continue;
if (batadv_netlink_dump_hardif_entry(msg, portid, seq, if (batadv_netlink_dump_hardif_entry(msg, portid, cb,
hard_iface)) { hard_iface)) {
i--; i--;
break; break;
} }
} }
rcu_read_unlock(); rtnl_unlock();
dev_put(soft_iface); dev_put(soft_iface);
......
...@@ -16,7 +16,5 @@ ...@@ -16,7 +16,5 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>. * along with this program; if not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/module.h>
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include "trace.h" #include "trace.h"
...@@ -21,7 +21,13 @@ ...@@ -21,7 +21,13 @@
#include "main.h" #include "main.h"
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/percpu.h>
#include <linux/printk.h>
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include <linux/types.h>
#undef TRACE_SYSTEM #undef TRACE_SYSTEM
#define TRACE_SYSTEM batadv #define TRACE_SYSTEM batadv
......
...@@ -1145,14 +1145,15 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) ...@@ -1145,14 +1145,15 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
* batadv_tt_local_dump_entry() - Dump one TT local entry into a message * batadv_tt_local_dump_entry() - Dump one TT local entry into a message
* @msg :Netlink message to dump into * @msg :Netlink message to dump into
* @portid: Port making netlink request * @portid: Port making netlink request
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @bat_priv: The bat priv with all the soft interface information * @bat_priv: The bat priv with all the soft interface information
* @common: tt local & tt global common data * @common: tt local & tt global common data
* *
* Return: Error code, or 0 on success * Return: Error code, or 0 on success
*/ */
static int static int
batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_priv *bat_priv, struct batadv_priv *bat_priv,
struct batadv_tt_common_entry *common) struct batadv_tt_common_entry *common)
{ {
...@@ -1173,12 +1174,14 @@ batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1173,12 +1174,14 @@ batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
batadv_softif_vlan_put(vlan); batadv_softif_vlan_put(vlan);
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family, hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
NLM_F_MULTI, &batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_TRANSTABLE_LOCAL); BATADV_CMD_GET_TRANSTABLE_LOCAL);
if (!hdr) if (!hdr)
return -ENOBUFS; return -ENOBUFS;
genl_dump_check_consistent(cb, hdr);
if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) || if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) || nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) || nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
...@@ -1201,34 +1204,39 @@ batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq, ...@@ -1201,34 +1204,39 @@ batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
* batadv_tt_local_dump_bucket() - Dump one TT local bucket into a message * batadv_tt_local_dump_bucket() - Dump one TT local bucket into a message
* @msg: Netlink message to dump into * @msg: Netlink message to dump into
* @portid: Port making netlink request * @portid: Port making netlink request
* @seq: Sequence number of netlink message * @cb: Control block containing additional options
* @bat_priv: The bat priv with all the soft interface information * @bat_priv: The bat priv with all the soft interface information
* @head: Pointer to the list containing the local tt entries * @hash: hash to dump
* @bucket: bucket index to dump
* @idx_s: Number of entries to skip * @idx_s: Number of entries to skip
* *
* Return: Error code, or 0 on success * Return: Error code, or 0 on success
*/ */
static int static int
batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq, batadv_tt_local_dump_bucket(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_priv *bat_priv, struct batadv_priv *bat_priv,
struct hlist_head *head, int *idx_s) struct batadv_hashtable *hash, unsigned int bucket,
int *idx_s)
{ {
struct batadv_tt_common_entry *common; struct batadv_tt_common_entry *common;
int idx = 0; int idx = 0;
rcu_read_lock(); spin_lock_bh(&hash->list_locks[bucket]);
hlist_for_each_entry_rcu(common, head, hash_entry) { cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(common, &hash->table[bucket], hash_entry) {
if (idx++ < *idx_s) if (idx++ < *idx_s)
continue; continue;
if (batadv_tt_local_dump_entry(msg, portid, seq, bat_priv, if (batadv_tt_local_dump_entry(msg, portid, cb, bat_priv,
common)) { common)) {
rcu_read_unlock(); spin_unlock_bh(&hash->list_locks[bucket]);
*idx_s = idx - 1; *idx_s = idx - 1;
return -EMSGSIZE; return -EMSGSIZE;
} }
} }
rcu_read_unlock(); spin_unlock_bh(&hash->list_locks[bucket]);
*idx_s = 0; *idx_s = 0;
return 0; return 0;
...@@ -1248,7 +1256,6 @@ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -1248,7 +1256,6 @@ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_priv *bat_priv; struct batadv_priv *bat_priv;
struct batadv_hard_iface *primary_if = NULL; struct batadv_hard_iface *primary_if = NULL;
struct batadv_hashtable *hash; struct batadv_hashtable *hash;
struct hlist_head *head;
int ret; int ret;
int ifindex; int ifindex;
int bucket = cb->args[0]; int bucket = cb->args[0];
...@@ -1276,10 +1283,8 @@ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb) ...@@ -1276,10 +1283,8 @@ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
hash = bat_priv->tt.local_hash; hash = bat_priv->tt.local_hash;
while (bucket < hash->size) { while (bucket < hash->size) {
head = &hash->table[bucket]; if (batadv_tt_local_dump_bucket(msg, portid, cb, bat_priv,
hash, bucket, &idx))
if (batadv_tt_local_dump_bucket(msg, portid, cb->nlh->nlmsg_seq,
bat_priv, head, &idx))
break; break;
bucket++; bucket++;
......
...@@ -1096,12 +1096,15 @@ struct batadv_priv_gw { ...@@ -1096,12 +1096,15 @@ struct batadv_priv_gw {
/** @gateway_list: list of available gateway nodes */ /** @gateway_list: list of available gateway nodes */
struct hlist_head gateway_list; struct hlist_head gateway_list;
/** @list_lock: lock protecting gateway_list & curr_gw */ /** @list_lock: lock protecting gateway_list, curr_gw, generation */
spinlock_t list_lock; spinlock_t list_lock;
/** @curr_gw: pointer to currently selected gateway node */ /** @curr_gw: pointer to currently selected gateway node */
struct batadv_gw_node __rcu *curr_gw; struct batadv_gw_node __rcu *curr_gw;
/** @generation: current (generation) sequence number */
unsigned int generation;
/** /**
* @mode: gateway operation: off, client or server (see batadv_gw_modes) * @mode: gateway operation: off, client or server (see batadv_gw_modes)
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment