Skip to content

Commit

Permalink
Add BGP profile to Vnet routes (#2337)
Browse files Browse the repository at this point in the history
*Add BGP profile support to Vnet routes
  • Loading branch information
prsunny authored Jul 8, 2022
1 parent fe11cc7 commit bf91a49
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 22 deletions.
58 changes: 50 additions & 8 deletions orchagent/vnetorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,28 @@ bool VNetVrfObject::addRoute(IpPrefix& ipPrefix, NextHopGroupKey& nexthops)
return true;
}

void VNetVrfObject::addProfile(IpPrefix& ipPrefix, string& profile)
{
profile_[ipPrefix] = profile;
}

void VNetVrfObject::removeProfile(IpPrefix& ipPrefix)
{
if (profile_.find(ipPrefix) != profile_.end())
{
profile_.erase(ipPrefix);
}
}

string VNetVrfObject::getProfile(IpPrefix& ipPrefix)
{
if (profile_.find(ipPrefix) != profile_.end())
{
return profile_[ipPrefix];
}
return string();
}

void VNetVrfObject::increaseNextHopRefCount(const nextHop& nh)
{
/* Return when there is no next hop (dropped) */
Expand Down Expand Up @@ -872,7 +894,7 @@ bool VNetRouteOrch::removeNextHopGroup(const string& vnet, const NextHopGroupKey

template<>
bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipPrefix,
NextHopGroupKey& nexthops, string& op,
NextHopGroupKey& nexthops, string& op, string& profile,
const map<NextHopKey, IpAddress>& monitors)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -1011,6 +1033,7 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
syncd_nexthop_groups_[vnet][nhg].tunnel_routes.erase(ipPrefix);
}
vrf_obj->removeRoute(ipPrefix);
vrf_obj->removeProfile(ipPrefix);
}

syncd_nexthop_groups_[vnet][nexthops].tunnel_routes.insert(ipPrefix);
Expand All @@ -1019,7 +1042,12 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
syncd_nexthop_groups_[vnet][nexthops].ref_count++;
vrf_obj->addRoute(ipPrefix, nexthops);

postRouteState(vnet, ipPrefix, nexthops);
if (!profile.empty())
{
vrf_obj->addProfile(ipPrefix, profile);
}

postRouteState(vnet, ipPrefix, nexthops, profile);
}
else if (op == DEL_COMMAND)
{
Expand Down Expand Up @@ -1071,6 +1099,7 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
}

vrf_obj->removeRoute(ipPrefix);
vrf_obj->removeProfile(ipPrefix);

removeRouteState(vnet, ipPrefix);
}
Expand Down Expand Up @@ -1609,7 +1638,7 @@ void VNetRouteOrch::delEndpointMonitor(const string& vnet, NextHopGroupKey& next
}
}

void VNetRouteOrch::postRouteState(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops)
void VNetRouteOrch::postRouteState(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops, string& profile)
{
const string state_db_key = vnet + state_db_key_delimiter + ipPrefix.to_string();
vector<FieldValueTuple> fvVector;
Expand All @@ -1634,7 +1663,7 @@ void VNetRouteOrch::postRouteState(const string& vnet, IpPrefix& ipPrefix, NextH
{
if (route_state == "active")
{
addRouteAdvertisement(ipPrefix);
addRouteAdvertisement(ipPrefix, profile);
}
else
{
Expand All @@ -1650,11 +1679,18 @@ void VNetRouteOrch::removeRouteState(const string& vnet, IpPrefix& ipPrefix)
removeRouteAdvertisement(ipPrefix);
}

void VNetRouteOrch::addRouteAdvertisement(IpPrefix& ipPrefix)
void VNetRouteOrch::addRouteAdvertisement(IpPrefix& ipPrefix, string& profile)
{
const string key = ipPrefix.to_string();
vector<FieldValueTuple> fvs;
fvs.push_back(FieldValueTuple("", ""));
if (profile.empty())
{
fvs.push_back(FieldValueTuple("", ""));
}
else
{
fvs.push_back(FieldValueTuple("profile", profile));
}
state_vnet_rt_adv_table_->set(key, fvs);
}

Expand Down Expand Up @@ -1865,7 +1901,8 @@ void VNetRouteOrch::updateVnetTunnel(const BfdUpdate& update)
// Post configured in State DB
for (auto ip_pfx : syncd_nexthop_groups_[vnet][nexthops].tunnel_routes)
{
postRouteState(vnet, ip_pfx, nexthops);
string profile = vrf_obj->getProfile(ip_pfx);
postRouteState(vnet, ip_pfx, nexthops, profile);
}
}
}
Expand All @@ -1878,6 +1915,7 @@ bool VNetRouteOrch::handleTunnel(const Request& request)
vector<string> mac_list;
vector<string> vni_list;
vector<IpAddress> monitor_list;
string profile = "";

for (const auto& name: request.getAttrFieldNames())
{
Expand All @@ -1899,6 +1937,10 @@ bool VNetRouteOrch::handleTunnel(const Request& request)
{
monitor_list = request.getAttrIPList(name);
}
else if (name == "profile")
{
profile = request.getAttrString(name);
}
else
{
SWSS_LOG_INFO("Unknown attribute: %s", name.c_str());
Expand Down Expand Up @@ -1962,7 +2004,7 @@ bool VNetRouteOrch::handleTunnel(const Request& request)

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

return true;
Expand Down
13 changes: 10 additions & 3 deletions orchagent/vnetorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ struct nextHop

typedef std::map<IpPrefix, NextHopGroupKey> TunnelRoutes;
typedef std::map<IpPrefix, nextHop> RouteMap;
typedef std::map<IpPrefix, string> ProfileMap;

class VNetVrfObject : public VNetObject
{
Expand Down Expand Up @@ -181,6 +182,10 @@ class VNetVrfObject : public VNetObject
bool addRoute(IpPrefix& ipPrefix, nextHop& nh);
bool removeRoute(IpPrefix& ipPrefix);

void addProfile(IpPrefix& ipPrefix, string& profile);
void removeProfile(IpPrefix& ipPrefix);
string getProfile(IpPrefix& ipPrefix);

size_t getRouteCount() const;
bool getRouteNextHop(IpPrefix& ipPrefix, nextHop& nh);
bool hasRoute(IpPrefix& ipPrefix);
Expand All @@ -201,6 +206,7 @@ class VNetVrfObject : public VNetObject

TunnelRoutes tunnels_;
RouteMap routes_;
ProfileMap profile_;
};

typedef std::unique_ptr<VNetObject> VNetObject_T;
Expand Down Expand Up @@ -275,6 +281,7 @@ const request_description_t vnet_route_description = {
{ "vni", REQ_T_STRING },
{ "mac_address", REQ_T_STRING },
{ "endpoint_monitor", REQ_T_IP_LIST },
{ "profile", REQ_T_STRING },
},
{ }
};
Expand Down Expand Up @@ -356,16 +363,16 @@ class VNetRouteOrch : public Orch2, public Subject, public Observer
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 postRouteState(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops);
void postRouteState(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops, string& profile);
void removeRouteState(const string& vnet, IpPrefix& ipPrefix);
void addRouteAdvertisement(IpPrefix& ipPrefix);
void addRouteAdvertisement(IpPrefix& ipPrefix, string& profile);
void removeRouteAdvertisement(IpPrefix& ipPrefix);

void updateVnetTunnel(const BfdUpdate&);
bool updateTunnelRoute(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops, string& op);

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

template<typename T>
Expand Down
31 changes: 20 additions & 11 deletions tests/test_vnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,11 @@ def delete_vnet_local_routes(dvs, prefix, vnet_name):
time.sleep(2)


def create_vnet_routes(dvs, prefix, vnet_name, endpoint, mac="", vni=0, ep_monitor=""):
set_vnet_routes(dvs, prefix, vnet_name, endpoint, mac=mac, vni=vni, ep_monitor=ep_monitor)
def create_vnet_routes(dvs, prefix, vnet_name, endpoint, mac="", vni=0, ep_monitor="", profile=""):
set_vnet_routes(dvs, prefix, vnet_name, endpoint, mac=mac, vni=vni, ep_monitor=ep_monitor, profile=profile)


def set_vnet_routes(dvs, prefix, vnet_name, endpoint, mac="", vni=0, ep_monitor=""):
def set_vnet_routes(dvs, prefix, vnet_name, endpoint, mac="", vni=0, ep_monitor="", profile=""):
conf_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0)

attrs = [
Expand All @@ -160,6 +160,9 @@ def set_vnet_routes(dvs, prefix, vnet_name, endpoint, mac="", vni=0, ep_monitor=
if ep_monitor:
attrs.append(('endpoint_monitor', ep_monitor))

if profile:
attrs.append(('profile', profile))

tbl = swsscommon.Table(conf_db, "VNET_ROUTE_TUNNEL")
fvs = swsscommon.FieldValuePairs(attrs)
tbl.set("%s|%s" % (vnet_name, prefix), fvs)
Expand Down Expand Up @@ -490,13 +493,19 @@ def check_remove_state_db_routes(dvs, vnet, prefix):
assert vnet + '|' + prefix not in keys


def check_routes_advertisement(dvs, prefix):
def check_routes_advertisement(dvs, prefix, profile=""):
state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0)
tbl = swsscommon.Table(state_db, "ADVERTISE_NETWORK_TABLE")
keys = tbl.getKeys()

assert prefix in keys

if profile:
status, fvs = tbl.get(prefix)
assert status, "Got an error when get a key"
fvs = dict(fvs)
assert fvs['profile'] == profile


def check_remove_routes_advertisement(dvs, prefix):
state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0)
Expand Down Expand Up @@ -2011,7 +2020,7 @@ def test_vnet_orch_12(self, dvs, testlog):
vnet_obj.check_vxlan_tunnel(dvs, tunnel_name, '12.12.12.12')

vnet_obj.fetch_exist_entries(dvs)
create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet12', '12.0.0.1,12.0.0.2,12.0.0.3', ep_monitor='12.1.0.1,12.1.0.2,12.1.0.3')
create_vnet_routes(dvs, "100.100.1.1/32", 'Vnet12', '12.0.0.1,12.0.0.2,12.0.0.3', ep_monitor='12.1.0.1,12.1.0.2,12.1.0.3', profile="test_profile")

# default bfd status is down, route should not be programmed in this status
vnet_obj.check_del_vnet_routes(dvs, 'Vnet12', ["100.100.1.1/32"])
Expand All @@ -2025,14 +2034,14 @@ def test_vnet_orch_12(self, dvs, testlog):
time.sleep(2)
route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.2', '12.0.0.3'], tunnel_name)
check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1', '12.0.0.2', '12.0.0.3'])
check_routes_advertisement(dvs, "100.100.1.1/32")
check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile")

# Remove endpoint from group if it goes down
update_bfd_session_state(dvs, '12.1.0.2', 'Down')
time.sleep(2)
route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.3'], tunnel_name, route_ids=route1, nhg=nhg1_1)
check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1', '12.0.0.3'])
check_routes_advertisement(dvs, "100.100.1.1/32")
check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile")

# Create another tunnel route with endpoint group overlapped with route1
vnet_obj.fetch_exist_entries(dvs)
Expand All @@ -2054,15 +2063,15 @@ def test_vnet_orch_12(self, dvs, testlog):

route1, nhg1_1 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1'], tunnel_name, route_ids=route1, nhg=nhg1_1)
check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1'])
check_routes_advertisement(dvs, "100.100.1.1/32")
check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile")

# Set the route1 to a new group
set_vnet_routes(dvs, "100.100.1.1/32", 'Vnet12', '12.0.0.1,12.0.0.2,12.0.0.3,12.0.0.4', ep_monitor='12.1.0.1,12.1.0.2,12.1.0.3,12.1.0.4')
set_vnet_routes(dvs, "100.100.1.1/32", 'Vnet12', '12.0.0.1,12.0.0.2,12.0.0.3,12.0.0.4', ep_monitor='12.1.0.1,12.1.0.2,12.1.0.3,12.1.0.4', profile="test_profile2")
update_bfd_session_state(dvs, '12.1.0.4', 'Up')
time.sleep(2)
route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.4'], tunnel_name, route_ids=route1)
check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1', '12.0.0.4'])
check_routes_advertisement(dvs, "100.100.1.1/32")
check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile2")

# Check the previous nexthop group is removed
vnet_obj.fetch_exist_entries(dvs)
Expand All @@ -2073,7 +2082,7 @@ def test_vnet_orch_12(self, dvs, testlog):
time.sleep(2)
route1, nhg1_2 = vnet_obj.check_vnet_ecmp_routes(dvs, 'Vnet12', ['12.0.0.1', '12.0.0.2', '12.0.0.4'], tunnel_name, route_ids=route1, nhg=nhg1_2)
check_state_db_routes(dvs, 'Vnet12', "100.100.1.1/32", ['12.0.0.1', '12.0.0.2', '12.0.0.4'])
check_routes_advertisement(dvs, "100.100.1.1/32")
check_routes_advertisement(dvs, "100.100.1.1/32", "test_profile2")

# Set all endpoint to down state
update_bfd_session_state(dvs, '12.1.0.1', 'Down')
Expand Down

0 comments on commit bf91a49

Please sign in to comment.