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 @@
config BATMAN_ADV
tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
depends on NET
select CRC16
select LIBCRC32C
help
B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
......@@ -48,6 +47,7 @@ config BATMAN_ADV_BATMAN_V
config BATMAN_ADV_BLA
bool "Bridge Loop Avoidance"
depends on BATMAN_ADV && INET
select CRC16
default y
help
This option enables BLA (Bridge Loop Avoidance), a mechanism
......@@ -82,6 +82,7 @@ config BATMAN_ADV_NC
config BATMAN_ADV_MCAST
bool "Multicast optimisation"
depends on BATMAN_ADV && INET && !(BRIDGE=m && BATMAN_ADV=y)
default y
help
This option enables the multicast optimisation which aims to
reduce the air overhead while improving the reliability of
......@@ -100,12 +101,13 @@ config BATMAN_ADV_DEBUGFS
config BATMAN_ADV_DEBUG
bool "B.A.T.M.A.N. debugging"
depends on BATMAN_ADV_DEBUGFS
depends on BATMAN_ADV
help
This is an option for use by developers; most people should
say N here. This enables compilation of support for
outputting debugging information to the kernel log. The
output is controlled via the module parameter debug.
outputting debugging information to the debugfs log or tracing
buffer. The output is controlled via the batadv netdev specific
log_level setting.
config BATMAN_ADV_TRACING
bool "B.A.T.M.A.N. tracing support"
......
......@@ -34,7 +34,6 @@
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/pkt_sched.h>
......@@ -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
* @msg: Netlink message to dump into
* @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
* @gw_node: Gateway to be dumped
*
* 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_gw_node *gw_node)
{
......@@ -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);
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
NLM_F_MULTI, BATADV_CMD_GET_GATEWAYS);
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
&batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_GATEWAYS);
if (!hdr) {
ret = -ENOBUFS;
goto out;
}
genl_dump_check_consistent(cb, hdr);
ret = -EMSGSIZE;
if (curr_gw == gw_node)
......@@ -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 = 0;
rcu_read_lock();
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
spin_lock_bh(&bat_priv->gw.list_lock);
cb->seq = bat_priv->gw.generation << 1 | 1;
hlist_for_each_entry(gw_node, &bat_priv->gw.gateway_list, list) {
if (idx++ < idx_skip)
continue;
if (batadv_iv_gw_dump_entry(msg, portid, cb->nlh->nlmsg_seq,
bat_priv, gw_node)) {
if (batadv_iv_gw_dump_entry(msg, portid, cb, bat_priv,
gw_node)) {
idx_skip = idx - 1;
goto unlock;
}
......@@ -2682,7 +2687,7 @@ static void batadv_iv_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
idx_skip = idx;
unlock:
rcu_read_unlock();
spin_unlock_bh(&bat_priv->gw.list_lock);
cb->args[0] = idx_skip;
}
......
......@@ -27,11 +27,13 @@
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/kref.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/workqueue.h>
......@@ -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
* @msg: Netlink message to dump into
* @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
* @gw_node: Gateway to be dumped
*
* 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_gw_node *gw_node)
{
......@@ -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);
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
NLM_F_MULTI, BATADV_CMD_GET_GATEWAYS);
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
&batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_GATEWAYS);
if (!hdr) {
ret = -ENOBUFS;
goto out;
}
genl_dump_check_consistent(cb, hdr);
ret = -EMSGSIZE;
if (curr_gw == gw_node) {
......@@ -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 = 0;
rcu_read_lock();
hlist_for_each_entry_rcu(gw_node, &bat_priv->gw.gateway_list, list) {
spin_lock_bh(&bat_priv->gw.list_lock);
cb->seq = bat_priv->gw.generation << 1 | 1;
hlist_for_each_entry(gw_node, &bat_priv->gw.gateway_list, list) {
if (idx++ < idx_skip)
continue;
if (batadv_v_gw_dump_entry(msg, portid, cb->nlh->nlmsg_seq,
bat_priv, gw_node)) {
if (batadv_v_gw_dump_entry(msg, portid, cb, bat_priv,
gw_node)) {
idx_skip = idx - 1;
goto unlock;
}
......@@ -1032,7 +1040,7 @@ static void batadv_v_gw_dump(struct sk_buff *msg, struct netlink_callback *cb,
idx_skip = idx;
unlock:
rcu_read_unlock();
spin_unlock_bh(&bat_priv->gw.list_lock);
cb->args[0] = idx_skip;
}
......
......@@ -2094,14 +2094,15 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
* to a netlink socket
* @msg: buffer for the message
* @portid: netlink port
* @seq: Sequence number of netlink message
* @cb: Control block containing additional options
* @primary_if: primary interface
* @claim: entry to dump
*
* Return: 0 or error code.
*/
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_bla_claim *claim)
{
......@@ -2111,13 +2112,16 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
void *hdr;
int ret = -EINVAL;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
NLM_F_MULTI, BATADV_CMD_GET_BLA_CLAIM);
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
&batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_BLA_CLAIM);
if (!hdr) {
ret = -ENOBUFS;
goto out;
}
genl_dump_check_consistent(cb, hdr);
is_own = batadv_compare_eth(claim->backbone_gw->orig,
primary_addr);
......@@ -2153,28 +2157,33 @@ batadv_bla_claim_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
* to a netlink socket
* @msg: buffer for the message
* @portid: netlink port
* @seq: Sequence number of netlink message
* @cb: Control block containing additional options
* @primary_if: primary interface
* @head: bucket to dump
* @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip
*
* Return: always 0.
*/
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 hlist_head *head, int *idx_skip)
struct batadv_hashtable *hash, unsigned int bucket,
int *idx_skip)
{
struct batadv_bla_claim *claim;
int idx = 0;
int ret = 0;
rcu_read_lock();
hlist_for_each_entry_rcu(claim, head, hash_entry) {
spin_lock_bh(&hash->list_locks[bucket]);
cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(claim, &hash->table[bucket], hash_entry) {
if (idx++ < *idx_skip)
continue;
ret = batadv_bla_claim_dump_entry(msg, portid, seq,
ret = batadv_bla_claim_dump_entry(msg, portid, cb,
primary_if, claim);
if (ret) {
*idx_skip = idx - 1;
......@@ -2184,7 +2193,7 @@ batadv_bla_claim_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
*idx_skip = 0;
unlock:
rcu_read_unlock();
spin_unlock_bh(&hash->list_locks[bucket]);
return ret;
}
......@@ -2204,7 +2213,6 @@ int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_hashtable *hash;
struct batadv_priv *bat_priv;
int bucket = cb->args[0];
struct hlist_head *head;
int idx = cb->args[1];
int ifindex;
int ret = 0;
......@@ -2230,11 +2238,8 @@ int batadv_bla_claim_dump(struct sk_buff *msg, struct netlink_callback *cb)
}
while (bucket < hash->size) {
head = &hash->table[bucket];
if (batadv_bla_claim_dump_bucket(msg, portid,
cb->nlh->nlmsg_seq,
primary_if, head, &idx))
if (batadv_bla_claim_dump_bucket(msg, portid, cb, primary_if,
hash, bucket, &idx))
break;
bucket++;
}
......@@ -2325,14 +2330,15 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
* netlink socket
* @msg: buffer for the message
* @portid: netlink port
* @seq: Sequence number of netlink message
* @cb: Control block containing additional options
* @primary_if: primary interface
* @backbone_gw: entry to dump
*
* Return: 0 or error code.
*/
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_bla_backbone_gw *backbone_gw)
{
......@@ -2343,13 +2349,16 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
void *hdr;
int ret = -EINVAL;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
NLM_F_MULTI, BATADV_CMD_GET_BLA_BACKBONE);
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
&batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_BLA_BACKBONE);
if (!hdr) {
ret = -ENOBUFS;
goto out;
}
genl_dump_check_consistent(cb, hdr);
is_own = batadv_compare_eth(backbone_gw->orig, primary_addr);
spin_lock_bh(&backbone_gw->crc_lock);
......@@ -2386,28 +2395,33 @@ batadv_bla_backbone_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
* a netlink socket
* @msg: buffer for the message
* @portid: netlink port
* @seq: Sequence number of netlink message
* @cb: Control block containing additional options
* @primary_if: primary interface
* @head: bucket to dump
* @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip
*
* Return: always 0.
*/
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 hlist_head *head, int *idx_skip)
struct batadv_hashtable *hash,
unsigned int bucket, int *idx_skip)
{
struct batadv_bla_backbone_gw *backbone_gw;
int idx = 0;
int ret = 0;
rcu_read_lock();
hlist_for_each_entry_rcu(backbone_gw, head, hash_entry) {
spin_lock_bh(&hash->list_locks[bucket]);
cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(backbone_gw, &hash->table[bucket], hash_entry) {
if (idx++ < *idx_skip)
continue;
ret = batadv_bla_backbone_dump_entry(msg, portid, seq,
ret = batadv_bla_backbone_dump_entry(msg, portid, cb,
primary_if, backbone_gw);
if (ret) {
*idx_skip = idx - 1;
......@@ -2417,7 +2431,7 @@ batadv_bla_backbone_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
*idx_skip = 0;
unlock:
rcu_read_unlock();
spin_unlock_bh(&hash->list_locks[bucket]);
return ret;
}
......@@ -2437,7 +2451,6 @@ int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_hashtable *hash;
struct batadv_priv *bat_priv;
int bucket = cb->args[0];
struct hlist_head *head;
int idx = cb->args[1];
int ifindex;
int ret = 0;
......@@ -2463,11 +2476,8 @@ int batadv_bla_backbone_dump(struct sk_buff *msg, struct netlink_callback *cb)
}
while (bucket < hash->size) {
head = &hash->table[bucket];
if (batadv_bla_backbone_dump_bucket(msg, portid,
cb->nlh->nlmsg_seq,
primary_if, head, &idx))
if (batadv_bla_backbone_dump_bucket(msg, portid, cb, primary_if,
hash, bucket, &idx))
break;
bucket++;
}
......
......@@ -19,6 +19,7 @@
#include "debugfs.h"
#include "main.h"
#include <asm/current.h>
#include <linux/dcache.h>
#include <linux/debugfs.h>
#include <linux/err.h>
......@@ -27,6 +28,7 @@
#include <linux/fs.h>
#include <linux/netdevice.h>
#include <linux/printk.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/stddef.h>
......
......@@ -863,23 +863,27 @@ int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
* netlink socket
* @msg: buffer for the message
* @portid: netlink port
* @seq: Sequence number of netlink message
* @cb: Control block containing additional options
* @dat_entry: entry to dump
*
* Return: 0 or error code.
*/
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)
{
int msecs;
void *hdr;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
NLM_F_MULTI, BATADV_CMD_GET_DAT_CACHE);
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
&batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_DAT_CACHE);
if (!hdr)
return -ENOBUFS;
genl_dump_check_consistent(cb, hdr);
msecs = jiffies_to_msecs(jiffies - dat_entry->last_update);
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,
* a netlink socket
* @msg: buffer for the message
* @portid: netlink port
* @seq: Sequence number of netlink message
* @head: bucket to dump
* @cb: Control block containing additional options
* @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip
*
* Return: 0 or error code.
*/
static int
batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
struct hlist_head *head, int *idx_skip)
batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_hashtable *hash, unsigned int bucket,
int *idx_skip)
{
struct batadv_dat_entry *dat_entry;
int idx = 0;
rcu_read_lock();
hlist_for_each_entry_rcu(dat_entry, head, hash_entry) {
spin_lock_bh(&hash->list_locks[bucket]);
cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(dat_entry, &hash->table[bucket], hash_entry) {
if (idx < *idx_skip)
goto skip;
if (batadv_dat_cache_dump_entry(msg, portid, seq,
dat_entry)) {
rcu_read_unlock();
if (batadv_dat_cache_dump_entry(msg, portid, cb, dat_entry)) {
spin_unlock_bh(&hash->list_locks[bucket]);
*idx_skip = idx;
return -EMSGSIZE;
......@@ -930,7 +938,7 @@ batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
skip:
idx++;
}
rcu_read_unlock();
spin_unlock_bh(&hash->list_locks[bucket]);
return 0;
}
......@@ -951,7 +959,6 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_hashtable *hash;
struct batadv_priv *bat_priv;
int bucket = cb->args[0];
struct hlist_head *head;
int idx = cb->args[1];
int ifindex;
int ret = 0;
......@@ -977,10 +984,7 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
}
while (bucket < hash->size) {
head = &hash->table[bucket];
if (batadv_dat_cache_dump_bucket(msg, portid,
cb->nlh->nlmsg_seq, head,
if (batadv_dat_cache_dump_bucket(msg, portid, cb, hash, bucket,
&idx))
break;
......
......@@ -377,6 +377,7 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
kref_get(&gw_node->refcount);
hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list);
bat_priv->gw.generation++;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"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,
if (!hlist_unhashed(&gw_node->list)) {
hlist_del_init_rcu(&gw_node->list);
batadv_gw_node_put(gw_node);
bat_priv->gw.generation++;
}
spin_unlock_bh(&bat_priv->gw.list_lock);
......@@ -518,6 +520,7 @@ void batadv_gw_node_free(struct batadv_priv *bat_priv)
&bat_priv->gw.gateway_list, list) {
hlist_del_init_rcu(&gw_node->list);
batadv_gw_node_put(gw_node);
bat_priv->gw.generation++;
}
spin_unlock_bh(&bat_priv->gw.list_lock);
}
......
......@@ -951,6 +951,7 @@ batadv_hardif_add_interface(struct net_device *net_dev)
batadv_check_known_mac_addr(hard_iface->net_dev);
kref_get(&hard_iface->refcount);
list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list);
batadv_hardif_generation++;
return hard_iface;
......@@ -993,6 +994,7 @@ void batadv_hardif_remove_interfaces(void)
list_for_each_entry_safe(hard_iface, hard_iface_tmp,
&batadv_hardif_list, list) {
list_del_rcu(&hard_iface->list);
batadv_hardif_generation++;
batadv_hardif_remove_interface(hard_iface);
}
rtnl_unlock();
......@@ -1054,6 +1056,7 @@ static int batadv_hard_if_event(struct notifier_block *this,
case NETDEV_UNREGISTER:
case NETDEV_PRE_TYPE_CHANGE:
list_del_rcu(&hard_iface->list);
batadv_hardif_generation++;
batadv_hardif_remove_interface(hard_iface);
break;
......
......@@ -32,6 +32,8 @@ static void batadv_hash_init(struct batadv_hashtable *hash)
INIT_HLIST_HEAD(&hash->table[i]);
spin_lock_init(&hash->list_locks[i]);
}
atomic_set(&hash->generation, 0);
}
/**
......
......@@ -21,6 +21,7 @@
#include "main.h"
#include <linux/atomic.h>
#include <linux/compiler.h>
#include <linux/list.h>
#include <linux/rculist.h>
......@@ -58,6 +59,9 @@ struct batadv_hashtable {
/** @size: size of hashtable */
u32 size;
/** @generation: current (generation) sequence number */
atomic_t generation;
};
/* allocates and clears the hash */
......@@ -112,6 +116,7 @@ static inline int batadv_hash_add(struct batadv_hashtable *hash,
/* no duplicate found in list, add new element */
hlist_add_head_rcu(data_node, head);
atomic_inc(&hash->generation);
ret = 0;
......@@ -154,6 +159,7 @@ static inline void *batadv_hash_remove(struct batadv_hashtable *hash,
data_save = node;
hlist_del_rcu(node);
atomic_inc(&hash->generation);
break;
}
spin_unlock_bh(&hash->list_locks[index]);
......
......@@ -43,6 +43,8 @@
#include "debugfs.h"
#include "trace.h"
#ifdef CONFIG_BATMAN_ADV_DEBUGFS
#define BATADV_LOG_BUFF_MASK (batadv_log_buff_len - 1)
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,
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)
{
if (!try_module_get(THIS_MODULE))
......@@ -259,3 +234,34 @@ void batadv_debug_log_cleanup(struct batadv_priv *bat_priv)
kfree(bat_priv->debug_log);
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 @@
* list traversals just rcu-locked
*/
struct list_head batadv_hardif_list;
unsigned int batadv_hardif_generation;
static int (*batadv_rx_handler[256])(struct sk_buff *skb,
struct batadv_hard_iface *recv_if);
......@@ -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->tp_list);
bat_priv->gw.generation = 0;
ret = batadv_v_mesh_init(bat_priv);
if (ret < 0)
goto err;
......
......@@ -25,7 +25,7 @@
#define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION
#define BATADV_SOURCE_VERSION "2018.4"
#define BATADV_SOURCE_VERSION "2019.0"
#endif
/* B.A.T.M.A.N. parameters */
......@@ -247,6 +247,7 @@ static inline int batadv_print_vid(unsigned short vid)
}
extern struct list_head batadv_hardif_list;
extern unsigned int batadv_hardif_generation;
extern unsigned char batadv_broadcast_addr[];
extern struct workqueue_struct *batadv_event_workqueue;
......
......@@ -1365,22 +1365,26 @@ int batadv_mcast_mesh_info_put(struct sk_buff *msg,
* to a netlink socket
* @msg: buffer for the message
* @portid: netlink port
* @seq: Sequence number of netlink message
* @cb: Control block containing additional options
* @orig_node: originator to dump the multicast flags of
*
* Return: 0 or error code.
*/
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)
{
void *hdr;
hdr = genlmsg_put(msg, portid, seq, &batadv_netlink_family,
NLM_F_MULTI, BATADV_CMD_GET_MCAST_FLAGS);
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
&batadv_netlink_family, NLM_F_MULTI,
BATADV_CMD_GET_MCAST_FLAGS);
if (!hdr)
return -ENOBUFS;
genl_dump_check_consistent(cb, hdr);
if (nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
orig_node->orig)) {
genlmsg_cancel(msg, hdr);
......@@ -1405,21 +1409,26 @@ batadv_mcast_flags_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
* table to a netlink socket
* @msg: buffer for the message
* @portid: netlink port
* @seq: Sequence number of netlink message
* @head: bucket to dump
* @cb: Control block containing additional options
* @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip
*
* Return: 0 or error code.
*/
static int
batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
struct hlist_head *head, long *idx_skip)
batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid,
struct netlink_callback *cb,
struct batadv_hashtable *hash,
unsigned int bucket, long *idx_skip)
{
struct batadv_orig_node *orig_node;
long idx = 0;
rcu_read_lock();
hlist_for_each_entry_rcu(orig_node, head, hash_entry) {
spin_lock_bh(&hash->list_locks[bucket]);
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,
&orig_node->capa_initialized))
continue;
......@@ -1427,9 +1436,8 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
if (idx < *idx_skip)
goto skip;
if (batadv_mcast_flags_dump_entry(msg, portid, seq,
orig_node)) {
rcu_read_unlock();
if (batadv_mcast_flags_dump_entry(msg, portid, cb, orig_node)) {
spin_unlock_bh(&hash->list_locks[bucket]);
*idx_skip = idx;
return -EMSGSIZE;
......@@ -1438,7 +1446,7 @@ batadv_mcast_flags_dump_bucket(struct sk_buff *msg, u32 portid, u32 seq,
skip:
idx++;
}
rcu_read_unlock();
spin_unlock_bh(&hash->list_locks[bucket]);
return 0;
}
......@@ -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
* @msg: buffer for the message
* @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
* @bucket: current bucket 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,
* Return: 0 or error code.
*/
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_hashtable *hash = bat_priv->orig_hash;
long bucket_tmp = *bucket;
struct hlist_head *head;
long idx_tmp = *idx;
while (bucket_tmp < hash->size) {
head = &hash->table[bucket_tmp];
if (batadv_mcast_flags_dump_bucket(msg, portid, seq, head,
&idx_tmp))
if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash,
*bucket, &idx_tmp))
break;
bucket_tmp++;
......@@ -1550,8 +1556,7 @@ int batadv_mcast_flags_dump(struct sk_buff *msg, struct netlink_callback *cb)
return ret;
bat_priv = netdev_priv(primary_if->soft_iface);
ret = __batadv_mcast_flags_dump(msg, portid, cb->nlh->nlmsg_seq,
bat_priv, bucket, idx);
ret = __batadv_mcast_flags_dump(msg, portid, cb, bat_priv, bucket, idx);
batadv_hardif_put(primary_if);
return ret;
......
......@@ -29,11 +29,11 @@
#include <linux/if_ether.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/printk.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/stddef.h>
#include <linux/types.h>
......@@ -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
* @msg: Netlink message to dump into
* @portid: Port making netlink request
* @seq: Sequence number of netlink message
* @cb: Control block containing additional options
* @hard_iface: Hard interface to dump
*
* Return: error code, or 0 on success
*/
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 net_device *net_dev = hard_iface->net_dev;
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);
if (!hdr)
return -EMSGSIZE;
genl_dump_check_consistent(cb, hdr);
if (nla_put_u32(msg, BATADV_ATTR_HARD_IFINDEX,
net_dev->ifindex) ||
nla_put_string(msg, BATADV_ATTR_HARD_IFNAME,
......@@ -498,7 +502,6 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_hard_iface *hard_iface;
int ifindex;
int portid = NETLINK_CB(cb->skb).portid;
int seq = cb->nlh->nlmsg_seq;
int skip = cb->args[0];
int i = 0;
......@@ -516,23 +519,24 @@ batadv_netlink_dump_hardifs(struct sk_buff *msg, struct netlink_callback *cb)
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)
continue;
if (i++ < skip)
continue;
if (batadv_netlink_dump_hardif_entry(msg, portid, seq,
if (batadv_netlink_dump_hardif_entry(msg, portid, cb,
hard_iface)) {
i--;
break;
}
}
rcu_read_unlock();
rtnl_unlock();
dev_put(soft_iface);
......
......@@ -16,7 +16,5 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/module.h>
#define CREATE_TRACE_POINTS
#include "trace.h"
......@@ -21,7 +21,13 @@
#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/types.h>
#undef TRACE_SYSTEM
#define TRACE_SYSTEM batadv
......
......@@ -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
* @msg :Netlink message to dump into
* @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
* @common: tt local & tt global common data
*
* Return: Error code, or 0 on success
*/
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_tt_common_entry *common)
{
......@@ -1173,12 +1174,14 @@ batadv_tt_local_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
batadv_softif_vlan_put(vlan);
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_TRANSTABLE_LOCAL);
if (!hdr)
return -ENOBUFS;
genl_dump_check_consistent(cb, hdr);
if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
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,
* batadv_tt_local_dump_bucket() - Dump one TT local bucket into a message
* @msg: Netlink message to dump into
* @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
* @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
*
* Return: Error code, or 0 on success
*/
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 hlist_head *head, int *idx_s)
struct batadv_hashtable *hash, unsigned int bucket,
int *idx_s)
{
struct batadv_tt_common_entry *common;
int idx = 0;
rcu_read_lock();
hlist_for_each_entry_rcu(common, head, hash_entry) {
spin_lock_bh(&hash->list_locks[bucket]);
cb->seq = atomic_read(&hash->generation) << 1 | 1;
hlist_for_each_entry(common, &hash->table[bucket], hash_entry) {
if (idx++ < *idx_s)
continue;
if (batadv_tt_local_dump_entry(msg, portid, seq, bat_priv,
if (batadv_tt_local_dump_entry(msg, portid, cb, bat_priv,
common)) {
rcu_read_unlock();
spin_unlock_bh(&hash->list_locks[bucket]);
*idx_s = idx - 1;
return -EMSGSIZE;
}
}
rcu_read_unlock();
spin_unlock_bh(&hash->list_locks[bucket]);
*idx_s = 0;
return 0;
......@@ -1248,7 +1256,6 @@ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
struct batadv_priv *bat_priv;
struct batadv_hard_iface *primary_if = NULL;
struct batadv_hashtable *hash;
struct hlist_head *head;
int ret;
int ifindex;
int bucket = cb->args[0];
......@@ -1276,10 +1283,8 @@ int batadv_tt_local_dump(struct sk_buff *msg, struct netlink_callback *cb)
hash = bat_priv->tt.local_hash;
while (bucket < hash->size) {
head = &hash->table[bucket];
if (batadv_tt_local_dump_bucket(msg, portid, cb->nlh->nlmsg_seq,
bat_priv, head, &idx))
if (batadv_tt_local_dump_bucket(msg, portid, cb, bat_priv,
hash, bucket, &idx))
break;
bucket++;
......
......@@ -1096,12 +1096,15 @@ struct batadv_priv_gw {
/** @gateway_list: list of available gateway nodes */
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;
/** @curr_gw: pointer to currently selected gateway node */
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)
*/
......
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