From 3b81a1e5f205482b8ea30edbfd39559c4368ac4d Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 6 Sep 2018 09:50:26 -0700 Subject: [PATCH] L2 BVI/FIB: Update L2 FIB table when BVI's MAC changes also some moving of l2 headers to reduce dependencies Change-Id: I7a700a411a91451ef13fd65f9c90de2432b793bb Signed-off-by: Neale Ranns --- src/plugins/dpdk/device/device.c | 3 ++- src/plugins/gbp/gbp_classify.c | 2 ++ src/plugins/gbp/gbp_endpoint.c | 3 +++ src/plugins/gbp/gbp_endpoint_group.c | 2 ++ src/plugins/gbp/gbp_fwd.c | 1 + src/plugins/l2e/l2e.c | 1 + src/vnet/classify/in_out_acl.c | 2 ++ src/vnet/classify/policer_classify.c | 1 + src/vnet/classify/vnet_classify.h | 3 --- src/vnet/devices/af_packet/device.c | 2 +- src/vnet/ethernet/arp.c | 1 + src/vnet/ethernet/interface.c | 15 ++++++++++++++- src/vnet/gre/interface.c | 1 + src/vnet/interface.c | 8 ++++++-- src/vnet/interface.h | 3 ++- src/vnet/ip/ip6_neighbor.c | 1 + src/vnet/ipsec-gre/interface.c | 1 + src/vnet/l2/l2_fib.c | 4 ++-- src/vnet/l2/l2_fib.h | 8 ++++---- src/vnet/l2/l2_fwd.c | 1 + src/vnet/l2/l2_input.c | 21 +++++++++++++++++++++ src/vnet/l2/l2_input.h | 3 +++ src/vnet/l2tp/decap.c | 1 + src/vnet/policer/node_funcs.c | 2 ++ src/vnet/qos/qos_record.c | 2 ++ test/test_ip4_irb.py | 27 +++++++++++++++++++-------- test/vpp_interface.py | 9 ++++++++- 27 files changed, 104 insertions(+), 24 deletions(-) diff --git a/src/plugins/dpdk/device/device.c b/src/plugins/dpdk/device/device.c index c38eec09d81..fcabe6e2dd6 100644 --- a/src/plugins/dpdk/device/device.c +++ b/src/plugins/dpdk/device/device.c @@ -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; diff --git a/src/plugins/gbp/gbp_classify.c b/src/plugins/gbp/gbp_classify.c index 859d4f95173..6b91d8cf099 100644 --- a/src/plugins/gbp/gbp_classify.c +++ b/src/plugins/gbp/gbp_classify.c @@ -16,6 +16,8 @@ */ #include +#include +#include typedef enum gbp_src_classify_type_t_ { diff --git a/src/plugins/gbp/gbp_endpoint.c b/src/plugins/gbp/gbp_endpoint.c index cffa6da836c..0522f613f7d 100644 --- a/src/plugins/gbp/gbp_endpoint.c +++ b/src/plugins/gbp/gbp_endpoint.c @@ -19,6 +19,9 @@ #include #include +#include +#include +#include /** * IP4 destintion address to destination EPG mapping table diff --git a/src/plugins/gbp/gbp_endpoint_group.c b/src/plugins/gbp/gbp_endpoint_group.c index ed312d305a1..c5c06660f94 100644 --- a/src/plugins/gbp/gbp_endpoint_group.c +++ b/src/plugins/gbp/gbp_endpoint_group.c @@ -20,6 +20,8 @@ #include #include +#include +#include /** * Pool of GBP endpoint_groups diff --git a/src/plugins/gbp/gbp_fwd.c b/src/plugins/gbp/gbp_fwd.c index fec5703d014..e4814337558 100644 --- a/src/plugins/gbp/gbp_fwd.c +++ b/src/plugins/gbp/gbp_fwd.c @@ -14,6 +14,7 @@ */ #include +#include /** * Grouping of global data for the GBP source EPG classification feature diff --git a/src/plugins/l2e/l2e.c b/src/plugins/l2e/l2e.c index e95c281c716..a56c25c54f8 100644 --- a/src/plugins/l2e/l2e.c +++ b/src/plugins/l2e/l2e.c @@ -18,6 +18,7 @@ #include #include +#include /** * Grouping of global data for the L2 emulation feature diff --git a/src/vnet/classify/in_out_acl.c b/src/vnet/classify/in_out_acl.c index 2d156ff4373..553c353b7ae 100644 --- a/src/vnet/classify/in_out_acl.c +++ b/src/vnet/classify/in_out_acl.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include in_out_acl_main_t in_out_acl_main; diff --git a/src/vnet/classify/policer_classify.c b/src/vnet/classify/policer_classify.c index 542ba1015ed..4cf12a24e9e 100644 --- a/src/vnet/classify/policer_classify.c +++ b/src/vnet/classify/policer_classify.c @@ -13,6 +13,7 @@ * limitations under the License. */ #include +#include policer_classify_main_t policer_classify_main; diff --git a/src/vnet/classify/vnet_classify.h b/src/vnet/classify/vnet_classify.h index 791b8fd18b7..4fea95d5b72 100644 --- a/src/vnet/classify/vnet_classify.h +++ b/src/vnet/classify/vnet_classify.h @@ -26,9 +26,6 @@ #include #include #include -#include -#include -#include #include /* for API error numbers */ #include diff --git a/src/vnet/devices/af_packet/device.c b/src/vnet/devices/af_packet/device.c index 0b0697b705f..b8c7501710e 100644 --- a/src/vnet/devices/af_packet/device.c +++ b/src/vnet/devices/af_packet/device.c @@ -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 = diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c index b5c2e6dc748..275d606266b 100644 --- a/src/vnet/ethernet/arp.c +++ b/src/vnet/ethernet/arp.c @@ -26,6 +26,7 @@ #include #include #include +#include /** * @file diff --git a/src/vnet/ethernet/interface.c b/src/vnet/ethernet/interface.c index bef13b8672c..d44a8a8ecb0 100644 --- a/src/vnet/ethernet/interface.c +++ b/src/vnet/ethernet/interface.c @@ -42,6 +42,7 @@ #include #include #include +#include #include /** @@ -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* */ diff --git a/src/vnet/gre/interface.c b/src/vnet/gre/interface.c index 70c6c4df3b3..cd7f952cce5 100644 --- a/src/vnet/gre/interface.c +++ b/src/vnet/gre/interface.c @@ -24,6 +24,7 @@ #include #include #include +#include static const char *gre_tunnel_type_names[] = GRE_TUNNEL_TYPE_NAMES; diff --git a/src/vnet/interface.c b/src/vnet/interface.c index 1e69ccbf6ea..e04ba9b10af 100644 --- a/src/vnet/interface.c +++ b/src/vnet/interface.c @@ -42,6 +42,7 @@ #include #include #include +#include #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 { diff --git a/src/vnet/interface.h b/src/vnet/interface.h index b34d19c55ef..30023ebded3 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -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) diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 1093009dd15..a54f9e91810 100755 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -25,6 +25,7 @@ #include #include #include +#include /** * @file diff --git a/src/vnet/ipsec-gre/interface.c b/src/vnet/ipsec-gre/interface.c index 8903df01c04..a51ca7f69dd 100644 --- a/src/vnet/ipsec-gre/interface.c +++ b/src/vnet/ipsec-gre/interface.c @@ -27,6 +27,7 @@ #include #include #include +#include #include diff --git a/src/vnet/l2/l2_fib.c b/src/vnet/l2/l2_fib.c index 60d0db56d9d..dcfee7bf6e2 100644 --- a/src/vnet/l2/l2_fib.c +++ b/src/vnet/l2/l2_fib.c @@ -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; diff --git a/src/vnet/l2/l2_fib.h b/src/vnet/l2/l2_fib.h index a958023eaea..77b5e7b9454 100644 --- a/src/vnet/l2/l2_fib.h +++ b/src/vnet/l2/l2_fib.h @@ -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); diff --git a/src/vnet/l2/l2_fwd.c b/src/vnet/l2/l2_fwd.c index 8c03683b133..fd7f54b41ef 100644 --- a/src/vnet/l2/l2_fwd.c +++ b/src/vnet/l2/l2_fwd.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index fd6f9eb462c..7e41c886dec 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -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. diff --git a/src/vnet/l2/l2_input.h b/src/vnet/l2/l2_input.h index ea9dcad63e5..4b303482df9 100644 --- a/src/vnet/l2/l2_input.h +++ b/src/vnet/l2/l2_input.h @@ -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 diff --git a/src/vnet/l2tp/decap.c b/src/vnet/l2tp/decap.c index 334f1feca4a..5925cdb7f41 100644 --- a/src/vnet/l2tp/decap.c +++ b/src/vnet/l2tp/decap.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Statistics (not really errors) */ #define foreach_l2t_decap_error \ diff --git a/src/vnet/policer/node_funcs.c b/src/vnet/policer/node_funcs.c index 9a25dbb3cc6..5c185991e8b 100644 --- a/src/vnet/policer/node_funcs.c +++ b/src/vnet/policer/node_funcs.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include /* Dispatch functions meant to be instantiated elsewhere */ diff --git a/src/vnet/qos/qos_record.c b/src/vnet/qos/qos_record.c index 1433a02527b..3f43f48d8df 100644 --- a/src/vnet/qos/qos_record.c +++ b/src/vnet/qos/qos_record.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include /** * Per-interface, per-protocol vector of feature on/off configurations diff --git a/test/test_ip4_irb.py b/test/test_ip4_irb.py index 460cb43b726..6aad60a7609 100644 --- a/test/test_ip4_irb.py +++ b/test/test_ip4_irb.py @@ -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) diff --git a/test/vpp_interface.py b/test/vpp_interface.py index e14a31eb722..1db34ba7958 100644 --- a/test/vpp_interface.py +++ b/test/vpp_interface.py @@ -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 -- 2.16.6