Skip to content

Commit

Permalink
[Vxlanmgr] vnet netdev cleanup during config reload fix (sonic-net#2191)
Browse files Browse the repository at this point in the history
* 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 <vkarri@nvidia.com>
  • Loading branch information
vivekrnv authored Mar 26, 2022
1 parent 2bef62b commit 7350d49
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 14 deletions.
71 changes: 57 additions & 14 deletions cfgmgr/vxlanmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1031,29 +1031,59 @@ int VxlanMgr::deleteVxlanNetdevice(std::string vxlan_dev_name)
return swss::exec(cmd, res);
}

std::vector<std::string> VxlanMgr::parseNetDev(const string& stdout){
std::vector<std::string> netdevs;
std::regex device_name_pattern("^\\d+:\\s+([^:]+)");
std::smatch match_result;
auto lines = tokenize(stdout, '\n');
for (const std::string & line : lines)
{
SWSS_LOG_DEBUG("line : %s\n",line.c_str());
if (!std::regex_search(line, match_result, device_name_pattern))
{
continue;
}
std::string dev_name = match_result[1];
netdevs.push_back(dev_name);
}
return netdevs;
}

void VxlanMgr::getAllVxlanNetDevices()
{
std::string stdout;
const std::string cmd = std::string("") + IP_CMD + " link show type vxlan";

// Get VxLan Netdev Interfaces
std::string cmd = std::string("") + IP_CMD + " link show type vxlan";
int ret = swss::exec(cmd, stdout);
if (ret != 0)
{
SWSS_LOG_ERROR("Cannot get devices by command : %s", cmd.c_str());
return;
SWSS_LOG_ERROR("Cannot get vxlan devices by command : %s", cmd.c_str());
stdout.clear();
}
std::regex device_name_pattern("^\\d+:\\s+([^:]+)");
std::smatch match_result;
auto lines = tokenize(stdout, '\n');
for (const std::string & line : lines)
std::vector<std::string> netdevs = parseNetDev(stdout);
for (auto netdev : netdevs)
{
SWSS_LOG_INFO("line : %s\n",line.c_str());
if (!std::regex_search(line, match_result, device_name_pattern))
m_vxlanNetDevices[netdev] = VXLAN;
}

// Get VxLanIf Netdev Interfaces
cmd = std::string("") + IP_CMD + " link show type bridge";
ret = swss::exec(cmd, stdout);
if (ret != 0)
{
SWSS_LOG_ERROR("Cannot get vxlanIf devices by command : %s", cmd.c_str());
stdout.clear();
}
netdevs = parseNetDev(stdout);
for (auto netdev : netdevs)
{
if (netdev.find(VXLAN_IF_NAME_PREFIX) == 0)
{
continue;
m_vxlanNetDevices[netdev] = VXLAN_IF;
}
std::string vxlan_dev_name = match_result[1];
m_vxlanNetDevices[vxlan_dev_name] = vxlan_dev_name;
}

return;
}

Expand Down Expand Up @@ -1150,8 +1180,21 @@ void VxlanMgr::clearAllVxlanDevices()
{
for (auto it = m_vxlanNetDevices.begin(); it != m_vxlanNetDevices.end();)
{
SWSS_LOG_INFO("Deleting Stale NetDevice vxlandevname %s\n", (it->first).c_str());
deleteVxlanNetdevice(it->first);
std::string netdev_name = it->first;
std::string netdev_type = it->second;
SWSS_LOG_INFO("Deleting Stale NetDevice %s, type: %s\n", netdev_name.c_str(), netdev_type.c_str());
VxlanInfo info;
std::string res;
if (netdev_type.compare(VXLAN))
{
info.m_vxlan = netdev_name;
cmdDeleteVxlan(info, res);
}
else if(netdev_type.compare(VXLAN_IF))
{
info.m_vxlanIf = netdev_name;
cmdDeleteVxlanIf(info, res);
}
it = m_vxlanNetDevices.erase(it);
}
}
Expand Down
2 changes: 2 additions & 0 deletions cfgmgr/vxlanmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "orch.h"

#include <map>
#include <vector>
#include <memory>
#include <string>
#include <utility>
Expand Down Expand Up @@ -70,6 +71,7 @@ class VxlanMgr : public Orch
int createVxlanNetdevice(std::string vxlanTunnelName, std::string vni_id,
std::string src_ip, std::string dst_ip, std::string vlan_id);
int deleteVxlanNetdevice(std::string vxlan_dev_name);
std::vector<std::string> parseNetDev(const std::string& stdout);
void getAllVxlanNetDevices();

/*
Expand Down
72 changes: 72 additions & 0 deletions tests/test_vxlan_tunnel.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ def create_entry_pst(db, table, separator, key, pairs):
create_entry(tbl, key, pairs)


def delete_entry_pst(db, table, key):
tbl = swsscommon.ProducerStateTable(db, table)
tbl._del(key)
time.sleep(1)


def delete_entry_tbl(db, table, key):
tbl = swsscommon.Table(db, table)
tbl._del(key)
time.sleep(1)


def how_many_entries_exist(db, table):
tbl = swsscommon.Table(db, table)
return len(tbl.getKeys())
Expand Down Expand Up @@ -324,6 +336,66 @@ def test_vxlan_term_orch(self, dvs, testlog):
create_vxlan_tunnel_entry(dvs, 'tunnel_4', 'entry_2', tunnel_map_map, 'Vlan57', '857',
tunnel_map_ids, tunnel_map_entry_ids, tunnel_ids, tunnel_term_ids)

def apply_test_vnet_cfg(cfg_db):

# create VXLAN Tunnel
create_entry_tbl(
cfg_db,
"VXLAN_TUNNEL", '|', "tunnel1",
[
("src_ip", "1.1.1.1")
],
)

# create VNET
create_entry_tbl(
cfg_db,
"VNET", '|', "tunnel1",
[
("vxlan_tunnel", "tunnel1"),
("vni", "1")
],
)

return


@pytest.fixture
def env_setup(dvs):
cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)

create_entry_pst(
app_db,
"SWITCH_TABLE", ':', "switch",
[
("vxlan_router_mac", "00:01:02:03:04:05")
],
)

apply_test_vnet_cfg(cfg_db)

yield

delete_entry_pst(app_db, "SWITCH_TABLE", "switch")
delete_entry_tbl(cfg_db, "VXLAN_TUNNEL", "tunnel1")
delete_entry_tbl(cfg_db, "VNET", "Vnet1")

def test_vnet_cleanup_config_reload(dvs, env_setup):

# Restart vxlanmgrd Process
dvs.runcmd(["systemctl", "restart", "vxlanmgrd"])

# Reapply cfg to simulate cfg reload
cfg_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)
apply_test_vnet_cfg(cfg_db)

time.sleep(0.5)

# Check if the netdevices is created as expected
ret, stdout = dvs.runcmd(["ip", "link", "show"])
assert "Vxlan1" in stdout
assert "Brvxlan1" in stdout

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

0 comments on commit 7350d49

Please sign in to comment.