L2 BVI/FIB: Update L2 FIB table when BVI's MAC changes 02/14702/5
authorNeale Ranns <nranns@cisco.com>
Thu, 6 Sep 2018 16:50:26 +0000 (09:50 -0700)
committerJohn Lo <loj@cisco.com>
Sat, 8 Sep 2018 14:51:48 +0000 (14:51 +0000)
also some moving of l2 headers to reduce dependencies

Change-Id: I7a700a411a91451ef13fd65f9c90de2432b793bb
Signed-off-by: Neale Ranns <nranns@cisco.com>
27 files changed:
src/plugins/dpdk/device/device.c
src/plugins/gbp/gbp_classify.c
src/plugins/gbp/gbp_endpoint.c
src/plugins/gbp/gbp_endpoint_group.c
src/plugins/gbp/gbp_fwd.c
src/plugins/l2e/l2e.c
src/vnet/classify/in_out_acl.c
src/vnet/classify/policer_classify.c
src/vnet/classify/vnet_classify.h
src/vnet/devices/af_packet/device.c
src/vnet/ethernet/arp.c
src/vnet/ethernet/interface.c
src/vnet/gre/interface.c
src/vnet/interface.c
src/vnet/interface.h
src/vnet/ip/ip6_neighbor.c
src/vnet/ipsec-gre/interface.c
src/vnet/l2/l2_fib.c
src/vnet/l2/l2_fib.h
src/vnet/l2/l2_fwd.c
src/vnet/l2/l2_input.c
src/vnet/l2/l2_input.h
src/vnet/l2tp/decap.c
src/vnet/policer/node_funcs.c
src/vnet/qos/qos_record.c
test/test_ip4_irb.py
test/vpp_interface.py

index c38eec0..fcabe6e 100644 (file)
@@ -43,7 +43,8 @@ static char *dpdk_tx_func_error_strings[] = {
 };
 
 static clib_error_t *
-dpdk_set_mac_address (vnet_hw_interface_t * hi, char *address)
+dpdk_set_mac_address (vnet_hw_interface_t * hi,
+                     const u8 * old_address, const u8 * address)
 {
   int error;
   dpdk_main_t *dm = &dpdk_main;
index 859d4f9..6b91d8c 100644 (file)
@@ -16,6 +16,8 @@
  */
 
 #include <plugins/gbp/gbp.h>
+#include <vnet/l2/l2_input.h>
+#include <vnet/l2/feat_bitmap.h>
 
 typedef enum gbp_src_classify_type_t_
 {
index cffa6da..0522f61 100644 (file)
@@ -19,6 +19,9 @@
 #include <plugins/gbp/gbp_endpoint_group.h>
 
 #include <vnet/ethernet/arp_packet.h>
+#include <vnet/l2/l2_input.h>
+#include <vnet/l2/l2_output.h>
+#include <vnet/l2/feat_bitmap.h>
 
 /**
  * IP4 destintion address to destination EPG mapping table
index ed312d3..c5c0666 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <vnet/dpo/dvr_dpo.h>
 #include <vnet/fib/fib_table.h>
+#include <vnet/l2/l2_input.h>
+#include <vnet/l2/feat_bitmap.h>
 
 /**
  * Pool of GBP endpoint_groups
index fec5703..e481433 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <plugins/gbp/gbp.h>
+#include <vnet/l2/l2_input.h>
 
 /**
  * Grouping of global data for the GBP source EPG classification feature
index e95c281..a56c25c 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <plugins/l2e/l2e.h>
 #include <vnet/l2/l2_input.h>
+#include <vnet/l2/feat_bitmap.h>
 
 /**
  * Grouping of global data for the L2 emulation feature
index 2d156ff..553c353 100644 (file)
@@ -15,6 +15,8 @@
 #include <vnet/ip/ip.h>
 #include <vnet/classify/vnet_classify.h>
 #include <vnet/classify/in_out_acl.h>
+#include <vnet/l2/l2_output.h>
+#include <vnet/l2/l2_input.h>
 
 in_out_acl_main_t in_out_acl_main;
 
index 542ba10..4cf12a2 100644 (file)
@@ -13,6 +13,7 @@
  * limitations under the License.
  */
 #include <vnet/classify/policer_classify.h>
+#include <vnet/l2/l2_input.h>
 
 policer_classify_main_t policer_classify_main;
 
index 791b8fd..4fea95d 100644 (file)
@@ -26,9 +26,6 @@
 #include <vnet/ip/ip4_packet.h>
 #include <vnet/ip/ip6_packet.h>
 #include <vlib/cli.h>
-#include <vnet/l2/l2_input.h>
-#include <vnet/l2/l2_output.h>
-#include <vnet/l2/feat_bitmap.h>
 #include <vnet/api_errno.h>    /* for API error numbers */
 
 #include <vppinfra/error.h>
index 0b0697b..b8c7501 100644 (file)
@@ -278,7 +278,7 @@ af_packet_subif_add_del_function (vnet_main_t * vnm,
 }
 
 static clib_error_t *af_packet_set_mac_address_function
-  (struct vnet_hw_interface_t *hi, char *address)
+  (struct vnet_hw_interface_t *hi, const u8 * old_address, const u8 * address)
 {
   af_packet_main_t *apm = &af_packet_main;
   af_packet_if_t *apif =
index b5c2e6d..275d606 100644 (file)
@@ -26,6 +26,7 @@
 #include <vnet/adj/adj_nbr.h>
 #include <vnet/adj/adj_mcast.h>
 #include <vnet/mpls/mpls.h>
+#include <vnet/l2/feat_bitmap.h>
 
 /**
  * @file
index bef13b8..d44a8a8 100644 (file)
@@ -42,6 +42,7 @@
 #include <vnet/pg/pg.h>
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/l2/l2_input.h>
+#include <vnet/l2/l2_bd.h>
 #include <vnet/adj/adj.h>
 
 /**
@@ -218,7 +219,8 @@ ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
 }
 
 static clib_error_t *
-ethernet_mac_change (vnet_hw_interface_t * hi, char *mac_address)
+ethernet_mac_change (vnet_hw_interface_t * hi,
+                    const u8 * old_address, const u8 * mac_address)
 {
   ethernet_interface_t *ei;
   ethernet_main_t *em;
@@ -633,12 +635,23 @@ simulated_ethernet_admin_up_down (vnet_main_t * vnm, u32 hw_if_index,
   return 0;
 }
 
+static clib_error_t *
+simulated_ethernet_mac_change (vnet_hw_interface_t * hi,
+                              const u8 * old_address, const u8 * mac_address)
+{
+  l2input_interface_mac_change (hi->sw_if_index, old_address, mac_address);
+
+  return (NULL);
+}
+
+
 /* *INDENT-OFF* */
 VNET_DEVICE_CLASS (ethernet_simulated_device_class) = {
   .name = "Loopback",
   .format_device_name = format_simulated_ethernet_name,
   .tx_function = simulated_ethernet_interface_tx,
   .admin_up_down_function = simulated_ethernet_admin_up_down,
+  .mac_addr_change_function = simulated_ethernet_mac_change,
 };
 /* *INDENT-ON* */
 
index 70c6c4d..cd7f952 100644 (file)
@@ -24,6 +24,7 @@
 #include <vnet/adj/adj_midchain.h>
 #include <vnet/adj/adj_nbr.h>
 #include <vnet/mpls/mpls.h>
+#include <vnet/l2/l2_input.h>
 
 static const char *gre_tunnel_type_names[] = GRE_TUNNEL_TYPE_NAMES;
 
index 1e69ccb..e04ba9b 100644 (file)
@@ -42,6 +42,7 @@
 #include <vnet/fib/ip6_fib.h>
 #include <vnet/adj/adj.h>
 #include <vnet/adj/adj_mcast.h>
+#include <vnet/l2/l2_input.h>
 
 #define VNET_INTERFACE_SET_FLAGS_HELPER_IS_CREATE (1 << 0)
 #define VNET_INTERFACE_SET_FLAGS_HELPER_WANT_REDISTRIBUTE (1 << 1)
@@ -1501,12 +1502,14 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm,
 
   if (hi->hw_address)
     {
+      u8 *old_address = vec_dup (hi->hw_address);
       vnet_device_class_t *dev_class =
        vnet_get_device_class (vnm, hi->dev_class_index);
       if (dev_class->mac_addr_change_function)
        {
          error =
-           dev_class->mac_addr_change_function (hi, (char *) mac_address);
+           dev_class->mac_addr_change_function (hi, old_address,
+                                                mac_address);
        }
       if (!error)
        {
@@ -1515,7 +1518,7 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm,
          hw_class = vnet_get_hw_interface_class (vnm, hi->hw_class_index);
 
          if (NULL != hw_class->mac_addr_change_function)
-           hw_class->mac_addr_change_function (hi, (char *) mac_address);
+           hw_class->mac_addr_change_function (hi, old_address, mac_address);
        }
       else
        {
@@ -1523,6 +1526,7 @@ vnet_hw_interface_change_mac_address_helper (vnet_main_t * vnm,
            clib_error_return (0,
                               "MAC Address Change is not supported on this interface");
        }
+      vec_free (old_address);
     }
   else
     {
index b34d19c..30023eb 100644 (file)
@@ -69,7 +69,8 @@ typedef clib_error_t *(vnet_subif_add_del_function_t)
 
 /* Interface set mac address callback. */
 typedef clib_error_t *(vnet_interface_set_mac_address_function_t)
-  (struct vnet_hw_interface_t * hi, char *address);
+  (struct vnet_hw_interface_t * hi,
+   const u8 * old_address, const u8 * new_address);
 
 /* Interface set rx mode callback. */
 typedef clib_error_t *(vnet_interface_set_rx_mode_function_t)
index 1093009..a54f9e9 100755 (executable)
@@ -25,6 +25,7 @@
 #include <vnet/fib/ip6_fib.h>
 #include <vnet/mfib/ip6_mfib.h>
 #include <vnet/ip/ip6_ll_table.h>
+#include <vnet/l2/l2_input.h>
 
 /**
  * @file
index 8903df0..a51ca7f 100644 (file)
@@ -27,6 +27,7 @@
 #include <vnet/ipsec-gre/ipsec_gre.h>
 #include <vnet/ip/format.h>
 #include <vnet/ipsec/ipsec.h>
+#include <vnet/l2/l2_input.h>
 
 #include <vnet/ipsec/esp.h>
 
index 60d0db5..dcfee7b 100644 (file)
@@ -376,7 +376,7 @@ l2fib_cur_seq_num (u32 bd_index, u32 sw_if_index)
  * If the entry already exists then overwrite it
  */
 void
-l2fib_add_entry (u8 * mac, u32 bd_index,
+l2fib_add_entry (const u8 * mac, u32 bd_index,
                 u32 sw_if_index, l2fib_entry_result_flags_t flags)
 {
   l2fib_entry_key_t key;
@@ -660,7 +660,7 @@ VLIB_CLI_COMMAND (l2fib_test_command, static) = {
  * sw_if_index is non-zero and does not match that in the entry.
  */
 u32
-l2fib_del_entry (u8 * mac, u32 bd_index, u32 sw_if_index)
+l2fib_del_entry (const u8 * mac, u32 bd_index, u32 sw_if_index)
 {
   l2fib_entry_result_t result;
   l2fib_main_t *mp = &l2fib_main;
index a958023..77b5e7b 100644 (file)
@@ -218,7 +218,7 @@ l2fib_compute_hash_bucket (l2fib_entry_key_t * key)
  * l2fib_make_key() does read those two Bytes but does not use them.
  */
 always_inline u64 __attribute__ ((no_sanitize_address))
-l2fib_make_key (u8 * mac_address, u16 bd_index)
+l2fib_make_key (const u8 * mac_address, u16 bd_index)
 {
   u64 temp;
 
@@ -440,19 +440,19 @@ l2fib_lookup_4 (BVT (clib_bihash) * mac_table,
 void l2fib_clear_table (void);
 
 void
-l2fib_add_entry (u8 * mac,
+l2fib_add_entry (const u8 * mac,
                 u32 bd_index,
                 u32 sw_if_index, l2fib_entry_result_flags_t flags);
 
 static inline void
-l2fib_add_filter_entry (u8 * mac, u32 bd_index)
+l2fib_add_filter_entry (const u8 * mac, u32 bd_index)
 {
   l2fib_add_entry (mac, bd_index, ~0,
                   (L2FIB_ENTRY_RESULT_FLAG_FILTER |
                    L2FIB_ENTRY_RESULT_FLAG_STATIC));
 }
 
-u32 l2fib_del_entry (u8 * mac, u32 bd_index, u32 sw_if_index);
+u32 l2fib_del_entry (const u8 * mac, u32 bd_index, u32 sw_if_index);
 
 void l2fib_start_ager_scan (vlib_main_t * vm);
 
index 8c03683..fd7f54b 100644 (file)
@@ -25,6 +25,7 @@
 #include <vnet/l2/l2_bvi.h>
 #include <vnet/l2/l2_fwd.h>
 #include <vnet/l2/l2_fib.h>
+#include <vnet/l2/feat_bitmap.h>
 
 #include <vppinfra/error.h>
 #include <vppinfra/hash.h>
index fd6f9eb..7e41c88 100644 (file)
@@ -539,6 +539,27 @@ l2input_set_bridge_features (u32 bd_index, u32 feat_mask, u32 feat_value)
   return bd_config->feature_bitmap;
 }
 
+void
+l2input_interface_mac_change (u32 sw_if_index,
+                             const u8 * old_address, const u8 * new_address)
+{
+  /* check if the sw_if_index passed is a BVI in a BD */
+  l2_input_config_t *intf_config;
+
+  intf_config = l2input_intf_config (sw_if_index);
+
+  if (intf_config->bridge && intf_config->bvi)
+    {
+      /* delete and re-add l2fib entry for the bvi interface */
+      l2fib_del_entry (old_address, intf_config->bd_index, sw_if_index);
+      l2fib_add_entry (new_address,
+                      intf_config->bd_index,
+                      sw_if_index,
+                      L2FIB_ENTRY_RESULT_FLAG_BVI |
+                      L2FIB_ENTRY_RESULT_FLAG_STATIC);
+    }
+}
+
 /**
  * Set the subinterface to run in l2 or l3 mode.
  * For L3 mode, just the sw_if_index is specified.
index ea9dcad..4b30348 100644 (file)
@@ -197,6 +197,9 @@ u32 l2input_intf_bitmap_enable (u32 sw_if_index,
 /* Sets modifies flags from a bridge domain */
 u32 l2input_set_bridge_features (u32 bd_index, u32 feat_mask, u32 feat_value);
 
+void l2input_interface_mac_change (u32 sw_if_index,
+                                  const u8 * old_address,
+                                  const u8 * new_address);
 
 #define MODE_L3        0
 #define MODE_L2_BRIDGE 1
index 334f1fe..5925cdb 100644 (file)
@@ -21,6 +21,7 @@
 #include <vnet/ip/ip.h>
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/l2tp/l2tp.h>
+#include <vnet/l2/l2_input.h>
 
 /* Statistics (not really errors) */
 #define foreach_l2t_decap_error                                 \
index 9a25dbb..5c18599 100644 (file)
@@ -22,6 +22,8 @@
 #include <vnet/ip/ip.h>
 #include <vnet/classify/policer_classify.h>
 #include <vnet/classify/vnet_classify.h>
+#include <vnet/l2/feat_bitmap.h>
+#include <vnet/l2/l2_input.h>
 
 
 /* Dispatch functions meant to be instantiated elsewhere */
index 1433a02..3f43f48 100644 (file)
@@ -18,6 +18,8 @@
 #include <vnet/ip/ip6_to_ip4.h>
 #include <vnet/feature/feature.h>
 #include <vnet/qos/qos_types.h>
+#include <vnet/l2/l2_input.h>
+#include <vnet/l2/feat_bitmap.h>
 
 /**
  * Per-interface, per-protocol vector of feature on/off configurations
index 460cb43..6aad60a 100644 (file)
@@ -31,6 +31,7 @@ from scapy.layers.l2 import Ether
 from scapy.layers.inet import IP, UDP
 
 from framework import VppTestCase, VppTestRunner
+from util import mactobinary
 
 
 class TestIpIrb(VppTestCase):
@@ -238,26 +239,36 @@ class TestIpIrb(VppTestCase):
 
         self.assertListEqual(rcvd1.res, rcvd2.res)
 
-    def test_ip4_irb_2(self):
-        """ IPv4 IRB test 2
-
-        Test scenario:
-            - ip traffic from pg0 and pg1 ends on pg2
-        """
-
+    def send_and_verify_l2_to_ip(self):
         stream1 = self.create_stream_l2_to_ip(
             self.pg0, self.loop0, self.pg2, self.pg_if_packet_sizes)
         stream2 = self.create_stream_l2_to_ip(
             self.pg1, self.loop0, self.pg2, self.pg_if_packet_sizes)
+        self.vapi.cli("clear trace")
         self.pg0.add_stream(stream1)
         self.pg1.add_stream(stream2)
 
         self.pg_enable_capture(self.pg_interfaces)
         self.pg_start()
 
-        rcvd = self.pg2.get_capture()
+        rcvd = self.pg2.get_capture(514)
         self.verify_capture_l2_to_ip(self.pg2, self.loop0, rcvd)
 
+    def test_ip4_irb_2(self):
+        """ IPv4 IRB test 2
+
+        Test scenario:
+            - ip traffic from pg0 and pg1 ends on pg2
+        """
+        self.send_and_verify_l2_to_ip()
+
+        # change the BVI's mac and resed traffic
+        self.loop0.set_mac("00:00:00:11:11:33")
+
+        self.send_and_verify_l2_to_ip()
+        # check it wasn't flooded
+        self.pg1.assert_nothing_captured(remark="UU Flood")
+
 
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)
index e14a31e..1db34ba 100644 (file)
@@ -1,7 +1,7 @@
 from abc import abstractmethod, ABCMeta
 import socket
 
-from util import Host, mk_ll_addr
+from util import Host, mk_ll_addr, mactobinary
 
 
 class VppInterface(object):
@@ -170,6 +170,13 @@ class VppInterface(object):
         self._hosts_by_ip4 = {}
         self._hosts_by_ip6 = {}
 
+    def set_mac(self, mac):
+        self._local_mac = mac
+        self._local_ip6_ll = mk_ll_addr(mac)
+        self.test.vapi.sw_interface_set_mac_address(
+            self.sw_if_index,
+            mactobinary(self._local_mac))
+
     def set_sw_if_index(self, sw_if_index):
         self._sw_if_index = sw_if_index