From: Andreas Pape apape@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 apape@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_ */