diff mbox

dat optimization test

Message ID OFDCB0C675.8A026ED2-ONC1257E0D.002690BF-C1257E0D.0026F071@phoenixcontact.com
State Superseded, archived
Headers show

Commit Message

Andreas Pape March 19, 2015, 7:05 a.m. UTC
From e0b37ee6d7d82648768dc98a95c3a61d7edf86dd Mon Sep 17 00:00:00 2001
From: Andreas Pape <apape@phoenixcontact.com>
Date: Wed, 18 Mar 2015 11:03:22 +0100
Subject: [PATCH] dat optimization test


Signed-off-by: Andreas Pape <apape@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(-)

 
@@ -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:
diff mbox

Patch

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;