88 lines
3.9 KiB
Diff
88 lines
3.9 KiB
Diff
From: Andreas Pape <APape@phoenixcontact.com>
|
|
Date: Mon, 5 Sep 2016 13:20:26 +0200
|
|
Subject: batman-adv: prevent duplication of ARP replies when DAT is used
|
|
|
|
If none of the backbone gateways in a bla setup has already knowledge of
|
|
the mac address searched for in an incoming ARP request from the backbone
|
|
an address resolution via the DHT of DAT is started. The gateway can send
|
|
several ARP requests to different DHT nodes and therefore can get several
|
|
replies. This patch assures that not all of the possible ARP replies are
|
|
returned to the backbone by checking the local DAT cache of the gateway.
|
|
If there is an entry in the local cache the gateway has already learned
|
|
the requested address and there is no need to forward the additional reply
|
|
to the backbone.
|
|
Furthermore it is checked if this gateway has claimed the source of the ARP
|
|
reply and only forwards it to the backbone if it has claimed the source or
|
|
if there is no claim at all.
|
|
|
|
Signed-off-by: Andreas Pape <apape@phoenixcontact.com>
|
|
Acked-by: Simon Wunderlich <sw@simonwunderlich.de>
|
|
[sven@narfation.org: fix conflicts with current version]
|
|
Signed-off-by: Sven Eckelmann <sven@narfation.org>
|
|
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
|
|
|
|
Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/81e422051cf0403e40615eb306d0ddaaddfee611
|
|
|
|
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
|
|
index 4cfc9672507ba718d975a2f869bb89fc38e0d934..16216532c1d82c09337a9c5e7a4cd5b4ad3ded5d 100644
|
|
--- a/net/batman-adv/distributed-arp-table.c
|
|
+++ b/net/batman-adv/distributed-arp-table.c
|
|
@@ -1205,6 +1205,7 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
|
|
bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
|
|
struct sk_buff *skb, int hdr_size)
|
|
{
|
|
+ struct batadv_dat_entry *dat_entry = NULL;
|
|
u16 type;
|
|
__be32 ip_src, ip_dst;
|
|
u8 *hw_src, *hw_dst;
|
|
@@ -1227,12 +1228,41 @@ 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 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);
|
|
+ if (dat_entry && batadv_compare_eth(hw_src, dat_entry->mac_addr)) {
|
|
+ batadv_dbg(BATADV_DBG_DAT, bat_priv, "Doubled ARP reply removed: ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]; dat_entry: %pM-%pI4\n",
|
|
+ hw_src, &ip_src, hw_dst, &ip_dst,
|
|
+ dat_entry->mac_addr, &dat_entry->ip);
|
|
+ dropped = true;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
/* 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);
|
|
|
|
+ /* If BLA is enabled, only forward ARP replies if we have claimed the
|
|
+ * source of the ARP reply or if no one else of the same backbone has
|
|
+ * already claimed that client. This prevents that different gateways
|
|
+ * to the same backbone all forward the ARP reply leading to multiple
|
|
+ * replies in the backbone.
|
|
+ */
|
|
+ if (!batadv_bla_check_claim(bat_priv, hw_src, vid)) {
|
|
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
|
|
+ "Device %pM claimed by another backbone gw. Drop ARP reply.\n",
|
|
+ hw_src);
|
|
+ dropped = true;
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
/* if this REPLY is directed to a client of mine, let's deliver the
|
|
* packet to the interface
|
|
*/
|
|
@@ -1245,6 +1275,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
|
|
out:
|
|
if (dropped)
|
|
kfree_skb(skb);
|
|
+ if (dat_entry)
|
|
+ batadv_dat_entry_put(dat_entry);
|
|
/* if dropped == false -> deliver to the interface */
|
|
return dropped;
|
|
}
|