diff --git a/orchagent/vnetorch.cpp b/orchagent/vnetorch.cpp index 4640d68853fb..a3acf10e0e06 100644 --- a/orchagent/vnetorch.cpp +++ b/orchagent/vnetorch.cpp @@ -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) */ @@ -872,7 +894,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(); @@ -1011,6 +1033,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); @@ -1019,7 +1042,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) { @@ -1071,6 +1099,7 @@ bool VNetRouteOrch::doRouteTask(const string& vnet, IpPrefix& ipP } vrf_obj->removeRoute(ipPrefix); + vrf_obj->removeProfile(ipPrefix); removeRouteState(vnet, ipPrefix); } @@ -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 fvVector; @@ -1634,7 +1663,7 @@ void VNetRouteOrch::postRouteState(const string& vnet, IpPrefix& ipPrefix, NextH { if (route_state == "active") { - addRouteAdvertisement(ipPrefix); + addRouteAdvertisement(ipPrefix, profile); } else { @@ -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 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); } @@ -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); } } } @@ -1878,6 +1915,7 @@ bool VNetRouteOrch::handleTunnel(const Request& request) vector mac_list; vector vni_list; vector monitor_list; + string profile = ""; for (const auto& name: request.getAttrFieldNames()) { @@ -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()); @@ -1962,7 +2004,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 26e073333770..4f63764a0ee2 100644 --- a/orchagent/vnetorch.h +++ b/orchagent/vnetorch.h @@ -139,6 +139,7 @@ struct nextHop typedef std::map TunnelRoutes; typedef std::map RouteMap; +typedef std::map ProfileMap; class VNetVrfObject : public VNetObject { @@ -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); @@ -201,6 +206,7 @@ class VNetVrfObject : public VNetObject TunnelRoutes tunnels_; RouteMap routes_; + ProfileMap profile_; }; typedef std::unique_ptr VNetObject_T; @@ -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 }, }, { } }; @@ -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& 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 60a2ed8c33ff..0dec1f7446e4 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) @@ -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"]) @@ -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) @@ -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) @@ -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')