From d5d2afd70eb0e6678c7970e111c3070fbc39afc9 Mon Sep 17 00:00:00 2001 From: Prince Date: Sat, 18 Jun 2022 00:14:02 +0000 Subject: [PATCH] Add BGP profile to Vnet routes --- orchagent/vnetorch.cpp | 58 ++++++++++++++++++++++++++++++++++++------ orchagent/vnetorch.h | 13 +++++++--- tests/test_vnet.py | 31 ++++++++++++++-------- 3 files changed, 80 insertions(+), 22 deletions(-) diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index 069a91d017f..e7c69a75344 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -169,6 +169,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) */ @@ -820,7 +842,7 @@ bool VNetRouteOrch::removeNextHopGroup(const string& vnet, const NextHopGroupKey template<> bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipPrefix, - NextHopGroupKey& nexthops, string& op, + NextHopGroupKey& nexthops, string& op, string& profile, const map& monitors) { SWSS_LOG_ENTER(); @@ -959,6 +981,7 @@ bool VNetRouteOrch::doRouteTask(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); @@ -967,7 +990,12 @@ bool VNetRouteOrch::doRouteTask(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) { @@ -1019,6 +1047,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP } vrf_obj->removeRoute(ipPrefix); + vrf_obj->removeProfile(ipPrefix); removeRouteState(vnet, ipPrefix); } @@ -1556,7 +1585,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 fvVector; @@ -1581,7 +1610,7 @@ void VNetRouteOrch::postRouteState(const string& vnet, IpPrefix& ipPrefix, NextH { if (route_state == "active") { - addRouteAdvertisement(ipPrefix); + addRouteAdvertisement(ipPrefix, profile); } else { @@ -1597,11 +1626,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 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); } @@ -1792,7 +1828,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); } } } @@ -1805,6 +1842,7 @@ bool VNetRouteOrch::handleTunnel(const Request& request) vector mac_list; vector vni_list; vector monitor_list; + string profile = ""; for (const auto& name: request.getAttrFieldNames()) { @@ -1826,6 +1864,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()); @@ -1889,7 +1931,7 @@ bool VNetRouteOrch::handleTunnel(const Request& request) if (vnet_orch_->isVnetExecVrf()) { - return doRouteTask(vnet_name, ip_pfx, nhg, op, monitors); + return doRouteTask(vnet_name, ip_pfx, nhg, op, profile, monitors); } return true; diff --git a/orchagent/vnetorch.h b/orchagent/vnetorch.h index 53c4acf1e66..f7e134f6655 100644 --- a/orchagent/vnetorch.h +++ b/orchagent/vnetorch.h @@ -140,6 +140,7 @@ struct nextHop typedef std::map TunnelRoutes; typedef std::map RouteMap; +typedef std::map ProfileMap; class VNetVrfObject : public VNetObject { @@ -182,6 +183,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); @@ -199,6 +204,7 @@ class VNetVrfObject : public VNetObject TunnelRoutes tunnels_; RouteMap routes_; + ProfileMap profile_; }; typedef std::unique_ptr VNetObject_T; @@ -270,6 +276,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 }, }, { } }; @@ -351,16 +358,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& 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 - 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& monitors=std::map()); template diff --git a/tests/test_vnet.py b/tests/test_vnet.py index 412cbb7de32..5efb1cc3697 100644 --- a/tests/test_vnet.py +++ b/tests/test_vnet.py @@ -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 = [ @@ -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) @@ -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) @@ -1986,7 +1995,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"]) @@ -2000,14 +2009,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) @@ -2029,15 +2038,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) @@ -2048,7 +2057,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')