* [batadv,v10 0/2] batman-adv: increase DAT DHT timeout
@ 2026-09-18 22:55 Linus Lüssing
2026-09-18 22:55 ` [batadv,v10 1/2] batman-adv: split DAT cache into DAT cache and DAT DHT Linus Lüssing
2026-09-18 22:55 ` [batadv,v10 2/2] batman-adv: increase DAT DHT timeout Linus Lüssing
0 siblings, 2 replies; 4+ messages in thread
From: Linus Lüssing @ 2026-09-18 22:55 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Linus Lüssing
This patchset increases the DAT DHT timeout to reduce the amount
of broadcasted ARP Replies.
To increase the timeout only for DAT DHT entries added via DHT-PUT but
not for any other entry in the DAT cache the DAT cache and DAT DHT
concepts are split into two separate hash tables (PATCH 1/2).
PATCH 2/2 then increases the timeout for DAT DHT entries from 5 to
30 minutes.
The motivation for this patchset is based on the observations made here:
https://www.open-mesh.org/projects/batman-adv/wiki/DAT_DHCP_Snooping
In tests at Freifunk Lübeck with ~180 mesh nodes and Gluon
this reduced the ARP broadcast overhead, measured over 7 days, as
follows:
- Total: 6677.66 bits/s -> 677.26 bits/s => -89.86%
11.92 pkts/s -> 1.21 pkts/s => -89.85%
- from gateways: 5618.02 bits/s -> 212.28 => -96.22%
10.03 pkts/s -> 0.38 pkts/s => -96.21%
Also see graphics and a few more test details here:
- https://www.open-mesh.org/projects/batman-adv/wiki/DAT_DHCP_Snooping#Result-2
Regards,
Linus
---
Changelog v10:
- PATCH 1/3: removed, already applied
- PATCH 0/2: cover letter: removed test time period and "v5" reference
- PATCH 1/2:
- fixed kerneldoc in batadv_dat_hash_free(),
replaced "bat_priv" with "hash"
- added missing kerneldoc in batadv_dat_snoop_incoming_arp_reply()
for is_dht_put
- rebase to current main branch:
- adopted new bat_priv kernel doc description,
"soft interface" -> "mesh interface"
- adopted variable rename from soft_iface to mesh_iface
Changelog v9:
- PATCH 1/3:
- fixed typo in a comment: ENOENT -> ENONET
Changelog v8:
- PATCH 1/3:
- fixing / cleaning up includes
- fixing function kernel doc titles
- fixing bugs introduced in v7 in the error handling of
batadv_orig_dump() and batadv_neigh_dump(), using a goto
pattern with more explicit labels
Changelog v7:
- adding PATCH 1/3 to add the batadv_netlink_get_softif() wrapper to
reduce the amount of duplicate code, both in the current code base
but also for the next PATCH 2/3
Changelog v6:
- removed renaming+deprecation of BATADV_P_DAT_CACHE_REPLY in PATCH 1/2
- small commit message rewording in PATCH 1/2
Changelog v5:
- rebased to current main branch
-> removed now obsolete debugfs code
Changelog v4:
- rebased to: acfc9a214d01695
("batman-adv: genetlink: make policy common to family")
Changelog v3:
formerly:
"batman-adv: Increase purge timeout on DAT DHT candidates"
https://patchwork.open-mesh.org/patch/17728/
- fixed the potential jiffies overflow and jiffies initialization
issues by replacing the last_dht_update timeout variable with
a split of DAT cache and DAT DHT into two separate hash tables
-> instead of maintaining two timeouts in one DAT entry two DAT
entries are created and maintained in their respective DAT
cache and DAT DHT hash tables
Changelog v2:
formerly:
"batman-adv: Increase DHCP snooped DAT entry purge timeout in DHT"
(https://patchwork.open-mesh.org/patch/17364/)
- removed the extended timeouts flag in the DHT-PUT messages introduced
in v1 again
- removed DHCP dependency
Linus Lüssing (2):
batman-adv: split DAT cache into DAT cache and DAT DHT
batman-adv: increase DAT DHT timeout
include/uapi/linux/batman_adv.h | 5 +
net/batman-adv/distributed-arp-table.c | 337 +++++++++++++++++++------
net/batman-adv/distributed-arp-table.h | 13 +-
net/batman-adv/main.h | 3 +-
net/batman-adv/netlink.c | 5 +
net/batman-adv/routing.c | 7 +-
net/batman-adv/types.h | 7 +-
7 files changed, 288 insertions(+), 89 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [batadv,v10 1/2] batman-adv: split DAT cache into DAT cache and DAT DHT
2026-09-18 22:55 [batadv,v10 0/2] batman-adv: increase DAT DHT timeout Linus Lüssing
@ 2026-09-18 22:55 ` Linus Lüssing
2026-09-21 1:07 ` Linus Lüssing
2026-09-18 22:55 ` [batadv,v10 2/2] batman-adv: increase DAT DHT timeout Linus Lüssing
1 sibling, 1 reply; 4+ messages in thread
From: Linus Lüssing @ 2026-09-18 22:55 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Linus Lüssing
Similar to the translation table split the (mostly) locally maintained
DAT cache and the DAT DHT concepts into two separate tables.
This eases the monitoring and debugging regarding the origin of DAT
entries. And allows to apply differing properties to entries in the DAT
cache and DAT DHT in the future, like distinct timeouts.
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
include/uapi/linux/batman_adv.h | 5 +
net/batman-adv/distributed-arp-table.c | 319 +++++++++++++++++++------
net/batman-adv/distributed-arp-table.h | 13 +-
net/batman-adv/netlink.c | 5 +
net/batman-adv/routing.c | 7 +-
net/batman-adv/types.h | 7 +-
6 files changed, 271 insertions(+), 85 deletions(-)
diff --git a/include/uapi/linux/batman_adv.h b/include/uapi/linux/batman_adv.h
index 936bcac270b5..7379c1509f77 100644
--- a/include/uapi/linux/batman_adv.h
+++ b/include/uapi/linux/batman_adv.h
@@ -613,6 +613,11 @@ enum batadv_nl_commands {
*/
BATADV_CMD_SET_VLAN,
+ /**
+ * @BATADV_CMD_GET_DAT_DHT: Query list of DAT DHT entries
+ */
+ BATADV_CMD_GET_DAT_DHT,
+
/* add new commands above here */
/**
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index a4be5b2a87d7..d2a599c9651d 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -211,17 +211,17 @@ static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
}
/**
- * __batadv_dat_purge() - delete entries from the DAT local storage
- * @bat_priv: the bat priv with all the mesh interface information
+ * __batadv_dat_purge() - delete entries from a DAT hash table
+ * @hash: the hash table to delete from
* @to_purge: function in charge to decide whether an entry has to be purged or
* not. This function takes the dat_entry as argument and has to
* returns a boolean value: true is the entry has to be deleted,
* false otherwise
*
- * Loops over each entry in the DAT local storage and deletes it if and only if
+ * Loops over each entry in a DAT hash table and deletes it if and only if
* the to_purge function passed as argument returns true.
*/
-static void __batadv_dat_purge(struct batadv_priv *bat_priv,
+static void __batadv_dat_purge(struct batadv_hashtable *hash,
bool (*to_purge)(struct batadv_dat_entry *))
{
spinlock_t *list_lock; /* protects write access to the hash lists */
@@ -230,12 +230,12 @@ static void __batadv_dat_purge(struct batadv_priv *bat_priv,
struct hlist_head *head;
u32 i;
- if (!bat_priv->dat.hash)
+ if (!hash)
return;
- for (i = 0; i < bat_priv->dat.hash->size; i++) {
- head = &bat_priv->dat.hash->table[i];
- list_lock = &bat_priv->dat.hash->list_locks[i];
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+ list_lock = &hash->list_locks[i];
spin_lock_bh(list_lock);
hlist_for_each_entry_safe(dat_entry, node_tmp, head,
@@ -268,7 +268,8 @@ static void batadv_dat_purge(struct work_struct *work)
priv_dat = container_of(delayed_work, struct batadv_priv_dat, work);
bat_priv = container_of(priv_dat, struct batadv_priv, dat);
- __batadv_dat_purge(bat_priv, batadv_dat_to_purge);
+ __batadv_dat_purge(bat_priv->dat.cache_hash, batadv_dat_to_purge);
+ __batadv_dat_purge(bat_priv->dat.dht_hash, batadv_dat_to_purge);
batadv_dat_start_timer(bat_priv);
}
@@ -387,19 +388,17 @@ static u32 batadv_hash_dat(const void *data, u32 size)
}
/**
- * batadv_dat_entry_hash_find() - look for a given dat_entry in the local hash
- * table
- * @bat_priv: the bat priv with all the mesh interface information
+ * batadv_dat_entry_hash_find() - look for a given dat_entry in a hash table
+ * @hash: the hash table to search in
* @ip: search key
* @vid: VLAN identifier
*
* Return: the dat_entry if found, NULL otherwise.
*/
static struct batadv_dat_entry *
-batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
+batadv_dat_entry_hash_find(struct batadv_hashtable *hash, __be32 ip,
unsigned short vid)
{
- struct batadv_hashtable *hash = bat_priv->dat.hash;
struct batadv_dat_entry *dat_entry_tmp = NULL;
struct batadv_dat_entry *dat_entry;
struct batadv_dat_entry to_find;
@@ -434,29 +433,64 @@ batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip,
return dat_entry_tmp;
}
+/**
+ * batadv_dat_cache_entry_find() - look for a given dat_entry in the DAT cache
+ * @bat_priv: the bat priv with all the mesh interface information
+ * @ip: search key
+ * @vid: VLAN identifier
+ *
+ * Return: the dat_entry if found, NULL otherwise.
+ */
+static inline struct batadv_dat_entry *
+batadv_dat_cache_entry_find(struct batadv_priv *bat_priv, __be32 ip,
+ unsigned short vid)
+{
+ return batadv_dat_entry_hash_find(bat_priv->dat.cache_hash, ip, vid);
+}
+
+/**
+ * batadv_dat_dht_entry_find() - look for a given dat_entry in the DAT DHT
+ * @bat_priv: the bat priv with all the mesh interface information
+ * @ip: search key
+ * @vid: VLAN identifier
+ *
+ * Return: the dat_entry if found, NULL otherwise.
+ */
+static inline struct batadv_dat_entry *
+batadv_dat_dht_entry_find(struct batadv_priv *bat_priv, __be32 ip,
+ unsigned short vid)
+{
+ return batadv_dat_entry_hash_find(bat_priv->dat.dht_hash, ip, vid);
+}
+
/**
* batadv_dat_entry_add() - add a new dat entry or update it if already exists
* @bat_priv: the bat priv with all the mesh interface information
+ * @hash: the hash table to add to
* @ip: ipv4 to add/edit
* @mac_addr: mac address to assign to the given ipv4
* @vid: VLAN identifier
+ * @tablename: the name of the hash table to add to
*/
-static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
- u8 *mac_addr, unsigned short vid)
+static void
+batadv_dat_entry_add(struct batadv_priv *bat_priv,
+ struct batadv_hashtable *hash, __be32 ip,
+ u8 *mac_addr, unsigned short vid,
+ const char *tablename)
{
u64 u64_mac = ether_addr_to_u64(mac_addr);
struct batadv_dat_entry *dat_entry;
int hash_added;
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip, vid);
+ dat_entry = batadv_dat_entry_hash_find(hash, ip, vid);
/* if this entry is already known, just update it */
if (dat_entry) {
atomic64_set(&dat_entry->mac_addr, u64_mac);
dat_entry->last_update = jiffies;
batadv_dbg(BATADV_DBG_DAT, bat_priv,
- "Entry updated: %pI4 %pM (vid: %d)\n",
- &dat_entry->ip, mac_addr,
+ "Entry updated in %s: %pI4 %pM (vid: %d)\n",
+ tablename, &dat_entry->ip, mac_addr,
batadv_print_vid(vid));
goto out;
}
@@ -472,7 +506,7 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
kref_init(&dat_entry->refcount);
kref_get(&dat_entry->refcount);
- hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
+ hash_added = batadv_hash_add(hash, batadv_compare_dat,
batadv_hash_dat, dat_entry,
&dat_entry->hash_entry);
@@ -482,13 +516,44 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
goto out;
}
- batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM (vid: %d)\n",
- &dat_entry->ip, mac_addr, batadv_print_vid(vid));
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "New entry added in %s: %pI4 %pM (vid: %d)\n",
+ tablename, &dat_entry->ip, mac_addr, batadv_print_vid(vid));
out:
batadv_dat_entry_put(dat_entry);
}
+/**
+ * batadv_dat_cache_entry_add() - add or update dat_entry in the DAT cache
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip: ipv4 to add/edit
+ * @mac_addr: mac address to assign to the given ipv4
+ * @vid: VLAN identifier
+ */
+static inline void
+batadv_dat_cache_entry_add(struct batadv_priv *bat_priv, __be32 ip,
+ u8 *mac_addr, unsigned short vid)
+{
+ batadv_dat_entry_add(bat_priv, bat_priv->dat.cache_hash, ip, mac_addr,
+ vid, "cache");
+}
+
+/**
+ * batadv_dat_dht_entry_add() - add or update dat_entry in the DAT DHT
+ * @bat_priv: the bat priv with all the mesh interface information
+ * @ip: ipv4 to add/edit
+ * @mac_addr: mac address to assign to the given ipv4
+ * @vid: VLAN identifier
+ */
+static inline void
+batadv_dat_dht_entry_add(struct batadv_priv *bat_priv, __be32 ip,
+ u8 *mac_addr, unsigned short vid)
+{
+ batadv_dat_entry_add(bat_priv, bat_priv->dat.dht_hash, ip, mac_addr,
+ vid, "dht");
+}
+
#ifdef CONFIG_BATMAN_ADV_DEBUG
/**
@@ -870,19 +935,57 @@ static void batadv_dat_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv,
}
/**
- * batadv_dat_hash_free() - free the local DAT hash table
- * @bat_priv: the bat priv with all the mesh interface information
+ * batadv_dat_hash_free() - free a DAT hash table
+ * @hash: the hash table to free
*/
-static void batadv_dat_hash_free(struct batadv_priv *bat_priv)
+static void batadv_dat_hash_free(struct batadv_hashtable **hash)
{
- if (!bat_priv->dat.hash)
+ if (!(*hash))
return;
- __batadv_dat_purge(bat_priv, NULL);
+ __batadv_dat_purge(*hash, NULL);
- batadv_hash_destroy(bat_priv->dat.hash);
+ batadv_hash_destroy(*hash);
- bat_priv->dat.hash = NULL;
+ *hash = NULL;
+}
+
+/**
+ * batadv_dat_cache_hash_init() - initialise the DAT cache hash table
+ * @bat_priv: the bat priv with all the mesh interface information
+ *
+ * Return: 0 in case of success, a negative error code otherwise
+ */
+static int batadv_dat_cache_hash_init(struct batadv_priv *bat_priv)
+{
+ if (bat_priv->dat.cache_hash)
+ return 0;
+
+ bat_priv->dat.cache_hash = batadv_hash_new(1024);
+
+ if (!bat_priv->dat.cache_hash)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * batadv_dat_dht_hash_init() - initialise the DAT DHT hash table
+ * @bat_priv: the bat priv with all the mesh interface information
+ *
+ * Return: 0 in case of success, a negative error code otherwise
+ */
+static int batadv_dat_dht_hash_init(struct batadv_priv *bat_priv)
+{
+ if (bat_priv->dat.dht_hash)
+ return 0;
+
+ bat_priv->dat.dht_hash = batadv_hash_new(1024);
+
+ if (!bat_priv->dat.dht_hash)
+ return -ENOMEM;
+
+ return 0;
}
/**
@@ -893,13 +996,15 @@ static void batadv_dat_hash_free(struct batadv_priv *bat_priv)
*/
int batadv_dat_init(struct batadv_priv *bat_priv)
{
- if (bat_priv->dat.hash)
- return 0;
+ int ret;
- bat_priv->dat.hash = batadv_hash_new(1024);
+ ret = batadv_dat_cache_hash_init(bat_priv);
+ if (ret < 0)
+ return ret;
- if (!bat_priv->dat.hash)
- return -ENOMEM;
+ ret = batadv_dat_dht_hash_init(bat_priv);
+ if (ret < 0)
+ return ret;
INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge);
batadv_dat_start_timer(bat_priv);
@@ -922,23 +1027,25 @@ void batadv_dat_free(struct batadv_priv *bat_priv)
disable_delayed_work_sync(&bat_priv->dat.work);
- batadv_dat_hash_free(bat_priv);
+ batadv_dat_hash_free(&bat_priv->dat.cache_hash);
+ batadv_dat_hash_free(&bat_priv->dat.dht_hash);
}
/**
- * batadv_dat_cache_dump_entry() - dump one entry of the DAT cache table to a
- * netlink socket
+ * batadv_dat_dump_entry() - dump one entry of a DAT hash table to a netlink
+ * socket
* @msg: buffer for the message
* @portid: netlink port
* @cb: Control block containing additional options
* @dat_entry: entry to dump
+ * @cmd: generic netlink command
*
* Return: 0 or error code.
*/
static int
-batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid,
- struct netlink_callback *cb,
- struct batadv_dat_entry *dat_entry)
+batadv_dat_dump_entry(struct sk_buff *msg, u32 portid,
+ struct netlink_callback *cb,
+ struct batadv_dat_entry *dat_entry, u8 cmd)
{
u8 mac[ETH_ALEN] __aligned(2);
u64 u64_mac;
@@ -946,8 +1053,7 @@ batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid,
void *hdr;
hdr = genlmsg_put(msg, portid, cb->nlh->nlmsg_seq,
- &batadv_netlink_family, NLM_F_MULTI,
- BATADV_CMD_GET_DAT_CACHE);
+ &batadv_netlink_family, NLM_F_MULTI, cmd);
if (!hdr)
return -ENOBUFS;
@@ -971,22 +1077,23 @@ batadv_dat_cache_dump_entry(struct sk_buff *msg, u32 portid,
}
/**
- * batadv_dat_cache_dump_bucket() - dump one bucket of the DAT cache table to
- * a netlink socket
+ * batadv_dat_dump_bucket() - dump one bucket of a DAT hash table to a netlink
+ * socket
* @msg: buffer for the message
* @portid: netlink port
* @cb: Control block containing additional options
* @hash: hash to dump
* @bucket: bucket index to dump
* @idx_skip: How many entries to skip
+ * @cmd: generic netlink command
*
* Return: 0 or error code.
*/
static int
-batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid,
- struct netlink_callback *cb,
- struct batadv_hashtable *hash, unsigned int bucket,
- int *idx_skip)
+batadv_dat_dump_bucket(struct sk_buff *msg, u32 portid,
+ struct netlink_callback *cb,
+ struct batadv_hashtable *hash, unsigned int bucket,
+ int *idx_skip, u8 cmd)
{
struct batadv_dat_entry *dat_entry;
int idx = 0;
@@ -998,7 +1105,7 @@ batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid,
if (idx < *idx_skip)
goto skip;
- if (batadv_dat_cache_dump_entry(msg, portid, cb, dat_entry)) {
+ if (batadv_dat_dump_entry(msg, portid, cb, dat_entry, cmd)) {
spin_unlock_bh(&hash->list_locks[bucket]);
*idx_skip = idx;
@@ -1014,30 +1121,26 @@ batadv_dat_cache_dump_bucket(struct sk_buff *msg, u32 portid,
}
/**
- * batadv_dat_cache_dump() - dump DAT cache table to a netlink socket
+ * batadv_dat_dump() - dump a DAT hash table to a netlink socket
+ * @bat_priv: the bat priv with all the mesh interface information
* @msg: buffer for the message
* @cb: callback structure containing arguments
+ * @hash: the hash table to dump from
+ * @cmd: generic netlink command
*
* Return: message length.
*/
-int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
+static int
+batadv_dat_dump(struct batadv_priv *bat_priv, struct sk_buff *msg,
+ struct netlink_callback *cb, struct batadv_hashtable *hash,
+ u8 cmd)
{
- struct batadv_hard_iface *primary_if = NULL;
int portid = NETLINK_CB(cb->skb).portid;
- struct net_device *mesh_iface;
- struct batadv_hashtable *hash;
- struct batadv_priv *bat_priv;
+ struct batadv_hard_iface *primary_if;
int bucket = cb->args[0];
int idx = cb->args[1];
int ret = 0;
- mesh_iface = batadv_netlink_get_meshif(cb);
- if (IS_ERR(mesh_iface))
- return PTR_ERR(mesh_iface);
-
- bat_priv = netdev_priv(mesh_iface);
- hash = bat_priv->dat.hash;
-
primary_if = batadv_primary_if_get_selected(bat_priv);
if (!primary_if || primary_if->if_status != BATADV_IF_ACTIVE) {
ret = -ENOENT;
@@ -1045,8 +1148,8 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
}
while (bucket < hash->size) {
- if (batadv_dat_cache_dump_bucket(msg, portid, cb, hash, bucket,
- &idx))
+ if (batadv_dat_dump_bucket(msg, portid, cb, hash, bucket, &idx,
+ cmd))
break;
bucket++;
@@ -1061,8 +1164,58 @@ int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
out:
batadv_hardif_put(primary_if);
+ return ret;
+}
+
+/**
+ * batadv_dat_cache_dump() - dump the DAT cache table to a netlink socket
+ * @msg: buffer for the message
+ * @cb: callback structure containing arguments
+ *
+ * Return: Message length on success or a negative error number otherwise.
+ */
+int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
+{
+ struct net_device *mesh_iface;
+ struct batadv_priv *bat_priv;
+ int ret;
+
+ mesh_iface = batadv_netlink_get_meshif(cb);
+ if (IS_ERR(mesh_iface))
+ return PTR_ERR(mesh_iface);
+
+ bat_priv = netdev_priv(mesh_iface);
+
+ ret = batadv_dat_dump(bat_priv, msg, cb, bat_priv->dat.cache_hash,
+ BATADV_CMD_GET_DAT_CACHE);
+
dev_put(mesh_iface);
+ return ret;
+}
+/**
+ * batadv_dat_dht_dump() - dump the DAT DHT table to a netlink socket
+ * @msg: buffer for the message
+ * @cb: callback structure containing arguments
+ *
+ * Return: Message length on success or a negative error number otherwise.
+ */
+int batadv_dat_dht_dump(struct sk_buff *msg, struct netlink_callback *cb)
+{
+ struct net_device *mesh_iface;
+ struct batadv_priv *bat_priv;
+ int ret;
+
+ mesh_iface = batadv_netlink_get_meshif(cb);
+ if (IS_ERR(mesh_iface))
+ return PTR_ERR(mesh_iface);
+
+ bat_priv = netdev_priv(mesh_iface);
+
+ ret = batadv_dat_dump(bat_priv, msg, cb, bat_priv->dat.dht_hash,
+ BATADV_CMD_GET_DAT_DHT);
+
+ dev_put(mesh_iface);
return ret;
}
@@ -1269,9 +1422,9 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
hw_src = batadv_arp_hw_src(skb, hdr_size);
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_cache_entry_add(bat_priv, ip_src, hw_src, vid);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
+ dat_entry = batadv_dat_cache_entry_find(bat_priv, ip_dst, vid);
if (dat_entry) {
u64_mac = atomic64_read(&dat_entry->mac_addr);
u64_to_ether_addr(u64_mac, mac);
@@ -1374,9 +1527,9 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing incoming ARP REQUEST");
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_cache_entry_add(bat_priv, ip_src, hw_src, vid);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
+ dat_entry = batadv_dat_dht_entry_find(bat_priv, ip_dst, vid);
if (!dat_entry)
goto out;
@@ -1443,8 +1596,8 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
hw_dst = batadv_arp_hw_dst(skb, hdr_size);
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ batadv_dat_cache_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_cache_entry_add(bat_priv, ip_dst, hw_dst, vid);
/* Send the ARP reply to the candidates for both the IP addresses that
* the node obtained from the ARP reply
@@ -1461,6 +1614,8 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
* @bat_priv: the bat priv with all the mesh interface information
* @skb: packet to check
* @hdr_size: size of the encapsulation header
+ * @is_dht_put: ARP reply is part of a unicast 4addr DHT PUT packet and should
+ * not only update our local DAT cache but also our local DAT DHT
*
* Warning: This function may reallocate the skb data buffer via
* batadv_dat_get_vid()/... Any pointer into the skb data (e.g. obtained
@@ -1471,7 +1626,8 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
* packet has to be delivered to the interface
*/
bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
- struct sk_buff *skb, int hdr_size)
+ struct sk_buff *skb, int hdr_size,
+ bool is_dht_put)
{
struct batadv_dat_entry *dat_entry = NULL;
u8 mac[ETH_ALEN] __aligned(2);
@@ -1504,13 +1660,18 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
hw_dst = batadv_arp_hw_dst(skb, hdr_size);
ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+ if (is_dht_put) {
+ batadv_dat_dht_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_dht_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ }
+
/* If ip_dst is already in cache and has the right mac address,
* drop this frame if this ARP reply is destined for us because it's
* most probably an ARP reply generated by another node of the DHT.
* We have most probably received already a reply earlier. Delivering
* this frame would lead to doubled receive of an ARP reply.
*/
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_src, vid);
+ dat_entry = batadv_dat_cache_entry_find(bat_priv, ip_src, vid);
if (dat_entry) {
u64_mac = atomic64_read(&dat_entry->mac_addr);
u64_to_ether_addr(u64_mac, mac);
@@ -1527,8 +1688,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
/* Update our internal cache with both the IP addresses the node got
* within the ARP reply
*/
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ batadv_dat_cache_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_cache_entry_add(bat_priv, ip_dst, hw_dst, vid);
if (dropped)
goto out;
@@ -1782,8 +1943,8 @@ static void batadv_dat_put_dhcp(struct batadv_priv *bat_priv, u8 *chaddr,
skb_set_network_header(skb, ETH_HLEN);
- batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid);
- batadv_dat_entry_add(bat_priv, ip_dst, hw_dst, vid);
+ batadv_dat_cache_entry_add(bat_priv, yiaddr, chaddr, vid);
+ batadv_dat_cache_entry_add(bat_priv, ip_dst, hw_dst, vid);
batadv_dat_forward_data(bat_priv, skb, yiaddr, vid,
BATADV_P_DAT_DHT_PUT);
@@ -1918,8 +2079,8 @@ void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv,
ethhdr = (struct ethhdr *)(skb->data + hdr_size);
hw_src = ethhdr->h_source;
- batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid);
- batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
+ batadv_dat_cache_entry_add(bat_priv, yiaddr, chaddr, vid);
+ batadv_dat_cache_entry_add(bat_priv, ip_src, hw_src, vid);
batadv_dbg(BATADV_DBG_DAT, bat_priv,
"Snooped from incoming DHCPACK (server address): %pI4, %pM (vid: %i)\n",
@@ -1972,7 +2133,7 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
goto out;
ip_dst = batadv_arp_ip_dst(forw_packet->skb, hdr_size);
- dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
+ dat_entry = batadv_dat_cache_entry_find(bat_priv, ip_dst, vid);
/* check if the node already got this entry */
if (!dat_entry) {
batadv_dbg(BATADV_DBG_DAT, bat_priv,
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h
index e7b75e82eb1d..ad81b7db921e 100644
--- a/net/batman-adv/distributed-arp-table.h
+++ b/net/batman-adv/distributed-arp-table.h
@@ -31,7 +31,8 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb);
bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
- struct sk_buff *skb, int hdr_size);
+ struct sk_buff *skb, int hdr_size,
+ bool is_dht_put);
void batadv_dat_snoop_outgoing_dhcp_ack(struct batadv_priv *bat_priv,
struct sk_buff *skb,
__be16 proto,
@@ -74,6 +75,7 @@ batadv_dat_init_own_addr(struct batadv_priv *bat_priv,
int batadv_dat_init(struct batadv_priv *bat_priv);
void batadv_dat_free(struct batadv_priv *bat_priv);
int batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb);
+int batadv_dat_dht_dump(struct sk_buff *msg, struct netlink_callback *cb);
/**
* batadv_dat_inc_counter() - increment the correct DAT packet counter
@@ -126,7 +128,8 @@ batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
static inline bool
batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
- struct sk_buff *skb, int hdr_size)
+ struct sk_buff *skb, int hdr_size,
+ bool is_dht_put)
{
return false;
}
@@ -176,6 +179,12 @@ batadv_dat_cache_dump(struct sk_buff *msg, struct netlink_callback *cb)
return -EOPNOTSUPP;
}
+static inline int
+batadv_dat_dht_dump(struct sk_buff *msg, struct netlink_callback *cb)
+{
+ return -EOPNOTSUPP;
+}
+
static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
u8 subtype)
{
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c
index 1177b3ceaf03..26584e0a2cc8 100644
--- a/net/batman-adv/netlink.c
+++ b/net/batman-adv/netlink.c
@@ -1498,6 +1498,11 @@ static const struct genl_small_ops batadv_netlink_ops[] = {
.flags = GENL_UNS_ADMIN_PERM,
.dumpit = batadv_dat_cache_dump,
},
+ {
+ .cmd = BATADV_CMD_GET_DAT_DHT,
+ .flags = GENL_ADMIN_PERM,
+ .dumpit = batadv_dat_dht_dump,
+ },
{
.cmd = BATADV_CMD_GET_MCAST_FLAGS,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index 6442f5d0cc93..5cf26e8b3257 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -1046,6 +1046,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
struct batadv_orig_node *orig_node = NULL;
int hdr_size = sizeof(*unicast_packet);
enum batadv_subtype subtype;
+ bool is_dht_put = false;
int ret = NET_RX_DROP;
u8 *orig_addr_gw;
u8 *orig_addr;
@@ -1105,6 +1106,8 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
orig_addr = unicast_4addr_packet->src;
orig_node = batadv_orig_hash_find(bat_priv,
orig_addr);
+ } else if (subtype == BATADV_P_DAT_DHT_PUT) {
+ is_dht_put = true;
}
}
@@ -1112,7 +1115,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
hdr_size))
goto rx_success;
if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb,
- hdr_size))
+ hdr_size, is_dht_put))
goto rx_success;
batadv_dat_snoop_incoming_dhcp_ack(bat_priv, skb, hdr_size);
@@ -1353,7 +1356,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size))
goto rx_success;
- if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size))
+ if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size, false))
goto rx_success;
batadv_dat_snoop_incoming_dhcp_ack(bat_priv, skb, hdr_size);
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index c19caa84e692..045727c3adc0 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -1211,8 +1211,11 @@ struct batadv_priv_dat {
/** @addr: node DAT address */
batadv_dat_addr_t addr;
- /** @hash: hashtable representing the local ARP cache */
- struct batadv_hashtable *hash;
+ /** @cache_hash: hashtable representing the local ARP cache */
+ struct batadv_hashtable *cache_hash;
+
+ /** @dht_hash: hashtable representing the local DAT DHT */
+ struct batadv_hashtable *dht_hash;
/** @work: work queue callback item for cache purging */
struct delayed_work work;
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [batadv,v10 2/2] batman-adv: increase DAT DHT timeout
2026-09-18 22:55 [batadv,v10 0/2] batman-adv: increase DAT DHT timeout Linus Lüssing
2026-09-18 22:55 ` [batadv,v10 1/2] batman-adv: split DAT cache into DAT cache and DAT DHT Linus Lüssing
@ 2026-09-18 22:55 ` Linus Lüssing
1 sibling, 0 replies; 4+ messages in thread
From: Linus Lüssing @ 2026-09-18 22:55 UTC (permalink / raw)
To: b.a.t.m.a.n; +Cc: Linus Lüssing
Currently, the DHT_GET messages of the DAT will likely be left
unanswered due to the following issues:
When a node has a matching DAT Cache entry for a local ARP Request then
this node will answer it directly with the information provided by the
cache. This however, will likely lead to missing ARP Replies from the
original host. Which in turn leads to the DAT DHT not being updated.
Then the local DAT cache entry will time out, triggering a unicasted
DHT_GET. However, as the 5min. timeout has passed, the DAT DHT
candidates will likely have purged their entry, too.
So basically this results in an ARP Request broadcast fallback every
five minutes.
A second issue is that it is quite common that a host which has long
gone offline will be tried to be contacted by another one at some remote
period larger than the current 5min. timeout. This too leads to flooded
ARP Requests.
With this patch the purge timeout for DAT DHT entries is increased to
30min to reduce the number of DAT ARP broadcast fallbacks.
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
net/batman-adv/distributed-arp-table.c | 22 +++++++++++++++++-----
net/batman-adv/main.h | 3 ++-
2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index d2a599c9651d..de1f47183438 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -199,15 +199,27 @@ static void batadv_dat_entry_put(struct batadv_dat_entry *dat_entry)
}
/**
- * batadv_dat_to_purge() - check whether a dat_entry has to be purged or not
+ * batadv_dat_cache_to_purge() - check if a cache entry has to be purged or not
* @dat_entry: the entry to check
*
* Return: true if the entry has to be purged now, false otherwise.
*/
-static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
+static bool batadv_dat_cache_to_purge(struct batadv_dat_entry *dat_entry)
{
return batadv_has_timed_out(dat_entry->last_update,
- BATADV_DAT_ENTRY_TIMEOUT);
+ BATADV_DAT_CACHE_ENTRY_TIMEOUT);
+}
+
+/**
+ * batadv_dat_dht_to_purge() - check if a DHT entry has to be purged or not
+ * @dat_entry: the entry to check
+ *
+ * Return: true if the entry has to be purged now, false otherwise.
+ */
+static bool batadv_dat_dht_to_purge(struct batadv_dat_entry *dat_entry)
+{
+ return batadv_has_timed_out(dat_entry->last_update,
+ BATADV_DAT_DHT_ENTRY_TIMEOUT);
}
/**
@@ -268,8 +280,8 @@ static void batadv_dat_purge(struct work_struct *work)
priv_dat = container_of(delayed_work, struct batadv_priv_dat, work);
bat_priv = container_of(priv_dat, struct batadv_priv, dat);
- __batadv_dat_purge(bat_priv->dat.cache_hash, batadv_dat_to_purge);
- __batadv_dat_purge(bat_priv->dat.dht_hash, batadv_dat_to_purge);
+ __batadv_dat_purge(bat_priv->dat.cache_hash, batadv_dat_cache_to_purge);
+ __batadv_dat_purge(bat_priv->dat.dht_hash, batadv_dat_dht_to_purge);
batadv_dat_start_timer(bat_priv);
}
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h
index e738758ee4a7..17af6322e157 100644
--- a/net/batman-adv/main.h
+++ b/net/batman-adv/main.h
@@ -36,7 +36,8 @@
#define BATADV_TT_WORK_PERIOD 5000 /* 5 seconds */
#define BATADV_ORIG_WORK_PERIOD 1000 /* 1 second */
#define BATADV_MCAST_WORK_PERIOD 500 /* 0.5 seconds */
-#define BATADV_DAT_ENTRY_TIMEOUT (5 * 60000) /* 5 mins in milliseconds */
+#define BATADV_DAT_CACHE_ENTRY_TIMEOUT (5 * 60000) /* 5 mins in milliseconds */
+#define BATADV_DAT_DHT_ENTRY_TIMEOUT (30 * 60000) /* 30 mins in milliseconds */
/* sliding packet range of received originator messages in sequence numbers
* (should be a multiple of our word size)
*/
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [batadv,v10 1/2] batman-adv: split DAT cache into DAT cache and DAT DHT
2026-09-18 22:55 ` [batadv,v10 1/2] batman-adv: split DAT cache into DAT cache and DAT DHT Linus Lüssing
@ 2026-09-21 1:07 ` Linus Lüssing
0 siblings, 0 replies; 4+ messages in thread
From: Linus Lüssing @ 2026-09-21 1:07 UTC (permalink / raw)
To: b.a.t.m.a.n
tl;dr: One of the four suggestions makes sense to me. For 1(.5)
other points don't make sense to me / are overlooking an aspect, imo.
For the remaining points I don't think they are a big issue, or at least
for now not worth the extra complexity / refactoring work needed?
On Fri, Sep 18, 2026 at 11:11:00PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] batadv: incomplete DAT hash split breaks DHCP snooping and broadcasts
> --
>
> commit 40cf52e0667d2a02a686b866fe2dc385205cdc83
> Author: Linus Lüssing <linus.luessing@c0d3.blue>
>
> batman-adv: split DAT cache into DAT cache and DAT DHT
>
> This commit separates the locally maintained DAT cache and the DAT DHT into
> two distinct hash tables. This split is intended to ease monitoring and
> allow differing properties for cache vs DHT entries.
>
> > diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
> > index a4be5b2a87d7a..d2a599c9651d7 100644
> > --- a/net/batman-adv/distributed-arp-table.c
> > +++ b/net/batman-adv/distributed-arp-table.c
>
> [ ... ]
>
> > @@ -1421,9 +1421,9 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
> > hw_src = batadv_arp_hw_src(skb, hdr_size);
> > ip_dst = batadv_arp_ip_dst(skb, hdr_size);
> >
> > - batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
> > + batadv_dat_cache_entry_add(bat_priv, ip_src, hw_src, vid);
> >
> > - dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
> > + dat_entry = batadv_dat_cache_entry_find(bat_priv, ip_dst, vid);
> > if (dat_entry) {
> > u64_mac = atomic64_read(&dat_entry->mac_addr);
>
> [Severity: High]
> Does this fail to reply locally if the node has the requested entry in the
> DAT DHT but not the DAT cache?
>
> If the node is the DHT candidate, checking only the cache hash could bypass
> local DHT knowledge and trigger unnecessary remote DHT_GET requests.
I don't think these DHT_GET requests are unnecessary. The local DAT DHT
information might (sometimes) be outdated if due to new or vanishing nodes
we are not one of the three DAT DHT candidates anymore. We should
check on the current DHT candidates instead then in my opinion.
Also a DHT_GET is not that costly (at least compared to a
broadcast flooded ARP request, for instance).
(And thirdly, I'm also wondering if in the future in larger and/or more
dynamic or lossy networks it might make sense to check all
BATADV_P_DAT_CACHE_REPLY answers and choose the MAC address with the
most votes. In case one of the candidates might have an
outdated DHT entry somehow. Or if a candidate were generating
corrupted/bogus replies. We've seen broken, bit-flipping devices
in our networks before.)
>
> [ ... ]
>
> > @@ -1525,9 +1525,9 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
> >
> > batadv_dbg_arp(bat_priv, skb, hdr_size, "Parsing incoming ARP REQUEST");
> >
> > - batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
> > + batadv_dat_cache_entry_add(bat_priv, ip_src, hw_src, vid);
> >
> > - dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
> > + dat_entry = batadv_dat_dht_entry_find(bat_priv, ip_dst, vid);
> > if (!dat_entry)
> > goto out;
>
> [Severity: High]
> Will this miss DHT entries that were improperly stored in the cache hash
> instead of the DHT hash?
>
> If a node's local client sends an ARP reply or if a DHCP DHT_PUT is saved
> in the cache hash, a remote DHT_GET will fail here because
> batadv_dat_snoop_incoming_arp_request only searches the DHT hash.
The short answer would be: In theory valid but not sure if it's an
issue in practice.
If our own, local node is one of the candidates then other nodes might
loose one of the three potential candidates. But for one thing there
are two other candidates and for another depending on the network size
could be rare. In small networks would happen more often, but in
smaller networks with therefore shorter paths just two candidates
should generally be fine, too.
If one were trying to not loose a candidate (but I'm not sure if
that is worth it for now? Or if that should be extra patches
later?):
Option A)
>From batadv_dat_snoop_outgoing_arp_reply() /
batadv_dat_snoop_outgoing_dhcp_ack() always add to local DHT,
regardless if we are an actual DHT candidate.
Downside: From "batctl dd" we wouldn't know anymore if the entry
came from a local addition or via a DHT PUT. (one could maybe add
a flag to a DHT entry though for the batctl visualization...)
Option B)
Make batadv_choose_next_candidate() consider our own, local orig
address, too. Add a BATADV_DAT_CANDIDATE_SELF type.
Make batadv_dat_forward_data() add to the local DHT (without
sending a DHT PUT message to ourself?) if this local orig is a
candidate.
Downside: More rework and extra checks.
Upside: Currently, also before these patches, if the local node is
a candidate then we might do a superfluous DHT_PUSH to a node which
is not actually a candidate from the perspective of other nodes.
Consdering the own node for the DHT ring, too, would solve that as
well.
>
> [ ... ]
>
> > @@ -2077,8 +2077,8 @@ void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv,
> > ethhdr = (struct ethhdr *)(skb->data + hdr_size);
> > hw_src = ethhdr->h_source;
> >
> > - batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid);
> > - batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
> > + batadv_dat_cache_entry_add(bat_priv, yiaddr, chaddr, vid);
> > + batadv_dat_cache_entry_add(bat_priv, ip_src, hw_src, vid);
> >
> > batadv_dbg(BATADV_DBG_DAT, bat_priv,
>
> [Severity: High]
> When a DHT candidate receives a DHT_PUT containing a DHCP packet, should
> these entries be saved in the DHT hash instead of the cache hash?
>
> Saving them to the cache hash unconditionally makes them invisible to
> subsequent DHT_GET queries that only check the DHT hash.
Makes sense, indeed a batadv_dat_snoop_incoming_dhcp_ack() should
behave similar to a batadv_dat_snoop_incoming_arp_reply() which it
currently does not. So if the incoming DHCP ACK came via a
DHT_PUT then I'd change this patch to add to the local DHT, too,
in a v11.
>
> [ ... ]
>
> > @@ -2132,7 +2132,7 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
> > goto out;
> >
> > ip_dst = batadv_arp_ip_dst(forw_packet->skb, hdr_size);
> > - dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
> > + dat_entry = batadv_dat_cache_entry_find(bat_priv, ip_dst, vid);
> > /* check if the node already got this entry */
> > if (!dat_entry) {
>
> [Severity: High]
> Does this fail to drop the broadcast packet if the node knows the answer
> via the DHT hash rather than the cache hash?
>
> By only checking the cache, known DHT entries fail to suppress ARP
> broadcasts, which can lead to unnecessary broadcast storms.
Similar to the first reply: The local DHT entry might be outdated.
A broadcast in that case would seem safer to me.
(Alternatively, with the "Option B)" mentioned above one could
potentially also avoid the broadcast. But still a bit tricky,
as we don't have an orig-node for ourself and therefore can't
simply send a DHT_GET to ourself / can't treat ourself as any
other DAT candidate?)
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260918225549.31315-1-linus.luessing@c0d3.blue?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-09-21 1:07 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-18 22:55 [batadv,v10 0/2] batman-adv: increase DAT DHT timeout Linus Lüssing
2026-09-18 22:55 ` [batadv,v10 1/2] batman-adv: split DAT cache into DAT cache and DAT DHT Linus Lüssing
2026-09-21 1:07 ` Linus Lüssing
2026-09-18 22:55 ` [batadv,v10 2/2] batman-adv: increase DAT DHT timeout Linus Lüssing
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox