This batman-adv cleanup patchset includes the following patches, all by

Sven Eckelmann:
 
  - drop batman-adv specific version
 
  - MAINTAINERS housekeeping for batman-adv (two patches)
 
  - add missing includes
 
  - use atomic_xchg() for gw.reselect check
 
  - extract netdev wifi detection information object
 
  - replace inappropriate atomic access with (READ|WRITE)_ONCE
    (six patches)
 
  - tt: replace open-coded overflow check with helper
 
  - tvlv: avoid unnecessary OGM buffer reallocations
 
  - use neigh_node's orig_node only as id
 -----BEGIN PGP SIGNATURE-----
 
 iQJKBAABCgA0FiEE1ilQI7G+y+fdhnrfoSvjmEKSnqEFAmodehcWHHN3QHNpbW9u
 d3VuZGVybGljaC5kZQAKCRChK+OYQpKeoVWXD/9Z4kRbjVRr7ZkdiQ6hf/ZXh83s
 iEmnec6bEpKdn9/bvQxFC0i87Ngf0XBeJQedGjrAuL5eEOPw50u3AZGX8uRKa9M/
 BGuYvmd97vNPnHPv5yPIqQ5DuApv4CJ0BUpG4WpzL2SbizybudNIZ5gQk4FyPvQw
 mjJ8WZXHh3ntfoUiDW2TOkRH1xA/wdV9Q5uEmJnhYKhyNvzK7K6/GhIsZ+vO+puO
 gcFcFjxNqQ0w37fclYP8RU8/6YqPaDdzxwv/1sT4L0eDbZR5Ex2VPT0DmiJk73tE
 ZX83gMvXR3qVFjVr9e2MWHjm3aEfufdKyd7n4XNapcRUR2eCfeLsnJ9wzuJFx49X
 4w/eoBdj9cgrpYpn1ptG+mZe8gzvS0Wz8Uy4OdReQV8DvT0ajMYKCfshhmeIWJrv
 qjLKDPqtCPbq9paBkjChiS+/QABJQYkHMdoTUZKyOHITY8s2/9zRrQCOD9j1VYzo
 0vAnz7jZny/5Z47b5w6ddgS3ecU9eaAAjr4g+3ZfAJ1iXBTedxDOqL96iZZVblIH
 gFIxyinlmxh8xkRNpvb5RpoYtiI0aBSFnPExmxSTlWqFLGAQDi9MvaWvR/Yvnwso
 nntU1nJBG2cF/Tta7onZJzAbGwfZRDbqOt8+TbY3XtytTamOoTkuilPpMLg7XiMZ
 Q5nZJEwOGIVwevAtPg==
 =bwmN
 -----END PGP SIGNATURE-----

Merge tag 'batadv-next-pullrequest-20260601' of https://git.open-mesh.org/batadv

Simon Wunderlich says:

====================
This batman-adv cleanup patchset includes the following patches, all by
Sven Eckelmann:

 - drop batman-adv specific version

 - MAINTAINERS housekeeping for batman-adv (two patches)

 - add missing includes

 - use atomic_xchg() for gw.reselect check

 - extract netdev wifi detection information object

 - replace inappropriate atomic access with (READ|WRITE)_ONCE
   (six patches)

 - tt: replace open-coded overflow check with helper

 - tvlv: avoid unnecessary OGM buffer reallocations

 - use neigh_node's orig_node only as id

* tag 'batadv-next-pullrequest-20260601' of https://git.open-mesh.org/batadv:
  batman-adv: use neigh_node's orig_node only as id
  batman-adv: tvlv: avoid unnecessary OGM buffer reallocations
  batman-adv: tt: replace open-coded overflow check with helper
  batman-adv: replace non-atomic last_ttvn with (READ|WRITE)_ONCE
  batman-adv: replace non-atomic packet_size_max with (READ|WRITE)_ONCE
  batman-adv: replace non-atomic mesh state with (READ|WRITE)_ONCE
  batman-adv: replace non-atomic vlan config fields with (READ|WRITE)_ONCE
  batman-adv: replace non-atomic hardif config fields with (READ|WRITE)_ONCE
  batman-adv: replace non-atomic meshif config fields with (READ|WRITE)_ONCE
  batman-adv: extract netdev wifi detection information object
  batman-adv: use atomic_xchg() for gw.reselect check
  batman-adv: add missing includes
  MAINTAINERS: Don't send batman-adv patches to netdev
  MAINTAINERS: Rename batman-adv T(ree)
  batman-adv: drop batman-adv specific version
====================

Link: https://patch.msgid.link/20260601123629.707089-1-sw@simonwunderlich.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-06-02 12:00:48 -07:00
commit f8524d16e2
28 changed files with 582 additions and 300 deletions

View File

@ -4449,7 +4449,7 @@ W: https://www.open-mesh.org/
Q: https://patchwork.open-mesh.org/project/batman/list/
B: https://www.open-mesh.org/projects/batman-adv/issues
C: ircs://irc.hackint.org/batadv
T: git https://git.open-mesh.org/linux-merge.git
T: git https://git.open-mesh.org/batadv.git
F: Documentation/networking/batman-adv.rst
F: include/uapi/linux/batadv_packet.h
F: include/uapi/linux/batman_adv.h
@ -18642,6 +18642,7 @@ F: net/
F: samples/pktgen/
F: tools/net/
F: tools/testing/selftests/net/
X: Documentation/networking/batman-adv.rst
X: Documentation/networking/mac80211-injection.rst
X: Documentation/networking/mac80211_hwsim/
X: Documentation/networking/regulatory.rst
@ -18652,6 +18653,7 @@ X: include/net/iw_handler.h
X: include/net/mac80211.h
X: include/net/wext.h
X: net/9p/
X: net/batman-adv/
X: net/bluetooth/
X: net/can/
X: net/ceph/

View File

@ -30,5 +30,6 @@ batman-adv-$(CONFIG_BATMAN_ADV_TRACING) += trace.o
batman-adv-y += tp_meter.o
batman-adv-y += translation-table.o
batman-adv-y += tvlv.o
batman-adv-y += version.o
CFLAGS_trace.o := -I$(src)

View File

@ -13,6 +13,7 @@
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/cache.h>
#include <linux/compiler.h>
#include <linux/container_of.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
@ -194,14 +195,17 @@ static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
get_random_bytes(&random_seqno, sizeof(random_seqno));
atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
hard_iface->bat_iv.ogm_buff.len = BATADV_OGM_HLEN;
hard_iface->bat_iv.ogm_buff.capacity = BATADV_OGM_HLEN;
hard_iface->bat_iv.ogm_buff.header_length = BATADV_OGM_HLEN;
ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff.capacity, GFP_ATOMIC);
if (!ogm_buff) {
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
return -ENOMEM;
}
hard_iface->bat_iv.ogm_buff = ogm_buff;
hard_iface->bat_iv.ogm_buff.buf = ogm_buff;
batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
batadv_ogm_packet->packet_type = BATADV_IV_OGM;
@ -220,8 +224,9 @@ static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
{
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
kfree(hard_iface->bat_iv.ogm_buff);
hard_iface->bat_iv.ogm_buff = NULL;
kfree(hard_iface->bat_iv.ogm_buff.buf);
memset(&hard_iface->bat_iv.ogm_buff, 0,
sizeof(hard_iface->bat_iv.ogm_buff));
mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
@ -235,7 +240,7 @@ static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
ogm_buff = hard_iface->bat_iv.ogm_buff;
ogm_buff = hard_iface->bat_iv.ogm_buff.buf;
if (!ogm_buff)
goto unlock;
@ -257,7 +262,7 @@ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
ogm_buff = hard_iface->bat_iv.ogm_buff;
ogm_buff = hard_iface->bat_iv.ogm_buff.buf;
if (!ogm_buff)
goto unlock;
@ -274,7 +279,7 @@ batadv_iv_ogm_emit_send_time(const struct batadv_priv *bat_priv)
{
unsigned int msecs;
msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
msecs = READ_ONCE(bat_priv->orig_interval) - BATADV_JITTER;
msecs += get_random_u32_below(2 * BATADV_JITTER);
return jiffies + msecs_to_jiffies(msecs);
@ -289,7 +294,7 @@ static unsigned long batadv_iv_ogm_fwd_send_time(void)
/* apply hop penalty for a normal link */
static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
{
int hop_penalty = atomic_read(&bat_priv->hop_penalty);
int hop_penalty = READ_ONCE(bat_priv->hop_penalty);
int new_tq;
new_tq = tq * (BATADV_TQ_MAX_VALUE - hop_penalty);
@ -555,7 +560,7 @@ static bool batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
unsigned int skb_size;
atomic_t *queue_left = own_packet ? NULL : &bat_priv->batman_queue_left;
if (atomic_read(&bat_priv->aggregated_ogms))
if (READ_ONCE(bat_priv->aggregated_ogms))
skb_size = max_t(unsigned int, BATADV_MAX_AGGREGATION_BYTES,
packet_len);
else
@ -641,6 +646,7 @@ static bool batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
struct batadv_ogm_packet *batadv_ogm_packet;
bool direct_link;
unsigned long max_aggregation_jiffies;
bool aggregated_ogms;
batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
direct_link = !!(batadv_ogm_packet->flags & BATADV_DIRECTLINK);
@ -648,8 +654,10 @@ static bool batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
/* find position for the packet in the forward queue */
spin_lock_bh(&bat_priv->forw_bat_list_lock);
aggregated_ogms = READ_ONCE(bat_priv->aggregated_ogms);
/* own packets are not to be aggregated */
if (atomic_read(&bat_priv->aggregated_ogms) && !own_packet) {
if (aggregated_ogms && !own_packet) {
hlist_for_each_entry(forw_packet_pos,
&bat_priv->forw_bat_list, list) {
if (batadv_iv_ogm_can_aggregate(batadv_ogm_packet,
@ -675,7 +683,7 @@ static bool batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,
* we hold it back for a while, so that it might be aggregated
* later on
*/
if (!own_packet && atomic_read(&bat_priv->aggregated_ogms))
if (!own_packet && aggregated_ogms)
send_time += max_aggregation_jiffies;
return batadv_iv_ogm_aggregate_new(packet_buff, packet_len,
@ -792,10 +800,9 @@ batadv_iv_ogm_slide_own_bcast_window(struct batadv_hard_iface *hard_iface)
static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
{
struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface);
unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
struct batadv_ogm_buf *ogm_buff = &hard_iface->bat_iv.ogm_buff;
struct batadv_ogm_packet *batadv_ogm_packet;
struct batadv_hard_iface *primary_if, *tmp_hard_iface;
int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
struct list_head *iter;
u32 seqno;
u16 tvlv_len = 0;
@ -807,7 +814,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
/* interface already disabled by batadv_iv_ogm_iface_disable */
if (!*ogm_buff)
if (!ogm_buff->buf)
return;
/* the interface gets activated here to avoid race conditions between
@ -826,9 +833,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
* appended as it may alter the tt tvlv container
*/
batadv_tt_local_commit_changes(bat_priv);
ret = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
ogm_buff_len,
BATADV_OGM_HLEN);
ret = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff);
if (ret < 0) {
reschedule = true;
goto out;
@ -837,7 +842,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
tvlv_len = ret;
}
batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
batadv_ogm_packet = ogm_buff->buf;
batadv_ogm_packet->tvlv_len = htons(tvlv_len);
/* change sequence number to network order */
@ -853,7 +858,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
/* OGMs from secondary interfaces are only scheduled on their
* respective interfaces.
*/
scheduled = batadv_iv_ogm_queue_add(bat_priv, *ogm_buff, *ogm_buff_len,
scheduled = batadv_iv_ogm_queue_add(bat_priv, ogm_buff->buf, ogm_buff->len,
hard_iface, hard_iface, 1, send_time);
if (!scheduled)
reschedule = true;
@ -869,8 +874,8 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
if (!kref_get_unless_zero(&tmp_hard_iface->refcount))
continue;
scheduled = batadv_iv_ogm_queue_add(bat_priv, *ogm_buff,
*ogm_buff_len, hard_iface,
scheduled = batadv_iv_ogm_queue_add(bat_priv, ogm_buff->buf,
ogm_buff->len, hard_iface,
tmp_hard_iface, 1, send_time);
batadv_hardif_put(tmp_hard_iface);
@ -888,7 +893,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
*/
queue_delayed_work(batadv_event_workqueue,
&hard_iface->bat_iv.reschedule_work,
msecs_to_jiffies(atomic_read(&bat_priv->orig_interval)));
msecs_to_jiffies(READ_ONCE(bat_priv->orig_interval)));
}
batadv_hardif_put(primary_if);
@ -1214,7 +1219,7 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
inv_asym_penalty = BATADV_TQ_MAX_VALUE * neigh_rq_inv_cube;
inv_asym_penalty /= neigh_rq_max_cube;
tq_asym_penalty = BATADV_TQ_MAX_VALUE - inv_asym_penalty;
tq_iface_hop_penalty -= atomic_read(&if_incoming->hop_penalty);
tq_iface_hop_penalty -= READ_ONCE(if_incoming->hop_penalty);
/* penalize if the OGM is forwarded on the same interface. WiFi
* interfaces and other half duplex devices suffer from throughput
@ -1773,7 +1778,7 @@ static void batadv_iv_send_outstanding_bat_ogm_packet(struct work_struct *work)
delayed_work);
bat_priv = netdev_priv(forw_packet->if_incoming->mesh_iface);
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) {
if (READ_ONCE(bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) {
dropped = true;
goto out;
}
@ -2321,7 +2326,7 @@ static void batadv_iv_iface_enabled(struct batadv_hard_iface *hard_iface)
static void batadv_iv_init_sel_class(struct batadv_priv *bat_priv)
{
/* set default TQ difference threshold to 20 */
atomic_set(&bat_priv->gw.sel_class, 20);
WRITE_ONCE(bat_priv->gw.sel_class, 20);
}
static struct batadv_gw_node *
@ -2353,7 +2358,7 @@ batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
tq_avg = router_ifinfo->bat_iv.tq_avg;
switch (atomic_read(&bat_priv->gw.sel_class)) {
switch (READ_ONCE(bat_priv->gw.sel_class)) {
case 1: /* fast connection */
tmp_gw_factor = tq_avg * tq_avg;
tmp_gw_factor *= gw_node->bandwidth_down;
@ -2407,13 +2412,14 @@ static bool batadv_iv_gw_is_eligible(struct batadv_priv *bat_priv,
{
struct batadv_neigh_ifinfo *router_orig_ifinfo = NULL;
struct batadv_neigh_ifinfo *router_gw_ifinfo = NULL;
u32 sel_class = READ_ONCE(bat_priv->gw.sel_class);
struct batadv_neigh_node *router_gw = NULL;
struct batadv_neigh_node *router_orig = NULL;
u8 gw_tq_avg, orig_tq_avg;
bool ret = false;
/* dynamic re-election is performed only on fast or late switch */
if (atomic_read(&bat_priv->gw.sel_class) <= 2)
if (sel_class <= 2)
return false;
router_gw = batadv_orig_router_get(curr_gw_orig, BATADV_IF_DEFAULT);
@ -2448,8 +2454,7 @@ static bool batadv_iv_gw_is_eligible(struct batadv_priv *bat_priv,
/* if the routing class is greater than 3 the value tells us how much
* greater the TQ value of the new gateway must be
*/
if ((atomic_read(&bat_priv->gw.sel_class) > 3) &&
(orig_tq_avg - gw_tq_avg < atomic_read(&bat_priv->gw.sel_class)))
if (sel_class > 3 && orig_tq_avg - gw_tq_avg < sel_class)
goto out;
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,

View File

@ -7,8 +7,8 @@
#include "bat_v.h"
#include "main.h"
#include <linux/atomic.h>
#include <linux/cache.h>
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/if_ether.h>
#include <linux/init.h>
@ -505,7 +505,7 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
static void batadv_v_init_sel_class(struct batadv_priv *bat_priv)
{
/* set default throughput difference threshold to 5Mbps */
atomic_set(&bat_priv->gw.sel_class, 50);
WRITE_ONCE(bat_priv->gw.sel_class, 50);
}
/**
@ -602,7 +602,7 @@ static bool batadv_v_gw_is_eligible(struct batadv_priv *bat_priv,
u32 gw_throughput, orig_throughput, threshold;
bool ret = false;
threshold = atomic_read(&bat_priv->gw.sel_class);
threshold = READ_ONCE(bat_priv->gw.sel_class);
curr_gw = batadv_gw_node_get(bat_priv, curr_gw_orig);
if (!curr_gw) {
@ -812,8 +812,8 @@ void batadv_v_hardif_init(struct batadv_hard_iface *hard_iface)
/* enable link throughput auto-detection by setting the throughput
* override to zero
*/
atomic_set(&hard_iface->bat_v.throughput_override, 0);
atomic_set(&hard_iface->bat_v.elp_interval, 500);
WRITE_ONCE(hard_iface->bat_v.throughput_override, 0);
WRITE_ONCE(hard_iface->bat_v.elp_interval, 500);
hard_iface->bat_v.aggr_len = 0;
skb_queue_head_init(&hard_iface->bat_v.aggr_list);

View File

@ -10,6 +10,7 @@
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/byteorder/generic.h>
#include <linux/compiler.h>
#include <linux/container_of.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
@ -62,7 +63,7 @@ static void batadv_v_elp_start_timer(struct batadv_hard_iface *hard_iface)
{
unsigned int msecs;
msecs = atomic_read(&hard_iface->bat_v.elp_interval) - BATADV_JITTER;
msecs = READ_ONCE(hard_iface->bat_v.elp_interval) - BATADV_JITTER;
msecs += get_random_u32_below(2 * BATADV_JITTER);
queue_delayed_work(batadv_event_workqueue, &hard_iface->bat_v.elp_wq,
@ -85,6 +86,7 @@ static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
struct ethtool_link_ksettings link_settings;
struct net_device *real_netdev;
struct station_info sinfo;
u32 wifi_flags;
u32 throughput;
int ret;
@ -97,7 +99,7 @@ static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
/* if the user specified a customised value for this interface, then
* return it directly
*/
throughput = atomic_read(&hard_iface->bat_v.throughput_override);
throughput = READ_ONCE(hard_iface->bat_v.throughput_override);
if (throughput != 0) {
*pthroughput = throughput;
return true;
@ -106,8 +108,9 @@ static bool batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh,
/* if this is a wireless device, then ask its throughput through
* cfg80211 API
*/
if (batadv_is_wifi_hardif(hard_iface)) {
if (!batadv_is_cfg80211_hardif(hard_iface))
wifi_flags = batadv_hardif_get_wifi_flags(hard_iface);
if (batadv_is_wifi(wifi_flags)) {
if (!batadv_is_cfg80211(wifi_flags))
/* unsupported WiFi driver version */
goto default_throughput;
@ -304,7 +307,7 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
hard_iface = container_of(bat_v, struct batadv_hard_iface, bat_v);
bat_priv = netdev_priv(hard_iface->mesh_iface);
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
if (READ_ONCE(bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
goto out;
/* we are in the process of shutting this interface down */
@ -322,7 +325,7 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
elp_packet = (struct batadv_elp_packet *)skb->data;
elp_packet->seqno = htonl(atomic_read(&hard_iface->bat_v.elp_seqno));
elp_interval = atomic_read(&hard_iface->bat_v.elp_interval);
elp_interval = READ_ONCE(hard_iface->bat_v.elp_interval);
elp_packet->elp_interval = htonl(elp_interval);
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,

View File

@ -8,7 +8,9 @@
#include "main.h"
#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/compiler.h>
#include <linux/container_of.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
@ -105,7 +107,7 @@ static void batadv_v_ogm_start_timer(struct batadv_priv *bat_priv)
if (delayed_work_pending(&bat_priv->bat_v.ogm_wq))
return;
msecs = atomic_read(&bat_priv->orig_interval) - BATADV_JITTER;
msecs = READ_ONCE(bat_priv->orig_interval) - BATADV_JITTER;
msecs += get_random_u32_below(2 * BATADV_JITTER);
queue_delayed_work(batadv_event_workqueue, &bat_priv->bat_v.ogm_wq,
msecs_to_jiffies(msecs));
@ -246,7 +248,7 @@ static void batadv_v_ogm_queue_on_if(struct batadv_priv *bat_priv,
return;
}
if (!atomic_read(&bat_priv->aggregated_ogms)) {
if (!READ_ONCE(bat_priv->aggregated_ogms)) {
batadv_v_ogm_send_to_if(bat_priv, skb, hard_iface);
return;
}
@ -268,39 +270,35 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
{
struct batadv_hard_iface *hard_iface;
struct batadv_ogm2_packet *ogm_packet;
struct batadv_ogm_buf *ogm_buff;
struct sk_buff *skb, *skb_tmp;
unsigned char **ogm_buff;
struct list_head *iter;
int *ogm_buff_len;
u16 tvlv_len;
int ret;
lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex);
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
if (READ_ONCE(bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
goto out;
ogm_buff = &bat_priv->bat_v.ogm_buff;
ogm_buff_len = &bat_priv->bat_v.ogm_buff_len;
/* tt changes have to be committed before the tvlv data is
* appended as it may alter the tt tvlv container
*/
batadv_tt_local_commit_changes(bat_priv);
ret = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff,
ogm_buff_len,
BATADV_OGM2_HLEN);
ret = batadv_tvlv_container_ogm_append(bat_priv, ogm_buff);
if (ret < 0)
goto reschedule;
tvlv_len = ret;
skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + *ogm_buff_len);
skb = netdev_alloc_skb_ip_align(NULL, ETH_HLEN + ogm_buff->len);
if (!skb)
goto reschedule;
skb_reserve(skb, ETH_HLEN);
skb_put_data(skb, *ogm_buff, *ogm_buff_len);
skb_put_data(skb, ogm_buff->buf, ogm_buff->len);
ogm_packet = (struct batadv_ogm2_packet *)skb->data;
ogm_packet->seqno = htonl(atomic_read(&bat_priv->bat_v.ogm_seqno));
@ -446,10 +444,10 @@ void batadv_v_ogm_primary_iface_set(struct batadv_hard_iface *primary_iface)
struct batadv_ogm2_packet *ogm_packet;
mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
if (!bat_priv->bat_v.ogm_buff)
if (!bat_priv->bat_v.ogm_buff.buf)
goto unlock;
ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
ogm_packet = bat_priv->bat_v.ogm_buff.buf;
ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
unlock:
@ -484,9 +482,9 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
struct batadv_hard_iface *if_outgoing,
u32 throughput)
{
int if_hop_penalty = atomic_read(&if_incoming->hop_penalty);
int hop_penalty = atomic_read(&bat_priv->hop_penalty);
int hop_penalty_max = BATADV_TQ_MAX_VALUE;
u32 if_hop_penalty = READ_ONCE(if_incoming->hop_penalty);
u32 hop_penalty = READ_ONCE(bat_priv->hop_penalty);
u32 hop_penalty_max = BATADV_TQ_MAX_VALUE;
/* Apply per hardif hop penalty */
throughput = throughput * (hop_penalty_max - if_hop_penalty) /
@ -721,7 +719,7 @@ static bool batadv_v_ogm_route_update(struct batadv_priv *bat_priv,
* don't route towards it
*/
router = batadv_orig_router_get(orig_node, if_outgoing);
if (router && router->orig_node != orig_node && !orig_neigh_router) {
if (router && ACCESS_PRIVATE(router, orig_node_id) != orig_node && !orig_neigh_router) {
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
"Drop packet: OGM via unknown neighbor!\n");
goto out;
@ -1050,12 +1048,15 @@ int batadv_v_ogm_init(struct batadv_priv *bat_priv)
unsigned char *ogm_buff;
u32 random_seqno;
bat_priv->bat_v.ogm_buff_len = BATADV_OGM2_HLEN;
ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff_len, GFP_ATOMIC);
bat_priv->bat_v.ogm_buff.len = BATADV_OGM2_HLEN;
bat_priv->bat_v.ogm_buff.capacity = BATADV_OGM2_HLEN;
bat_priv->bat_v.ogm_buff.header_length = BATADV_OGM2_HLEN;
ogm_buff = kzalloc(bat_priv->bat_v.ogm_buff.capacity, GFP_ATOMIC);
if (!ogm_buff)
return -ENOMEM;
bat_priv->bat_v.ogm_buff = ogm_buff;
bat_priv->bat_v.ogm_buff.buf = ogm_buff;
ogm_packet = (struct batadv_ogm2_packet *)ogm_buff;
ogm_packet->packet_type = BATADV_OGM2;
ogm_packet->version = BATADV_COMPAT_VERSION;
@ -1083,9 +1084,8 @@ void batadv_v_ogm_free(struct batadv_priv *bat_priv)
mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
kfree(bat_priv->bat_v.ogm_buff);
bat_priv->bat_v.ogm_buff = NULL;
bat_priv->bat_v.ogm_buff_len = 0;
kfree(bat_priv->bat_v.ogm_buff.buf);
memset(&bat_priv->bat_v.ogm_buff, 0, sizeof(bat_priv->bat_v.ogm_buff));
mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
}

View File

@ -8,6 +8,7 @@
#include "main.h"
#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/compiler.h>
#include <linux/container_of.h>
@ -1379,7 +1380,7 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
bat_priv->bla.claim_dest.group = group;
/* purge everything when bridge loop avoidance is turned off */
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
if (!READ_ONCE(bat_priv->bridge_loop_avoidance))
oldif = NULL;
if (!oldif) {
@ -1483,7 +1484,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)
batadv_bla_purge_claims(bat_priv, primary_if, 0);
batadv_bla_purge_backbone_gw(bat_priv, 0);
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
if (!READ_ONCE(bat_priv->bridge_loop_avoidance))
goto out;
if (atomic_dec_and_test(&bat_priv->bla.loopdetect_next)) {
@ -1782,7 +1783,7 @@ bool batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, u8 *orig,
struct batadv_bla_backbone_gw *backbone_gw;
int i;
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
if (!READ_ONCE(bat_priv->bridge_loop_avoidance))
return false;
if (!hash)
@ -1820,7 +1821,7 @@ bool batadv_bla_is_backbone_gw(struct sk_buff *skb,
struct batadv_bla_backbone_gw *backbone_gw;
unsigned short vid;
if (!atomic_read(&orig_node->bat_priv->bridge_loop_avoidance))
if (!READ_ONCE(orig_node->bat_priv->bridge_loop_avoidance))
return false;
/* first, find out the vid. */
@ -1952,7 +1953,7 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb,
if (!primary_if)
goto handled;
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
if (!READ_ONCE(bat_priv->bridge_loop_avoidance))
goto allow;
if (batadv_bla_loopdetect_check(bat_priv, skb, primary_if, vid))
@ -2084,7 +2085,7 @@ bool batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb,
if (!primary_if)
goto out;
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
if (!READ_ONCE(bat_priv->bridge_loop_avoidance))
goto allow;
if (batadv_bla_process_claim(bat_priv, primary_if, skb))
@ -2504,7 +2505,7 @@ bool batadv_bla_check_claim(struct batadv_priv *bat_priv,
struct batadv_hard_iface *primary_if = NULL;
bool ret = true;
if (!atomic_read(&bat_priv->bridge_loop_avoidance))
if (!READ_ONCE(bat_priv->bridge_loop_avoidance))
return ret;
primary_if = batadv_primary_if_get_selected(bat_priv);

View File

@ -9,6 +9,7 @@
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/container_of.h>
#include <linux/err.h>
@ -742,7 +743,7 @@ static void batadv_dat_tvlv_container_update(struct batadv_priv *bat_priv)
{
char dat_mode;
dat_mode = atomic_read(&bat_priv->distributed_arp_table);
dat_mode = READ_ONCE(bat_priv->distributed_arp_table);
switch (dat_mode) {
case 0:
@ -1138,7 +1139,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
int hdr_size = 0;
unsigned short vid;
if (!atomic_read(&bat_priv->distributed_arp_table))
if (!READ_ONCE(bat_priv->distributed_arp_table))
goto out;
vid = batadv_dat_get_vid(skb, &hdr_size);
@ -1233,7 +1234,7 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
unsigned short vid;
int err;
if (!atomic_read(&bat_priv->distributed_arp_table))
if (!READ_ONCE(bat_priv->distributed_arp_table))
goto out;
vid = batadv_dat_get_vid(skb, &hdr_size);
@ -1295,7 +1296,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
int hdr_size = 0;
unsigned short vid;
if (!atomic_read(&bat_priv->distributed_arp_table))
if (!READ_ONCE(bat_priv->distributed_arp_table))
return;
vid = batadv_dat_get_vid(skb, &hdr_size);
@ -1343,7 +1344,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
bool dropped = false;
unsigned short vid;
if (!atomic_read(&bat_priv->distributed_arp_table))
if (!READ_ONCE(bat_priv->distributed_arp_table))
goto out;
vid = batadv_dat_get_vid(skb, &hdr_size);
@ -1713,7 +1714,7 @@ void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv,
u8 chaddr[BATADV_DHCP_CHADDR_LEN];
__be32 ip_src, yiaddr;
if (!atomic_read(&bat_priv->distributed_arp_table))
if (!READ_ONCE(bat_priv->distributed_arp_table))
return;
if (!batadv_dat_check_dhcp_ack(skb, proto, &ip_src, chaddr, &yiaddr))
@ -1743,7 +1744,7 @@ void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv,
__be16 proto;
u8 *hw_src;
if (!atomic_read(&bat_priv->distributed_arp_table))
if (!READ_ONCE(bat_priv->distributed_arp_table))
return;
if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN)))
@ -1788,7 +1789,7 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
int hdr_size = sizeof(struct batadv_bcast_packet);
unsigned short vid;
if (!atomic_read(&bat_priv->distributed_arp_table))
if (!READ_ONCE(bat_priv->distributed_arp_table))
goto out;
/* If this packet is an ARP_REQUEST and the node already has the

View File

@ -8,6 +8,7 @@
#include "main.h"
#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>

View File

@ -8,6 +8,7 @@
#include "main.h"
#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/container_of.h>
#include <linux/err.h>
@ -170,7 +171,7 @@ void batadv_gw_check_client_stop(struct batadv_priv *bat_priv)
{
struct batadv_gw_node *curr_gw;
if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
if (READ_ONCE(bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
return;
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
@ -202,7 +203,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
struct batadv_neigh_ifinfo *router_ifinfo = NULL;
char gw_addr[18] = { '\0' };
if (atomic_read(&bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
if (READ_ONCE(bat_priv->gw.mode) != BATADV_GW_MODE_CLIENT)
goto out;
if (!bat_priv->algo_ops->gw.get_best_gw_node)
@ -210,7 +211,7 @@ void batadv_gw_election(struct batadv_priv *bat_priv)
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw)
if (atomic_xchg(&bat_priv->gw.reselect, 0) == 0 && curr_gw)
goto out;
/* if gw.reselect is set to 1 it means that a previous call to
@ -702,7 +703,7 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv,
if (!gw_node)
goto out;
switch (atomic_read(&bat_priv->gw.mode)) {
switch (READ_ONCE(bat_priv->gw.mode)) {
case BATADV_GW_MODE_SERVER:
/* If we are a GW then we are our best GW. We can artificially
* set the tq towards ourself as the maximum value

View File

@ -7,8 +7,8 @@
#include "gateway_common.h"
#include "main.h"
#include <linux/atomic.h>
#include <linux/byteorder/generic.h>
#include <linux/compiler.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <uapi/linux/batadv_packet.h>
@ -25,10 +25,10 @@
void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv)
{
struct batadv_tvlv_gateway_data gw;
enum batadv_gw_modes gw_mode;
u32 down, up;
char gw_mode;
gw_mode = atomic_read(&bat_priv->gw.mode);
gw_mode = READ_ONCE(bat_priv->gw.mode);
switch (gw_mode) {
case BATADV_GW_MODE_OFF:
@ -36,8 +36,8 @@ void batadv_gw_tvlv_container_update(struct batadv_priv *bat_priv)
batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_GW, 1);
break;
case BATADV_GW_MODE_SERVER:
down = atomic_read(&bat_priv->gw.bandwidth_down);
up = atomic_read(&bat_priv->gw.bandwidth_up);
down = READ_ONCE(bat_priv->gw.bandwidth_down);
up = READ_ONCE(bat_priv->gw.bandwidth_up);
gw.bandwidth_down = htonl(down);
gw.bandwidth_up = htonl(up);
batadv_tvlv_container_register(bat_priv, BATADV_TVLV_GW, 1,
@ -83,7 +83,7 @@ static void batadv_gw_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
/* restart gateway selection */
if (gateway.bandwidth_down != 0 &&
atomic_read(&bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT)
READ_ONCE(bat_priv->gw.mode) == BATADV_GW_MODE_CLIENT)
batadv_gw_check_election(bat_priv, orig);
}
@ -96,7 +96,7 @@ void batadv_gw_init(struct batadv_priv *bat_priv)
if (bat_priv->algo_ops->gw.init_sel_class)
bat_priv->algo_ops->gw.init_sel_class(bat_priv);
else
atomic_set(&bat_priv->gw.sel_class, 1);
WRITE_ONCE(bat_priv->gw.sel_class, 1);
batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1,
NULL, NULL, BATADV_TVLV_GW, 1,

View File

@ -7,7 +7,7 @@
#include "hard-interface.h"
#include "main.h"
#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/compiler.h>
#include <linux/container_of.h>
@ -25,6 +25,8 @@
#include <linux/notifier.h>
#include <linux/printk.h>
#include <linux/rculist.h>
#include <linux/rhashtable-types.h>
#include <linux/rhashtable.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@ -42,6 +44,15 @@
#include "send.h"
#include "translation-table.h"
static const struct rhashtable_params batadv_wifi_net_devices_params = {
.key_len = sizeof(struct net_device *),
.key_offset = offsetof(struct batadv_wifi_net_device_state, netdev),
.head_offset = offsetof(struct batadv_wifi_net_device_state, l),
.automatic_shrinking = true,
};
static struct rhashtable batadv_wifi_net_devices;
/**
* batadv_hardif_release() - release hard interface from lists and queue for
* free after rcu grace period
@ -355,21 +366,28 @@ static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
}
/**
* batadv_is_cfg80211_hardif() - check if the given hardif is a cfg80211 wifi
* interface
* batadv_hardif_get_wifi_flags() - retrieve wifi flags for hard_iface
* @hard_iface: the device to check
*
* Return: true if the net device is a cfg80211 wireless device, false
* otherwise.
* Return: batadv_hard_iface_wifi_flags flags of the device
*/
bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface)
u32 batadv_hardif_get_wifi_flags(struct batadv_hard_iface *hard_iface)
{
u32 allowed_flags = 0;
struct batadv_wifi_net_device_state *device_state;
u32 wifi_flags = 0;
allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
if (!hard_iface)
return 0;
return !!(hard_iface->wifi_flags & allowed_flags);
rcu_read_lock();
device_state = rhashtable_lookup_fast(&batadv_wifi_net_devices,
&hard_iface->net_dev,
batadv_wifi_net_devices_params);
if (device_state)
wifi_flags = READ_ONCE(device_state->wifi_flags);
rcu_read_unlock();
return wifi_flags;
}
/**
@ -380,10 +398,9 @@ bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface)
*/
bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface)
{
if (!hard_iface)
return false;
u32 wifi_flags = batadv_hardif_get_wifi_flags(hard_iface);
return hard_iface->wifi_flags != 0;
return batadv_is_wifi(wifi_flags);
}
/**
@ -594,7 +611,7 @@ int batadv_hardif_min_mtu(struct net_device *mesh_iface)
}
rcu_read_unlock();
if (atomic_read(&bat_priv->fragmentation) == 0)
if (READ_ONCE(bat_priv->fragmentation) == 0)
goto out;
/* with fragmentation enabled the maximum size of internally generated
@ -611,7 +628,7 @@ int batadv_hardif_min_mtu(struct net_device *mesh_iface)
* overhead). For example, this value is used by TT to compute the
* maximum local table size
*/
atomic_set(&bat_priv->packet_size_max, min_mtu);
WRITE_ONCE(bat_priv->packet_size_max, min_mtu);
/* the real mesh-interface MTU is computed by removing the payload
* overhead from the maximum amount of bytes that was just computed.
@ -709,6 +726,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
int max_header_len = batadv_max_header_len();
unsigned int required_mtu;
unsigned int hardif_mtu;
bool fragmentation;
int ret;
hardif_mtu = READ_ONCE(hard_iface->net_dev->mtu);
@ -746,15 +764,14 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
batadv_info(hard_iface->mesh_iface, "Adding interface: %s\n",
hard_iface->net_dev->name);
if (atomic_read(&bat_priv->fragmentation) &&
hardif_mtu < required_mtu)
fragmentation = READ_ONCE(bat_priv->fragmentation);
if (fragmentation && hardif_mtu < required_mtu)
batadv_info(hard_iface->mesh_iface,
"The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to %i would solve the problem.\n",
hard_iface->net_dev->name, hardif_mtu,
required_mtu);
if (!atomic_read(&bat_priv->fragmentation) &&
hardif_mtu < required_mtu)
if (!fragmentation && hardif_mtu < required_mtu)
batadv_info(hard_iface->mesh_iface,
"The MTU of interface %s is too small (%i) to handle the transport of batman-adv packets. If you experience problems getting traffic through try increasing the MTU to %i.\n",
hard_iface->net_dev->name, hardif_mtu,
@ -889,11 +906,10 @@ batadv_hardif_add_interface(struct net_device *net_dev)
kref_init(&hard_iface->refcount);
hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
hard_iface->wifi_flags = batadv_wifi_flags_evaluate(net_dev);
if (batadv_is_wifi_hardif(hard_iface))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
atomic_set(&hard_iface->hop_penalty, 0);
WRITE_ONCE(hard_iface->hop_penalty, 0);
batadv_v_hardif_init(hard_iface);
@ -941,6 +957,131 @@ static int batadv_hard_if_event_meshif(unsigned long event,
return NOTIFY_DONE;
}
/**
* batadv_wifi_net_device_insert() - save information about wifi net_device
* @net_dev: net_device to add to batadv_wifi_net_devices
* @wifi_flags: net_device which generated an event
*
* Return: 0 on result, negative value on error
*/
static int
batadv_wifi_net_device_insert(struct net_device *net_dev, u32 wifi_flags)
{
struct batadv_wifi_net_device_state *device_state;
int ret;
ASSERT_RTNL();
device_state = kzalloc_obj(*device_state, GFP_ATOMIC);
if (!device_state)
return -ENOMEM;
device_state->wifi_flags = wifi_flags;
netdev_hold(net_dev, &device_state->dev_tracker, GFP_ATOMIC);
device_state->netdev = net_dev;
WRITE_ONCE(device_state->wifi_flags, wifi_flags);
ret = rhashtable_insert_fast(&batadv_wifi_net_devices, &device_state->l,
batadv_wifi_net_devices_params);
if (ret < 0)
goto err_free;
return 0;
err_free:
netdev_put(device_state->netdev, &device_state->dev_tracker);
kfree(device_state);
return ret;
}
/**
* batadv_wifi_net_device_remove() - remove information about wifi net_device
* @device_state: wifi net_device state to remove from batadv_wifi_net_device_state
*/
static void
batadv_wifi_net_device_remove(struct batadv_wifi_net_device_state *device_state)
{
ASSERT_RTNL();
rhashtable_remove_fast(&batadv_wifi_net_devices, &device_state->l,
batadv_wifi_net_devices_params);
netdev_put(device_state->netdev, &device_state->dev_tracker);
kfree_rcu(device_state, rcu);
}
/**
* batadv_wifi_net_device_update() - update wifi state of net_device
* @net_dev: net_device to update in batadv_wifi_net_devices
*
* The device will only be stored in batadv_wifi_net_devices when
* it could be identified as wifi device. If the net_device is no
* longer a wifi device, it is automatically removed from
* batadv_wifi_net_devices.
*/
static void
batadv_wifi_net_device_update(struct net_device *net_dev)
{
struct batadv_wifi_net_device_state *device_state;
u32 wifi_flags;
ASSERT_RTNL();
wifi_flags = batadv_wifi_flags_evaluate(net_dev);
device_state = rhashtable_lookup_fast(&batadv_wifi_net_devices,
&net_dev,
batadv_wifi_net_devices_params);
if (device_state) {
if (batadv_is_wifi(wifi_flags))
WRITE_ONCE(device_state->wifi_flags, wifi_flags);
else
batadv_wifi_net_device_remove(device_state);
} else if (batadv_is_wifi(wifi_flags)) {
batadv_wifi_net_device_insert(net_dev, wifi_flags);
}
}
/**
* batadv_wifi_net_device_unregister() - remove wifi state of net_device
* @net_dev: net_device to remove from batadv_wifi_net_devices
*/
static void
batadv_wifi_net_device_unregister(struct net_device *net_dev)
{
struct batadv_wifi_net_device_state *device_state;
ASSERT_RTNL();
device_state = rhashtable_lookup_fast(&batadv_wifi_net_devices,
&net_dev,
batadv_wifi_net_devices_params);
if (!device_state)
return;
batadv_wifi_net_device_remove(device_state);
}
/**
* batadv_wifi_net_device_event() - handle network events for batadv_wifi_net_devices
* @event: enum netdev_cmd event to handle
* @net_dev: net_device to update in batadv_wifi_net_devices
*/
static void batadv_wifi_net_device_event(unsigned long event,
struct net_device *net_dev)
{
switch (event) {
case NETDEV_REGISTER:
case NETDEV_POST_TYPE_CHANGE:
case NETDEV_CHANGEUPPER:
batadv_wifi_net_device_update(net_dev);
break;
case NETDEV_UNREGISTER:
case NETDEV_PRE_TYPE_CHANGE:
batadv_wifi_net_device_unregister(net_dev);
break;
}
}
static int batadv_hard_if_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
@ -952,6 +1093,8 @@ static int batadv_hard_if_event(struct notifier_block *this,
if (batadv_meshif_is_valid(net_dev))
return batadv_hard_if_event_meshif(event, net_dev);
batadv_wifi_net_device_event(event, net_dev);
hard_iface = batadv_hardif_get_by_netdev(net_dev);
if (!hard_iface && (event == NETDEV_REGISTER ||
event == NETDEV_POST_TYPE_CHANGE))
@ -995,8 +1138,9 @@ static int batadv_hard_if_event(struct notifier_block *this,
if (hard_iface == primary_if)
batadv_primary_if_update_addr(bat_priv, NULL);
break;
case NETDEV_REGISTER:
case NETDEV_POST_TYPE_CHANGE:
case NETDEV_CHANGEUPPER:
hard_iface->wifi_flags = batadv_wifi_flags_evaluate(net_dev);
if (batadv_is_wifi_hardif(hard_iface))
hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
break;
@ -1014,3 +1158,22 @@ static int batadv_hard_if_event(struct notifier_block *this,
struct notifier_block batadv_hard_if_notifier = {
.notifier_call = batadv_hard_if_event,
};
/**
* batadv_wifi_net_devices_init() - Initialize wifi devices cache
*
* Return: 0 on success, negative error code on failure
*/
int __init batadv_wifi_net_devices_init(void)
{
return rhashtable_init(&batadv_wifi_net_devices,
&batadv_wifi_net_devices_params);
}
/**
* batadv_wifi_net_devices_deinit() - Deinitialize wifi devices cache
*/
void batadv_wifi_net_devices_deinit(void)
{
rhashtable_destroy(&batadv_wifi_net_devices);
}

View File

@ -10,6 +10,7 @@
#include "main.h"
#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/kref.h>
#include <linux/netdevice.h>
#include <linux/rcupdate.h>
@ -69,7 +70,7 @@ extern struct notifier_block batadv_hard_if_notifier;
struct net_device *__batadv_get_real_netdev(struct net_device *net_device);
struct net_device *batadv_get_real_netdev(struct net_device *net_device);
bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface);
u32 batadv_hardif_get_wifi_flags(struct batadv_hard_iface *hard_iface);
bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface);
struct batadv_hard_iface*
batadv_hardif_get_by_netdev(const struct net_device *net_dev);
@ -81,6 +82,8 @@ void batadv_update_min_mtu(struct net_device *mesh_iface);
void batadv_hardif_release(struct kref *ref);
int batadv_hardif_no_broadcast(struct batadv_hard_iface *if_outgoing,
u8 *orig_addr, u8 *orig_neigh);
int __init batadv_wifi_net_devices_init(void);
void batadv_wifi_net_devices_deinit(void);
/**
* batadv_hardif_put() - decrement the hard interface refcounter and possibly
@ -119,4 +122,33 @@ batadv_primary_if_get_selected(struct batadv_priv *bat_priv)
return hard_iface;
}
/**
* batadv_is_cfg80211() - check if the given hardif is a cfg80211
* wifi interface
* @wifi_flags: extracted batadv_hard_iface_wifi_flagss of an net_device
*
* Return: true if the net device is a cfg80211 wireless device, false
* otherwise.
*/
static inline bool batadv_is_cfg80211(u32 wifi_flags)
{
u32 allowed_flags = 0;
allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
return !!(wifi_flags & allowed_flags);
}
/**
* batadv_is_wifi() - check if flags belong to wifi interface
* @wifi_flags: extracted batadv_hard_iface_wifi_flagss of an net_device
*
* Return: true if the net device is a 802.11 wireless device, false otherwise.
*/
static inline bool batadv_is_wifi(u32 wifi_flags)
{
return wifi_flags != 0;
}
#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */

View File

@ -76,7 +76,7 @@ __printf(2, 3);
#define _batadv_dbg(type, bat_priv, ratelimited, fmt, arg...) \
do { \
struct batadv_priv *__batpriv = (bat_priv); \
if (atomic_read(&__batpriv->log_level) & (type) && \
if (READ_ONCE(__batpriv->log_level) & (type) && \
(!(ratelimited) || net_ratelimit())) \
batadv_debug_log(__batpriv, fmt, ## arg); \
} \

View File

@ -33,6 +33,7 @@
#include <linux/sprintf.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/utsname.h>
#include <linux/workqueue.h>
#include <net/dsfield.h>
#include <net/genetlink.h>
@ -104,22 +105,33 @@ static int __init batadv_init(void)
batadv_tp_meter_init();
batadv_event_workqueue = create_singlethread_workqueue("bat_events");
if (!batadv_event_workqueue)
if (!batadv_event_workqueue) {
ret = -ENOMEM;
goto err_create_wq;
}
ret = batadv_wifi_net_devices_init();
if (ret < 0)
goto err_init_wifi;
register_netdevice_notifier(&batadv_hard_if_notifier);
rtnl_link_register(&batadv_link_ops);
batadv_netlink_register();
pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n",
BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION);
init_utsname()->release, BATADV_COMPAT_VERSION);
return 0;
err_init_wifi:
destroy_workqueue(batadv_event_workqueue);
batadv_event_workqueue = NULL;
rcu_barrier();
err_create_wq:
batadv_tt_cache_destroy();
return -ENOMEM;
return ret;
}
static void __exit batadv_exit(void)
@ -133,6 +145,7 @@ static void __exit batadv_exit(void)
rcu_barrier();
batadv_wifi_net_devices_deinit();
batadv_tt_cache_destroy();
}
@ -187,31 +200,31 @@ int batadv_mesh_init(struct net_device *mesh_iface)
ret = batadv_originator_init(bat_priv);
if (ret < 0) {
atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
goto err_orig;
}
ret = batadv_tt_init(bat_priv);
if (ret < 0) {
atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
goto err_tt;
}
ret = batadv_v_mesh_init(bat_priv);
if (ret < 0) {
atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
goto err_v;
}
ret = batadv_bla_init(bat_priv);
if (ret < 0) {
atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
goto err_bla;
}
ret = batadv_dat_init(bat_priv);
if (ret < 0) {
atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
goto err_dat;
}
@ -219,7 +232,7 @@ int batadv_mesh_init(struct net_device *mesh_iface)
batadv_mcast_init(bat_priv);
atomic_set(&bat_priv->gw.reselect, 0);
atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_ACTIVE);
return 0;
@ -233,7 +246,7 @@ int batadv_mesh_init(struct net_device *mesh_iface)
batadv_originator_free(bat_priv);
err_orig:
batadv_purge_outstanding_packets(bat_priv, NULL);
atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_INACTIVE);
return ret;
}
@ -246,7 +259,7 @@ void batadv_mesh_free(struct net_device *mesh_iface)
{
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_DEACTIVATING);
batadv_purge_outstanding_packets(bat_priv, NULL);
batadv_tp_stop_all(bat_priv);
@ -277,7 +290,7 @@ void batadv_mesh_free(struct net_device *mesh_iface)
free_percpu(bat_priv->bat_counters);
bat_priv->bat_counters = NULL;
atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_INACTIVE);
}
/**
@ -441,7 +454,7 @@ int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
bat_priv = netdev_priv(hard_iface->mesh_iface);
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
goto err_free;
/* discard frames on not active interfaces */
@ -614,7 +627,7 @@ bool batadv_vlan_ap_isola_get(struct batadv_priv *bat_priv, unsigned short vid)
*/
vlan = batadv_meshif_vlan_get(bat_priv, vid);
if (vlan) {
ap_isolation_enabled = atomic_read(&vlan->ap_isolation);
ap_isolation_enabled = READ_ONCE(vlan->ap_isolation);
batadv_meshif_vlan_put(vlan);
}
@ -684,6 +697,5 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR(BATADV_DRIVER_AUTHOR);
MODULE_DESCRIPTION(BATADV_DRIVER_DESC);
MODULE_VERSION(BATADV_SOURCE_VERSION);
MODULE_ALIAS_RTNL_LINK("batadv");
MODULE_ALIAS_GENL_FAMILY(BATADV_NL_NAME);

View File

@ -12,10 +12,6 @@
#define BATADV_DRIVER_DESC "B.A.T.M.A.N. advanced"
#define BATADV_DRIVER_DEVICE "batman-adv"
#ifndef BATADV_SOURCE_VERSION
#define BATADV_SOURCE_VERSION "2025.5"
#endif
/* B.A.T.M.A.N. parameters */
#define BATADV_TQ_MAX_VALUE 255

View File

@ -8,6 +8,7 @@
#include "main.h"
#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/cache.h>
#include <linux/compiler.h>
@ -36,6 +37,7 @@
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/utsname.h>
#include <net/netlink.h>
#include <net/rtnetlink.h>
#include <uapi/linux/batadv_packet.h>
@ -123,7 +125,7 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
eth_hw_addr_set(dev, addr->sa_data);
/* only modify transtable if it has been initialized before */
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
return 0;
rcu_read_lock();
@ -190,7 +192,7 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
int network_offset = ETH_HLEN;
__be16 proto;
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
goto dropped;
/* reset control block to avoid left overs from previous users */
@ -255,7 +257,7 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
goto dropped;
gw_mode = atomic_read(&bat_priv->gw.mode);
gw_mode = READ_ONCE(bat_priv->gw.mode);
if (is_multicast_ether_addr(ethhdr->h_dest)) {
/* if gw mode is off, broadcast every packet */
if (gw_mode == BATADV_GW_MODE_OFF) {
@ -565,7 +567,7 @@ int batadv_meshif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
vlan->vid = vid;
kref_init(&vlan->refcount);
atomic_set(&vlan->ap_isolation, 0);
WRITE_ONCE(vlan->ap_isolation, 0);
kref_get(&vlan->refcount);
hlist_add_head_rcu(&vlan->list, &bat_priv->meshif_vlan_list);
@ -752,36 +754,36 @@ static int batadv_meshif_init_late(struct net_device *dev)
if (!bat_priv->bat_counters)
return -ENOMEM;
atomic_set(&bat_priv->aggregated_ogms, 1);
atomic_set(&bat_priv->bonding, 0);
WRITE_ONCE(bat_priv->aggregated_ogms, 1);
WRITE_ONCE(bat_priv->bonding, 0);
#ifdef CONFIG_BATMAN_ADV_BLA
atomic_set(&bat_priv->bridge_loop_avoidance, 1);
WRITE_ONCE(bat_priv->bridge_loop_avoidance, 1);
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
atomic_set(&bat_priv->distributed_arp_table, 1);
WRITE_ONCE(bat_priv->distributed_arp_table, 1);
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
atomic_set(&bat_priv->multicast_mode, 1);
atomic_set(&bat_priv->multicast_fanout, 16);
WRITE_ONCE(bat_priv->multicast_mode, 1);
WRITE_ONCE(bat_priv->multicast_fanout, 16);
atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0);
atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0);
atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0);
atomic_set(&bat_priv->mcast.num_no_mc_ptype_capa, 0);
#endif
atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF);
atomic_set(&bat_priv->gw.bandwidth_down, 100);
atomic_set(&bat_priv->gw.bandwidth_up, 20);
atomic_set(&bat_priv->orig_interval, 1000);
atomic_set(&bat_priv->hop_penalty, 30);
WRITE_ONCE(bat_priv->gw.mode, BATADV_GW_MODE_OFF);
WRITE_ONCE(bat_priv->gw.bandwidth_down, 100);
WRITE_ONCE(bat_priv->gw.bandwidth_up, 20);
WRITE_ONCE(bat_priv->orig_interval, 1000);
WRITE_ONCE(bat_priv->hop_penalty, 30);
#ifdef CONFIG_BATMAN_ADV_DEBUG
atomic_set(&bat_priv->log_level, 0);
WRITE_ONCE(bat_priv->log_level, 0);
#endif
atomic_set(&bat_priv->fragmentation, 1);
atomic_set(&bat_priv->packet_size_max, BATADV_MAX_MTU);
WRITE_ONCE(bat_priv->fragmentation, 1);
WRITE_ONCE(bat_priv->packet_size_max, BATADV_MAX_MTU);
atomic_set(&bat_priv->bcast_queue_left, BATADV_BCAST_QUEUE_LEN);
atomic_set(&bat_priv->batman_queue_left, BATADV_BATMAN_QUEUE_LEN);
atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
WRITE_ONCE(bat_priv->mesh_state, BATADV_MESH_INACTIVE);
atomic_set(&bat_priv->bcast_seqno, 1);
atomic_set(&bat_priv->tt.vn, 0);
atomic_set(&bat_priv->tt.ogm_append_cnt, 0);
@ -892,7 +894,7 @@ static void batadv_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
strscpy(info->driver, "B.A.T.M.A.N. advanced", sizeof(info->driver));
strscpy(info->version, BATADV_SOURCE_VERSION, sizeof(info->version));
strscpy(info->version, init_utsname()->release, sizeof(info->version));
strscpy(info->fw_version, "N/A", sizeof(info->fw_version));
strscpy(info->bus_info, "batman", sizeof(info->bus_info));
}

View File

@ -1099,7 +1099,7 @@ static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv,
{
struct ethhdr *ethhdr = eth_hdr(skb);
if (!atomic_read(&bat_priv->multicast_mode))
if (!READ_ONCE(bat_priv->multicast_mode))
return -EINVAL;
switch (ntohs(ethhdr->h_proto)) {
@ -1204,7 +1204,7 @@ batadv_mcast_forw_mode_by_count(struct batadv_priv *bat_priv,
batadv_mcast_forw_push(bat_priv, skb, vid, is_routable, count))
return BATADV_FORW_MCAST;
if (count <= atomic_read(&bat_priv->multicast_fanout))
if (count <= READ_ONCE(bat_priv->multicast_fanout))
return BATADV_FORW_UCASTS;
return BATADV_FORW_BCAST;

View File

@ -13,6 +13,7 @@
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/cache.h>
#include <linux/compiler.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/gfp.h>
@ -28,6 +29,7 @@
#include <linux/skbuff.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/utsname.h>
#include <net/genetlink.h>
#include <net/net_namespace.h>
#include <net/netlink.h>
@ -179,7 +181,7 @@ static int batadv_netlink_mesh_fill_ap_isolation(struct sk_buff *msg,
if (!vlan)
return 0;
ap_isolation = atomic_read(&vlan->ap_isolation);
ap_isolation = READ_ONCE(vlan->ap_isolation);
batadv_meshif_vlan_put(vlan);
return nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED,
@ -202,7 +204,7 @@ static int batadv_netlink_set_mesh_ap_isolation(struct nlattr *attr,
if (!vlan)
return -ENOENT;
atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr));
WRITE_ONCE(vlan->ap_isolation, !!nla_get_u8(attr));
batadv_meshif_vlan_put(vlan);
return 0;
@ -233,7 +235,7 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
if (!hdr)
return -ENOBUFS;
if (nla_put_string(msg, BATADV_ATTR_VERSION, BATADV_SOURCE_VERSION) ||
if (nla_put_string(msg, BATADV_ATTR_VERSION, init_utsname()->release) ||
nla_put_string(msg, BATADV_ATTR_ALGO_NAME,
bat_priv->algo_ops->name) ||
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, mesh_iface->ifindex) ||
@ -267,7 +269,7 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
}
if (nla_put_u8(msg, BATADV_ATTR_AGGREGATED_OGMS_ENABLED,
!!atomic_read(&bat_priv->aggregated_ogms)))
!!READ_ONCE(bat_priv->aggregated_ogms)))
goto nla_put_failure;
if (batadv_netlink_mesh_fill_ap_isolation(msg, bat_priv))
@ -282,35 +284,35 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
goto nla_put_failure;
if (nla_put_u8(msg, BATADV_ATTR_BONDING_ENABLED,
!!atomic_read(&bat_priv->bonding)))
!!READ_ONCE(bat_priv->bonding)))
goto nla_put_failure;
#ifdef CONFIG_BATMAN_ADV_BLA
if (nla_put_u8(msg, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED,
!!atomic_read(&bat_priv->bridge_loop_avoidance)))
!!READ_ONCE(bat_priv->bridge_loop_avoidance)))
goto nla_put_failure;
#endif /* CONFIG_BATMAN_ADV_BLA */
#ifdef CONFIG_BATMAN_ADV_DAT
if (nla_put_u8(msg, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED,
!!atomic_read(&bat_priv->distributed_arp_table)))
!!READ_ONCE(bat_priv->distributed_arp_table)))
goto nla_put_failure;
#endif /* CONFIG_BATMAN_ADV_DAT */
if (nla_put_u8(msg, BATADV_ATTR_FRAGMENTATION_ENABLED,
!!atomic_read(&bat_priv->fragmentation)))
!!READ_ONCE(bat_priv->fragmentation)))
goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_DOWN,
atomic_read(&bat_priv->gw.bandwidth_down)))
READ_ONCE(bat_priv->gw.bandwidth_down)))
goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_GW_BANDWIDTH_UP,
atomic_read(&bat_priv->gw.bandwidth_up)))
READ_ONCE(bat_priv->gw.bandwidth_up)))
goto nla_put_failure;
if (nla_put_u8(msg, BATADV_ATTR_GW_MODE,
atomic_read(&bat_priv->gw.mode)))
READ_ONCE(bat_priv->gw.mode)))
goto nla_put_failure;
if (bat_priv->algo_ops->gw.get_best_gw_node &&
@ -319,32 +321,32 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
* in use does not implement the GW API
*/
if (nla_put_u32(msg, BATADV_ATTR_GW_SEL_CLASS,
atomic_read(&bat_priv->gw.sel_class)))
READ_ONCE(bat_priv->gw.sel_class)))
goto nla_put_failure;
}
if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
atomic_read(&bat_priv->hop_penalty)))
READ_ONCE(bat_priv->hop_penalty)))
goto nla_put_failure;
#ifdef CONFIG_BATMAN_ADV_DEBUG
if (nla_put_u32(msg, BATADV_ATTR_LOG_LEVEL,
atomic_read(&bat_priv->log_level)))
READ_ONCE(bat_priv->log_level)))
goto nla_put_failure;
#endif /* CONFIG_BATMAN_ADV_DEBUG */
#ifdef CONFIG_BATMAN_ADV_MCAST
if (nla_put_u8(msg, BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED,
!atomic_read(&bat_priv->multicast_mode)))
!READ_ONCE(bat_priv->multicast_mode)))
goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_MULTICAST_FANOUT,
atomic_read(&bat_priv->multicast_fanout)))
READ_ONCE(bat_priv->multicast_fanout)))
goto nla_put_failure;
#endif /* CONFIG_BATMAN_ADV_MCAST */
if (nla_put_u32(msg, BATADV_ATTR_ORIG_INTERVAL,
atomic_read(&bat_priv->orig_interval)))
READ_ONCE(bat_priv->orig_interval)))
goto nla_put_failure;
batadv_hardif_put(primary_if);
@ -432,7 +434,7 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED]) {
attr = info->attrs[BATADV_ATTR_AGGREGATED_OGMS_ENABLED];
atomic_set(&bat_priv->aggregated_ogms, !!nla_get_u8(attr));
WRITE_ONCE(bat_priv->aggregated_ogms, !!nla_get_u8(attr));
}
if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) {
@ -456,14 +458,14 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[BATADV_ATTR_BONDING_ENABLED]) {
attr = info->attrs[BATADV_ATTR_BONDING_ENABLED];
atomic_set(&bat_priv->bonding, !!nla_get_u8(attr));
WRITE_ONCE(bat_priv->bonding, !!nla_get_u8(attr));
}
#ifdef CONFIG_BATMAN_ADV_BLA
if (info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED]) {
attr = info->attrs[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED];
atomic_set(&bat_priv->bridge_loop_avoidance,
WRITE_ONCE(bat_priv->bridge_loop_avoidance,
!!nla_get_u8(attr));
batadv_bla_status_update(bat_priv->mesh_iface);
}
@ -473,7 +475,7 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED]) {
attr = info->attrs[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED];
atomic_set(&bat_priv->distributed_arp_table,
WRITE_ONCE(bat_priv->distributed_arp_table,
!!nla_get_u8(attr));
batadv_dat_status_update(bat_priv->mesh_iface);
}
@ -482,7 +484,7 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED]) {
attr = info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED];
atomic_set(&bat_priv->fragmentation, !!nla_get_u8(attr));
WRITE_ONCE(bat_priv->fragmentation, !!nla_get_u8(attr));
rtnl_lock();
batadv_update_min_mtu(bat_priv->mesh_iface);
@ -492,14 +494,14 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN]) {
attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_DOWN];
atomic_set(&bat_priv->gw.bandwidth_down, nla_get_u32(attr));
WRITE_ONCE(bat_priv->gw.bandwidth_down, nla_get_u32(attr));
batadv_gw_tvlv_container_update(bat_priv);
}
if (info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP]) {
attr = info->attrs[BATADV_ATTR_GW_BANDWIDTH_UP];
atomic_set(&bat_priv->gw.bandwidth_up, nla_get_u32(attr));
WRITE_ONCE(bat_priv->gw.bandwidth_up, nla_get_u32(attr));
batadv_gw_tvlv_container_update(bat_priv);
}
@ -527,7 +529,7 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
* changing the gateway state
*/
batadv_gw_check_client_stop(bat_priv);
atomic_set(&bat_priv->gw.mode, gw_mode);
WRITE_ONCE(bat_priv->gw.mode, gw_mode);
batadv_gw_tvlv_container_update(bat_priv);
}
}
@ -546,7 +548,7 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
sel_class = nla_get_u32(attr);
if (sel_class >= 1 && sel_class <= sel_class_max) {
atomic_set(&bat_priv->gw.sel_class, sel_class);
WRITE_ONCE(bat_priv->gw.sel_class, sel_class);
batadv_gw_reselect(bat_priv);
}
}
@ -554,14 +556,14 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
atomic_set(&bat_priv->hop_penalty, nla_get_u8(attr));
WRITE_ONCE(bat_priv->hop_penalty, nla_get_u8(attr));
}
#ifdef CONFIG_BATMAN_ADV_DEBUG
if (info->attrs[BATADV_ATTR_LOG_LEVEL]) {
attr = info->attrs[BATADV_ATTR_LOG_LEVEL];
atomic_set(&bat_priv->log_level,
WRITE_ONCE(bat_priv->log_level,
nla_get_u32(attr) & BATADV_DBG_ALL);
}
#endif /* CONFIG_BATMAN_ADV_DEBUG */
@ -570,13 +572,13 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED]) {
attr = info->attrs[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED];
atomic_set(&bat_priv->multicast_mode, !nla_get_u8(attr));
WRITE_ONCE(bat_priv->multicast_mode, !nla_get_u8(attr));
}
if (info->attrs[BATADV_ATTR_MULTICAST_FANOUT]) {
attr = info->attrs[BATADV_ATTR_MULTICAST_FANOUT];
atomic_set(&bat_priv->multicast_fanout, nla_get_u32(attr));
WRITE_ONCE(bat_priv->multicast_fanout, nla_get_u32(attr));
}
#endif /* CONFIG_BATMAN_ADV_MCAST */
@ -589,7 +591,7 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
orig_interval = min_t(u32, orig_interval, INT_MAX);
orig_interval = max_t(u32, orig_interval, 2 * BATADV_JITTER);
atomic_set(&bat_priv->orig_interval, orig_interval);
WRITE_ONCE(bat_priv->orig_interval, orig_interval);
}
batadv_netlink_notify_mesh(bat_priv);
@ -809,16 +811,16 @@ static int batadv_netlink_hardif_fill(struct sk_buff *msg,
}
if (nla_put_u8(msg, BATADV_ATTR_HOP_PENALTY,
atomic_read(&hard_iface->hop_penalty)))
READ_ONCE(hard_iface->hop_penalty)))
goto nla_put_failure;
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
if (nla_put_u32(msg, BATADV_ATTR_ELP_INTERVAL,
atomic_read(&hard_iface->bat_v.elp_interval)))
READ_ONCE(hard_iface->bat_v.elp_interval)))
goto nla_put_failure;
if (nla_put_u32(msg, BATADV_ATTR_THROUGHPUT_OVERRIDE,
atomic_read(&hard_iface->bat_v.throughput_override)))
READ_ONCE(hard_iface->bat_v.throughput_override)))
goto nla_put_failure;
#endif /* CONFIG_BATMAN_ADV_BATMAN_V */
@ -911,7 +913,7 @@ static int batadv_netlink_set_hardif(struct sk_buff *skb,
if (info->attrs[BATADV_ATTR_HOP_PENALTY]) {
attr = info->attrs[BATADV_ATTR_HOP_PENALTY];
atomic_set(&hard_iface->hop_penalty, nla_get_u8(attr));
WRITE_ONCE(hard_iface->hop_penalty, nla_get_u8(attr));
}
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
@ -919,13 +921,13 @@ static int batadv_netlink_set_hardif(struct sk_buff *skb,
if (info->attrs[BATADV_ATTR_ELP_INTERVAL]) {
attr = info->attrs[BATADV_ATTR_ELP_INTERVAL];
atomic_set(&hard_iface->bat_v.elp_interval, nla_get_u32(attr));
WRITE_ONCE(hard_iface->bat_v.elp_interval, nla_get_u32(attr));
}
if (info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE]) {
attr = info->attrs[BATADV_ATTR_THROUGHPUT_OVERRIDE];
atomic_set(&hard_iface->bat_v.throughput_override,
WRITE_ONCE(hard_iface->bat_v.throughput_override,
nla_get_u32(attr));
}
#endif /* CONFIG_BATMAN_ADV_BATMAN_V */
@ -1020,7 +1022,7 @@ static int batadv_netlink_vlan_fill(struct sk_buff *msg,
goto nla_put_failure;
if (nla_put_u8(msg, BATADV_ATTR_AP_ISOLATION_ENABLED,
!!atomic_read(&vlan->ap_isolation)))
!!READ_ONCE(vlan->ap_isolation)))
goto nla_put_failure;
genlmsg_end(msg, hdr);
@ -1108,7 +1110,7 @@ static int batadv_netlink_set_vlan(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED]) {
attr = info->attrs[BATADV_ATTR_AP_ISOLATION_ENABLED];
atomic_set(&vlan->ap_isolation, !!nla_get_u8(attr));
WRITE_ONCE(vlan->ap_isolation, !!nla_get_u8(attr));
}
batadv_netlink_notify_vlan(bat_priv, vlan);

View File

@ -7,7 +7,6 @@
#include "originator.h"
#include "main.h"
#include <linux/atomic.h>
#include <linux/container_of.h>
#include <linux/err.h>
#include <linux/errno.h>
@ -694,9 +693,12 @@ batadv_neigh_node_create(struct batadv_orig_node *orig_node,
kref_get(&hard_iface->refcount);
ether_addr_copy(neigh_node->addr, neigh_addr);
neigh_node->if_incoming = hard_iface;
neigh_node->orig_node = orig_node;
neigh_node->last_seen = jiffies;
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
ACCESS_PRIVATE(neigh_node, orig_node_id) = orig_node;
#endif
/* increment unique neighbor refcount */
kref_get(&hardif_neigh->refcount);
neigh_node->hardif_neigh = hardif_neigh;
@ -966,7 +968,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
orig_node->bat_priv = bat_priv;
ether_addr_copy(orig_node->orig, addr);
batadv_dat_init_orig_node_addr(orig_node);
atomic_set(&orig_node->last_ttvn, 0);
WRITE_ONCE(orig_node->last_ttvn, 0);
orig_node->tt_buff = NULL;
orig_node->tt_buff_len = 0;
orig_node->last_seen = jiffies;

View File

@ -543,7 +543,7 @@ batadv_find_router(struct batadv_priv *bat_priv,
/* only consider bonding for recv_if == BATADV_IF_DEFAULT (first hop)
* and if activated.
*/
if (!(recv_if == BATADV_IF_DEFAULT && atomic_read(&bat_priv->bonding)))
if (!(recv_if == BATADV_IF_DEFAULT && READ_ONCE(bat_priv->bonding)))
return router;
/* bonding: loop through the list of possible routers found
@ -765,7 +765,7 @@ batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, struct sk_buff *skb,
goto out;
orig_addr = orig_node->orig;
orig_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
orig_ttvn = READ_ONCE(orig_node->last_ttvn);
}
/* update the packet header */
@ -845,7 +845,7 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
if (!orig_node)
return false;
curr_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
curr_ttvn = READ_ONCE(orig_node->last_ttvn);
batadv_orig_node_put(orig_node);
}

View File

@ -185,7 +185,7 @@ int batadv_send_skb_to_orig(struct sk_buff *skb,
/* Check if the skb is too large to send in one piece and fragment
* it if needed.
*/
if (atomic_read(&bat_priv->fragmentation) &&
if (READ_ONCE(bat_priv->fragmentation) &&
skb->len > neigh_node->if_incoming->net_dev->mtu) {
/* Fragment and send packet. */
ret = batadv_frag_send_packet(skb, orig_node, neigh_node);
@ -222,7 +222,7 @@ batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size,
struct batadv_orig_node *orig_node)
{
struct batadv_unicast_packet *unicast_packet;
u8 ttvn = (u8)atomic_read(&orig_node->last_ttvn);
u8 ttvn = READ_ONCE(orig_node->last_ttvn);
if (batadv_skb_head_push(skb, hdr_size) < 0)
return false;
@ -1047,7 +1047,7 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
delayed_work);
bat_priv = netdev_priv(forw_packet->if_incoming->mesh_iface);
if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) {
if (READ_ONCE(bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING) {
dropped = true;
goto out;
}

View File

@ -999,7 +999,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,
/* look for an already existing test towards this node */
spin_lock_bh(&bat_priv->tp_list_lock);
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE) {
spin_unlock_bh(&bat_priv->tp_list_lock);
batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE,
dst, bat_priv, session_cookie);
@ -1387,7 +1387,7 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv,
struct batadv_tp_vars *tp_vars = NULL;
spin_lock_bh(&bat_priv->tp_list_lock);
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
goto out_unlock;
tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig,
@ -1518,7 +1518,7 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb)
{
struct batadv_icmp_tp_packet *icmp;
if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
if (READ_ONCE(bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
goto out;
icmp = (struct batadv_icmp_tp_packet *)skb->data;

View File

@ -9,6 +9,7 @@
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/bug.h>
#include <linux/build_bug.h>
#include <linux/byteorder/generic.h>
#include <linux/cache.h>
@ -648,7 +649,7 @@ bool batadv_tt_local_add(struct net_device *mesh_iface, const u8 *addr,
/* Ignore the client if we cannot send it in a full table response. */
table_size = batadv_tt_local_table_transmit_size(bat_priv);
table_size += batadv_tt_len(1);
packet_size_max = atomic_read(&bat_priv->packet_size_max);
packet_size_max = READ_ONCE(bat_priv->packet_size_max);
if (table_size > packet_size_max) {
net_ratelimited_function(batadv_info, mesh_iface,
"Local translation table size (%i) exceeds maximum packet size (%i); Ignoring new local tt entry: %pM\n",
@ -798,10 +799,10 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
{
u16 num_vlan = 0;
u16 tvlv_len = 0;
unsigned int change_offset;
struct batadv_tvlv_tt_vlan_data *tt_vlan;
struct batadv_orig_node_vlan *vlan;
u16 total_entries = 0;
size_t change_offset;
u8 *tt_change_ptr;
int vlan_entries;
u16 sum_entries;
@ -825,14 +826,11 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
if (*tt_len < 0)
*tt_len = batadv_tt_len(total_entries);
if (change_offset > U16_MAX || *tt_len > U16_MAX - change_offset) {
if (check_add_overflow(*tt_len, change_offset, &tvlv_len)) {
*tt_len = 0;
goto out;
}
tvlv_len = *tt_len;
tvlv_len += change_offset;
*tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
if (!*tt_data) {
*tt_len = 0;
@ -840,7 +838,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
}
(*tt_data)->flags = BATADV_NO_FLAGS;
(*tt_data)->ttvn = atomic_read(&orig_node->last_ttvn);
(*tt_data)->ttvn = READ_ONCE(orig_node->last_ttvn);
(*tt_data)->num_vlan = htons(num_vlan);
tt_vlan = (*tt_data)->vlan_data;
@ -1821,7 +1819,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq,
if (!hdr)
return -ENOBUFS;
last_ttvn = atomic_read(&orig->orig_node->last_ttvn);
last_ttvn = READ_ONCE(orig->orig_node->last_ttvn);
if (nla_put(msg, BATADV_ATTR_TT_ADDRESS, ETH_ALEN, common->addr) ||
nla_put(msg, BATADV_ATTR_ORIG_ADDRESS, ETH_ALEN,
@ -3012,7 +3010,7 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
if (!res_dst_orig_node)
goto out;
orig_ttvn = (u8)atomic_read(&req_dst_orig_node->last_ttvn);
orig_ttvn = READ_ONCE(req_dst_orig_node->last_ttvn);
req_ttvn = tt_data->ttvn;
/* this node doesn't have the requested data */
@ -3068,7 +3066,7 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
/* Don't send the response, if larger than fragmented packet. */
tt_len = sizeof(struct batadv_unicast_tvlv_packet) + tvlv_len;
if (tt_len > atomic_read(&bat_priv->packet_size_max)) {
if (tt_len > READ_ONCE(bat_priv->packet_size_max)) {
net_ratelimited_function(batadv_info, bat_priv->mesh_iface,
"Ignoring TT_REQUEST from %pM; Response size exceeds max packet size.\n",
res_dst_orig_node->orig);
@ -3299,7 +3297,7 @@ static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
orig_node->tt_buff = NULL;
spin_unlock_bh(&orig_node->tt_buff_lock);
atomic_set(&orig_node->last_ttvn, ttvn);
WRITE_ONCE(orig_node->last_ttvn, ttvn);
out:
batadv_orig_node_put(orig_node);
@ -3315,7 +3313,7 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
batadv_tt_save_orig_buffer(bat_priv, orig_node, tt_change,
batadv_tt_len(tt_num_changes));
atomic_set(&orig_node->last_ttvn, ttvn);
WRITE_ONCE(orig_node->last_ttvn, ttvn);
}
/**
@ -3729,7 +3727,7 @@ bool batadv_is_ap_isolated(struct batadv_priv *bat_priv, u8 *src, u8 *dst,
if (!vlan)
return false;
if (!atomic_read(&vlan->ap_isolation))
if (!READ_ONCE(vlan->ap_isolation))
goto vlan_put;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, dst, vid);
@ -3768,7 +3766,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv,
struct batadv_tvlv_tt_change *tt_change,
u16 tt_num_changes, u8 ttvn)
{
u8 orig_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
u8 orig_ttvn = READ_ONCE(orig_node->last_ttvn);
struct batadv_tvlv_tt_vlan_data *tt_vlan;
bool full_table = true;
bool has_tt_init;
@ -3910,7 +3908,7 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
if (!batadv_tt_global_add(bat_priv, orig_node, addr, vid,
BATADV_TT_CLIENT_TEMP,
atomic_read(&orig_node->last_ttvn)))
READ_ONCE(orig_node->last_ttvn)))
return false;
batadv_dbg(BATADV_DBG_TT, bat_priv,
@ -3931,7 +3929,7 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
void batadv_tt_local_resize_to_mtu(struct net_device *mesh_iface)
{
struct batadv_priv *bat_priv = netdev_priv(mesh_iface);
int packet_size_max = atomic_read(&bat_priv->packet_size_max);
int packet_size_max = READ_ONCE(bat_priv->packet_size_max);
int table_size, timeout = BATADV_TT_LOCAL_TIMEOUT / 2;
bool reduced = false;
@ -4124,7 +4122,7 @@ static int batadv_roam_tvlv_unicast_handler_v1(struct batadv_priv *bat_priv,
batadv_tt_global_add(bat_priv, orig_node, roaming_adv->client,
ntohs(roaming_adv->vid), BATADV_TT_CLIENT_ROAM,
atomic_read(&orig_node->last_ttvn) + 1);
READ_ONCE(orig_node->last_ttvn) + 1);
out:
batadv_orig_node_put(orig_node);

View File

@ -6,6 +6,7 @@
#include "main.h"
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/container_of.h>
#include <linux/errno.h>
@ -16,6 +17,7 @@
#include <linux/limits.h>
#include <linux/list.h>
#include <linux/lockdep.h>
#include <linux/log2.h>
#include <linux/netdevice.h>
#include <linux/pkt_sched.h>
#include <linux/rculist.h>
@ -266,32 +268,48 @@ void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
/**
* batadv_tvlv_realloc_packet_buff() - reallocate packet buffer to accommodate
* requested packet size
* @packet_buff: packet buffer
* @packet_buff_len: packet buffer size
* @min_packet_len: requested packet minimum size
* @ogm_buff: ogm packet buffer
* @additional_packet_len: requested additional packet size on top of minimum
* size
*
* Return: true of the packet buffer could be changed to the requested size,
* false otherwise.
*/
static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,
int *packet_buff_len,
int min_packet_len,
int additional_packet_len)
static bool batadv_tvlv_realloc_packet_buff(struct batadv_ogm_buf *ogm_buff,
size_t additional_packet_len)
{
unsigned char *new_buff;
size_t newcapacity;
size_t newlen;
new_buff = kmalloc(min_packet_len + additional_packet_len, GFP_ATOMIC);
newlen = ogm_buff->header_length + additional_packet_len;
newcapacity = roundup_pow_of_two(newlen);
/* nothing to reallocate */
if (newcapacity == ogm_buff->capacity) {
ogm_buff->len = newlen;
return true;
}
new_buff = kmalloc(newcapacity, GFP_ATOMIC);
/* keep old buffer if kmalloc should fail */
if (!new_buff)
return false;
if (!new_buff) {
/* continue to use oversize buffer if new data fits */
if (newlen <= ogm_buff->capacity) {
ogm_buff->len = newlen;
return true;
}
memcpy(new_buff, *packet_buff, min_packet_len);
kfree(*packet_buff);
*packet_buff = new_buff;
*packet_buff_len = min_packet_len + additional_packet_len;
return false;
}
memcpy(new_buff, ogm_buff->buf, ogm_buff->header_length);
kfree(ogm_buff->buf);
ogm_buff->buf = new_buff;
ogm_buff->len = newlen;
ogm_buff->capacity = newcapacity;
return true;
}
@ -300,10 +318,7 @@ static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,
* batadv_tvlv_container_ogm_append() - append tvlv container content to given
* OGM packet buffer
* @bat_priv: the bat priv with all the mesh interface information
* @packet_buff: ogm packet buffer
* @packet_buff_len: ogm packet buffer size including ogm header and tvlv
* content
* @packet_min_len: ogm header size to be preserved for the OGM itself
* @ogm_buff: ogm packet buffer
*
* The ogm packet might be enlarged or shrunk depending on the current size
* and the size of the to-be-appended tvlv containers.
@ -312,8 +327,7 @@ static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,
* if operation failed
*/
int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
unsigned char **packet_buff,
int *packet_buff_len, int packet_min_len)
struct batadv_ogm_buf *ogm_buff)
{
struct batadv_tvlv_container *tvlv;
struct batadv_tvlv_hdr *tvlv_hdr;
@ -329,8 +343,7 @@ int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
goto end;
}
ret = batadv_tvlv_realloc_packet_buff(packet_buff, packet_buff_len,
packet_min_len, tvlv_value_len);
ret = batadv_tvlv_realloc_packet_buff(ogm_buff, tvlv_value_len);
if (!ret) {
tvlv_len_ret = -ENOMEM;
goto end;
@ -341,7 +354,7 @@ int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
if (!tvlv_value_len)
goto end;
tvlv_value = (*packet_buff) + packet_min_len;
tvlv_value = (u8 *)ogm_buff->buf + ogm_buff->header_length;
hlist_for_each_entry(tvlv, &bat_priv->tvlv.container_list, list) {
tvlv_hdr = tvlv_value;

View File

@ -17,8 +17,7 @@ void batadv_tvlv_container_register(struct batadv_priv *bat_priv,
u8 type, u8 version,
void *tvlv_value, u16 tvlv_value_len);
int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,
unsigned char **packet_buff,
int *packet_buff_len, int packet_min_len);
struct batadv_ogm_buf *ogm_buff);
void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
struct batadv_ogm_packet *batadv_ogm_packet,
struct batadv_orig_node *orig_node);

View File

@ -21,6 +21,7 @@
#include <linux/mutex.h>
#include <linux/netdevice.h>
#include <linux/netlink.h>
#include <linux/rhashtable-types.h>
#include <linux/sched.h> /* for linux/wait.h */
#include <linux/skbuff.h>
#include <linux/spinlock.h>
@ -70,15 +71,29 @@ enum batadv_dhcp_recipient {
*/
#define BATADV_TT_SYNC_MASK 0x00F0
/**
* struct batadv_ogm_buf - Buffer to construct an OGM with TVLV
*/
struct batadv_ogm_buf {
/** @buf: buffer holding the OGM packet */
void *buf;
/** @len: length of the OGM packet buffer data */
size_t len;
/** @capacity: size of allocated buf */
size_t capacity;
/** @header_length: fixed size header length (must be <= len) */
size_t header_length;
};
/**
* struct batadv_hard_iface_bat_iv - per hard-interface B.A.T.M.A.N. IV data
*/
struct batadv_hard_iface_bat_iv {
/** @ogm_buff: buffer holding the OGM packet */
unsigned char *ogm_buff;
/** @ogm_buff_len: length of the OGM packet buffer */
int ogm_buff_len;
struct batadv_ogm_buf ogm_buff;
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
atomic_t ogm_seqno;
@ -86,7 +101,7 @@ struct batadv_hard_iface_bat_iv {
/** @reschedule_work: recover OGM schedule after schedule error */
struct delayed_work reschedule_work;
/** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
/** @ogm_buff_mutex: lock protecting ogm_buff */
struct mutex ogm_buff_mutex;
};
@ -113,7 +128,7 @@ enum batadv_v_hard_iface_flags {
*/
struct batadv_hard_iface_bat_v {
/** @elp_interval: time interval between two ELP transmissions */
atomic_t elp_interval;
u32 elp_interval;
/** @elp_seqno: current ELP sequence number */
atomic_t elp_seqno;
@ -137,7 +152,7 @@ struct batadv_hard_iface_bat_v {
* @throughput_override: throughput override to disable link
* auto-detection
*/
atomic_t throughput_override;
u32 throughput_override;
/** @flags: interface specific flags */
u8 flags;
@ -166,6 +181,29 @@ enum batadv_hard_iface_wifi_flags {
BATADV_HARDIF_WIFI_CFG80211_INDIRECT = BIT(3),
};
/**
* struct batadv_wifi_net_device_state - cache of wifi information of net_devices
*/
struct batadv_wifi_net_device_state {
/** @l: anchor in rhashtable */
struct rhash_head l;
/** @netdev: pointer to the net_device */
struct net_device *netdev;
/** @dev_tracker: device tracker for @netdev */
netdevice_tracker dev_tracker;
/**
* @wifi_flags: flags whether this is (directly or indirectly) a wifi
* interface
*/
u32 wifi_flags;
/** @rcu: struct used for freeing in an RCU-safe manner */
struct rcu_head rcu;
};
/**
* struct batadv_hard_iface - network device known to batman-adv
*/
@ -181,12 +219,6 @@ struct batadv_hard_iface {
*/
u8 num_bcasts;
/**
* @wifi_flags: flags whether this is (directly or indirectly) a wifi
* interface
*/
u32 wifi_flags;
/** @net_dev: pointer to the net_device */
struct net_device *net_dev;
@ -218,7 +250,7 @@ struct batadv_hard_iface {
* @hop_penalty: penalty which will be applied to the tq-field
* of an OGM received via this interface
*/
atomic_t hop_penalty;
u8 hop_penalty;
/** @bat_iv: per hard-interface B.A.T.M.A.N. IV data */
struct batadv_hard_iface_bat_iv bat_iv;
@ -446,7 +478,7 @@ struct batadv_orig_node {
unsigned long capa_initialized;
/** @last_ttvn: last seen translation table version number */
atomic_t last_ttvn;
u8 last_ttvn;
/** @tt_buff: last tt changeset this node received from the orig node */
unsigned char *tt_buff;
@ -631,8 +663,15 @@ struct batadv_neigh_node {
/** @list: list node for &batadv_orig_node.neigh_list */
struct hlist_node list;
/** @orig_node: pointer to corresponding orig_node */
struct batadv_orig_node *orig_node;
#ifdef CONFIG_BATMAN_ADV_BATMAN_V
/**
* @orig_node_id: pointer to corresponding orig_node. It must only be used
* to identify the node but must NEVER be dereferenced. The reference counter
* was not increased when this was assigned because it would otherwise create
* a reference cycle.
*/
struct batadv_orig_node *__private orig_node_id;
#endif
/** @addr: the MAC address of the neighboring interface */
u8 addr[ETH_ALEN];
@ -1101,21 +1140,21 @@ struct batadv_priv_gw {
/**
* @mode: gateway operation: off, client or server (see batadv_gw_modes)
*/
atomic_t mode;
enum batadv_gw_modes mode;
/** @sel_class: gateway selection class (applies if gw_mode client) */
atomic_t sel_class;
u32 sel_class;
/**
* @bandwidth_down: advertised uplink download bandwidth (if gw_mode
* server)
*/
atomic_t bandwidth_down;
u32 bandwidth_down;
/**
* @bandwidth_up: advertised uplink upload bandwidth (if gw_mode server)
*/
atomic_t bandwidth_up;
u32 bandwidth_up;
/** @reselect: bool indicating a gateway re-selection is in progress */
atomic_t reselect;
@ -1441,7 +1480,7 @@ struct batadv_meshif_vlan {
unsigned short vid;
/** @ap_isolation: AP isolation state */
atomic_t ap_isolation; /* boolean */
u8 ap_isolation; /* boolean */
/** @tt: TT private attributes (VLAN specific) */
struct batadv_vlan_tt tt;
@ -1463,15 +1502,12 @@ struct batadv_meshif_vlan {
*/
struct batadv_priv_bat_v {
/** @ogm_buff: buffer holding the OGM packet */
unsigned char *ogm_buff;
/** @ogm_buff_len: length of the OGM packet buffer */
int ogm_buff_len;
struct batadv_ogm_buf ogm_buff;
/** @ogm_seqno: OGM sequence number - used to identify each OGM */
atomic_t ogm_seqno;
/** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */
/** @ogm_buff_mutex: lock protecting ogm_buff */
struct mutex ogm_buff_mutex;
/** @ogm_wq: workqueue used to schedule OGM transmissions */
@ -1486,7 +1522,7 @@ struct batadv_priv {
* @mesh_state: current status of the mesh
* (inactive/active/deactivating)
*/
atomic_t mesh_state;
enum batadv_mesh_state mesh_state;
/** @mesh_iface: net device which holds this struct as private data */
struct net_device *mesh_iface;
@ -1506,36 +1542,23 @@ struct batadv_priv {
/**
* @aggregated_ogms: bool indicating whether OGM aggregation is enabled
*/
atomic_t aggregated_ogms;
u8 aggregated_ogms;
/** @bonding: bool indicating whether traffic bonding is enabled */
atomic_t bonding;
u8 bonding;
/**
* @fragmentation: bool indicating whether traffic fragmentation is
* enabled
*/
atomic_t fragmentation;
/**
* @packet_size_max: max packet size that can be transmitted via
* multiple fragmented skbs or a single frame if fragmentation is
* disabled
*/
atomic_t packet_size_max;
/**
* @frag_seqno: incremental counter to identify chains of egress
* fragments
*/
atomic_t frag_seqno;
u8 fragmentation;
#ifdef CONFIG_BATMAN_ADV_BLA
/**
* @bridge_loop_avoidance: bool indicating whether bridge loop
* avoidance is enabled
*/
atomic_t bridge_loop_avoidance;
u8 bridge_loop_avoidance;
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
@ -1543,7 +1566,7 @@ struct batadv_priv {
* @distributed_arp_table: bool indicating whether distributed ARP table
* is enabled
*/
atomic_t distributed_arp_table;
u8 distributed_arp_table;
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
@ -1551,27 +1574,40 @@ struct batadv_priv {
* @multicast_mode: Enable or disable multicast optimizations on this
* node's sender/originating side
*/
atomic_t multicast_mode;
u8 multicast_mode;
/**
* @multicast_fanout: Maximum number of packet copies to generate for a
* multicast-to-unicast conversion
*/
atomic_t multicast_fanout;
u32 multicast_fanout;
#endif
/**
* @packet_size_max: max packet size that can be transmitted via
* multiple fragmented skbs or a single frame if fragmentation is
* disabled
*/
int packet_size_max;
/**
* @frag_seqno: incremental counter to identify chains of egress
* fragments
*/
atomic_t frag_seqno;
/** @orig_interval: OGM broadcast interval in milliseconds */
atomic_t orig_interval;
u32 orig_interval;
/**
* @hop_penalty: penalty which will be applied to an OGM's tq-field on
* every hop
*/
atomic_t hop_penalty;
u8 hop_penalty;
#ifdef CONFIG_BATMAN_ADV_DEBUG
/** @log_level: configured log level (see batadv_dbg_level) */
atomic_t log_level;
u32 log_level;
#endif
/**

12
net/batman-adv/version.c Normal file
View File

@ -0,0 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
#include <generated/utsrelease.h>
#include <linux/module.h>
/* WARNING userspace tools like batctl were relying on
* /sys/module/batman_adv/version to check if the module was loaded. If it
* isn't present, they usually error out before finishing setup of the batadv
* interface. It should be kept until it is unlikely that there are active
* installations of these "broken" versions of these tools with recent kernels.
*/
MODULE_VERSION(UTS_RELEASE);