From: "Linus Lüssing" <linus.luessing@c0d3.blue>
To: b.a.t.m.a.n@lists.open-mesh.org
Cc: "Linus Lüssing" <linus.luessing@c0d3.blue>
Subject: [batadv,v12 1/5] batman-adv: move local ARP reply code to subfunctions
Date: Sat, 3 Oct 2026 09:26:24 +0200 [thread overview]
Message-ID: <20261003072628.28052-2-linus.luessing@c0d3.blue> (raw)
In-Reply-To: <20261003072628.28052-1-linus.luessing@c0d3.blue>
Shorten the length of batadv_dat_snoop_outgoing_arp_request() by moving
the checks for and generation of a local ARP reply to a new subfunction.
This is also in preparation for reuseability for the DAT cache/DHT
split.
No functional change.
Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
---
net/batman-adv/distributed-arp-table.c | 181 ++++++++++++++-----------
1 file changed, 105 insertions(+), 76 deletions(-)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 74050bffedbc..1a0eb9d9812e 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -738,6 +738,103 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst,
return res;
}
+/**
+ * batadv_dat_arp_create_reply() - create an ARP Reply
+ * @bat_priv: the bat priv with all the mesh interface information
+ * @ip_src: ARP sender IP
+ * @ip_dst: ARP target IP
+ * @hw_src: Ethernet source and ARP sender MAC
+ * @hw_dst: Ethernet destination and ARP target MAC
+ * @vid: VLAN identifier (optional, set to zero otherwise)
+ *
+ * Creates an ARP Reply from the given values, optionally encapsulated in a
+ * VLAN header.
+ *
+ * Return: An skb containing an ARP Reply.
+ */
+static struct sk_buff *
+batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src,
+ __be32 ip_dst, u8 *hw_src, u8 *hw_dst,
+ unsigned short vid)
+{
+ struct sk_buff *skb;
+
+ skb = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_dst, bat_priv->mesh_iface,
+ ip_src, hw_dst, hw_src, hw_dst);
+ if (!skb)
+ return NULL;
+
+ skb_reset_mac_header(skb);
+
+ if (vid & BATADV_VLAN_HAS_TAG)
+ skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
+ vid & VLAN_VID_MASK);
+
+ return skb;
+}
+
+/**
+ * batadv_dat_arp_self_reply() - (maybe) reply to a local ARP request
+ * @bat_priv: the bat priv with all the mesh interface information
+ * @ip_src: ARP request sender IP (and ARP reply target IP)
+ * @ip_dst: ARP request target IP (and ARP reply sender IP)
+ * @hw_src: Ethernet source and ARP sender MAC of ARP request
+ * @hw_dst: Ethernet destination and ARP target MAC of ARP request
+ * @vid: VLAN identifier (optional, set to zero otherwise)
+ * @arp_len: ARP packet size, including ethernet frame
+ *
+ * If the ARP request target is not a local client and if BLA is
+ * enabled and we have BLA claimed this target then generate and reply
+ * with an ARP reply locally on our mesh interface.
+ *
+ * Return: 0 if we transmitted an ARP reply, -ENOMEM if we should have but
+ * could not create an ARP reply (e.g. due to out-of-memory), -EACCSS
+ * otherwise (because the client is local or due to BLA suppression).
+ */
+static int
+batadv_dat_arp_self_reply(struct batadv_priv *bat_priv, __be32 ip_src,
+ __be32 ip_dst, u8 *hw_src, u8 *hw_dst,
+ unsigned short vid, unsigned int arp_len)
+{
+ struct sk_buff *skb;
+
+ /* If the ARP request is destined for a local client the local
+ * client will answer itself. DAT would only generate a
+ * duplicate packet.
+ *
+ * Moreover, if the mesh-interface is enslaved into a bridge, an
+ * additional DAT answer may trigger kernel warnings about
+ * a packet coming from the wrong port.
+ */
+ if (batadv_is_my_client(bat_priv, hw_dst, vid))
+ return -EACCES;
+
+ /* If BLA is enabled, only send ARP replies if we have claimed
+ * the destination for the ARP request or if no one else of
+ * the backbone gws belonging to our backbone has claimed the
+ * destination.
+ */
+ if (!batadv_bla_check_claim(bat_priv, hw_dst, vid)) {
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "Device %pM claimed by another backbone gw. Don't send ARP reply!",
+ hw_dst);
+ return -EACCES;
+ }
+
+ skb = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src, hw_dst,
+ hw_src, vid);
+ if (!skb)
+ return -ENOMEM;
+
+ skb->protocol = eth_type_trans(skb, bat_priv->mesh_iface);
+
+ batadv_inc_counter(bat_priv, BATADV_CNT_RX);
+ batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, arp_len);
+
+ netif_rx(skb);
+ return 0;
+}
+
/**
* batadv_dat_forward_data() - copy and send payload to the selected candidates
* @bat_priv: the bat priv with all the mesh interface information
@@ -1179,41 +1276,6 @@ static unsigned short batadv_dat_get_vid(struct sk_buff *skb, int *hdr_size)
return vid;
}
-/**
- * batadv_dat_arp_create_reply() - create an ARP Reply
- * @bat_priv: the bat priv with all the mesh interface information
- * @ip_src: ARP sender IP
- * @ip_dst: ARP target IP
- * @hw_src: Ethernet source and ARP sender MAC
- * @hw_dst: Ethernet destination and ARP target MAC
- * @vid: VLAN identifier (optional, set to zero otherwise)
- *
- * Creates an ARP Reply from the given values, optionally encapsulated in a
- * VLAN header.
- *
- * Return: An skb containing an ARP Reply.
- */
-static struct sk_buff *
-batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src,
- __be32 ip_dst, u8 *hw_src, u8 *hw_dst,
- unsigned short vid)
-{
- struct sk_buff *skb;
-
- skb = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_dst, bat_priv->mesh_iface,
- ip_src, hw_dst, hw_src, hw_dst);
- if (!skb)
- return NULL;
-
- skb_reset_mac_header(skb);
-
- if (vid & BATADV_VLAN_HAS_TAG)
- skb = vlan_insert_tag(skb, htons(ETH_P_8021Q),
- vid & VLAN_VID_MASK);
-
- return skb;
-}
-
/**
* batadv_dat_snoop_outgoing_arp_request() - snoop the ARP request and try to
* answer using DAT
@@ -1232,10 +1294,9 @@ batadv_dat_arp_create_reply(struct batadv_priv *bat_priv, __be32 ip_src,
bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
struct sk_buff *skb)
{
- struct net_device *mesh_iface = bat_priv->mesh_iface;
struct batadv_dat_entry *dat_entry = NULL;
u8 mac[ETH_ALEN] __aligned(2);
- struct sk_buff *skb_new;
+ unsigned int arp_len;
unsigned short vid;
bool ret = false;
int hdr_size = 0;
@@ -1244,6 +1305,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
u16 type = 0;
u64 u64_mac;
u8 *hw_src;
+ int rep;
if (!READ_ONCE(bat_priv->distributed_arp_table))
goto out;
@@ -1253,6 +1315,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
goto out;
vid = batadv_dat_get_vid(skb, &hdr_size);
+ arp_len = skb->len + ETH_HLEN + hdr_size;
type = batadv_arp_get_type(bat_priv, skb, hdr_size);
/* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast
@@ -1274,46 +1337,12 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
u64_mac = atomic64_read(&dat_entry->mac_addr);
u64_to_ether_addr(u64_mac, mac);
- /* If the ARP request is destined for a local client the local
- * client will answer itself. DAT would only generate a
- * duplicate packet.
- *
- * Moreover, if the mesh-interface is enslaved into a bridge, an
- * additional DAT answer may trigger kernel warnings about
- * a packet coming from the wrong port.
- */
- if (batadv_is_my_client(bat_priv, mac, vid)) {
- ret = true;
- goto out;
- }
-
- /* If BLA is enabled, only send ARP replies if we have claimed
- * the destination for the ARP request or if no one else of
- * the backbone gws belonging to our backbone has claimed the
- * destination.
- */
- if (!batadv_bla_check_claim(bat_priv, mac, vid)) {
+ rep = batadv_dat_arp_self_reply(bat_priv, ip_src, ip_dst,
+ hw_src, mac, vid, arp_len);
+ if (!rep)
batadv_dbg(BATADV_DBG_DAT, bat_priv,
- "Device %pM claimed by another backbone gw. Don't send ARP reply!",
- mac);
- ret = true;
- goto out;
- }
-
- skb_new = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src,
- mac, hw_src, vid);
- if (!skb_new)
- goto out;
-
- skb_new->protocol = eth_type_trans(skb_new, mesh_iface);
-
- batadv_inc_counter(bat_priv, BATADV_CNT_RX);
- batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
- skb->len + ETH_HLEN + hdr_size);
-
- netif_rx(skb_new);
- batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n");
- ret = true;
+ "ARP request replied locally\n");
+ ret = (rep != -ENOMEM);
} else {
/* Send the request to the DHT */
ret = batadv_dat_forward_data(bat_priv, skb, ip_dst, vid,
--
2.55.0
next prev parent reply other threads:[~2026-10-03 7:27 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-03 7:26 [batadv,v12 0/5] batman-adv: increase DAT DHT timeout Linus Lüssing
2026-10-03 7:26 ` Linus Lüssing [this message]
2026-10-03 7:26 ` [batadv,v12 2/5] batman-adv: split DAT cache into DAT cache and DAT DHT Linus Lüssing
2026-10-03 8:04 ` Sven Eckelmann
2026-10-03 7:26 ` [batadv,v12 3/5] batman-adv: increase DAT DHT timeout Linus Lüssing
2026-10-03 7:26 ` [batadv,v12 4/5] batman-adv: avoid superfluous DAT DHT_PUT if self-candidate Linus Lüssing
2026-10-03 7:26 ` [batadv,v12 5/5] batman-adv: avoid superfluous DAT DHT_PUT additions to local DAT Linus Lüssing
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261003072628.28052-2-linus.luessing@c0d3.blue \
--to=linus.luessing@c0d3.blue \
--cc=b.a.t.m.a.n@lists.open-mesh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox