Skip to content

Commit 7350d49

Browse files
authored
[Vxlanmgr] vnet netdev cleanup during config reload fix (sonic-net#2191)
* Enhanced the Existing cleanup methods i.e. getAllVxlanNetDevices & clearAllVxlanDevices to also include any stale Brvxlan interfaces and remove them. Signed-off-by: Vivek Reddy Karri <[email protected]>
1 parent 2bef62b commit 7350d49

File tree

3 files changed

+131
-14
lines changed

3 files changed

+131
-14
lines changed

cfgmgr/vxlanmgr.cpp

+57-14
Original file line numberDiff line numberDiff line change
@@ -1031,29 +1031,59 @@ int VxlanMgr::deleteVxlanNetdevice(std::string vxlan_dev_name)
10311031
return swss::exec(cmd, res);
10321032
}
10331033

1034+
std::vector<std::string> VxlanMgr::parseNetDev(const string& stdout){
1035+
std::vector<std::string> netdevs;
1036+
std::regex device_name_pattern("^\\d+:\\s+([^:]+)");
1037+
std::smatch match_result;
1038+
auto lines = tokenize(stdout, '\n');
1039+
for (const std::string & line : lines)
1040+
{
1041+
SWSS_LOG_DEBUG("line : %s\n",line.c_str());
1042+
if (!std::regex_search(line, match_result, device_name_pattern))
1043+
{
1044+
continue;
1045+
}
1046+
std::string dev_name = match_result[1];
1047+
netdevs.push_back(dev_name);
1048+
}
1049+
return netdevs;
1050+
}
1051+
10341052
void VxlanMgr::getAllVxlanNetDevices()
10351053
{
10361054
std::string stdout;
1037-
const std::string cmd = std::string("") + IP_CMD + " link show type vxlan";
1055+
1056+
// Get VxLan Netdev Interfaces
1057+
std::string cmd = std::string("") + IP_CMD + " link show type vxlan";
10381058
int ret = swss::exec(cmd, stdout);
10391059
if (ret != 0)
10401060
{
1041-
SWSS_LOG_ERROR("Cannot get devices by command : %s", cmd.c_str());
1042-
return;
1061+
SWSS_LOG_ERROR("Cannot get vxlan devices by command : %s", cmd.c_str());
1062+
stdout.clear();
10431063
}
1044-
std::regex device_name_pattern("^\\d+:\\s+([^:]+)");
1045-
std::smatch match_result;
1046-
auto lines = tokenize(stdout, '\n');
1047-
for (const std::string & line : lines)
1064+
std::vector<std::string> netdevs = parseNetDev(stdout);
1065+
for (auto netdev : netdevs)
10481066
{
1049-
SWSS_LOG_INFO("line : %s\n",line.c_str());
1050-
if (!std::regex_search(line, match_result, device_name_pattern))
1067+
m_vxlanNetDevices[netdev] = VXLAN;
1068+
}
1069+
1070+
// Get VxLanIf Netdev Interfaces
1071+
cmd = std::string("") + IP_CMD + " link show type bridge";
1072+
ret = swss::exec(cmd, stdout);
1073+
if (ret != 0)
1074+
{
1075+
SWSS_LOG_ERROR("Cannot get vxlanIf devices by command : %s", cmd.c_str());
1076+
stdout.clear();
1077+
}
1078+
netdevs = parseNetDev(stdout);
1079+
for (auto netdev : netdevs)
1080+
{
1081+
if (netdev.find(VXLAN_IF_NAME_PREFIX) == 0)
10511082
{
1052-
continue;
1083+
m_vxlanNetDevices[netdev] = VXLAN_IF;
10531084
}
1054-
std::string vxlan_dev_name = match_result[1];
1055-
m_vxlanNetDevices[vxlan_dev_name] = vxlan_dev_name;
10561085
}
1086+
10571087
return;
10581088
}
10591089

@@ -1150,8 +1180,21 @@ void VxlanMgr::clearAllVxlanDevices()
11501180
{
11511181
for (auto it = m_vxlanNetDevices.begin(); it != m_vxlanNetDevices.end();)
11521182
{
1153-
SWSS_LOG_INFO("Deleting Stale NetDevice vxlandevname %s\n", (it->first).c_str());
1154-
deleteVxlanNetdevice(it->first);
1183+
std::string netdev_name = it->first;
1184+
std::string netdev_type = it->second;
1185+
SWSS_LOG_INFO("Deleting Stale NetDevice %s, type: %s\n", netdev_name.c_str(), netdev_type.c_str());
1186+
VxlanInfo info;
1187+
std::string res;
1188+
if (netdev_type.compare(VXLAN))
1189+
{
1190+
info.m_vxlan = netdev_name;
1191+
cmdDeleteVxlan(info, res);
1192+
}
1193+
else if(netdev_type.compare(VXLAN_IF))
1194+
{
1195+
info.m_vxlanIf = netdev_name;
1196+
cmdDeleteVxlanIf(info, res);
1197+
}
11551198
it = m_vxlanNetDevices.erase(it);
11561199
}
11571200
}

cfgmgr/vxlanmgr.h

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "orch.h"
77

88
#include <map>
9+
#include <vector>
910
#include <memory>
1011
#include <string>
1112
#include <utility>
@@ -70,6 +71,7 @@ class VxlanMgr : public Orch
7071
int createVxlanNetdevice(std::string vxlanTunnelName, std::string vni_id,
7172
std::string src_ip, std::string dst_ip, std::string vlan_id);
7273
int deleteVxlanNetdevice(std::string vxlan_dev_name);
74+
std::vector<std::string> parseNetDev(const std::string& stdout);
7375
void getAllVxlanNetDevices();
7476

7577
/*

tests/test_vxlan_tunnel.py

+72
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ def create_entry_pst(db, table, separator, key, pairs):
2626
create_entry(tbl, key, pairs)
2727

2828

29+
def delete_entry_pst(db, table, key):
30+
tbl = swsscommon.ProducerStateTable(db, table)
31+
tbl._del(key)
32+
time.sleep(1)
33+
34+
35+
def delete_entry_tbl(db, table, key):
36+
tbl = swsscommon.Table(db, table)
37+
tbl._del(key)
38+
time.sleep(1)
39+
40+
2941
def how_many_entries_exist(db, table):
3042
tbl = swsscommon.Table(db, table)
3143
return len(tbl.getKeys())
@@ -324,6 +336,66 @@ def test_vxlan_term_orch(self, dvs, testlog):
324336
create_vxlan_tunnel_entry(dvs, 'tunnel_4', 'entry_2', tunnel_map_map, 'Vlan57', '857',
325337
tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids)
326338

339+
def apply_test_vnet_cfg(cfg_db):
340+
341+
# create VXLAN Tunnel
342+
create_entry_tbl(
343+
cfg_db,
344+
"VXLAN_TUNNEL", '|', "tunnel1",
345+
[
346+
("src_ip", "1.1.1.1")
347+
],
348+
)
349+
350+
# create VNET
351+
create_entry_tbl(
352+
cfg_db,
353+
"VNET", '|', "tunnel1",
354+
[
355+
("vxlan_tunnel", "tunnel1"),
356+
("vni", "1")
357+
],
358+
)
359+
360+
return
361+
362+
363+
@pytest.fixture
364+
def env_setup(dvs):
365+
cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
366+
app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)
367+
368+
create_entry_pst(
369+
app_db,
370+
"SWITCH_TABLE", ':', "switch",
371+
[
372+
("vxlan_router_mac", "00:01:02:03:04:05")
373+
],
374+
)
375+
376+
apply_test_vnet_cfg(cfg_db)
377+
378+
yield
379+
380+
delete_entry_pst(app_db, "SWITCH_TABLE", "switch")
381+
delete_entry_tbl(cfg_db, "VXLAN_TUNNEL", "tunnel1")
382+
delete_entry_tbl(cfg_db, "VNET", "Vnet1")
383+
384+
def test_vnet_cleanup_config_reload(dvs, env_setup):
385+
386+
# Restart vxlanmgrd Process
387+
dvs.runcmd(["systemctl", "restart", "vxlanmgrd"])
388+
389+
# Reapply cfg to simulate cfg reload
390+
cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
391+
apply_test_vnet_cfg(cfg_db)
392+
393+
time.sleep(0.5)
394+
395+
# Check if the netdevices is created as expected
396+
ret, stdout = dvs.runcmd(["ip", "link", "show"])
397+
assert "Vxlan1" in stdout
398+
assert "Brvxlan1" in stdout
327399

328400
# Add Dummy always-pass test at end as workaroud
329401
# for issue when Flaky fail on final test it invokes module tear-down before retrying

0 commit comments

Comments
 (0)