From 750e0649bfc5144e6dce3cdd20835dabedfe3b50 Mon Sep 17 00:00:00 2001 From: Sudharsan Dhamal Gopalarathnam Date: Thu, 4 May 2023 11:54:58 -0700 Subject: [PATCH] [EVPN]Fixing race condition when EVPN NVO add comes late (#2756) * Sometime during config reload, EVPN NVO table arrives later than remote VNI table entries. In such scenarios, remote vni entries are ignored and this leads to traffic loss. Added fix to retry instead of ignoring. --- orchagent/vxlanorch.cpp | 6 ++--- tests/test_evpn_tunnel.py | 45 ++++++++++++++++++++++++++++++++++ tests/test_evpn_tunnel_p2mp.py | 43 ++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/orchagent/vxlanorch.cpp b/orchagent/vxlanorch.cpp index 1983cf7286..0b1f83f4ff 100644 --- a/orchagent/vxlanorch.cpp +++ b/orchagent/vxlanorch.cpp @@ -2353,7 +2353,7 @@ bool EvpnRemoteVnip2pOrch::addOperation(const Request& request) { SWSS_LOG_WARN("Remote VNI add: Source VTEP not found. remote=%s vid=%d", remote_vtep.c_str(), vlan_id); - return true; + return false; } VxlanTunnelOrch* tunnel_orch = gDirectory.get(); @@ -2522,7 +2522,7 @@ bool EvpnRemoteVnip2mpOrch::addOperation(const Request& request) { SWSS_LOG_WARN("Remote VNI add: Source VTEP not found. remote=%s vid=%d", end_point_ip.c_str(),vlan_id); - return true; + return false; } if (!gPortsOrch->getVlanByVlanId(vlan_id, vlanPort)) @@ -2602,7 +2602,7 @@ bool EvpnRemoteVnip2mpOrch::delOperation(const Request& request) auto vtep_ptr = evpn_orch->getEVPNVtep(); if (!vtep_ptr) { - SWSS_LOG_WARN("Remote VNI add: VTEP not found. remote=%s vid=%d", + SWSS_LOG_WARN("Remote VNI del: VTEP not found. remote=%s vid=%d", end_point_ip.c_str(), vlan_id); return true; } diff --git a/tests/test_evpn_tunnel.py b/tests/test_evpn_tunnel.py index 86f5ad53f6..245952ded3 100644 --- a/tests/test_evpn_tunnel.py +++ b/tests/test_evpn_tunnel.py @@ -213,6 +213,51 @@ def test_delayed_vlan_vni_map(self, dvs, testlog): vxlan_obj.remove_vlan(dvs, "100") vxlan_obj.remove_vlan(dvs, "101") + def test_delayed_evpn_nvo(self, dvs, testlog): + vxlan_obj = self.get_vxlan_obj() + + tunnel_name = 'tunnel_2' + map_name = 'map_1000_100' + map_name_1 = 'map_1001_101' + vlanlist = ['100'] + vnilist = ['1000'] + + vxlan_obj.fetch_exist_entries(dvs) + vxlan_obj.create_vlan1(dvs,"Vlan100") + vxlan_obj.create_vlan1(dvs,"Vlan101") + + vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') + vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') + vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') + + vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 2) + vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) + + + vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7', '1001') + vxlan_obj.check_vxlan_dip_tunnel_not_created(dvs, tunnel_name, '6.6.6.6', '7.7.7.7') + vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) + + print("Testing VLAN 101 extension") + vxlan_obj.check_vxlan_dip_tunnel(dvs, tunnel_name, '6.6.6.6', '7.7.7.7') + vxlan_obj.check_vlan_extension(dvs, '101', '7.7.7.7') + + print("Testing Vlan Extension removal") + vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7') + vxlan_obj.check_vlan_extension_delete(dvs, '101', '7.7.7.7') + vxlan_obj.check_vxlan_dip_tunnel_delete(dvs, '7.7.7.7') + + vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') + vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') + vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) + + print("Testing SIP Tunnel Deletion") + vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') + vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) + vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6') + vxlan_obj.remove_vlan(dvs, "100") + vxlan_obj.remove_vlan(dvs, "101") + def test_invalid_vlan_extension(self, dvs, testlog): vxlan_obj = self.get_vxlan_obj() diff --git a/tests/test_evpn_tunnel_p2mp.py b/tests/test_evpn_tunnel_p2mp.py index bbbb786f9a..a45b2f4b75 100644 --- a/tests/test_evpn_tunnel_p2mp.py +++ b/tests/test_evpn_tunnel_p2mp.py @@ -172,6 +172,49 @@ def test_delayed_vlan_vni_map(self, dvs, testlog): vxlan_obj.remove_vlan(dvs, "100") vxlan_obj.remove_vlan(dvs, "101") + def test_delayed_evpn_nvo(self, dvs, testlog): + vxlan_obj = self.get_vxlan_obj() + + tunnel_name = 'tunnel_2' + map_name = 'map_1000_100' + map_name_1 = 'map_1001_101' + vlanlist = ['100'] + vnilist = ['1000'] + + vxlan_obj.fetch_exist_entries(dvs) + vxlan_obj.create_vlan1(dvs,"Vlan100") + vxlan_obj.create_vlan1(dvs,"Vlan101") + + vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6') + vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') + vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') + vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7', '1001') + + vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count = 2) + vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist) + + + vxlan_obj.check_vlan_extension_not_created_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7') + vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name) + + print("Testing VLAN 101 extension") + vxlan_obj.check_vlan_extension_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7') + + print("Testing Vlan Extension removal") + vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7') + vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7') + + vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100') + vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101') + vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist) + + print("Testing SIP Tunnel Deletion") + vxlan_obj.remove_evpn_nvo(dvs, 'nvo1') + vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name) + vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False) + vxlan_obj.remove_vlan(dvs, "100") + vxlan_obj.remove_vlan(dvs, "101") + def test_invalid_vlan_extension(self, dvs, testlog): vxlan_obj = self.get_vxlan_obj()