Skip to content

Commit

Permalink
Vxlan tunnel endpoint custom monitoring APPL DB table. (#2589)
Browse files Browse the repository at this point in the history
* added support for monitoring, primary and adv_prefix. changed filter_mac to overlay_dmac
* Data Structures and code to write APP_DB VNET_MONITOR table entries for custom monitoring of Vxlan tunnel endpoints.
  • Loading branch information
siqbal1986 authored Jan 25, 2023
1 parent 7f03db2 commit c54b3d1
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 20 deletions.
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

0 comments on commit c54b3d1

Please sign in to comment.