From e0b37ee6d7d82648768dc98a95c3a61d7edf86dd Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape(a)phoenixcontact.com>
Date: Wed, 18 Mar 2015 11:03:22 +0100
Subject: [PATCH] dat optimization test
Signed-off-by: Andreas Pape <apape(a)phoenixcontact.com>
---
bridge_loop_avoidance.c | 60 +++++++++++++++++++++++++++++++++
bridge_loop_avoidance.h | 6 +++
distributed-arp-table.c | 85
++++++++++++++++++++++++++++++++++++++++++++++-
distributed-arp-table.h | 7 +++-
routing.c | 6 ++-
soft-interface.c | 17 ++++++++-
6 files changed, 175 insertions(+), 6 deletions(-)
diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c
index 6927589..bdc8ac9 100644
--- a/bridge_loop_avoidance.c
+++ b/bridge_loop_avoidance.c
@@ -1712,3 +1712,63 @@ out:
batadv_hardif_free_ref(primary_if);
return 0;
}
+
+/**
+ * batadv_check_local_claim
+ * @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
+ *
+ * batadv_check_local_claim:
+ * addr is checked if this address is claimed by the local device itself.
+ * If the address is not claimed at all, claim it.
+ * returns true if bla is disabled or the mac is claimed by the device
+ * returns false if the device addr is already claimed by another gateway
+ */
+bool batadv_check_local_claim(struct batadv_priv *bat_priv, uint8_t
*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)) {
+
+ primary_if = batadv_primary_if_get_selected(bat_priv);
+ if (!primary_if)
+ return ret;
+
+ /* First look if the mac address is is already 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
+ * Question: is this likey to happen?
+ */
+ batadv_dbg(BATADV_DBG_BLA, bat_priv, "No claim
found for %pM. Claim mac for us.\n",
+ search_claim.addr);
+
+ batadv_handle_claim(bat_priv,
+ primary_if,
+ primary_if->net_dev->dev_addr, addr,
+ vid);
+ }
+ }
+
+ if (claim)
+ batadv_claim_free_ref(claim);
+ if (primary_if)
+ batadv_hardif_free_ref(primary_if);
+ return ret;
+}
diff --git a/bridge_loop_avoidance.h b/bridge_loop_avoidance.h
index 43c985d..85f6ecb 100644
--- a/bridge_loop_avoidance.h
+++ b/bridge_loop_avoidance.h
@@ -37,6 +37,7 @@ void batadv_bla_update_orig_address(struct batadv_priv
*bat_priv,
struct batadv_hard_iface *oldif);
int batadv_bla_init(struct batadv_priv *bat_priv);
void batadv_bla_free(struct batadv_priv *bat_priv);
+bool batadv_check_local_claim(struct batadv_priv *bat_priv, uint8_t
*addr, unsigned short vid);
#define BATADV_BLA_CRC_INIT 0
#else /* ifdef CONFIG_BATMAN_ADV_BLA */
@@ -103,6 +104,11 @@ static inline void batadv_bla_free(struct batadv_priv
*bat_priv)
{
}
+bool batadv_check_local_claim(struct batadv_priv *bat_priv, uint8_t
*addr, unsigned short vid)
+{
+ return true;
+}
+
#endif /* ifdef CONFIG_BATMAN_ADV_BLA */
#endif /* ifndef _NET_BATMAN_ADV_BLA_H_ */
diff --git a/distributed-arp-table.c b/distributed-arp-table.c
index 107ad62..69b4484 100644
--- a/distributed-arp-table.c
+++ b/distributed-arp-table.c
@@ -23,6 +23,7 @@
#include "main.h"
#include "hash.h"
#include "distributed-arp-table.h"
+#include "bridge_loop_avoidance.h"
#include "hard-interface.h"
#include "originator.h"
#include "send.h"
@@ -327,6 +328,24 @@ out:
batadv_dat_entry_free_ref(dat_entry);
}
+/**
+ * batadv_dat_entry_check - check and update a dat entry
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip: ipv4 to add/edit
+ * @mac_addr: mac address to assign to the given ipv4
+ * @vid: VLAN identifier
+ *
+ * checks additionally, if dat is enabled. can be called from other
modules.
+ */
+void batadv_dat_entry_check(struct batadv_priv *bat_priv, __be32 ip,
+ uint8_t *mac_addr, unsigned short vid)
+{
+ if(!atomic_read(&bat_priv->distributed_arp_table))
+ return;
+
+ batadv_dat_entry_add(bat_priv, ip, mac_addr, vid);
+}
+
#ifdef CONFIG_BATMAN_ADV_DEBUG
/**
@@ -959,6 +978,16 @@ bool batadv_dat_snoop_outgoing_arp_request(struct
batadv_priv *bat_priv,
ret = true;
goto out;
}
+ /* If BLA is enabled, only send ARP REPLYs if we have
claimed
+ * the destination for the ARP request or if no one else
has already
+ * claimed that client.
+ */
+ if (!batadv_check_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.\n",
+ 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,
@@ -1008,6 +1037,8 @@ bool batadv_dat_snoop_incoming_arp_request(struct
batadv_priv *bat_priv,
uint8_t *hw_src;
struct sk_buff *skb_new;
struct batadv_dat_entry *dat_entry = NULL;
+ struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+ struct batadv_orig_node *orig_node = NULL;
bool ret = false;
unsigned short vid;
int err;
@@ -1031,8 +1062,31 @@ bool batadv_dat_snoop_incoming_arp_request(struct
batadv_priv *bat_priv,
batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid);
dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst, vid);
- if (!dat_entry)
+ if (!dat_entry) {
+
+ /* Check if this is a 4addr unicast DAT_DHT_GET frame from
another
+ * backbone gw. If yes, drop it as this leads to
multiplication of arp requests in bla setups
+ * as long as there is no dat_entry for the answer. In
this case better drop the DHT_GET.
+ * Normal bla code doesn't take care of these packets as
they are tunneled via unicast.
+ */
+ unicast_4addr_packet = (struct batadv_unicast_4addr_packet
*)skb->data;
+ orig_node = batadv_orig_hash_find(bat_priv,
unicast_4addr_packet->src);
+
+ if (orig_node) {
+ if ((unicast_4addr_packet->u.packet_type ==
BATADV_UNICAST_4ADDR) &&
+ (unicast_4addr_packet->subtype ==
BATADV_P_DAT_DHT_GET) &&
+ (batadv_bla_is_backbone_gw(skb,
orig_node, hdr_size))) {
+ batadv_dbg(BATADV_DBG_DAT, bat_priv,
+ "Doubled ARP request
removed: ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]; originator: %pM\n",
+ hw_src, &ip_src,
+ batadv_arp_hw_dst(skb,
hdr_size), &ip_dst, unicast_4addr_packet->src);
+ ret = true;
+ }
+ batadv_orig_node_free_ref(orig_node);
+ }
+
goto out;
+ }
skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
bat_priv->soft_iface, ip_dst, hw_src,
@@ -1128,6 +1182,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct
batadv_priv *bat_priv,
__be32 ip_src, ip_dst;
uint8_t *hw_src, *hw_dst;
bool ret = false;
+ struct batadv_dat_entry *dat_entry = NULL;
unsigned short vid;
if (!atomic_read(&bat_priv->distributed_arp_table))
@@ -1147,12 +1202,38 @@ 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 the frame if we are the destination of ARP reply
+ * as we most probably already delivered a corresponding 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);
+ ret = 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 REPLYs 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_check_local_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);
+ ret = true;
+ goto out;
+ }
+
/* if this REPLY is directed to a client of mine, let's deliver
the
* packet to the interface
*/
@@ -1160,6 +1241,8 @@ bool batadv_dat_snoop_incoming_arp_reply(struct
batadv_priv *bat_priv,
out:
if (ret)
kfree_skb(skb);
+ if (dat_entry)
+ batadv_dat_entry_free_ref(dat_entry);
/* if ret == false -> packet has to be delivered to the interface
*/
return ret;
}
diff --git a/distributed-arp-table.h b/distributed-arp-table.h
index 2fe0764..ed9c5c2 100644
--- a/distributed-arp-table.h
+++ b/distributed-arp-table.h
@@ -73,7 +73,8 @@ batadv_dat_init_own_addr(struct batadv_priv *bat_priv,
int batadv_dat_init(struct batadv_priv *bat_priv);
void batadv_dat_free(struct batadv_priv *bat_priv);
int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset);
-
+void batadv_dat_entry_check(struct batadv_priv *bat_priv, __be32 ip,
+ uint8_t *mac_addr, unsigned short vid);
/**
* batadv_dat_inc_counter - increment the correct DAT packet counter
* @bat_priv: the bat priv with all the soft interface information
@@ -161,6 +162,10 @@ static inline void batadv_dat_free(struct batadv_priv
*bat_priv)
{
}
+void batadv_dat_entry_check(struct batadv_priv *bat_priv, __be32 ip,
+ uint8_t *mac_addr, unsigned short vid)
+{
+}
static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
uint8_t subtype)
{
diff --git a/routing.c b/routing.c
index da83982..6f60538 100644
--- a/routing.c
+++ b/routing.c
@@ -1061,8 +1061,10 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
/* don't hand the broadcast up if it is from an originator
* from the same backbone.
*/
- if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size))
- goto out;
+ if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size)) {
+ kfree_skb(skb);
+ goto rx_success;
+ }
if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
hdr_size))
goto rx_success;
diff --git a/soft-interface.c b/soft-interface.c
index 78d63e3..5eb3191 100644
--- a/soft-interface.c
+++ b/soft-interface.c
@@ -358,8 +358,9 @@ void batadv_interface_rx(struct net_device
*soft_iface,
struct batadv_bcast_packet *batadv_bcast_packet;
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
__be16 ethertype = htons(ETH_P_BATMAN);
- struct vlan_ethhdr *vhdr;
+ struct vlan_ethhdr *vhdr = NULL;
struct ethhdr *ethhdr;
+ struct iphdr *iphdr;
unsigned short vid;
bool is_bcast;
@@ -382,11 +383,23 @@ void batadv_interface_rx(struct net_device
*soft_iface,
ethhdr = eth_hdr(skb);
switch (ntohs(ethhdr->h_proto)) {
+ case ETH_P_IP:
+ iphdr = (struct iphdr *)(skb->data + ETH_HLEN);
+ /* snoop incoming traffic for dat update using the source
mac and source ip */
+ batadv_dat_entry_check(bat_priv, iphdr->saddr,
ethhdr->h_source, vid);
+ break;
case ETH_P_8021Q:
vhdr = (struct vlan_ethhdr *)skb->data;
- if (vhdr->h_vlan_encapsulated_proto != ethertype)
+ if (vhdr->h_vlan_encapsulated_proto != ethertype) {
+ /* snoop incoming traffic for dat update using the
source mac and source ip.
+ * Consider also vlan tagged frames */
+ if (vhdr->h_vlan_encapsulated_proto == ETH_P_IP) {
+ iphdr = (struct iphdr *)(vhdr +
sizeof(struct vlan_ethhdr));
+ batadv_dat_entry_check(bat_priv,
iphdr->saddr, vhdr->h_source, vid);
+ }
break;
+ }
/* fall through */
case ETH_P_BATMAN:
--
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
___________________________________________________________________
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.
___________________________________________________________________