Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vxlan tunnel endpoint custom monitoring APPL DB table. #2589

Merged
merged 15 commits into from
Jan 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 98 additions & 15 deletions orchagent/vnetorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,8 +720,11 @@ VNetRouteOrch::VNetRouteOrch(DBConnector *db, vector<string> &tableNames, VNetOr
handler_map_.insert(handler_pair(APP_VNET_RT_TUNNEL_TABLE_NAME, &VNetRouteOrch::handleTunnel));

state_db_ = shared_ptr<DBConnector>(new DBConnector("STATE_DB", 0));
app_db_ = shared_ptr<DBConnector>(new DBConnector("APPL_DB", 0));

state_vnet_rt_tunnel_table_ = unique_ptr<Table>(new Table(state_db_.get(), STATE_VNET_RT_TUNNEL_TABLE_NAME));
state_vnet_rt_adv_table_ = unique_ptr<Table>(new Table(state_db_.get(), STATE_ADVERTISE_NETWORK_TABLE_NAME));
monitor_session_producer_ = unique_ptr<Table>(new Table(app_db_.get(), APP_VNET_MONITOR_TABLE_NAME));

gBfdOrch->attach(this);
}
Expand Down Expand Up @@ -900,6 +903,7 @@ bool VNetRouteOrch::removeNextHopGroup(const string& vnet, const NextHopGroupKey
template<>
bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipPrefix,
NextHopGroupKey& nexthops, string& op, string& profile,
const string& monitoring,
const map<NextHopKey, IpAddress>& monitors)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -940,7 +944,7 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
sai_object_id_t nh_id;
if (!hasNextHopGroup(vnet, nexthops))
{
setEndpointMonitor(vnet, monitors, nexthops);
setEndpointMonitor(vnet, monitors, nexthops, monitoring, ipPrefix);
if (nexthops.getSize() == 1)
{
NextHopKey nexthop(nexthops.to_string(), true);
Expand All @@ -957,7 +961,7 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
{
if (!addNextHopGroup(vnet, nexthops, vrf_obj))
{
delEndpointMonitor(vnet, nexthops);
delEndpointMonitor(vnet, nexthops, ipPrefix);
SWSS_LOG_ERROR("Failed to create next hop group %s", nexthops.to_string().c_str());
return false;
}
Expand Down Expand Up @@ -1031,7 +1035,7 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
NextHopKey nexthop(nhg.to_string(), true);
vrf_obj->removeTunnelNextHop(nexthop);
}
delEndpointMonitor(vnet, nhg);
delEndpointMonitor(vnet, nhg, ipPrefix);
}
else
{
Expand Down Expand Up @@ -1091,7 +1095,7 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
NextHopKey nexthop(nhg.to_string(), true);
vrf_obj->removeTunnelNextHop(nexthop);
}
delEndpointMonitor(vnet, nhg);
delEndpointMonitor(vnet, nhg, ipPrefix);
}
else
{
Expand Down Expand Up @@ -1609,39 +1613,118 @@ void VNetRouteOrch::removeBfdSession(const string& vnet, const NextHopKey& endpo
bfd_sessions_.erase(monitor_addr);
}

void VNetRouteOrch::setEndpointMonitor(const string& vnet, const map<NextHopKey, IpAddress>& monitors, NextHopGroupKey& nexthops)
void VNetRouteOrch::createMonitoringSession(const string& vnet, const NextHopKey& endpoint, const IpAddress& monitor_addr, IpPrefix& ipPrefix)
{
SWSS_LOG_ENTER();

IpAddress endpoint_addr = endpoint.ip_address;
if (monitor_info_[vnet].find(ipPrefix) != monitor_info_[vnet].end() &&
monitor_info_[vnet][ipPrefix].find(endpoint) != monitor_info_[vnet][ipPrefix].end())
{
SWSS_LOG_NOTICE("Monitoring session for prefix %s endpoint %s already exist", ipPrefix.to_string().c_str(), endpoint_addr.to_string().c_str());
return;
}
else
{
vector<FieldValueTuple> data;
auto *vnet_obj = vnet_orch_->getTypePtr<VNetVrfObject>(vnet);

auto overlay_dmac = vnet_obj->getOverlayDMac();
string key = ipPrefix.to_string() + ":" + monitor_addr.to_string();
FieldValueTuple fvTuple1("packet_type", "vxlan");
data.push_back(fvTuple1);

FieldValueTuple fvTuple3("overlay_dmac", overlay_dmac.to_string());
data.push_back(fvTuple3);

monitor_session_producer_->set(key, data);

MonitorSessionInfo& info = monitor_info_[vnet][ipPrefix][endpoint];
info.monitor = monitor_addr;
info.state = MONITOR_SESSION_STATE::MONITOR_SESSION_STATE_DOWN;
}
}

void VNetRouteOrch::removeMonitoringSession(const string& vnet, const NextHopKey& endpoint, const IpAddress& monitor_addr, IpPrefix& ipPrefix)
{
SWSS_LOG_ENTER();

IpAddress endpoint_addr = endpoint.ip_address;
if (monitor_info_[vnet].find(ipPrefix) == monitor_info_[vnet].end() ||
monitor_info_[vnet][ipPrefix].find(endpoint) == monitor_info_[vnet][ipPrefix].end())
{
SWSS_LOG_NOTICE("Monitor session for prefix %s endpoint %s does not exist", ipPrefix.to_string().c_str(), endpoint_addr.to_string().c_str());
}

string key = ipPrefix.to_string() + ":" + monitor_addr.to_string();
monitor_session_producer_->del(key);
monitor_info_[vnet][ipPrefix].erase(endpoint);
}

void VNetRouteOrch::setEndpointMonitor(const string& vnet, const map<NextHopKey, IpAddress>& monitors, NextHopGroupKey& nexthops, const string& monitoring, IpPrefix& ipPrefix)
{
SWSS_LOG_ENTER();

for (auto monitor : monitors)
{
NextHopKey nh = monitor.first;
IpAddress monitor_ip = monitor.second;
if (nexthop_info_[vnet].find(nh.ip_address) == nexthop_info_[vnet].end())
if (monitoring == "custom")
{
createBfdSession(vnet, nh, monitor_ip);
if (monitor_info_[vnet].find(ipPrefix) == monitor_info_[vnet].end() ||
monitor_info_[vnet][ipPrefix].find(nh) == monitor_info_[vnet][ipPrefix].end())
{
createMonitoringSession(vnet, nh, monitor_ip, ipPrefix);
}
}
else
{
if (nexthop_info_[vnet].find(nh.ip_address) == nexthop_info_[vnet].end())
{
createBfdSession(vnet, nh, monitor_ip);
}
nexthop_info_[vnet][nh.ip_address].ref_count++;
}

nexthop_info_[vnet][nh.ip_address].ref_count++;
}
}

void VNetRouteOrch::delEndpointMonitor(const string& vnet, NextHopGroupKey& nexthops)
void VNetRouteOrch::delEndpointMonitor(const string& vnet, NextHopGroupKey& nexthops, IpPrefix& ipPrefix)
{
SWSS_LOG_ENTER();

std::set<NextHopKey> nhks = nexthops.getNextHops();
bool is_custom_monitoring = false;
if (monitor_info_[vnet].find(ipPrefix) != monitor_info_[vnet].end())
{
is_custom_monitoring = true;
}
for (auto nhk: nhks)
{
IpAddress ip = nhk.ip_address;
if (nexthop_info_[vnet].find(ip) != nexthop_info_[vnet].end()) {
if (--nexthop_info_[vnet][ip].ref_count == 0)
if (is_custom_monitoring)
{
if ( monitor_info_[vnet][ipPrefix].find(nhk) != monitor_info_[vnet][ipPrefix].end())
{
IpAddress monitor_addr = nexthop_info_[vnet][ip].monitor_addr;
removeBfdSession(vnet, nhk, monitor_addr);
removeMonitoringSession(vnet, nhk, monitor_info_[vnet][ipPrefix][nhk].monitor, ipPrefix);
}
}
else
{
if (nexthop_info_[vnet].find(ip) != nexthop_info_[vnet].end()) {
if (--nexthop_info_[vnet][ip].ref_count == 0)
{
IpAddress monitor_addr = nexthop_info_[vnet][ip].monitor_addr;
{
removeBfdSession(vnet, nhk, monitor_addr);
}
}
}
}
}
if (is_custom_monitoring)
{
monitor_info_[vnet].erase(ipPrefix);
}
}

void VNetRouteOrch::postRouteState(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops, string& profile)
Expand Down Expand Up @@ -2024,7 +2107,7 @@ bool VNetRouteOrch::handleTunnel(const Request& request)

if (vnet_orch_->isVnetExecVrf())
{
return doRouteTask<VNetVrfObject>(vnet_name, ip_pfx, nhg, op, profile, monitors);
return doRouteTask<VNetVrfObject>(vnet_name, ip_pfx, nhg, op, profile, monitoring, monitors);
}

return true;
Expand Down
24 changes: 22 additions & 2 deletions orchagent/vnetorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@

extern sai_object_id_t gVirtualRouterId;

enum class MONITOR_SESSION_STATE
{
MONITOR_SESSION_STATE_UP,
MONITOR_SESSION_STATE_DOWN,
MONITOR_SESSION_STATE_UNKNOWN,
};
const request_description_t vnet_request_description = {
{ REQ_T_STRING },
{
Expand Down Expand Up @@ -339,9 +345,16 @@ struct BfdSessionInfo
NextHopKey endpoint;
};

struct MonitorSessionInfo
{
MONITOR_SESSION_STATE state;
IpAddress monitor;
};

typedef std::map<NextHopGroupKey, NextHopGroupInfo> VNetNextHopGroupInfoTable;
typedef std::map<IpPrefix, NextHopGroupKey> VNetTunnelRouteTable;
typedef std::map<IpAddress, BfdSessionInfo> BfdSessionTable;
typedef std::map<IpPrefix, std::map<NextHopKey, MonitorSessionInfo>> MonitorSessionTable;
typedef std::map<IpAddress, VNetNextHopInfo> VNetEndpointInfoTable;

class VNetRouteOrch : public Orch2, public Subject, public Observer
Expand Down Expand Up @@ -374,8 +387,11 @@ class VNetRouteOrch : public Orch2, public Subject, public Observer

void createBfdSession(const string& vnet, const NextHopKey& endpoint, const IpAddress& ipAddr);
void removeBfdSession(const string& vnet, const NextHopKey& endpoint, const IpAddress& ipAddr);
void setEndpointMonitor(const string& vnet, const map<NextHopKey, IpAddress>& monitors, NextHopGroupKey& nexthops);
void delEndpointMonitor(const string& vnet, NextHopGroupKey& nexthops);
void createMonitoringSession(const string& vnet, const NextHopKey& endpoint, const IpAddress& ipAddr, IpPrefix& ipPrefix);
void removeMonitoringSession(const string& vnet, const NextHopKey& endpoint, const IpAddress& ipAddr, IpPrefix& ipPrefix);
void setEndpointMonitor(const string& vnet, const map<NextHopKey, IpAddress>& monitors, NextHopGroupKey& nexthops,
const string& monitoring, IpPrefix& ipPrefix);
void delEndpointMonitor(const string& vnet, NextHopGroupKey& nexthops, IpPrefix& ipPrefix);
void postRouteState(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops, string& profile);
void removeRouteState(const string& vnet, IpPrefix& ipPrefix);
void addRouteAdvertisement(IpPrefix& ipPrefix, string& profile);
Expand All @@ -386,6 +402,7 @@ class VNetRouteOrch : public Orch2, public Subject, public Observer

template<typename T>
bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops, string& op, string& profile,
const string& monitoring,
const std::map<NextHopKey, IpAddress>& monitors=std::map<NextHopKey, IpAddress>());

template<typename T>
Expand All @@ -400,9 +417,12 @@ class VNetRouteOrch : public Orch2, public Subject, public Observer
std::map<std::string, VNetNextHopGroupInfoTable> syncd_nexthop_groups_;
std::map<std::string, VNetTunnelRouteTable> syncd_tunnel_routes_;
BfdSessionTable bfd_sessions_;
std::map<std::string, MonitorSessionTable> monitor_info_;
std::map<std::string, VNetEndpointInfoTable> nexthop_info_;
ProducerStateTable bfd_session_producer_;
unique_ptr<Table> monitor_session_producer_;
shared_ptr<DBConnector> state_db_;
shared_ptr<DBConnector> app_db_;
unique_ptr<Table> state_vnet_rt_tunnel_table_;
unique_ptr<Table> state_vnet_rt_adv_table_;
};
Expand Down
52 changes: 49 additions & 3 deletions tests/test_vnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ class VnetVxlanVrfTunnel(object):
ASIC_NEXT_HOP_GROUP = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP"
ASIC_NEXT_HOP_GROUP_MEMBER = "ASIC_STATE:SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER"
ASIC_BFD_SESSION = "ASIC_STATE:SAI_OBJECT_TYPE_BFD_SESSION"
APP_VNET_MONITOR = "VNET_MONITOR_TABLE"

def __init__(self):
self.tunnel_map_ids = set()
Expand Down Expand Up @@ -960,7 +961,21 @@ def _access_function():

return True


def check_custom_monitor_app_db(self, dvs, prefix, endpoint, packet_type, overlay_dmac):
app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)
key = prefix + ':' + endpoint
check_object(app_db, self.APP_VNET_MONITOR, key,
{
"packet_type": packet_type,
"overlay_dmac" : overlay_dmac
}
)
return True
def check_custom_monitor_deleted(self, dvs, prefix, endpoint):
app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0)
key = prefix + ':' + endpoint
check_deleted_object(app_db, self.APP_VNET_MONITOR, key)

class TestVnetOrch(object):

def get_vnet_obj(self):
Expand Down Expand Up @@ -2376,15 +2391,15 @@ def test_vnet_orch_17(self, dvs, testlog):
vnet_obj.fetch_exist_entries(dvs)

create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9')
create_vnet_entry(dvs, 'Vnet17', tunnel_name, '10009', "", overlay_dmac="22:33:33:44:44:66")
create_vnet_entry(dvs, 'Vnet17', tunnel_name, '10009', "")

vnet_obj.check_vnet_entry(dvs, 'Vnet17')
vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet17', '10009')

vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9')

vnet_obj.fetch_exist_entries(dvs)
create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet17', '9.0.0.1,9.0.0.2,9.0.0.3', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3', primary ='9.0.0.1',monitoring='custom', adv_prefix='100.100.1.1/27')
create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet17', '9.0.0.1,9.0.0.2,9.0.0.3', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3')

# default bfd status is down, route should not be programmed in this status
vnet_obj.check_del_vnet_routes(dvs, 'Vnet17', ["100.100.1.1/32"])
Expand Down Expand Up @@ -2432,6 +2447,37 @@ def test_vnet_orch_17(self, dvs, testlog):
delete_vnet_entry(dvs, 'Vnet17')
vnet_obj.check_del_vnet_entry(dvs, 'Vnet17')

'''
Test 18 - Test for vxlan custom monitoring config.
'''
def test_vnet_orch_18(self, dvs, testlog):
vnet_obj = self.get_vnet_obj()

tunnel_name = 'tunnel_18'

vnet_obj.fetch_exist_entries(dvs)

create_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9')
create_vnet_entry(dvs, 'Vnet18', tunnel_name, '10009', "", overlay_dmac="22:33:33:44:44:66")

vnet_obj.check_vnet_entry(dvs, 'Vnet18')
vnet_obj.check_vxlan_tunnel_entry(dvs, tunnel_name, 'Vnet18', '10009')

vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '9.9.9.9')

vnet_obj.fetch_exist_entries(dvs)
create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet18', '9.0.0.1,9.0.0.2,9.0.0.3', ep_monitor='9.1.0.1,9.1.0.2,9.1.0.3',primary ='9.0.0.1',monitoring='custom', adv_prefix='100.100.1.1/27')

vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.1/32", "9.1.0.1", "vxlan", "22:33:33:44:44:66")
vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.1/32", "9.1.0.2", "vxlan", "22:33:33:44:44:66")
vnet_obj.check_custom_monitor_app_db(dvs, "100.100.1.1/32", "9.1.0.3", "vxlan", "22:33:33:44:44:66")

delete_vnet_routes(dvs, "100.100.1.1/32", 'Vnet18')

vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.1")
vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.2")
vnet_obj.check_custom_monitor_deleted(dvs, "100.100.1.1/32", "9.1.0.3")

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