* [PATCH RFC batadv v2 1/5] batman-adv: limit numbers of parallel learned neighbors
2026-05-19 7:02 [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects Sven Eckelmann
@ 2026-05-19 7:02 ` Sven Eckelmann
2026-05-19 7:02 ` [PATCH RFC batadv v2 2/5] batman-adv: limit numbers of parallel learned originators Sven Eckelmann
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2026-05-19 7:02 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann
A malicious actor behind one bridge port may spam the kernel with OGMs with
a random source MAC address, each of which will create a neighbor node
entry, each of which is a dynamic allocation in the kernel. This will at
some point exhaust the available memory.
Mitigate this by maintaining a per meshif count of those automatically
generated entries in neigh_learned, and a limit in neigh_max_learned. If
the limit is hit new entries are not learned anymore.
For backwards compatibility, the default setting of 0 disables the limit.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
include/uapi/linux/batman_adv.h | 6 ++++++
net/batman-adv/mesh-interface.c | 3 +++
net/batman-adv/netlink.c | 11 +++++++++++
net/batman-adv/originator.c | 12 ++++++++++++
net/batman-adv/types.h | 6 ++++++
5 files changed, 38 insertions(+)
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index 936bcac2..addb6092 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -481,6 +481,12 @@ enum batadv_nl_attrs {
*/
BATADV_ATTR_MULTICAST_FANOUT,
+ /**
+ * @BATADV_ATTR_NEIGH_MAX_LEARNED: defines the maximum number of neighbors
+ * which can be learned in parallel
+ */
+ BATADV_ATTR_NEIGH_MAX_LEARNED,
+
/* add attributes above here, update the policy in netlink.c */
/**
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index 50c26037..b9302c58 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -790,6 +790,9 @@ static int batadv_meshif_init_late(struct net_device *dev)
#endif
atomic_set(&bat_priv->tp_num, 0);
+ atomic_set(&bat_priv->neigh_learned, 0);
+ WRITE_ONCE(bat_priv->neigh_max_learned, 0);
+
WRITE_ONCE(bat_priv->tt.local_changes, 0);
bat_priv->tt.last_changeset = NULL;
bat_priv->tt.last_changeset_len = 0;
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index e52f44e7..915a7d74 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>
@@ -146,6 +147,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
[BATADV_ATTR_ORIG_INTERVAL] = { .type = NLA_U32 },
[BATADV_ATTR_ELP_INTERVAL] = { .type = NLA_U32 },
[BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NLA_U32 },
+ [BATADV_ATTR_NEIGH_MAX_LEARNED] = { .type = NLA_U32 },
};
/**
@@ -347,6 +349,10 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
atomic_read(&bat_priv->orig_interval)))
goto nla_put_failure;
+ if (nla_put_u32(msg, BATADV_ATTR_NEIGH_MAX_LEARNED,
+ READ_ONCE(bat_priv->neigh_max_learned)))
+ goto nla_put_failure;
+
batadv_hardif_put(primary_if);
genlmsg_end(msg, hdr);
@@ -592,6 +598,11 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
atomic_set(&bat_priv->orig_interval, orig_interval);
}
+ if (info->attrs[BATADV_ATTR_NEIGH_MAX_LEARNED]) {
+ WRITE_ONCE(bat_priv->neigh_max_learned,
+ nla_get_u32(info->attrs[BATADV_ATTR_NEIGH_MAX_LEARNED]));
+ }
+
batadv_netlink_notify_mesh(bat_priv);
return 0;
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index b3468cca..90f553fc 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -671,6 +671,8 @@ batadv_neigh_node_create(struct batadv_orig_node *orig_node,
{
struct batadv_neigh_node *neigh_node;
struct batadv_hardif_neigh_node *hardif_neigh = NULL;
+ u32 neigh_max_learned;
+ int neigh_learned;
spin_lock_bh(&orig_node->neigh_list_lock);
@@ -678,6 +680,11 @@ batadv_neigh_node_create(struct batadv_orig_node *orig_node,
if (neigh_node)
goto out;
+ neigh_max_learned = READ_ONCE(orig_node->bat_priv->neigh_max_learned);
+ neigh_learned = atomic_read(&orig_node->bat_priv->neigh_learned);
+ if (neigh_max_learned && neigh_learned >= neigh_max_learned)
+ goto out;
+
hardif_neigh = batadv_hardif_neigh_get_or_create(hard_iface,
neigh_addr, orig_node);
if (!hardif_neigh)
@@ -701,6 +708,8 @@ batadv_neigh_node_create(struct batadv_orig_node *orig_node,
kref_get(&hardif_neigh->refcount);
neigh_node->hardif_neigh = hardif_neigh;
+ atomic_inc(&orig_node->bat_priv->neigh_learned);
+
/* extra reference for return */
kref_init(&neigh_node->refcount);
@@ -866,6 +875,8 @@ void batadv_orig_node_release(struct kref *ref)
&orig_node->neigh_list, list) {
hlist_del_rcu(&neigh_node->list);
batadv_neigh_node_put(neigh_node);
+
+ atomic_dec(&orig_node->bat_priv->neigh_learned);
}
hlist_for_each_entry_safe(orig_ifinfo, node_tmp,
@@ -1144,6 +1155,7 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv,
hlist_del_rcu(&neigh_node->list);
batadv_neigh_node_put(neigh_node);
+ atomic_dec(&bat_priv->neigh_learned);
} else {
/* only necessary if not the whole neighbor is to be
* deleted, but some interface has been removed.
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index c8c3e806..13349350 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1637,6 +1637,12 @@ struct batadv_priv {
/** @meshif_vlan_list_lock: lock protecting meshif_vlan_list */
spinlock_t meshif_vlan_list_lock;
+ /** @neigh_max_learned: Maximum number of neighbors */
+ u32 neigh_max_learned;
+
+ /** @neigh_learned: current number of learned neighbors */
+ atomic_t neigh_learned;
+
#ifdef CONFIG_BATMAN_ADV_BLA
/** @bla: bridge loop avoidance data */
struct batadv_priv_bla bla;
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH RFC batadv v2 2/5] batman-adv: limit numbers of parallel learned originators
2026-05-19 7:02 [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects Sven Eckelmann
2026-05-19 7:02 ` [PATCH RFC batadv v2 1/5] batman-adv: limit numbers of parallel learned neighbors Sven Eckelmann
@ 2026-05-19 7:02 ` Sven Eckelmann
2026-05-19 7:02 ` [PATCH RFC batadv v2 3/5] batman-adv: limit numbers of parallel learned DAT entries Sven Eckelmann
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2026-05-19 7:02 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann
A malicious actor behind one bridge port may spam the kernel with OGMs with
a random source MAC address, each of which will create an originator node
entry, each of which is a dynamic allocation in the kernel. This will at
some point exhaust the available memory.
Mitigate this by maintaining a per meshif count of those automatically
generated entries in orig_learned, and a limit in orig_max_learned. If the
limit is hit new entries are not learned anymore.
For backwards compatibility, the default setting of 0 disables the limit.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
include/uapi/linux/batman_adv.h | 6 ++++++
net/batman-adv/bat_iv_ogm.c | 13 ++++++++++++-
net/batman-adv/bat_v_ogm.c | 11 +++++++++++
net/batman-adv/mesh-interface.c | 3 +++
net/batman-adv/netlink.c | 10 ++++++++++
net/batman-adv/originator.c | 2 ++
net/batman-adv/types.h | 6 ++++++
7 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index addb6092..b3c04ab0 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -487,6 +487,12 @@ enum batadv_nl_attrs {
*/
BATADV_ATTR_NEIGH_MAX_LEARNED,
+ /**
+ * @BATADV_ATTR_ORIG_MAX_LEARNED: defines the maximum number of originator
+ * which can be learned in parallel
+ */
+ BATADV_ATTR_ORIG_MAX_LEARNED,
+
/* add attributes above here, update the policy in netlink.c */
/**
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index 74ef7dc2..cc289f55 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>
@@ -140,24 +141,34 @@ static struct batadv_orig_node *
batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr)
{
struct batadv_orig_node *orig_node;
+ u32 orig_max_learned;
+ int orig_learned;
int hash_added;
orig_node = batadv_orig_hash_find(bat_priv, addr);
if (orig_node)
return orig_node;
+ orig_max_learned = READ_ONCE(bat_priv->orig_max_learned);
+ orig_learned = atomic_read(&bat_priv->orig_learned);
+ if (orig_max_learned && orig_learned >= orig_max_learned)
+ return NULL;
+
orig_node = batadv_orig_node_new(bat_priv, addr);
if (!orig_node)
return NULL;
spin_lock_init(&orig_node->bat_iv.ogm_cnt_lock);
+ atomic_inc(&bat_priv->orig_learned);
kref_get(&orig_node->refcount);
hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
batadv_choose_orig, orig_node,
&orig_node->hash_entry);
- if (hash_added != 0)
+ if (hash_added != 0) {
+ atomic_dec(&bat_priv->orig_learned);
goto free_orig_node_hash;
+ }
return orig_node;
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c
index e3870492..dd57f4a7 100644
--- a/net/batman-adv/bat_v_ogm.c
+++ b/net/batman-adv/bat_v_ogm.c
@@ -9,6 +9,7 @@
#include <linux/atomic.h>
#include <linux/byteorder/generic.h>
+#include <linux/compiler.h>
#include <linux/container_of.h>
#include <linux/errno.h>
#include <linux/etherdevice.h>
@@ -54,16 +55,25 @@ struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv,
const u8 *addr)
{
struct batadv_orig_node *orig_node;
+ u32 orig_max_learned;
+ int orig_learned;
int hash_added;
orig_node = batadv_orig_hash_find(bat_priv, addr);
if (orig_node)
return orig_node;
+ orig_max_learned = READ_ONCE(bat_priv->orig_max_learned);
+ orig_learned = atomic_read(&bat_priv->orig_learned);
+ if (orig_max_learned && orig_learned >= orig_max_learned)
+ return NULL;
+
orig_node = batadv_orig_node_new(bat_priv, addr);
if (!orig_node)
return NULL;
+ atomic_inc(&bat_priv->orig_learned);
+
kref_get(&orig_node->refcount);
hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
batadv_choose_orig, orig_node,
@@ -73,6 +83,7 @@ struct batadv_orig_node *batadv_v_ogm_orig_get(struct batadv_priv *bat_priv,
batadv_orig_node_put(orig_node);
batadv_orig_node_put(orig_node);
orig_node = NULL;
+ atomic_dec(&bat_priv->orig_learned);
}
return orig_node;
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index b9302c58..fad788cc 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -793,6 +793,9 @@ static int batadv_meshif_init_late(struct net_device *dev)
atomic_set(&bat_priv->neigh_learned, 0);
WRITE_ONCE(bat_priv->neigh_max_learned, 0);
+ atomic_set(&bat_priv->orig_learned, 0);
+ WRITE_ONCE(bat_priv->orig_max_learned, 0);
+
WRITE_ONCE(bat_priv->tt.local_changes, 0);
bat_priv->tt.last_changeset = NULL;
bat_priv->tt.last_changeset_len = 0;
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 915a7d74..2b5fb1d6 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -148,6 +148,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
[BATADV_ATTR_ELP_INTERVAL] = { .type = NLA_U32 },
[BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NLA_U32 },
[BATADV_ATTR_NEIGH_MAX_LEARNED] = { .type = NLA_U32 },
+ [BATADV_ATTR_ORIG_MAX_LEARNED] = { .type = NLA_U32 },
};
/**
@@ -353,6 +354,10 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
READ_ONCE(bat_priv->neigh_max_learned)))
goto nla_put_failure;
+ if (nla_put_u32(msg, BATADV_ATTR_ORIG_MAX_LEARNED,
+ READ_ONCE(bat_priv->orig_max_learned)))
+ goto nla_put_failure;
+
batadv_hardif_put(primary_if);
genlmsg_end(msg, hdr);
@@ -603,6 +608,11 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
nla_get_u32(info->attrs[BATADV_ATTR_NEIGH_MAX_LEARNED]));
}
+ if (info->attrs[BATADV_ATTR_ORIG_MAX_LEARNED]) {
+ WRITE_ONCE(bat_priv->orig_max_learned,
+ nla_get_u32(info->attrs[BATADV_ATTR_ORIG_MAX_LEARNED]));
+ }
+
batadv_netlink_notify_mesh(bat_priv);
return 0;
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 90f553fc..3c48e006 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -930,6 +930,7 @@ void batadv_originator_free(struct batadv_priv *bat_priv)
head, hash_entry) {
hlist_del_rcu(&orig_node->hash_entry);
batadv_orig_node_put(orig_node);
+ atomic_dec(&bat_priv->orig_learned);
}
spin_unlock_bh(list_lock);
}
@@ -1297,6 +1298,7 @@ void batadv_purge_orig_ref(struct batadv_priv *bat_priv)
orig_node, -1,
"originator timed out");
batadv_orig_node_put(orig_node);
+ atomic_dec(&bat_priv->orig_learned);
continue;
}
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 13349350..49398aeb 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1643,6 +1643,12 @@ struct batadv_priv {
/** @neigh_learned: current number of learned neighbors */
atomic_t neigh_learned;
+ /** @orig_max_learned: Maximum number of originators */
+ u32 orig_max_learned;
+
+ /** @orig_learned: current number of learned originators */
+ atomic_t orig_learned;
+
#ifdef CONFIG_BATMAN_ADV_BLA
/** @bla: bridge loop avoidance data */
struct batadv_priv_bla bla;
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH RFC batadv v2 3/5] batman-adv: limit numbers of parallel learned DAT entries
2026-05-19 7:02 [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects Sven Eckelmann
2026-05-19 7:02 ` [PATCH RFC batadv v2 1/5] batman-adv: limit numbers of parallel learned neighbors Sven Eckelmann
2026-05-19 7:02 ` [PATCH RFC batadv v2 2/5] batman-adv: limit numbers of parallel learned originators Sven Eckelmann
@ 2026-05-19 7:02 ` Sven Eckelmann
2026-05-19 7:02 ` [PATCH RFC batadv v2 4/5] batman-adv: limit numbers of parallel learned BLA backbones Sven Eckelmann
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2026-05-19 7:02 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann
A malicious actor behind one bridge port may spam the kernel with OGMs with
a random source MAC address, each of which will create a DAT entry, each of
which is a dynamic allocation in the kernel. This will at some point
exhaust the available memory.
Mitigate this by maintaining a per meshif count of those automatically
generated entries in orig_learned, and a limit in orig_max_learned. If the
limit is hit new entries are not learned anymore.
For backwards compatibility, the default setting of 0 disables the limit.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
include/uapi/linux/batman_adv.h | 6 ++++++
net/batman-adv/distributed-arp-table.c | 11 +++++++++++
net/batman-adv/mesh-interface.c | 3 +++
net/batman-adv/netlink.c | 10 ++++++++++
net/batman-adv/types.h | 6 ++++++
5 files changed, 36 insertions(+)
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index b3c04ab0..cca87d42 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -493,6 +493,12 @@ enum batadv_nl_attrs {
*/
BATADV_ATTR_ORIG_MAX_LEARNED,
+ /**
+ * @BATADV_ATTR_DAT_MAX_LEARNED: defines the maximum number of DAT entries
+ * which can be learned in parallel
+ */
+ BATADV_ATTR_DAT_MAX_LEARNED,
+
/* add attributes above here, update the policy in netlink.c */
/**
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 0a8bd95e..99569a2f 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -181,6 +181,7 @@ static void __batadv_dat_purge(struct batadv_priv *bat_priv,
hlist_del_rcu(&dat_entry->hash_entry);
batadv_dat_entry_put(dat_entry);
+ atomic_dec(&bat_priv->dat_learned);
}
spin_unlock_bh(list_lock);
}
@@ -366,6 +367,8 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
u8 *mac_addr, unsigned short vid)
{
struct batadv_dat_entry *dat_entry;
+ u32 dat_max_learned;
+ int dat_learned;
int hash_added;
dat_entry = batadv_dat_entry_hash_find(bat_priv, ip, vid);
@@ -381,6 +384,11 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
goto out;
}
+ dat_max_learned = READ_ONCE(bat_priv->dat_max_learned);
+ dat_learned = atomic_read(&bat_priv->dat_learned);
+ if (dat_max_learned && dat_learned >= dat_max_learned)
+ goto out;
+
dat_entry = kmalloc_obj(*dat_entry, GFP_ATOMIC);
if (!dat_entry)
goto out;
@@ -391,6 +399,8 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
dat_entry->last_update = jiffies;
kref_init(&dat_entry->refcount);
+ atomic_inc(&bat_priv->dat_learned);
+
kref_get(&dat_entry->refcount);
hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
batadv_hash_dat, dat_entry,
@@ -399,6 +409,7 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
if (unlikely(hash_added != 0)) {
/* remove the reference for the hash */
batadv_dat_entry_put(dat_entry);
+ atomic_dec(&bat_priv->dat_learned);
goto out;
}
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index fad788cc..851a078d 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -759,6 +759,9 @@ static int batadv_meshif_init_late(struct net_device *dev)
#endif
#ifdef CONFIG_BATMAN_ADV_DAT
atomic_set(&bat_priv->distributed_arp_table, 1);
+
+ atomic_set(&bat_priv->dat_learned, 0);
+ WRITE_ONCE(bat_priv->dat_max_learned, 0);
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
atomic_set(&bat_priv->multicast_mode, 1);
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 2b5fb1d6..742b1e3e 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -149,6 +149,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
[BATADV_ATTR_THROUGHPUT_OVERRIDE] = { .type = NLA_U32 },
[BATADV_ATTR_NEIGH_MAX_LEARNED] = { .type = NLA_U32 },
[BATADV_ATTR_ORIG_MAX_LEARNED] = { .type = NLA_U32 },
+ [BATADV_ATTR_DAT_MAX_LEARNED] = { .type = NLA_U32 },
};
/**
@@ -298,6 +299,10 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
if (nla_put_u8(msg, BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED,
!!atomic_read(&bat_priv->distributed_arp_table)))
goto nla_put_failure;
+
+ if (nla_put_u32(msg, BATADV_ATTR_DAT_MAX_LEARNED,
+ READ_ONCE(bat_priv->dat_max_learned)))
+ goto nla_put_failure;
#endif /* CONFIG_BATMAN_ADV_DAT */
if (nla_put_u8(msg, BATADV_ATTR_FRAGMENTATION_ENABLED,
@@ -488,6 +493,11 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
!!nla_get_u8(attr));
batadv_dat_status_update(bat_priv->mesh_iface);
}
+
+ if (info->attrs[BATADV_ATTR_DAT_MAX_LEARNED]) {
+ WRITE_ONCE(bat_priv->dat_max_learned,
+ nla_get_u32(info->attrs[BATADV_ATTR_DAT_MAX_LEARNED]));
+ }
#endif /* CONFIG_BATMAN_ADV_DAT */
if (info->attrs[BATADV_ATTR_FRAGMENTATION_ENABLED]) {
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 49398aeb..c8bf2212 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1535,6 +1535,12 @@ struct batadv_priv {
* is enabled
*/
atomic_t distributed_arp_table;
+
+ /** @dat_max_learned: Maximum number of DAT entries */
+ u32 dat_max_learned;
+
+ /** @dat_learned: current number of learned DAT entries */
+ atomic_t dat_learned;
#endif
#ifdef CONFIG_BATMAN_ADV_MCAST
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH RFC batadv v2 4/5] batman-adv: limit numbers of parallel learned BLA backbones
2026-05-19 7:02 [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects Sven Eckelmann
` (2 preceding siblings ...)
2026-05-19 7:02 ` [PATCH RFC batadv v2 3/5] batman-adv: limit numbers of parallel learned DAT entries Sven Eckelmann
@ 2026-05-19 7:02 ` Sven Eckelmann
2026-05-19 9:10 ` Sven Eckelmann
2026-05-20 8:16 ` Simon Wunderlich
2026-05-19 7:02 ` [PATCH RFC batadv v2 5/5] batman-adv: limit numbers of parallel learned BLA claims Sven Eckelmann
2026-05-19 8:37 ` [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects Sven Eckelmann
5 siblings, 2 replies; 9+ messages in thread
From: Sven Eckelmann @ 2026-05-19 7:02 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann
A malicious actor behind one bridge port may spam the kernel with OGMs with
a random source MAC address, each of which will create a BLA backbone, each
of which is a dynamic allocation in the kernel. This will at some point
exhaust the available memory.
Mitigate this by maintaining a per meshif count of those automatically
generated entries in orig_learned, and a limit in orig_max_learned. If the
limit is hit new entries are not learned anymore.
For backwards compatibility, the default setting of 0 disables the limit.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
include/uapi/linux/batman_adv.h | 6 ++++++
net/batman-adv/bridge_loop_avoidance.c | 11 +++++++++++
net/batman-adv/mesh-interface.c | 3 +++
net/batman-adv/netlink.c | 10 ++++++++++
net/batman-adv/types.h | 6 ++++++
5 files changed, 36 insertions(+)
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index cca87d42..4188d83c 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -499,6 +499,12 @@ enum batadv_nl_attrs {
*/
BATADV_ATTR_DAT_MAX_LEARNED,
+ /**
+ * @BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED: defines the maximum number of BLA backbone
+ * which can be learned in parallel
+ */
+ BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED,
+
/* add attributes above here, update the policy in netlink.c */
/**
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index cec11f12..8bb8dec6 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -494,6 +494,8 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
{
struct batadv_bla_backbone_gw *entry;
struct batadv_orig_node *orig_node;
+ u32 bla_backbone_max_learned;
+ int bla_backbone_learned;
int hash_added;
entry = batadv_backbone_hash_find(bat_priv, orig, vid);
@@ -505,6 +507,11 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
"%s(): not found (%pM, %d), creating new entry\n", __func__,
orig, batadv_print_vid(vid));
+ bla_backbone_max_learned = READ_ONCE(bat_priv->bla_backbone_max_learned);
+ bla_backbone_learned = atomic_read(&bat_priv->bla_backbone_learned);
+ if (bla_backbone_max_learned && bla_backbone_learned >= bla_backbone_max_learned)
+ return NULL;
+
entry = kzalloc_obj(*entry, GFP_ATOMIC);
if (!entry)
return NULL;
@@ -520,6 +527,8 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
INIT_WORK(&entry->report_work, batadv_bla_loopdetect_report);
kref_init(&entry->refcount);
+ atomic_inc(&bat_priv->bla_backbone_learned);
+
kref_get(&entry->refcount);
hash_added = batadv_hash_add(bat_priv->bla.backbone_hash,
batadv_compare_backbone_gw,
@@ -529,6 +538,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
if (unlikely(hash_added != 0)) {
/* hash failed, free the structure */
kfree(entry);
+ atomic_dec(&bat_priv->bla_backbone_learned);
return NULL;
}
@@ -1256,6 +1266,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now)
hlist_del_rcu(&backbone_gw->hash_entry);
batadv_backbone_gw_put(backbone_gw);
+ atomic_dec(&bat_priv->bla_backbone_learned);
}
spin_unlock_bh(list_lock);
}
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index 851a078d..1594a2d6 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -790,6 +790,9 @@ static int batadv_meshif_init_late(struct net_device *dev)
atomic_set(&bat_priv->tt.ogm_append_cnt, 0);
#ifdef CONFIG_BATMAN_ADV_BLA
atomic_set(&bat_priv->bla.num_requests, 0);
+
+ atomic_set(&bat_priv->bla_backbone_learned, 0);
+ WRITE_ONCE(bat_priv->bla_backbone_max_learned, 0);
#endif
atomic_set(&bat_priv->tp_num, 0);
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 742b1e3e..5d4bccdc 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -150,6 +150,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
[BATADV_ATTR_NEIGH_MAX_LEARNED] = { .type = NLA_U32 },
[BATADV_ATTR_ORIG_MAX_LEARNED] = { .type = NLA_U32 },
[BATADV_ATTR_DAT_MAX_LEARNED] = { .type = NLA_U32 },
+ [BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED] = { .type = NLA_U32 },
};
/**
@@ -293,6 +294,10 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
if (nla_put_u8(msg, BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED,
!!atomic_read(&bat_priv->bridge_loop_avoidance)))
goto nla_put_failure;
+
+ if (nla_put_u32(msg, BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED,
+ READ_ONCE(bat_priv->bla_backbone_max_learned)))
+ goto nla_put_failure;
#endif /* CONFIG_BATMAN_ADV_BLA */
#ifdef CONFIG_BATMAN_ADV_DAT
@@ -483,6 +488,11 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
!!nla_get_u8(attr));
batadv_bla_status_update(bat_priv->mesh_iface);
}
+
+ if (info->attrs[BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED]) {
+ WRITE_ONCE(bat_priv->bla_backbone_max_learned,
+ nla_get_u32(info->attrs[BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED]));
+ }
#endif /* CONFIG_BATMAN_ADV_BLA */
#ifdef CONFIG_BATMAN_ADV_DAT
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index c8bf2212..c091b19e 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1656,6 +1656,12 @@ struct batadv_priv {
atomic_t orig_learned;
#ifdef CONFIG_BATMAN_ADV_BLA
+ /** @bla_backbone_max_learned: Maximum number of backbone_gw */
+ u32 bla_backbone_max_learned;
+
+ /** @bla_backbone_learned: current number of learned backbone_gw entries */
+ atomic_t bla_backbone_learned;
+
/** @bla: bridge loop avoidance data */
struct batadv_priv_bla bla;
#endif
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH RFC batadv v2 4/5] batman-adv: limit numbers of parallel learned BLA backbones
2026-05-19 7:02 ` [PATCH RFC batadv v2 4/5] batman-adv: limit numbers of parallel learned BLA backbones Sven Eckelmann
@ 2026-05-19 9:10 ` Sven Eckelmann
2026-05-20 8:16 ` Simon Wunderlich
1 sibling, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2026-05-19 9:10 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: simonwunderlich
[-- Attachment #1: Type: text/plain, Size: 1888 bytes --]
On Tuesday, 19 May 2026 09:02:18 CEST Sven Eckelmann wrote:
> @@ -505,6 +507,11 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
> "%s(): not found (%pM, %d), creating new entry\n", __func__,
> orig, batadv_print_vid(vid));
>
> + bla_backbone_max_learned = READ_ONCE(bat_priv->bla_backbone_max_learned);
> + bla_backbone_learned = atomic_read(&bat_priv->bla_backbone_learned);
> + if (bla_backbone_max_learned && bla_backbone_learned >= bla_backbone_max_learned)
> + return NULL;
> +
> entry = kzalloc_obj(*entry, GFP_ATOMIC);
> if (!entry)
> return NULL;
@Simon: remark from Sashiko, should we actually exempt own_gateway?
@@ -508,10 +508,12 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
"%s(): not found (%pM, %d), creating new entry\n", __func__,
orig, batadv_print_vid(vid));
- bla_backbone_max_learned = READ_ONCE(bat_priv->bla_backbone_max_learned);
- bla_backbone_learned = atomic_read(&bat_priv->bla_backbone_learned);
- if (bla_backbone_max_learned && bla_backbone_learned >= bla_backbone_max_learned)
- return NULL;
+ if (!own_backbone) {
+ bla_backbone_max_learned = READ_ONCE(bat_priv->bla_backbone_max_learned);
+ bla_backbone_learned = atomic_read(&bat_priv->bla_backbone_learned);
+ if (bla_backbone_max_learned && bla_backbone_learned >= bla_backbone_max_learned)
+ return NULL;
+ }
entry = kzalloc_obj(*entry, GFP_ATOMIC);
if (!entry)
@@ -539,7 +541,10 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const u8 *orig,
if (unlikely(hash_added != 0)) {
/* hash failed, free the structure */
kfree(entry);
- atomic_dec(&bat_priv->bla_backbone_learned);
+
+ if (!own_backbone)
+ atomic_dec(&bat_priv->bla_backbone_learned);
+
return NULL;
}
Regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH RFC batadv v2 4/5] batman-adv: limit numbers of parallel learned BLA backbones
2026-05-19 7:02 ` [PATCH RFC batadv v2 4/5] batman-adv: limit numbers of parallel learned BLA backbones Sven Eckelmann
2026-05-19 9:10 ` Sven Eckelmann
@ 2026-05-20 8:16 ` Simon Wunderlich
1 sibling, 0 replies; 9+ messages in thread
From: Simon Wunderlich @ 2026-05-20 8:16 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann, Sven Eckelmann
This looks mostly good and I like the approach in general!
commit message: batman-adv: limit numbers of parallel learned BLA backbones
numbers -> number
On Tuesday, May 19, 2026 9:02:18 AM Central European Summer Time Sven
Eckelmann wrote:
> A malicious actor behind one bridge port may spam the kernel with OGMs with
> a random source MAC address, each of which will create a BLA backbone, each
> of which is a dynamic allocation in the kernel. This will at some point
> exhaust the available memory.
To get backbone gateways, spamming OGMs is not sufficient (or not even
necessary), but BLA claims and/or BLA announcements need to be sent (with the
same group ID or need to exist on the mesh) on the backbone Ethernet.
Just sending OGMs will not create backbone GWs, so I think this commit message
needs to be revised (you already said it's a placeholder, so I think those are
the specifics for this counter ;] ).
>
> Mitigate this by maintaining a per meshif count of those automatically
> generated entries in orig_learned, and a limit in orig_max_learned. If the
> limit is hit new entries are not learned anymore.
>
> For backwards compatibility, the default setting of 0 disables the limit.
>
> Signed-off-by: Sven Eckelmann <sven@narfation.org>
> [...]
> ---
> include/uapi/linux/batman_adv.h | 6 ++++++
> net/batman-adv/bridge_loop_avoidance.c | 11 +++++++++++
> net/batman-adv/mesh-interface.c | 3 +++
> net/batman-adv/netlink.c | 10 ++++++++++
> net/batman-adv/types.h | 6 ++++++
> 5 files changed, 36 insertions(+)
>
> diff --git a/include/uapi/linux/batman_adv.h
> b/include/uapi/linux/batman_adv.h index cca87d42..4188d83c 100644
> --- a/include/uapi/linux/batman_adv.h
> +++ b/include/uapi/linux/batman_adv.h
> @@ -499,6 +499,12 @@ enum batadv_nl_attrs {
> */
> BATADV_ATTR_DAT_MAX_LEARNED,
>
> + /**
> + * @BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED: defines the maximum
number of
> BLA backbone
number of BLA backbones (add the s)
> + * which can be learned in parallel
> + */
> + BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED,
> +
> /* add attributes above here, update the policy in netlink.c */
>
> /**
> diff --git a/net/batman-adv/bridge_loop_avoidance.c
> b/net/batman-adv/bridge_loop_avoidance.c index cec11f12..8bb8dec6 100644
> --- a/net/batman-adv/bridge_loop_avoidance.c
> +++ b/net/batman-adv/bridge_loop_avoidance.c
> @@ -494,6 +494,8 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv,
> const u8 *orig, {
> struct batadv_bla_backbone_gw *entry;
> struct batadv_orig_node *orig_node;
> + u32 bla_backbone_max_learned;
> + int bla_backbone_learned;
> int hash_added;
>
> entry = batadv_backbone_hash_find(bat_priv, orig, vid);
> @@ -505,6 +507,11 @@ batadv_bla_get_backbone_gw(struct batadv_priv
> *bat_priv, const u8 *orig, "%s(): not found (%pM, %d), creating new
> entry\n", __func__, orig, batadv_print_vid(vid));
>
> + bla_backbone_max_learned = READ_ONCE(bat_priv-
>bla_backbone_max_learned);
> + bla_backbone_learned = atomic_read(&bat_priv-
>bla_backbone_learned);
> + if (bla_backbone_max_learned && bla_backbone_learned >=
> bla_backbone_max_learned) + return NULL;
> +
I think we should always allow "own backbones" to pass. This could be done by
adding an exception in this check.
If (for some, probably unlikely reason) an attacker fills up the table before
the own backbone is registered, this may create problems on many other
occurences.
> entry = kzalloc_obj(*entry, GFP_ATOMIC);
> if (!entry)
> return NULL;
> --- a/net/batman-adv/types.h
> +++ b/net/batman-adv/types.h
> @@ -1656,6 +1656,12 @@ struct batadv_priv {
> atomic_t orig_learned;
>
> #ifdef CONFIG_BATMAN_ADV_BLA
> + /** @bla_backbone_max_learned: Maximum number of backbone_gw */
> + u32 bla_backbone_max_learned;
> +
> + /** @bla_backbone_learned: current number of learned backbone_gw
entries
> */ + atomic_t bla_backbone_learned;
> +
should this go into batadv_priv_bla or along the other counters in
batadv_priv? I'm fine either way.
Thank you!
Simon
> /** @bla: bridge loop avoidance data */
> struct batadv_priv_bla bla;
> #endif
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC batadv v2 5/5] batman-adv: limit numbers of parallel learned BLA claims
2026-05-19 7:02 [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects Sven Eckelmann
` (3 preceding siblings ...)
2026-05-19 7:02 ` [PATCH RFC batadv v2 4/5] batman-adv: limit numbers of parallel learned BLA backbones Sven Eckelmann
@ 2026-05-19 7:02 ` Sven Eckelmann
2026-05-19 8:37 ` [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects Sven Eckelmann
5 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2026-05-19 7:02 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Sven Eckelmann
A malicious actor behind one bridge port may spam the kernel with OGMs with
a random source MAC address, each of which will create a BLA claim, each of
which is a dynamic allocation in the kernel. This will at some point
exhaust the available memory.
Mitigate this by maintaining a per meshif count of those automatically
generated entries in orig_learned, and a limit in orig_max_learned. If the
limit is hit new entries are not learned anymore.
For backwards compatibility, the default setting of 0 disables the limit.
Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
include/uapi/linux/batman_adv.h | 6 ++++++
net/batman-adv/bridge_loop_avoidance.c | 11 +++++++++++
net/batman-adv/mesh-interface.c | 3 +++
net/batman-adv/netlink.c | 10 ++++++++++
net/batman-adv/types.h | 6 ++++++
5 files changed, 36 insertions(+)
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index 4188d83c..65d1c0eb 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -505,6 +505,12 @@ enum batadv_nl_attrs {
*/
BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED,
+ /**
+ * @BATADV_ATTR_BLA_CLAIM_MAX_LEARNED: defines the maximum number of BLA claim
+ * which can be learned in parallel
+ */
+ BATADV_ATTR_BLA_CLAIM_MAX_LEARNED,
+
/* add attributes above here, update the policy in netlink.c */
/**
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 8bb8dec6..f39b02f9 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -320,6 +320,7 @@ batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw)
hlist_del_rcu(&claim->hash_entry);
batadv_claim_put(claim);
+ atomic_dec(&backbone_gw->bat_priv->bla_claim_learned);
}
spin_unlock_bh(list_lock);
}
@@ -700,7 +701,9 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
struct batadv_bla_backbone_gw *old_backbone_gw;
struct batadv_bla_claim *claim;
struct batadv_bla_claim search_claim;
+ u32 bla_claim_max_learned;
bool remove_crc = false;
+ int bla_claim_learned;
int hash_added;
ether_addr_copy(search_claim.addr, mac);
@@ -709,6 +712,11 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
/* create a new claim entry if it does not exist yet. */
if (!claim) {
+ bla_claim_max_learned = READ_ONCE(bat_priv->bla_claim_max_learned);
+ bla_claim_learned = atomic_read(&bat_priv->bla_claim_learned);
+ if (bla_claim_max_learned && bla_claim_learned >= bla_claim_max_learned)
+ return;
+
claim = kzalloc_obj(*claim, GFP_ATOMIC);
if (!claim)
return;
@@ -721,6 +729,8 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
claim->backbone_gw = backbone_gw;
kref_init(&claim->refcount);
+ atomic_inc(&bat_priv->bla_claim_learned);
+
batadv_dbg(BATADV_DBG_BLA, bat_priv,
"%s(): adding new entry %pM, vid %d to hash ...\n",
__func__, mac, batadv_print_vid(vid));
@@ -735,6 +745,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv,
/* only local changes happened. */
batadv_backbone_gw_put(backbone_gw);
kfree(claim);
+ atomic_dec(&bat_priv->bla_claim_learned);
return;
}
} else {
diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c
index 1594a2d6..8fd47cef 100644
--- a/net/batman-adv/mesh-interface.c
+++ b/net/batman-adv/mesh-interface.c
@@ -793,6 +793,9 @@ static int batadv_meshif_init_late(struct net_device *dev)
atomic_set(&bat_priv->bla_backbone_learned, 0);
WRITE_ONCE(bat_priv->bla_backbone_max_learned, 0);
+
+ atomic_set(&bat_priv->bla_claim_learned, 0);
+ WRITE_ONCE(bat_priv->bla_claim_max_learned, 0);
#endif
atomic_set(&bat_priv->tp_num, 0);
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 5d4bccdc..8cafbac5 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -151,6 +151,7 @@ static const struct nla_policy batadv_netlink_policy[NUM_BATADV_ATTR] = {
[BATADV_ATTR_ORIG_MAX_LEARNED] = { .type = NLA_U32 },
[BATADV_ATTR_DAT_MAX_LEARNED] = { .type = NLA_U32 },
[BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED] = { .type = NLA_U32 },
+ [BATADV_ATTR_BLA_CLAIM_MAX_LEARNED] = { .type = NLA_U32 },
};
/**
@@ -298,6 +299,10 @@ static int batadv_netlink_mesh_fill(struct sk_buff *msg,
if (nla_put_u32(msg, BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED,
READ_ONCE(bat_priv->bla_backbone_max_learned)))
goto nla_put_failure;
+
+ if (nla_put_u32(msg, BATADV_ATTR_BLA_CLAIM_MAX_LEARNED,
+ READ_ONCE(bat_priv->bla_claim_max_learned)))
+ goto nla_put_failure;
#endif /* CONFIG_BATMAN_ADV_BLA */
#ifdef CONFIG_BATMAN_ADV_DAT
@@ -493,6 +498,11 @@ static int batadv_netlink_set_mesh(struct sk_buff *skb, struct genl_info *info)
WRITE_ONCE(bat_priv->bla_backbone_max_learned,
nla_get_u32(info->attrs[BATADV_ATTR_BLA_BACKBONE_MAX_LEARNED]));
}
+
+ if (info->attrs[BATADV_ATTR_BLA_CLAIM_MAX_LEARNED]) {
+ WRITE_ONCE(bat_priv->bla_claim_max_learned,
+ nla_get_u32(info->attrs[BATADV_ATTR_BLA_CLAIM_MAX_LEARNED]));
+ }
#endif /* CONFIG_BATMAN_ADV_BLA */
#ifdef CONFIG_BATMAN_ADV_DAT
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index c091b19e..ddd9f1e0 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1662,6 +1662,12 @@ struct batadv_priv {
/** @bla_backbone_learned: current number of learned backbone_gw entries */
atomic_t bla_backbone_learned;
+ /** @bla_claim_max_learned: Maximum number of claim */
+ u32 bla_claim_max_learned;
+
+ /** @bla_claim_learned: current number of learned claim entries */
+ atomic_t bla_claim_learned;
+
/** @bla: bridge loop avoidance data */
struct batadv_priv_bla bla;
#endif
--
2.47.3
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects
2026-05-19 7:02 [PATCH RFC batadv v2 0/5] batman-adv: allow to specify limits for remote learned objects Sven Eckelmann
` (4 preceding siblings ...)
2026-05-19 7:02 ` [PATCH RFC batadv v2 5/5] batman-adv: limit numbers of parallel learned BLA claims Sven Eckelmann
@ 2026-05-19 8:37 ` Sven Eckelmann
5 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2026-05-19 8:37 UTC (permalink / raw)
To: b.a.t.m.a.n
[-- Attachment #1: Type: text/plain, Size: 359 bytes --]
On Tuesday, 19 May 2026 09:02:14 CEST Sven Eckelmann wrote:
> For the moment, I just want to demonstrate how this might work with some
> example code. I didn't invest any time to actually check out the other
> items in the list. So, please consider these lists as vague suggestions.
Please also consider the commit messages as placeholder :)
Regards,
Sven
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread