[v2,1/7] batman-adv: prevent multiple ARP replies sent by gateways if dat enabled

Message ID 1456492666-29672-1-git-send-email-apape@phoenixcontact.com (mailing list archive)
State Superseded, archived
Delegated to: Marek Lindner
Headers

Commit Message

Andreas Pape Feb. 26, 2016, 1:17 p.m. UTC
  If dat is enabled it must be made sure that only the backbone gw which has
claimed the remote destination for the ARP request answers the ARP request
directly if the MAC address is known due to the local dat table. This
prevents multiple ARP replies in a common backbone if more than one
gateway already knows the remote mac searched for in the ARP request.

Signed-off-by: Andreas Pape <apape@phoenixcontact.com>
---
 net/batman-adv/bridge_loop_avoidance.c |   59 ++++++++++++++++++++++++++++++++
 net/batman-adv/bridge_loop_avoidance.h |    9 +++++
 net/batman-adv/distributed-arp-table.c |   15 ++++++++
 3 files changed, 83 insertions(+), 0 deletions(-)

--
1.7.0.4



..................................................................
PHOENIX CONTACT ELECTRONICS GmbH

Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont
USt-Id-Nr.: DE811742156
Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
  

Comments

Antonio Quartulli March 2, 2016, 9:36 p.m. UTC | #1
Hi Andreas and thanks for your work on this topic :)

please find some comments inline

On Fri, Feb 26, 2016 at 02:17:46PM +0100, Andreas Pape wrote:

...

> +bool batadv_bla_handle_local_claim(struct batadv_priv *bat_priv,
> +				   u8 *addr, unsigned short vid)
> +{
> +	struct batadv_bla_claim search_claim;
> +	struct batadv_bla_claim *claim = NULL;
> +	struct batadv_hard_iface *primary_if = NULL;
> +	bool ret = true;
> +
> +	if (!atomic_read(&bat_priv->bridge_loop_avoidance))
> +		return ret;
> +
> +	primary_if = batadv_primary_if_get_selected(bat_priv);
> +	if (!primary_if)
> +		goto out;

do you really need this goto here ? I think you can just return ret.

This way you can avoid the blind initialization of claim and primary_if and you
can also remove the 'out' label at all.

> +
> +	/* First look if the mac address is claimed */
> +	ether_addr_copy(search_claim.addr, addr);
> +	search_claim.vid = vid;
> +
> +	claim = batadv_claim_hash_find(bat_priv, &search_claim);
> +
> +	/* If there is a claim and we are not owner of the claim,
> +	 * return false;

no need for the ';' here :)

> +	 */
> +	if (claim) {
> +		if (!batadv_compare_eth(claim->backbone_gw->orig,
> +					primary_if->net_dev->dev_addr))
> +			ret = false;
> +	} else {
> +		/* If there is no claim, claim the device */
> +		batadv_dbg(BATADV_DBG_BLA, bat_priv,
> +			   "Handle claim locally for currently not claimed mac %pM.\n",
> +			   search_claim.addr);
> +
> +		batadv_handle_claim(bat_priv, primary_if,
> +				    primary_if->net_dev->dev_addr, addr, vid);
> +	}
> +

...

> @@ -1000,6 +1001,20 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
>  			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_handle_local_claim(bat_priv,
> +						   dat_entry->mac_addr, vid)) {

I like the approach you take to fix this issue, however I don't understand why
you want to "manually" claim a client.

If I recall correctly, a backbone node
will try to claim a client only if the latter tries to use such node to enter
the LAN.
In this situation the client may never use this backbone to enter the LAN (i.e. bad
metric towards this node) and therefore we are forcing a claim that is not
correct.

Simon, what do you think ?

Imho it is ok to *not* reply to the ARP request is the client is not claimed,
but I don't understand why claiming it now.


> Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont
> USt-Id-Nr.: DE811742156
> Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
> Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
> ___________________________________________________________________
> Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte Informationen. Wenn Sie nicht der richtige Adressat sind oder diese E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren, jegliche anderweitige Verwendung sowie die unbefugte Weitergabe dieser Mail ist nicht gestattet.
> ----------------------------------------------------------------------------------------------------
> This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure, distribution or other use of the material or parts thereof is strictly forbidden.

Are you sure this footer does not conflict with the GPL ? Not sure how important
this is, but I'd rather not send it along with patches.
However, if you use git-send-email this footer should not appear at all.


Cheers,
  
Andreas Pape March 4, 2016, 7:11 a.m. UTC | #2
Hi Antonio,

>
> > +bool batadv_bla_handle_local_claim(struct batadv_priv *bat_priv,
> > +               u8 *addr, unsigned short vid)
> > +{
> > +   struct batadv_bla_claim search_claim;
> > +   struct batadv_bla_claim *claim = NULL;
> > +   struct batadv_hard_iface *primary_if = NULL;
> > +   bool ret = true;
> > +
> > +   if (!atomic_read(&bat_priv->bridge_loop_avoidance))
> > +      return ret;
> > +
> > +   primary_if = batadv_primary_if_get_selected(bat_priv);
> > +   if (!primary_if)
> > +      goto out;
>
> do you really need this goto here ? I think you can just return ret.
>
> This way you can avoid the blind initialization of claim and
> primary_if and you
> can also remove the 'out' label at all.
>
I tried to "copy" the coding style of other functions. But in this case
you are right that this is senseless here.

> > +
> > +   /* First look if the mac address is claimed */
> > +   ether_addr_copy(search_claim.addr, addr);
> > +   search_claim.vid = vid;
> > +
> > +   claim = batadv_claim_hash_find(bat_priv, &search_claim);
> > +
> > +   /* If there is a claim and we are not owner of the claim,
> > +    * return false;
>
> no need for the ';' here :)
>
> > +    */
> > +   if (claim) {
> > +      if (!batadv_compare_eth(claim->backbone_gw->orig,
> > +               primary_if->net_dev->dev_addr))
> > +         ret = false;
> > +   } else {
> > +      /* If there is no claim, claim the device */
> > +      batadv_dbg(BATADV_DBG_BLA, bat_priv,
> > +            "Handle claim locally for currently not claimed mac
%pM.\n",
> > +            search_claim.addr);
> > +
> > +      batadv_handle_claim(bat_priv, primary_if,
> > +                primary_if->net_dev->dev_addr, addr, vid);
> > +   }
> > +
>
> ...
>
> > @@ -1000,6 +1001,20 @@ bool batadv_dat_snoop_outgoing_arp_request
> (struct batadv_priv *bat_priv,
> >           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_handle_local_claim(bat_priv,
> > +                     dat_entry->mac_addr, vid)) {
>
> I like the approach you take to fix this issue, however I don't
understand why
> you want to "manually" claim a client.
>

This was meant to be something like a safety measure. DAT and BLA tables
are not
synchronized and can timeout separately, right? What, if a client address
is still
available in DAT but the client is not claimed anymore. In this case I
think that
claiming the client might be a good idea. I misused DAT here to make sure
that the
claim table is up to date. In my test setup running DAT and BLA on a
number of
backbone gateways I still have problems with looping packets (although
having all
of my patches applied). The problems have become significantly less often
but
from time to time there are still some occurring.
In all of these cases clients from the mesh have been
unclaimed somehow or they have been considered as having roamed to the
backbone
(for an unknown reason the workaround in patch 7/7 did not work in that
case).

> If I recall correctly, a backbone node
> will try to claim a client only if the latter tries to use such node to
enter
> the LAN.
> In this situation the client may never use this backbone to enter
> the LAN (i.e. bad
> metric towards this node) and therefore we are forcing a claim that is
not
> correct.
>
> Simon, what do you think ?
>
> Imho it is ok to *not* reply to the ARP request is the client is not
claimed,
> but I don't understand why claiming it now.
>
>
> > Sitz der Gesellschaft / registered office of the company: 31812 Bad
Pyrmont
> > USt-Id-Nr.: DE811742156
> > Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
> > Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
> > ___________________________________________________________________
> > Diese E-Mail enthält vertrauliche und/oder rechtlich geschützte
> Informationen. Wenn Sie nicht der richtige Adressat sind oder diese
> E-Mail irrtümlich erhalten haben, informieren Sie bitte sofort den
> Absender und vernichten Sie diese Mail. Das unerlaubte Kopieren,
> jegliche anderweitige Verwendung sowie die unbefugte Weitergabe
> dieser Mail ist nicht gestattet.
> >
>
----------------------------------------------------------------------------------------------------
> > This e-mail may contain confidential and/or privileged
> information. If you are not the intended recipient (or have received
> this e-mail in error) please notify the sender immediately and
> destroy this e-mail. Any unauthorized copying, disclosure,
> distribution or other use of the material or parts thereof is
> strictly forbidden.
>
> Are you sure this footer does not conflict with the GPL ? Not sure
> how important
> this is, but I'd rather not send it along with patches.
> However, if you use git-send-email this footer should not appear at all.
>

That's a good point. Indeed, I used git send-email. The footer is
automatically
applied by our e-mail server if e-mails leave our company network.
Therefore
my current problem is that I cannot prevent it. But it says "may contain"
and
"if you are not the intended recipient". In this case it's clear that it
does not
contain any confidential or proprietary information by the gpl nature of
your project
and you (i.e. the mailing list) are the intended recipient.

Thanks for the feedback and kind regards,
Andreas



..................................................................
PHOENIX CONTACT ELECTRONICS GmbH

Sitz der Gesellschaft / registered office of the company: 31812 Bad Pyrmont
USt-Id-Nr.: DE811742156
Amtsgericht Hannover HRB 100528 / district court Hannover HRB 100528
Geschäftsführer / Executive Board: Roland Bent, Dr. Martin Heubeck
  
Simon Wunderlich March 10, 2016, 2:36 p.m. UTC | #3
Hi Andreas,

On Friday 04 March 2016 08:11:05 Andreas Pape wrote:
> Hi Antonio,
> 
> > > +bool batadv_bla_handle_local_claim(struct batadv_priv *bat_priv,
> > > +               u8 *addr, unsigned short vid)
> > > +{
> > > +   struct batadv_bla_claim search_claim;
> > > +   struct batadv_bla_claim *claim = NULL;
> > > +   struct batadv_hard_iface *primary_if = NULL;
> > > +   bool ret = true;
> > > +
> > > +   if (!atomic_read(&bat_priv->bridge_loop_avoidance))
> > > +      return ret;
> > > +
> > > +   primary_if = batadv_primary_if_get_selected(bat_priv);
> > > +   if (!primary_if)
> > > +      goto out;
> > 
> > do you really need this goto here ? I think you can just return ret.
> > 
> > This way you can avoid the blind initialization of claim and
> > primary_if and you
> > can also remove the 'out' label at all.
> 
> I tried to "copy" the coding style of other functions. But in this case
> you are right that this is senseless here.
> 
> > > +
> > > +   /* First look if the mac address is claimed */
> > > +   ether_addr_copy(search_claim.addr, addr);
> > > +   search_claim.vid = vid;
> > > +
> > > +   claim = batadv_claim_hash_find(bat_priv, &search_claim);
> > > +
> > > +   /* If there is a claim and we are not owner of the claim,
> > > +    * return false;
> > 
> > no need for the ';' here :)
> > 
> > > +    */
> > > +   if (claim) {
> > > +      if (!batadv_compare_eth(claim->backbone_gw->orig,
> > > +               primary_if->net_dev->dev_addr))
> > > +         ret = false;
> > > +   } else {
> > > +      /* If there is no claim, claim the device */
> > > +      batadv_dbg(BATADV_DBG_BLA, bat_priv,
> > > +            "Handle claim locally for currently not claimed mac
> 
> %pM.\n",
> 
> > > +            search_claim.addr);
> > > +
> > > +      batadv_handle_claim(bat_priv, primary_if,
> > > +                primary_if->net_dev->dev_addr, addr, vid);
> > > +   }
> > > +
> > 
> > ...
> > 
> > > @@ -1000,6 +1001,20 @@ bool batadv_dat_snoop_outgoing_arp_request
> > 
> > (struct batadv_priv *bat_priv,
> > 
> > >           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_handle_local_claim(bat_priv,
> > > +                     dat_entry->mac_addr, vid)) {
> > 
> > I like the approach you take to fix this issue, however I don't
> 
> understand why
> 
> > you want to "manually" claim a client.
> 
> This was meant to be something like a safety measure. DAT and BLA tables
> are not
> synchronized and can timeout separately, right? What, if a client address
> is still
> available in DAT but the client is not claimed anymore. In this case I
> think that
> claiming the client might be a good idea. I misused DAT here to make sure
> that the
> claim table is up to date. In my test setup running DAT and BLA on a
> number of
> backbone gateways I still have problems with looping packets (although
> having all
> of my patches applied). The problems have become significantly less often
> but
> from time to time there are still some occurring.
> In all of these cases clients from the mesh have been
> unclaimed somehow or they have been considered as having roamed to the
> backbone
> (for an unknown reason the workaround in patch 7/7 did not work in that
> case).

I would agree to Antonio that sending a claim is not necessary, and might 
actually lead to bad choices of the outgoing backbone gateway. After all, at 
this point any "random" backbone gateway may answer to this request, just 
because it has the DAT entry, but maybe may actually not be able to reach the 
client via the mesh.

I think checking if a local claim exists is a good idea, but sending a claim 
is not a good idea - this might introduce effects which will be even more 
complicated to debug.

Cheers,
      Simon
  

Patch

diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
index 0a6c8b8..07dba86 100644
--- a/net/batman-adv/bridge_loop_avoidance.c
+++ b/net/batman-adv/bridge_loop_avoidance.c
@@ -1906,3 +1906,62 @@  out:
 		batadv_hardif_put(primary_if);
 	return 0;
 }
+
+/**
+ * batadv_bla_handle_local_claim - check if address is claimed and claim it
+ *  if it isn't
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: mac address of which the claim status is checked
+ * @vid: the VLAN ID
+ *
+ * addr is checked if this address is claimed by the local device itself.
+ * If the address is not claimed at all, claim it.
+ *
+ * Return: true if bla is disabled or the mac is claimed by the device,
+ * false if the device addr is already claimed by another gateway
+ */
+bool batadv_bla_handle_local_claim(struct batadv_priv *bat_priv,
+				   u8 *addr, unsigned short vid)
+{
+	struct batadv_bla_claim search_claim;
+	struct batadv_bla_claim *claim = NULL;
+	struct batadv_hard_iface *primary_if = NULL;
+	bool ret = true;
+
+	if (!atomic_read(&bat_priv->bridge_loop_avoidance))
+		return ret;
+
+	primary_if = batadv_primary_if_get_selected(bat_priv);
+	if (!primary_if)
+		goto out;
+
+	/* First look if the mac address is claimed */
+	ether_addr_copy(search_claim.addr, addr);
+	search_claim.vid = vid;
+
+	claim = batadv_claim_hash_find(bat_priv, &search_claim);
+
+	/* If there is a claim and we are not owner of the claim,
+	 * return false;
+	 */
+	if (claim) {
+		if (!batadv_compare_eth(claim->backbone_gw->orig,
+					primary_if->net_dev->dev_addr))
+			ret = false;
+	} else {
+		/* If there is no claim, claim the device */
+		batadv_dbg(BATADV_DBG_BLA, bat_priv,
+			   "Handle claim locally for currently not claimed mac %pM.\n",
+			   search_claim.addr);
+
+		batadv_handle_claim(bat_priv, primary_if,
+				    primary_if->net_dev->dev_addr, addr, vid);
+	}
+
+out:
+	if (claim)
+		batadv_claim_put(claim);
+	if (primary_if)
+		batadv_hardif_put(primary_if);
+	return ret;
+}
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h
index 579f0fa..ddf6b9d 100644
--- a/net/batman-adv/bridge_loop_avoidance.h
+++ b/net/batman-adv/bridge_loop_avoidance.h
@@ -46,6 +46,8 @@  void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
 void batadv_bla_status_update(struct net_device *net_dev);
 int batadv_bla_init(struct batadv_priv *bat_priv);
 void batadv_bla_free(struct batadv_priv *bat_priv);
+bool batadv_bla_handle_local_claim(struct batadv_priv *bat_priv, u8 *addr,
+				   unsigned short vid);

 #define BATADV_BLA_CRC_INIT	0
 #else /* ifdef CONFIG_BATMAN_ADV_BLA */
@@ -111,6 +113,13 @@  static inline void batadv_bla_free(struct batadv_priv *bat_priv)
 {
 }

+static inline
+bool batadv_bla_handle_local_claim(struct batadv_priv *bat_priv, u8 *addr,
+				   unsigned short vid)
+{
+	return true;
+}
+
 #endif /* ifdef CONFIG_BATMAN_ADV_BLA */

 #endif /* ifndef _NET_BATMAN_ADV_BLA_H_ */
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index e96d7c7..a9152e7 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -48,6 +48,7 @@ 
 #include "originator.h"
 #include "send.h"
 #include "translation-table.h"
+#include "bridge_loop_avoidance.h"

 static void batadv_dat_purge(struct work_struct *work);

@@ -1000,6 +1001,20 @@  bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
 			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_handle_local_claim(bat_priv,
+						   dat_entry->mac_addr, vid)) {
+			batadv_dbg(BATADV_DBG_DAT, bat_priv,
+				   "Device %pM claimed by another backbone gw. Don't send ARP reply!",
+				   dat_entry->mac_addr);
+			ret = true;
+			goto out;
+		}
+
 		skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
 				     bat_priv->soft_iface, ip_dst, hw_src,
 				     dat_entry->mac_addr, hw_src);