Skip to content

Commit 8de52bf

Browse files
authored
[EVPN]Handling race condition when remote VNI arrives before tunnel map entry (sonic-net#2642)
*Added check in remote VNI add to ensure vxlan tunnel map is created before adding the remote end point.
1 parent e99e2e4 commit 8de52bf

File tree

4 files changed

+151
-0
lines changed

4 files changed

+151
-0
lines changed

orchagent/vxlanorch.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -2349,13 +2349,24 @@ bool EvpnRemoteVnip2pOrch::addOperation(const Request& request)
23492349

23502350
VxlanTunnelOrch* tunnel_orch = gDirectory.get<VxlanTunnelOrch*>();
23512351
Port tunnelPort, vlanPort;
2352+
VxlanTunnelMapOrch* vxlan_tun_map_orch = gDirectory.get<VxlanTunnelMapOrch*>();
2353+
std::string vniVlanMapName;
2354+
uint32_t tmp_vlan_id = 0;
2355+
sai_object_id_t tnl_map_entry_id = SAI_NULL_OBJECT_ID;
23522356

23532357
if (!gPortsOrch->getVlanByVlanId(vlan_id, vlanPort))
23542358
{
23552359
SWSS_LOG_WARN("Vxlan tunnel map vlan id doesn't exist: %d", vlan_id);
23562360
return false;
23572361
}
23582362

2363+
/* Remote end point can be added only after local VLAN to VNI map gets created */
2364+
if (!vxlan_tun_map_orch->isVniVlanMapExists(vni_id, vniVlanMapName, &tnl_map_entry_id, &tmp_vlan_id))
2365+
{
2366+
SWSS_LOG_WARN("Vxlan tunnel map is not created for vni:%d", vni_id);
2367+
return false;
2368+
}
2369+
23592370
if (tunnel_orch->getTunnelPort(remote_vtep,tunnelPort))
23602371
{
23612372
SWSS_LOG_INFO("Vxlan tunnelPort exists: %s", remote_vtep.c_str());
@@ -2492,6 +2503,11 @@ bool EvpnRemoteVnip2mpOrch::addOperation(const Request& request)
24922503
}
24932504

24942505
VxlanTunnelOrch* tunnel_orch = gDirectory.get<VxlanTunnelOrch*>();
2506+
VxlanTunnelMapOrch* vxlan_tun_map_orch = gDirectory.get<VxlanTunnelMapOrch*>();
2507+
std::string vniVlanMapName;
2508+
uint32_t tmp_vlan_id = 0;
2509+
sai_object_id_t tnl_map_entry_id = SAI_NULL_OBJECT_ID;
2510+
24952511
Port tunnelPort, vlanPort;
24962512
auto vtep_ptr = evpn_orch->getEVPNVtep();
24972513
if (!vtep_ptr)
@@ -2507,6 +2523,13 @@ bool EvpnRemoteVnip2mpOrch::addOperation(const Request& request)
25072523
return false;
25082524
}
25092525

2526+
/* Remote end point can be added only after local VLAN to VNI map gets created */
2527+
if (!vxlan_tun_map_orch->isVniVlanMapExists(vni_id, vniVlanMapName, &tnl_map_entry_id, &tmp_vlan_id))
2528+
{
2529+
SWSS_LOG_WARN("Vxlan tunnel map is not created for vni: %d", vni_id);
2530+
return false;
2531+
}
2532+
25102533
auto src_vtep = vtep_ptr->getSrcIP().to_string();
25112534
if (tunnel_orch->getTunnelPort(src_vtep,tunnelPort, true))
25122535
{

tests/evpn_tunnel.py

+38
Original file line numberDiff line numberDiff line change
@@ -697,6 +697,18 @@ def check_vxlan_dip_tunnel(self, dvs, vtep_name, src_ip, dip):
697697

698698
self.bridgeport_map[dip] = ret[0]
699699

700+
def check_vxlan_dip_tunnel_not_created(self, dvs, vtep_name, src_ip, dip):
701+
state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0)
702+
703+
expected_state_attributes = {
704+
'src_ip': src_ip,
705+
'dst_ip': dip,
706+
'tnl_src': 'EVPN',
707+
}
708+
709+
ret = self.helper.get_key_with_attr(state_db, 'VXLAN_TUNNEL_TABLE', expected_state_attributes)
710+
assert len(ret) == 0, "Tunnel Statetable entry created"
711+
700712
def check_vlan_extension_delete(self, dvs, vlan_name, dip):
701713
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)
702714

@@ -777,6 +789,32 @@ def check_vlan_extension_p2mp(self, dvs, vlan_name, sip, dip):
777789
assert len(ret) == 1, "More than 1 L2MC group member created"
778790
self.l2mcgroup_member_map[dip+vlan_name] = ret[0]
779791

792+
def check_vlan_extension_not_created_p2mp(self, dvs, vlan_name, sip, dip):
793+
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)
794+
tbl = swsscommon.Table(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_VLAN')
795+
expected_vlan_attributes = {
796+
'SAI_VLAN_ATTR_VLAN_ID': vlan_name,
797+
}
798+
ret = self.helper.get_key_with_attr(asic_db, 'ASIC_STATE:SAI_OBJECT_TYPE_VLAN', expected_vlan_attributes)
799+
assert len(ret) > 0, "VLAN entry not created"
800+
assert len(ret) == 1, "More than 1 VLAN entry created"
801+
802+
self.vlan_id_map[vlan_name] = ret[0]
803+
status, fvs = tbl.get(self.vlan_id_map[vlan_name])
804+
805+
print(fvs)
806+
807+
uuc_flood_type = None
808+
bc_flood_type = None
809+
uuc_flood_group = None
810+
bc_flood_group = None
811+
812+
for attr,value in fvs:
813+
assert attr != 'SAI_VLAN_ATTR_UNKNOWN_UNICAST_FLOOD_CONTROL_TYPE', "Unknown unicast flood control type is set"
814+
assert attr != 'SAI_VLAN_ATTR_BROADCAST_FLOOD_CONTROL_TYPE', "Broadcast flood control type is set"
815+
assert attr != 'SAI_VLAN_ATTR_UNKNOWN_UNICAST_FLOOD_GROUP', "Unknown unicast flood group is set"
816+
assert attr != 'SAI_VLAN_ATTR_UNKNOWN_UNICAST_FLOOD_CONTROL_TYPE', "Broadcast flood group is set"
817+
780818
def check_vxlan_tunnel_entry(self, dvs, tunnel_name, vnet_name, vni_id):
781819
asic_db = swsscommon.DBConnector(swsscommon.ASIC_DB, dvs.redis_sock, 0)
782820

tests/test_evpn_tunnel.py

+46
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ def test_p2p_tunnel(self, dvs, testlog):
5959
vnilist = ['1000', '1001', '1002']
6060

6161
vxlan_obj.fetch_exist_entries(dvs)
62+
vxlan_obj.create_vlan1(dvs,"Vlan100")
63+
vxlan_obj.create_vlan1(dvs,"Vlan101")
64+
vxlan_obj.create_vlan1(dvs,"Vlan102")
6265
vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6')
6366
vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
6467
vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101')
@@ -161,3 +164,46 @@ def test_p2mp_tunnel_with_dip(self, dvs, testlog):
161164
print("Testing SIP Tunnel Deletion")
162165
vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name)
163166
vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6')
167+
168+
def test_delayed_vlan_vni_map(self, dvs, testlog):
169+
vxlan_obj = self.get_vxlan_obj()
170+
171+
tunnel_name = 'tunnel_2'
172+
map_name = 'map_1000_100'
173+
map_name_1 = 'map_1001_101'
174+
vlanlist = ['100']
175+
vnilist = ['1000']
176+
177+
vxlan_obj.fetch_exist_entries(dvs)
178+
vxlan_obj.create_vlan1(dvs,"Vlan100")
179+
vxlan_obj.create_vlan1(dvs,"Vlan101")
180+
181+
vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6')
182+
vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
183+
184+
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, tunnel_map_entry_count = 1)
185+
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
186+
187+
vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name)
188+
189+
vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7', '1001')
190+
vxlan_obj.check_vxlan_dip_tunnel_not_created(dvs, tunnel_name, '6.6.6.6', '7.7.7.7')
191+
vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101')
192+
193+
print("Testing VLAN 101 extension")
194+
vxlan_obj.check_vxlan_dip_tunnel(dvs, tunnel_name, '6.6.6.6', '7.7.7.7')
195+
vxlan_obj.check_vlan_extension(dvs, '101', '7.7.7.7')
196+
197+
print("Testing Vlan Extension removal")
198+
vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7')
199+
vxlan_obj.check_vlan_extension_delete(dvs, '101', '7.7.7.7')
200+
vxlan_obj.check_vxlan_dip_tunnel_delete(dvs, '7.7.7.7')
201+
202+
vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
203+
vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101')
204+
vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist)
205+
206+
print("Testing SIP Tunnel Deletion")
207+
vxlan_obj.remove_evpn_nvo(dvs, 'nvo1')
208+
vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name)
209+
vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6')

tests/test_evpn_tunnel_p2mp.py

+44
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ def test_vlan_extension(self, dvs, testlog):
5757
vnilist = ['1000', '1001', '1002']
5858

5959
vxlan_obj.fetch_exist_entries(dvs)
60+
vxlan_obj.create_vlan1(dvs,"Vlan100")
61+
vxlan_obj.create_vlan1(dvs,"Vlan101")
62+
vxlan_obj.create_vlan1(dvs,"Vlan102")
6063
vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6')
6164
vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
6265
vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101')
@@ -122,3 +125,44 @@ def test_vlan_extension(self, dvs, testlog):
122125
vxlan_obj.remove_evpn_nvo(dvs, 'nvo1')
123126
vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name)
124127
vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False)
128+
129+
def test_delayed_vlan_vni_map(self, dvs, testlog):
130+
vxlan_obj = self.get_vxlan_obj()
131+
132+
tunnel_name = 'tunnel_2'
133+
map_name = 'map_1000_100'
134+
map_name_1 = 'map_1001_101'
135+
vlanlist = ['100']
136+
vnilist = ['1000']
137+
138+
vxlan_obj.fetch_exist_entries(dvs)
139+
vxlan_obj.create_vlan1(dvs,"Vlan100")
140+
vxlan_obj.create_vlan1(dvs,"Vlan101")
141+
142+
vxlan_obj.create_vxlan_tunnel(dvs, tunnel_name, '6.6.6.6')
143+
vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
144+
145+
vxlan_obj.check_vxlan_sip_tunnel(dvs, tunnel_name, '6.6.6.6', vlanlist, vnilist, ignore_bp=False, tunnel_map_entry_count = 1)
146+
vxlan_obj.check_vxlan_tunnel_map_entry(dvs, tunnel_name, vlanlist, vnilist)
147+
148+
vxlan_obj.create_evpn_nvo(dvs, 'nvo1', tunnel_name)
149+
150+
vxlan_obj.create_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7', '1001')
151+
vxlan_obj.check_vlan_extension_not_created_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7')
152+
vxlan_obj.create_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101')
153+
154+
print("Testing VLAN 101 extension")
155+
vxlan_obj.check_vlan_extension_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7')
156+
157+
print("Testing Vlan Extension removal")
158+
vxlan_obj.remove_evpn_remote_vni(dvs, 'Vlan101', '7.7.7.7')
159+
vxlan_obj.check_vlan_extension_delete_p2mp(dvs, '101', '6.6.6.6', '7.7.7.7')
160+
161+
vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name, '1000', 'Vlan100')
162+
vxlan_obj.remove_vxlan_tunnel_map(dvs, tunnel_name, map_name_1, '1001', 'Vlan101')
163+
vxlan_obj.check_vxlan_tunnel_map_entry_delete(dvs, tunnel_name, vlanlist, vnilist)
164+
165+
print("Testing SIP Tunnel Deletion")
166+
vxlan_obj.remove_evpn_nvo(dvs, 'nvo1')
167+
vxlan_obj.remove_vxlan_tunnel(dvs, tunnel_name)
168+
vxlan_obj.check_vxlan_sip_tunnel_delete(dvs, tunnel_name, '6.6.6.6', ignore_bp=False)

0 commit comments

Comments
 (0)