From: Andreas Pape <ap...@phoenixcontact.com>

Like in the case of the patch for batadv_bla_tx to handle a race
condition when claiming a mac address for bla, a similar situation
can occur when claiming is triggered via batadv_bla_rx. This patch
solves this with a similar approach as for batadv_bla_tx.

Signed-off-by: Andreas Pape <ap...@phoenixcontact.com>
---
 net/batman-adv/bridge_loop_avoidance.c |   31 ++++++++++++++++++++-----------
 net/batman-adv/translation-table.c     |   26 ++++++++++++++++++++++++++
 net/batman-adv/translation-table.h     |    3 +++
 3 files changed, 49 insertions(+), 11 deletions(-)

diff --git a/net/batman-adv/bridge_loop_avoidance.c 
b/net/batman-adv/bridge_loop_avoidance.c
index d07e89e..cab8980 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1847,19 +1847,28 @@ bool batadv_bla_rx(struct batadv_priv *bat_priv, struct 
sk_buff *skb,
 
        if (!claim) {
                /* possible optimization: race for a claim */
-               /* No claim exists yet, claim it for us!
+               /* Make sure this packet is not looping back
+                * from our own backbone.
                 */
 
-               batadv_dbg(BATADV_DBG_BLA, bat_priv,
-                          "bla_rx(): Unclaimed MAC %pM found. Claim it. Local: 
%s\n",
-                          ethhdr->h_source,
-                          batadv_is_my_client(bat_priv,
-                                              ethhdr->h_source, vid) ?
-                          "yes" : "no");
-               batadv_handle_claim(bat_priv, primary_if,
-                                   primary_if->net_dev->dev_addr,
-                                   ethhdr->h_source, vid);
-               goto allow;
+               if (batadv_tt_local_has_timed_out(bat_priv, ethhdr->h_source,
+                                                 vid, 100)) {
+                       /* No claim exists yet, claim it for us!
+                        */
+                       batadv_dbg(BATADV_DBG_BLA, bat_priv,
+                                  "bla_rx(): Unclaimed MAC %pM found. Claim 
it. Local: %s\n",
+                                  ethhdr->h_source,
+                                  batadv_is_my_client(bat_priv,
+                                                      ethhdr->h_source, vid) ?
+                                  "yes" : "no");
+
+                       batadv_handle_claim(bat_priv, primary_if,
+                                           primary_if->net_dev->dev_addr,
+                                           ethhdr->h_source, vid);
+                       goto allow;
+               } else {
+                       goto handled;
+               }
        }
 
        /* if it is our own claim ... */
diff --git a/net/batman-adv/translation-table.c 
b/net/batman-adv/translation-table.c
index e75b493..b908195 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -4380,3 +4380,29 @@ void batadv_tt_cache_destroy(void)
        kmem_cache_destroy(batadv_tt_req_cache);
        kmem_cache_destroy(batadv_tt_roam_cache);
 }
+
+bool batadv_tt_local_has_timed_out(struct batadv_priv *bat_priv,
+                                  const u8 *addr, unsigned short vid,
+                                  unsigned int timeout)
+{
+       struct batadv_tt_local_entry *tt_local_entry;
+       bool ret = true;
+
+       tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
+       if (!tt_local_entry)
+               goto out;
+       /* Check if the client has been logically deleted (but is kept for
+        * consistency purpose)
+        */
+       if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
+           (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
+               goto out;
+       /* Check that the tt_local_entry has a certain age */
+       if (!batadv_has_timed_out(tt_local_entry->last_seen, timeout))
+               ret = false;
+
+out:
+       if (tt_local_entry)
+               batadv_tt_local_entry_put(tt_local_entry);
+       return ret;
+}
diff --git a/net/batman-adv/translation-table.h 
b/net/batman-adv/translation-table.h
index 411d586..b05d0d8 100644
--- a/net/batman-adv/translation-table.h
+++ b/net/batman-adv/translation-table.h
@@ -65,5 +65,8 @@ bool batadv_tt_global_is_isolated(struct batadv_priv 
*bat_priv,
 
 int batadv_tt_cache_init(void);
 void batadv_tt_cache_destroy(void);
+bool batadv_tt_local_has_timed_out(struct batadv_priv *bat_priv,
+                                  const u8 *addr, unsigned short vid,
+                                  unsigned int timeout);
 
 #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
-- 
1.7.0.4

Reply via email to