* [PATCH net-next 01/15] batman-adv: drop batman-adv specific version
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-29 0:14 ` Jakub Kicinski
2026-05-28 14:29 ` [PATCH net-next 02/15] MAINTAINERS: Rename batman-adv T(ree) Simon Wunderlich
` (13 subsequent siblings)
14 siblings, 1 reply; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
Bumping the version number on the first pull request after each merge
window was deemed inappropriate for an in-tree component. The version
number carries little meaningful information in the context of the Linux
kernel release model, where stable and distribution might all carry
slightly different patches (without any change to the batman-adv version).
Instead, expose a UTS_RELEASE-based string to consumers of the netlink
and ethtool interfaces. But keep it in a separate file to avoid whole
batman-adv recompilations when generated/utsrelease.h is recreated.
Link: https://lore.kernel.org/r/20210203163302.13e8a2a7@kicinski-fedora-pc1c0hjn.dhcp.thefacebook.com
Link: https://lore.kernel.org/r/YnfjtpuAaH+Zkf9S@unreal
Link: https://lore.kernel.org/r/Y9faTA0rNSXg%2FsLD@nanopsycho
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/Makefile | 1 +
net/batman-adv/main.c | 4 ++--
net/batman-adv/main.h | 4 ----
net/batman-adv/mesh-interface.c | 3 ++-
net/batman-adv/netlink.c | 3 ++-
net/batman-adv/version.c | 18 ++++++++++++++++++
net/batman-adv/version.h | 8 ++++++++
7 files changed, 33 insertions(+), 8 deletions(-)
create mode 100644 net/batman-adv/version.c
create mode 100644 net/batman-adv/version.h
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile
index d3c4d4143c144..5d7456f1240d7 100644
--- a/net/batman-adv/Makefile
+++ b/net/batman-adv/Makefile
@@ -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)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index a4d33ee0fda59..b7acccdf3ce05 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -57,6 +57,7 @@
#include "send.h"
#include "tp_meter.h"
#include "translation-table.h"
+#include "version.h"
/* List manipulations on hardif_list have to be rtnl_lock()'ed,
* list traversals just rcu-locked
@@ -112,7 +113,7 @@ static int __init batadv_init(void)
batadv_netlink_register();
pr_info("B.A.T.M.A.N. advanced %s (compatibility version %i) loaded\n",
- BATADV_SOURCE_VERSION, BATADV_COMPAT_VERSION);
+ batadv_version, BATADV_COMPAT_VERSION);
return 0;
@@ -684,6 +685,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);
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index af230b017bc17..f68fc8b7239cd 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -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
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index e7aa45bc6b7ad..a244f5425406b 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -49,6 +49,7 @@
#include "multicast.h"
#include "send.h"
#include "translation-table.h"
+#include "version.h"
/**
* batadv_skb_head_push() - Increase header size and move (push) head pointer
@@ -892,7 +893,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, batadv_version, sizeof(info->version));
strscpy(info->fw_version, "N/A", sizeof(info->fw_version));
strscpy(info->bus_info, "batman", sizeof(info->bus_info));
}
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 78c651f634cd3..8db29afeaa40b 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -47,6 +47,7 @@
#include "originator.h"
#include "tp_meter.h"
#include "translation-table.h"
+#include "version.h"
struct genl_family batadv_netlink_family;
@@ -233,7 +234,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, batadv_version) ||
nla_put_string(msg, BATADV_ATTR_ALGO_NAME,
bat_priv->algo_ops->name) ||
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, mesh_iface->ifindex) ||
diff --git a/net/batman-adv/version.c b/net/batman-adv/version.c
new file mode 100644
index 0000000000000..6a7c26e4bc945
--- /dev/null
+++ b/net/batman-adv/version.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include "version.h"
+
+#include <generated/utsrelease.h>
+#include <linux/module.h>
+
+#define BATADV_SOURCE_VERSION "linux-" UTS_RELEASE
+
+const char *batadv_version = BATADV_SOURCE_VERSION;
+
+/* 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(BATADV_SOURCE_VERSION);
diff --git a/net/batman-adv/version.h b/net/batman-adv/version.h
new file mode 100644
index 0000000000000..d8af91f365ff9
--- /dev/null
+++ b/net/batman-adv/version.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _NET_BATMAN_ADV_VERSION_H_
+#define _NET_BATMAN_ADV_VERSION_H_
+
+extern const char *batadv_version;
+
+#endif /* _NET_BATMAN_ADV_VERSION_H_ */
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH net-next 01/15] batman-adv: drop batman-adv specific version
2026-05-28 14:29 ` [PATCH net-next 01/15] batman-adv: drop batman-adv specific version Simon Wunderlich
@ 2026-05-29 0:14 ` Jakub Kicinski
2026-05-29 7:06 ` Sven Eckelmann
0 siblings, 1 reply; 20+ messages in thread
From: Jakub Kicinski @ 2026-05-29 0:14 UTC (permalink / raw)
To: Simon Wunderlich
Cc: netdev, David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman,
b.a.t.m.a.n, Sven Eckelmann
On Thu, 28 May 2026 16:29:10 +0200 Simon Wunderlich wrote:
> +#define BATADV_SOURCE_VERSION "linux-" UTS_RELEASE
What purpose that does "linux-" prefix serve?
The unwritten rule is that the OOT drivers have to append something
to their version to distinguish themselves. In-tree version is just
the pure kernel version.
To be clear, definitely a move in the right direction. I hope we can
move _all the way_ in the right direction, tho, without still defining
OOT-feeling version.h file with a dedicated BATADV_SOURCE_VERSION
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH net-next 01/15] batman-adv: drop batman-adv specific version
2026-05-29 0:14 ` Jakub Kicinski
@ 2026-05-29 7:06 ` Sven Eckelmann
2026-05-29 18:24 ` Jakub Kicinski
0 siblings, 1 reply; 20+ messages in thread
From: Sven Eckelmann @ 2026-05-29 7:06 UTC (permalink / raw)
To: Simon Wunderlich, Jakub Kicinski
Cc: netdev, David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman,
b.a.t.m.a.n
[-- Attachment #1: Type: text/plain, Size: 1148 bytes --]
On Friday, 29 May 2026 02:14:12 CEST Jakub Kicinski wrote:
> On Thu, 28 May 2026 16:29:10 +0200 Simon Wunderlich wrote:
> > +#define BATADV_SOURCE_VERSION "linux-" UTS_RELEASE
>
> What purpose that does "linux-" prefix serve?
> The unwritten rule is that the OOT drivers have to append something
> to their version to distinguish themselves. In-tree version is just
> the pure kernel version.
We don't have a real preference here. If you prefer UTS_RELEASE only then I
get rid of BATADV_SOURCE_VERSION and just use it in both places in
version.c
https://git.open-mesh.org/batadv.git/commit/?id=8cc63db2462ad7d3ee213059025bf5fffe2e7982
> To be clear, definitely a move in the right direction. I hope we can
> move _all the way_ in the right direction, tho, without still defining
> OOT-feeling version.h file with a dedicated BATADV_SOURCE_VERSION
version.c and version.h are there to not recompile more parts of batman-adv
than necessary when the linux kernel version changes. Has nothing to do
with OOT. If you consider this a no-go, I can also just place
generated/utsrelease.h + UTS_RELEASE in the three different files.
Regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH net-next 01/15] batman-adv: drop batman-adv specific version
2026-05-29 7:06 ` Sven Eckelmann
@ 2026-05-29 18:24 ` Jakub Kicinski
2026-05-29 19:23 ` Sven Eckelmann
0 siblings, 1 reply; 20+ messages in thread
From: Jakub Kicinski @ 2026-05-29 18:24 UTC (permalink / raw)
To: Sven Eckelmann
Cc: Simon Wunderlich, netdev, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, b.a.t.m.a.n
On Fri, 29 May 2026 09:06:56 +0200 Sven Eckelmann wrote:
> On Friday, 29 May 2026 02:14:12 CEST Jakub Kicinski wrote:
> > On Thu, 28 May 2026 16:29:10 +0200 Simon Wunderlich wrote:
> > > +#define BATADV_SOURCE_VERSION "linux-" UTS_RELEASE
> >
> > What purpose that does "linux-" prefix serve?
> > The unwritten rule is that the OOT drivers have to append something
> > to their version to distinguish themselves. In-tree version is just
> > the pure kernel version.
>
> We don't have a real preference here. If you prefer UTS_RELEASE only then I
> get rid of BATADV_SOURCE_VERSION and just use it in both places in
> version.c
>
> https://git.open-mesh.org/batadv.git/commit/?id=8cc63db2462ad7d3ee213059025bf5fffe2e7982
>
> > To be clear, definitely a move in the right direction. I hope we can
> > move _all the way_ in the right direction, tho, without still defining
> > OOT-feeling version.h file with a dedicated BATADV_SOURCE_VERSION
>
> version.c and version.h are there to not recompile more parts of batman-adv
> than necessary when the linux kernel version changes. Has nothing to do
> with OOT. If you consider this a no-go, I can also just place
> generated/utsrelease.h + UTS_RELEASE in the three different files.
Ah! My bad, sorry for the accusation! :)
The re-compilation thing is annoying but it's solvable.
Please TAL at commit 3f9ed5f5aa9ecffd2 for inspiration.
Thank you!
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH net-next 01/15] batman-adv: drop batman-adv specific version
2026-05-29 18:24 ` Jakub Kicinski
@ 2026-05-29 19:23 ` Sven Eckelmann
0 siblings, 0 replies; 20+ messages in thread
From: Sven Eckelmann @ 2026-05-29 19:23 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Simon Wunderlich, netdev, David S. Miller, Eric Dumazet,
Paolo Abeni, Simon Horman, b.a.t.m.a.n
[-- Attachment #1: Type: text/plain, Size: 1451 bytes --]
On Friday, 29 May 2026 20:24:30 CEST Jakub Kicinski wrote:
> > > To be clear, definitely a move in the right direction. I hope we can
> > > move _all the way_ in the right direction, tho, without still defining
> > > OOT-feeling version.h file with a dedicated BATADV_SOURCE_VERSION
> >
> > version.c and version.h are there to not recompile more parts of batman-adv
> > than necessary when the linux kernel version changes. Has nothing to do
> > with OOT. If you consider this a no-go, I can also just place
> > generated/utsrelease.h + UTS_RELEASE in the three different files.
>
> Ah! My bad, sorry for the accusation! 🙂
>
> The re-compilation thing is annoying but it's solvable.
> Please TAL at commit 3f9ed5f5aa9ecffd2 for inspiration.
Interesting, didn't knew about it. This should work for the in-function ones
and avoids the const batadv_version string + version.h.
https://git.open-mesh.org/batadv.git/commit/?id=6f864eb5cfd8315b8f9a29167263282fe4593f3a
Now we are left with version.c. MODULE_VERSION doesn't accept "dynamically
generated" strings for obvious reasons. Which could be handled via:
* MODULE_VERSION(UTS_RELEASE) in version.c (keeping it in a separate file)
* MODULE_VERSION(UTS_RELEASE) in main.c (requires recompilation of main.c)
* MODULE_VERSION($STATIC_STRING) in main.c (then somebody needs to come up
with one)
* something else
What would you prefer?
Regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH net-next 02/15] MAINTAINERS: Rename batman-adv T(ree)
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 01/15] batman-adv: drop batman-adv specific version Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 03/15] MAINTAINERS: Don't send batman-adv patches to netdev Simon Wunderlich
` (12 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
Replace the batman-adv tree name "linux-merge" with "batadv" to match the
patch prefix convention used in subject lines (e.g. "[PATCH batadv 1/10]").
The previous name "linux-merge" was ambiguous and was not suitable as a
easy-to-recognize prefix. Routing of patches to net-next vs. net remains at
maintainer discretion.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
MAINTAINERS | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index f1d2a924d53dc..741fb4166aa2b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4440,7 +4440,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
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 03/15] MAINTAINERS: Don't send batman-adv patches to netdev
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 01/15] batman-adv: drop batman-adv specific version Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 02/15] MAINTAINERS: Rename batman-adv T(ree) Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 04/15] batman-adv: add missing includes Simon Wunderlich
` (11 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
Do not send batman-adv patches directly to the networking maintainers or
the netdev mailing list for initial review. Keeping these patch iterations
off netdev reduces review load, especially for patchsets that require
multiple revisions before reaching consensus.
After the review was finished on the BATMAN ADVANCED mailing list, the
patches will be queued up and then submitted to netdev as PR, including the
full patchset in the same thread (for the last review).
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
MAINTAINERS | 2 ++
1 file changed, 2 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 741fb4166aa2b..75ff01377fc6f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18635,6 +18635,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
@@ -18645,6 +18646,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/
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 04/15] batman-adv: add missing includes
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (2 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 03/15] MAINTAINERS: Don't send batman-adv patches to netdev Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 05/15] batman-adv: use atomic_xchg() for gw.reselect check Simon Wunderlich
` (10 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
Some of the recent fixes required features from new header files. There is
currently no build problem because transitive includes take care of it. But
the batman-adv source code tries to avoid the dependency to
transitive/implicite includes because it has no control over them and they
might get removed at some point.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/bat_v_ogm.c | 1 +
net/batman-adv/bridge_loop_avoidance.c | 1 +
net/batman-adv/distributed-arp-table.c | 1 +
net/batman-adv/fragmentation.c | 1 +
net/batman-adv/gateway_client.c | 1 +
net/batman-adv/hard-interface.c | 1 +
net/batman-adv/mesh-interface.c | 1 +
net/batman-adv/translation-table.c | 1 +
net/batman-adv/tvlv.c | 1 +
9 files changed, 9 insertions(+)
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index d66ca77b1aaa3..6436e9bc079b6 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -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/errno.h>
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index ffe854018bd3a..f6ca69252ff7c 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -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>
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 0a8bd95e2f99e..c6084ae6760c5 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -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>
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c
index e9553db423491..14ccf7811bf62 100644
--- a/net/batman-adv/fragmentation.c
+++ b/net/batman-adv/fragmentation.c
@@ -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>
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index a9d0346e8332e..ec743ce39be47 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -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>
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index d6732c34aeafc..4b3804ef70b6f 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -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>
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index a244f5425406b..307874069b84e 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -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>
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 9f6e67771ffa8..28869f65ada09 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -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>
diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c
index cc6ac580c6208..8e8b54e2172ef 100644
--- a/net/batman-adv/tvlv.c
+++ b/net/batman-adv/tvlv.c
@@ -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>
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 05/15] batman-adv: use atomic_xchg() for gw.reselect check
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (3 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 04/15] batman-adv: add missing includes Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 06/15] batman-adv: extract netdev wifi detection information object Simon Wunderlich
` (9 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
batadv_gw_election() only needs to test whether gw.reselect was set and
clear it afterwards. Replace the batadv_atomic_dec_not_zero()
[atomic_add_unless(..., -1, 0)] call with atomic_xchg(..., 0) to simplify
the logic and make the intent more explicit.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/gateway_client.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index ec743ce39be47..026627c8ba45b 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -211,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
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 06/15] batman-adv: extract netdev wifi detection information object
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (4 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 05/15] batman-adv: use atomic_xchg() for gw.reselect check Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 07/15] batman-adv: replace non-atomic meshif config fields with (READ|WRITE)_ONCE Simon Wunderlich
` (8 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
Previously, wifi_flags were stored directly in batadv_hard_iface, which is
created for every network interface on the system (including those never
attached to a mesh interface). This wastes memory and complicates the
long-term goal of lazily allocating batadv_hard_iface only for interfaces
that actually join a mesh.
The problem is that several batman-adv features need wifi detection for
net_devices (and their underlying devices) regardless of whether a
batadv_hard_iface exists for them:
* B.A.T.M.A.N. IV TQ hop penalty calculation
* B.A.T.M.A.N. V ELP probing / throughput estimation
* AP isolation
To decouple wifi detection from batadv_hard_iface lifetime, introduce a
global rhashtable (batadv_wifi_net_devices) mapping net_device pointers to
batadv_wifi_net_device_state objects. Only net_devices that are actually
detected as (indirect) wifi interfaces occupy an entry, keeping the common
(non-wifi) case allocation-free.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/bat_v_elp.c | 6 +-
net/batman-adv/hard-interface.c | 189 +++++++++++++++++++++++++++++---
net/batman-adv/hard-interface.h | 34 +++++-
net/batman-adv/main.c | 16 ++-
net/batman-adv/types.h | 30 ++++-
5 files changed, 250 insertions(+), 25 deletions(-)
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index fdc2abe96d777..e207093de79fe 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -85,6 +85,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;
@@ -106,8 +107,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;
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 4b3804ef70b6f..ca9f5c37fb543 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -26,6 +26,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>
@@ -43,6 +45,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
@@ -356,21 +367,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;
+
+ if (!hard_iface)
+ return 0;
- allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
- allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
+ 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 !!(hard_iface->wifi_flags & allowed_flags);
+ return wifi_flags;
}
/**
@@ -381,10 +399,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);
}
/**
@@ -890,7 +907,6 @@ 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;
@@ -942,6 +958,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)
{
@@ -953,6 +1094,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))
@@ -996,8 +1139,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;
@@ -1015,3 +1159,20 @@ 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
+ */
+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);
+}
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 9ba8fb2bdceb4..089e65c8a4817 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -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_ */
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index b7acccdf3ce05..a3993a8337648 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -105,8 +105,14 @@ 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);
@@ -117,10 +123,15 @@ static int __init batadv_init(void)
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)
@@ -134,6 +145,7 @@ static void __exit batadv_exit(void)
rcu_barrier();
+ batadv_wifi_net_devices_deinit();
batadv_tt_cache_destroy();
}
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index a01ee46d97f34..16fe843577421 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -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>
@@ -166,6 +167,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 +205,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;
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 07/15] batman-adv: replace non-atomic meshif config fields with (READ|WRITE)_ONCE
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (5 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 06/15] batman-adv: extract netdev wifi detection information object Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 08/15] batman-adv: replace non-atomic hardif " Simon Wunderlich
` (7 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
The meshif configuration values are only accessed as plain loads/stores and
do not require full atomic_t semantics. Convert these fields to native
integer types and replace their users with READ_ONCE()/WRITE_ONCE() to
avoid load/store tearing.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/bat_iv_ogm.c | 26 +++++++-----
net/batman-adv/bat_v.c | 5 ++-
net/batman-adv/bat_v_ogm.c | 7 ++--
net/batman-adv/bridge_loop_avoidance.c | 14 +++----
net/batman-adv/distributed-arp-table.c | 16 ++++----
net/batman-adv/gateway_client.c | 6 +--
net/batman-adv/gateway_common.c | 14 +++----
net/batman-adv/hard-interface.c | 10 ++---
net/batman-adv/log.h | 2 +-
net/batman-adv/mesh-interface.c | 28 ++++++-------
net/batman-adv/multicast.c | 4 +-
net/batman-adv/netlink.c | 57 +++++++++++++-------------
net/batman-adv/originator.c | 1 -
net/batman-adv/routing.c | 2 +-
net/batman-adv/send.c | 2 +-
net/batman-adv/types.h | 54 ++++++++++++------------
16 files changed, 127 insertions(+), 121 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index b8b1b997960a9..5628017bee511 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -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>
@@ -274,7 +275,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 +290,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 +556,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 +642,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 +650,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 +679,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,
@@ -888,7 +892,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);
@@ -2321,7 +2325,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 +2357,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 +2411,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 +2453,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,
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
index de94447142642..492058a87682b 100644
--- a/net/batman-adv/bat_v.c
+++ b/net/batman-adv/bat_v.c
@@ -9,6 +9,7 @@
#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 +506,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 +603,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) {
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index 6436e9bc079b6..28f28b61ad6bc 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -10,6 +10,7 @@
#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>
@@ -106,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));
@@ -247,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;
}
@@ -486,7 +487,7 @@ static u32 batadv_v_forward_penalty(struct batadv_priv *bat_priv,
u32 throughput)
{
int if_hop_penalty = atomic_read(&if_incoming->hop_penalty);
- int hop_penalty = atomic_read(&bat_priv->hop_penalty);
+ int hop_penalty = READ_ONCE(bat_priv->hop_penalty);
int hop_penalty_max = BATADV_TQ_MAX_VALUE;
/* Apply per hardif hop penalty */
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index f6ca69252ff7c..87d6b11161e4a 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1380,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) {
@@ -1484,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)) {
@@ -1783,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)
@@ -1821,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. */
@@ -1953,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))
@@ -2085,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))
@@ -2505,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);
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index c6084ae6760c5..0b02018c5b850 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -743,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:
@@ -1139,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);
@@ -1234,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);
@@ -1296,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);
@@ -1344,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);
@@ -1714,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))
@@ -1744,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)))
@@ -1789,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
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index 026627c8ba45b..305488a74a256 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -171,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);
@@ -203,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)
@@ -703,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
diff --git a/net/batman-adv/gateway_common.c b/net/batman-adv/gateway_common.c
index 315fa90f0c947..675ebf098d4ec 100644
--- a/net/batman-adv/gateway_common.c
+++ b/net/batman-adv/gateway_common.c
@@ -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,
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index ca9f5c37fb543..f8a2ac1c235e5 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -612,7 +612,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
@@ -727,6 +727,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);
@@ -764,15 +765,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,
diff --git a/net/batman-adv/log.h b/net/batman-adv/log.h
index 225b747a2048e..a0d2b0d64b2b0 100644
--- a/net/batman-adv/log.h
+++ b/net/batman-adv/log.h
@@ -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); \
} \
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index 307874069b84e..dadb0784fa3e6 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -257,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) {
@@ -754,31 +754,31 @@ 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);
+ WRITE_ONCE(bat_priv->fragmentation, 1);
atomic_set(&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);
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index a3d3efe22d301..3274e2ac4f4a7 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -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;
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 8db29afeaa40b..92adaa40c8b60 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -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>
@@ -268,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))
@@ -283,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 &&
@@ -320,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);
@@ -433,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]) {
@@ -457,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);
}
@@ -474,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);
}
@@ -483,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);
@@ -493,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);
}
@@ -528,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);
}
}
@@ -547,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);
}
}
@@ -555,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 */
@@ -571,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 */
@@ -590,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);
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index ad4921b659d9d..0ce07bfdade59 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -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>
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 12c16f81cc51d..1dd295d934f49 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -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
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 60cd67ec9cea1..62ae98eef81e2 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -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);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 16fe843577421..c4845b5e43be0 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1119,21 +1119,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;
@@ -1524,36 +1524,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
@@ -1561,7 +1548,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
@@ -1569,27 +1556,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
+ */
+ atomic_t 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
/**
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 08/15] batman-adv: replace non-atomic hardif config fields with (READ|WRITE)_ONCE
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (6 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 07/15] batman-adv: replace non-atomic meshif config fields with (READ|WRITE)_ONCE Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 09/15] batman-adv: replace non-atomic vlan " Simon Wunderlich
` (6 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
The hardif configuration values are only accessed as plain loads/stores and
do not require full atomic_t semantics. Convert these fields to native
integer types and replace their users with READ_ONCE()/WRITE_ONCE() to
avoid load/store tearing.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/bat_iv_ogm.c | 2 +-
net/batman-adv/bat_v.c | 5 ++---
net/batman-adv/bat_v_elp.c | 7 ++++---
net/batman-adv/bat_v_ogm.c | 6 +++---
net/batman-adv/hard-interface.c | 2 +-
net/batman-adv/netlink.c | 12 ++++++------
net/batman-adv/types.h | 6 +++---
7 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 5628017bee511..df8e64588e1e7 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -1218,7 +1218,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
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
index 492058a87682b..ac2932da5472d 100644
--- a/net/batman-adv/bat_v.c
+++ b/net/batman-adv/bat_v.c
@@ -7,7 +7,6 @@
#include "bat_v.h"
#include "main.h"
-#include <linux/atomic.h>
#include <linux/cache.h>
#include <linux/compiler.h>
#include <linux/errno.h>
@@ -813,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);
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index e207093de79fe..0190fafcbed2d 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -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,
@@ -98,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;
@@ -324,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,
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index 28f28b61ad6bc..f4cd8cad97e0c 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -486,9 +486,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 = READ_ONCE(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) /
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index f8a2ac1c235e5..85a1f1154bb42 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -910,7 +910,7 @@ batadv_hardif_add_interface(struct net_device *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);
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 92adaa40c8b60..15f7166afd5a6 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -811,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 */
@@ -913,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
@@ -921,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 */
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index c4845b5e43be0..dd63cd28914d7 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -114,7 +114,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;
@@ -138,7 +138,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;
@@ -236,7 +236,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;
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 09/15] batman-adv: replace non-atomic vlan config fields with (READ|WRITE)_ONCE
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (7 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 08/15] batman-adv: replace non-atomic hardif " Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 10/15] batman-adv: replace non-atomic mesh state " Simon Wunderlich
` (5 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
The vlan configuration values are only accessed as plain loads/stores and
do not require full atomic_t semantics. Convert these fields to native
integer types and replace their users with READ_ONCE()/WRITE_ONCE() to
avoid load/store tearing.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/main.c | 2 +-
net/batman-adv/mesh-interface.c | 2 +-
net/batman-adv/netlink.c | 8 ++++----
net/batman-adv/translation-table.c | 2 +-
net/batman-adv/types.h | 2 +-
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index a3993a8337648..786b80a18b5d9 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -627,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);
}
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index dadb0784fa3e6..6d7f2dc326fe9 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -567,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);
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 15f7166afd5a6..7d2498c0ca16a 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -181,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,
@@ -204,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;
@@ -1022,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);
@@ -1110,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);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 28869f65ada09..515f26ff8c269 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -3730,7 +3730,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);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index dd63cd28914d7..cf01a670d8250 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1459,7 +1459,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;
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 10/15] batman-adv: replace non-atomic mesh state with (READ|WRITE)_ONCE
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (8 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 09/15] batman-adv: replace non-atomic vlan " Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 11/15] batman-adv: replace non-atomic packet_size_max " Simon Wunderlich
` (4 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
The mesh state is only accessed as plain loads/stores and does not require
full atomic_t semantics. Convert to an enum and replace its users with
READ_ONCE()/WRITE_ONCE() to avoid load/store tearing.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/bat_iv_ogm.c | 2 +-
net/batman-adv/bat_v_elp.c | 2 +-
net/batman-adv/bat_v_ogm.c | 2 +-
net/batman-adv/main.c | 20 ++++++++++----------
net/batman-adv/mesh-interface.c | 6 +++---
net/batman-adv/send.c | 2 +-
net/batman-adv/tp_meter.c | 6 +++---
net/batman-adv/types.h | 2 +-
8 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index df8e64588e1e7..c436b77674a56 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -1777,7 +1777,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;
}
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index 0190fafcbed2d..d53485d17220e 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -307,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 */
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index f4cd8cad97e0c..b337bd8e58e7d 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -279,7 +279,7 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
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;
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c
index 786b80a18b5d9..4aabbf2c3a5db 100644
--- a/net/batman-adv/main.c
+++ b/net/batman-adv/main.c
@@ -200,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;
}
@@ -232,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;
@@ -246,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;
}
@@ -259,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);
@@ -290,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);
}
/**
@@ -454,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 */
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index 6d7f2dc326fe9..72a0ec823e3ca 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -125,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();
@@ -192,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 */
@@ -783,7 +783,7 @@ static int batadv_meshif_init_late(struct net_device *dev)
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);
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index 62ae98eef81e2..c7e86c83242a2 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -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;
}
diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c
index 0fc4ca78e84eb..aefe757277b20 100644
--- a/net/batman-adv/tp_meter.c
+++ b/net/batman-adv/tp_meter.c
@@ -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;
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index cf01a670d8250..58375c0a643b8 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1504,7 +1504,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;
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 11/15] batman-adv: replace non-atomic packet_size_max with (READ|WRITE)_ONCE
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (9 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 10/15] batman-adv: replace non-atomic mesh state " Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 12/15] batman-adv: replace non-atomic last_ttvn " Simon Wunderlich
` (3 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
The maximum packet size of an meshif is only accessed as plain loads/stores
and does not require full atomic_t semantics. Convert to an native integer
and replace its users with READ_ONCE()/WRITE_ONCE() to avoid load/store
tearing.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/hard-interface.c | 3 +--
net/batman-adv/mesh-interface.c | 2 +-
net/batman-adv/translation-table.c | 6 +++---
net/batman-adv/types.h | 2 +-
4 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 85a1f1154bb42..af896b42b0d80 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -7,7 +7,6 @@
#include "hard-interface.h"
#include "main.h"
-#include <linux/atomic.h>
#include <linux/bug.h>
#include <linux/byteorder/generic.h>
#include <linux/compiler.h>
@@ -629,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.
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index 72a0ec823e3ca..dd01174fa5892 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -779,7 +779,7 @@ static int batadv_meshif_init_late(struct net_device *dev)
WRITE_ONCE(bat_priv->log_level, 0);
#endif
WRITE_ONCE(bat_priv->fragmentation, 1);
- atomic_set(&bat_priv->packet_size_max, BATADV_MAX_MTU);
+ 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);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 515f26ff8c269..e319b0796f7c8 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -649,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",
@@ -3069,7 +3069,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);
@@ -3932,7 +3932,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;
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 58375c0a643b8..51880748bc2f5 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1570,7 +1570,7 @@ struct batadv_priv {
* multiple fragmented skbs or a single frame if fragmentation is
* disabled
*/
- atomic_t packet_size_max;
+ u32 packet_size_max;
/**
* @frag_seqno: incremental counter to identify chains of egress
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 12/15] batman-adv: replace non-atomic last_ttvn with (READ|WRITE)_ONCE
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (10 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 11/15] batman-adv: replace non-atomic packet_size_max " Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 13/15] batman-adv: tt: replace open-coded overflow check with helper Simon Wunderlich
` (2 subsequent siblings)
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
The last TT version number of an meshif is only accessed as plain
loads/stores and does not require full atomic_t semantics. Convert to an
native integer and replace its users with READ_ONCE()/WRITE_ONCE() to avoid
load/store tearing.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/originator.c | 2 +-
net/batman-adv/routing.c | 4 ++--
net/batman-adv/send.c | 2 +-
net/batman-adv/translation-table.c | 16 ++++++++--------
net/batman-adv/types.h | 2 +-
5 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 0ce07bfdade59..d05c8240426bd 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -965,7 +965,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;
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 1dd295d934f49..cd4368b846add 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -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);
}
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c
index c7e86c83242a2..5f9da3606a8f5 100644
--- a/net/batman-adv/send.c
+++ b/net/batman-adv/send.c
@@ -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;
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index e319b0796f7c8..8903b2f84f512 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -841,7 +841,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;
@@ -1822,7 +1822,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,
@@ -3013,7 +3013,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 */
@@ -3300,7 +3300,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);
@@ -3316,7 +3316,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);
}
/**
@@ -3769,7 +3769,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;
@@ -3911,7 +3911,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,
@@ -4125,7 +4125,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);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 51880748bc2f5..5d4ad35c19636 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -464,7 +464,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;
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 13/15] batman-adv: tt: replace open-coded overflow check with helper
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (11 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 12/15] batman-adv: replace non-atomic last_ttvn " Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 14/15] batman-adv: tvlv: avoid unnecessary OGM buffer reallocations Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 15/15] batman-adv: use neigh_node's orig_node only as id Simon Wunderlich
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Antonio Quartulli,
Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
The commit 6043a632dd06 ("batman-adv: reject oversized global TT response
buffers") introduced an open-coded check to ensure that the allocated
buffer size can be stored in a u16. The check_add_overflow() helper can
perform the addition and overflow check in one step, so use that instead.
Acked-by: Antonio Quartulli <antonio@mandelbit.com>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/translation-table.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 8903b2f84f512..5e134d08a80fd 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -799,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;
@@ -826,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;
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 14/15] batman-adv: tvlv: avoid unnecessary OGM buffer reallocations
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (12 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 13/15] batman-adv: tt: replace open-coded overflow check with helper Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
2026-05-28 14:29 ` [PATCH net-next 15/15] batman-adv: use neigh_node's orig_node only as id Simon Wunderlich
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
Both OGMv1 (on the primary interface) and OGM2 unconditionally reallocated
their packet buffer on every transmission cycle, regardless of whether the
required size had changed. This meant a kfree/kmalloc pair even when the
TVLV payload size was identical to the previous send.
Introduce struct batadv_ogm_buf to encapsulate the OGM packet buffer
together with its current length, allocated capacity, and fixed header
length. This consolidates the separate buf/len arguments that were
previously threaded through each call site.
In batadv_tvlv_realloc_packet_buff(), the capacity is rounded up to the
next power of two so that small growth or shrinkage in TVLV data does not
trigger a reallocation. When kmalloc fails but the existing buffer is large
enough to hold the new data, the oversized buffer is reused rather than
returning an error.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/bat_iv_ogm.c | 35 ++++++++++++-----------
net/batman-adv/bat_v_ogm.c | 30 ++++++++++----------
net/batman-adv/tvlv.c | 56 ++++++++++++++++++++++---------------
net/batman-adv/tvlv.h | 3 +-
net/batman-adv/types.h | 31 +++++++++++++-------
5 files changed, 88 insertions(+), 67 deletions(-)
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index c436b77674a56..6f5a468c4084c 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -195,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;
@@ -221,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);
@@ -236,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;
@@ -258,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;
@@ -796,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;
@@ -811,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
@@ -830,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;
@@ -841,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 */
@@ -857,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;
@@ -873,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);
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index b337bd8e58e7d..2c4dca639709c 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -270,10 +270,9 @@ 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;
@@ -283,26 +282,23 @@ static void batadv_v_ogm_send_meshif(struct batadv_priv *bat_priv)
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));
@@ -448,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:
@@ -1052,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;
@@ -1085,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);
}
diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c
index 8e8b54e2172ef..cd75daea478c5 100644
--- a/net/batman-adv/tvlv.c
+++ b/net/batman-adv/tvlv.c
@@ -17,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>
@@ -267,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)
+ if (!new_buff) {
+ /* continue to use oversize buffer if new data fits */
+ if (newlen <= ogm_buff->capacity) {
+ ogm_buff->len = newlen;
+ return true;
+ }
+
return false;
+ }
+
+ memcpy(new_buff, ogm_buff->buf, ogm_buff->header_length);
+ kfree(ogm_buff->buf);
- memcpy(new_buff, *packet_buff, min_packet_len);
- kfree(*packet_buff);
- *packet_buff = new_buff;
- *packet_buff_len = min_packet_len + additional_packet_len;
+ ogm_buff->buf = new_buff;
+ ogm_buff->len = newlen;
+ ogm_buff->capacity = newcapacity;
return true;
}
@@ -301,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.
@@ -313,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;
@@ -330,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;
@@ -342,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;
diff --git a/net/batman-adv/tvlv.h b/net/batman-adv/tvlv.h
index f96f6b3f44a00..fc97838504431 100644
--- a/net/batman-adv/tvlv.h
+++ b/net/batman-adv/tvlv.h
@@ -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);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 5d4ad35c19636..c3b6af399110b 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -71,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;
@@ -87,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;
};
@@ -1481,15 +1495,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 */
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH net-next 15/15] batman-adv: use neigh_node's orig_node only as id
2026-05-28 14:29 [PATCH net-next 00/15] pull request for net-next: batman-adv 2026-05-28 Simon Wunderlich
` (13 preceding siblings ...)
2026-05-28 14:29 ` [PATCH net-next 14/15] batman-adv: tvlv: avoid unnecessary OGM buffer reallocations Simon Wunderlich
@ 2026-05-28 14:29 ` Simon Wunderlich
14 siblings, 0 replies; 20+ messages in thread
From: Simon Wunderlich @ 2026-05-28 14:29 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, b.a.t.m.a.n, Sven Eckelmann, Simon Wunderlich
From: Sven Eckelmann <sven@narfation.org>
The orig_node member of struct batadv_neigh_node is no longer used in
B.A.T.M.A.N. IV. But batadv_neigh_node_create() is still storing it.
Only batadv_v_ogm_route_update() uses it to check if we route toward
it - not needing the data stored in the batadv_orig_node object itself,
but merely a pointer to identify the originator.
The field cannot hold a proper reference because that would create a
reference cycle, so it must never be dereferenced. Rename it to
orig_node_id and mark it __private to make any future attempt to
dereference it immediately noticeable.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
net/batman-adv/bat_v_ogm.c | 2 +-
net/batman-adv/originator.c | 5 ++++-
net/batman-adv/types.h | 11 +++++++++--
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index 2c4dca639709c..5936d0048be01 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -719,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;
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index d05c8240426bd..15d660ca79376 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -693,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;
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index c3b6af399110b..1fbdd58b59bd9 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -663,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];
--
2.47.3
^ permalink raw reply related [flat|nested] 20+ messages in thread