Skip to content

Commit 925ce60

Browse files
Leyzastepanblyschak
authored andcommitted
[Vnetorch] Ecmp vnet local routes (#3935)
What I did Implement Vnet local routes for single and ecmp case using RouteOrch's methods. Why I did it To enable ecmp vnet routes and the ability to update between single to ecmp vnet routes which is required for some use cases. How I verified it Tested on virtual and physical switches, and unit tests.
1 parent 0de80c3 commit 925ce60

File tree

5 files changed

+351
-47
lines changed

5 files changed

+351
-47
lines changed

orchagent/routeorch.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,18 @@ class RouteOrch : public ZmqOrch, public Subject
224224
void decreaseNextHopRefCount(const NextHopGroupKey&);
225225
bool isRefCounterZero(const NextHopGroupKey&) const;
226226

227+
void flushRouteBulker() { gRouteBulker.flush(); }
228+
int getNextHopGroupRefCount(const NextHopGroupKey& key) { return m_syncdNextHopGroups[key].ref_count; }
229+
std::set<std::pair<NextHopGroupKey, sai_object_id_t>> &getBulkNhgReducedRefCnt() { return m_bulkNhgReducedRefCnt; }
230+
227231
bool addNextHopGroup(const NextHopGroupKey&);
228232
bool removeNextHopGroup(const NextHopGroupKey&, const bool is_default_route_nh_swap=false);
229233

234+
bool addRoute(RouteBulkContext& ctx, const NextHopGroupKey &nextHops);
235+
bool removeRoute(RouteBulkContext& ctx);
236+
bool addRoutePost(const RouteBulkContext& ctx, const NextHopGroupKey &nextHops);
237+
bool removeRoutePost(const RouteBulkContext& ctx);
238+
230239
void addNextHopRoute(const NextHopKey&, const RouteKey&);
231240
void removeNextHopRoute(const NextHopKey&, const RouteKey&);
232241
bool updateNextHopRoutes(const NextHopKey&, uint32_t&);
@@ -295,10 +304,6 @@ class RouteOrch : public ZmqOrch, public Subject
295304
ObjectBulker<sai_next_hop_group_api_t> gNextHopGroupMemberBulker;
296305

297306
void addTempRoute(RouteBulkContext& ctx, const NextHopGroupKey&);
298-
bool addRoute(RouteBulkContext& ctx, const NextHopGroupKey &nextHops);
299-
bool removeRoute(RouteBulkContext& ctx);
300-
bool addRoutePost(const RouteBulkContext& ctx, const NextHopGroupKey &nextHops);
301-
bool removeRoutePost(const RouteBulkContext& ctx);
302307

303308
void addTempLabelRoute(LabelRouteBulkContext& ctx, const NextHopGroupKey&);
304309
bool addLabelRoute(LabelRouteBulkContext& ctx, const NextHopGroupKey&);

orchagent/vnetorch.cpp

Lines changed: 123 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -245,20 +245,23 @@ void VNetVrfObject::decreaseNextHopRefCount(const nextHop& nh)
245245
}
246246
}
247247

248-
bool VNetVrfObject::addRoute(IpPrefix& ipPrefix, nextHop& nh)
248+
bool VNetVrfObject::addRoute(IpPrefix& ipPrefix, nextHop& nh, bool increaseRefCount)
249249
{
250250
if (hasRoute(ipPrefix))
251251
{
252252
SWSS_LOG_INFO("VNET route '%s' exists", ipPrefix.to_string().c_str());
253253
return false;
254254
}
255255

256-
increaseNextHopRefCount(nh);
256+
if (increaseRefCount)
257+
{
258+
increaseNextHopRefCount(nh);
259+
}
257260
routes_[ipPrefix] = nh;
258261
return true;
259262
}
260263

261-
bool VNetVrfObject::removeRoute(IpPrefix& ipPrefix)
264+
bool VNetVrfObject::removeRoute(IpPrefix& ipPrefix, bool decreaseRefCount)
262265
{
263266
if (!hasRoute(ipPrefix))
264267
{
@@ -276,7 +279,10 @@ bool VNetVrfObject::removeRoute(IpPrefix& ipPrefix)
276279
else
277280
{
278281
nextHop nh = routes_[ipPrefix];
279-
decreaseNextHopRefCount(nh);
282+
if (decreaseRefCount)
283+
{
284+
decreaseNextHopRefCount(nh);
285+
}
280286
routes_.erase(ipPrefix);
281287
}
282288
return true;
@@ -1525,6 +1531,86 @@ inline void VNetRouteOrch::removeSubnetDecapTerm(const IpPrefix &ipPrefix)
15251531
subnet_decap_terms_created_.erase(it);
15261532
}
15271533

1534+
bool VNetRouteOrch::setAndDeleteRoutesWithRouteOrch(const sai_object_id_t vr_id, const IpPrefix& ipPrefix,
1535+
const NextHopGroupKey& nhg, const string& op)
1536+
{
1537+
auto& bulkNhgReducedRefCnt = gRouteOrch->getBulkNhgReducedRefCnt();
1538+
1539+
// Get vnet name from vrf id
1540+
std::string vnet_name;
1541+
if (!vnet_orch_->getVnetNameByVrfId(vr_id, vnet_name))
1542+
{
1543+
SWSS_LOG_INFO("Failed to get VNET name for vrf id '0x%" PRIx64, vr_id);
1544+
return false;
1545+
}
1546+
1547+
// Set up route bulk context
1548+
string key = vnet_name + ":" + ipPrefix.to_string();
1549+
RouteBulkContext ctx(key, (op == SET_COMMAND));
1550+
ctx.vrf_id = vr_id;
1551+
ctx.ip_prefix = ipPrefix;
1552+
ctx.nhg = nhg;
1553+
1554+
if (op == SET_COMMAND)
1555+
{
1556+
// Add route via route orch
1557+
if (gRouteOrch->addRoute(ctx, nhg))
1558+
{
1559+
return true;
1560+
}
1561+
1562+
// Flush the route bulker, so routes will be written to syncd and ASIC
1563+
gRouteOrch->flushRouteBulker();
1564+
bulkNhgReducedRefCnt.clear();
1565+
1566+
// Post add route via route orch
1567+
if (gRouteOrch->addRoutePost(ctx, nhg))
1568+
{
1569+
SWSS_LOG_NOTICE("Route %s added via routeorch for vnet %s", ipPrefix.to_string().c_str(), vnet_name.c_str());
1570+
}
1571+
else
1572+
{
1573+
SWSS_LOG_ERROR("Route %s add failed in routeorch for vnet %s", ipPrefix.to_string().c_str(), vnet_name.c_str());
1574+
return false;
1575+
}
1576+
}
1577+
else if (op == DEL_COMMAND)
1578+
{
1579+
// Remove route via route orch
1580+
if (gRouteOrch->removeRoute(ctx))
1581+
{
1582+
return true;
1583+
}
1584+
1585+
// Flush the route bulker, so routes will be written to syncd and ASIC
1586+
gRouteOrch->flushRouteBulker();
1587+
bulkNhgReducedRefCnt.clear();
1588+
1589+
// Post remove route via route orch
1590+
if (gRouteOrch->removeRoutePost(ctx))
1591+
{
1592+
SWSS_LOG_NOTICE("Route %s removed via routeorch for vnet %s", ipPrefix.to_string().c_str(), vnet_name.c_str());
1593+
}
1594+
else
1595+
{
1596+
SWSS_LOG_ERROR("Route %s remove failed in routeorch for vnet %s", ipPrefix.to_string().c_str(), vnet_name.c_str());
1597+
return false;
1598+
}
1599+
}
1600+
1601+
// Remove next hop groups with 0 ref count
1602+
for (auto& it : bulkNhgReducedRefCnt)
1603+
{
1604+
if (gRouteOrch->getNextHopGroupRefCount(it.first) == 0)
1605+
{
1606+
gRouteOrch->removeNextHopGroup(it.first);
1607+
SWSS_LOG_INFO("Next hop group %s has 0 references, removed via routeorch", it.first.to_string().c_str());
1608+
}
1609+
}
1610+
1611+
return true;
1612+
}
1613+
15281614
template<>
15291615
bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipPrefix,
15301616
nextHop& nh, string& op)
@@ -1595,57 +1681,66 @@ bool VNetRouteOrch::doRouteTask<VNetVrfObject>(const string& vnet, IpPrefix& ipP
15951681
sai_ip_prefix_t pfx;
15961682
copy(pfx, ipPrefix);
15971683
sai_object_id_t nh_id=SAI_NULL_OBJECT_ID;
1684+
string nhg_str;
15981685

15991686
if (is_subnet)
16001687
{
16011688
nh_id = port.m_rif_id;
16021689
}
1603-
else if (nh.ips.getSize() == 1)
1690+
else
16041691
{
1605-
NextHopKey nexthop(nh.ips.to_string(), nh.ifname);
1606-
if (gNeighOrch->hasNextHop(nexthop))
1692+
// Populate next hop group string
1693+
auto ifnames = tokenize(nh.ifname, ',');
1694+
int idx = 0;
1695+
for (auto it : nh.ips.getIpAddresses())
16071696
{
1608-
nh_id = gNeighOrch->getNextHopId(nexthop);
1609-
}
1610-
else
1611-
{
1612-
SWSS_LOG_INFO("Failed to get next hop %s for %s",
1613-
nexthop.to_string().c_str(), ipPrefix.to_string().c_str());
1614-
return false;
1697+
if (!nhg_str.empty())
1698+
{
1699+
nhg_str += ",";
1700+
}
1701+
1702+
nhg_str += it.to_string() + "@" + ifnames[idx];
1703+
idx++;
16151704
}
16161705
}
1617-
else
1618-
{
1619-
// FIXME - Handle ECMP routes
1620-
SWSS_LOG_WARN("VNET ECMP NHs not implemented for '%s'", ipPrefix.to_string().c_str());
1621-
return true;
1622-
}
16231706

16241707
for (auto vr_id : vr_set)
16251708
{
16261709
if (vr_id == SAI_NULL_OBJECT_ID)
16271710
{
16281711
continue;
16291712
}
1630-
if (op == SET_COMMAND && !add_route(vr_id, pfx, nh_id))
1713+
1714+
if (is_subnet)
16311715
{
1632-
SWSS_LOG_INFO("Route add failed for %s", ipPrefix.to_string().c_str());
1633-
break;
1716+
if (op == SET_COMMAND && !add_route(vr_id, pfx, nh_id))
1717+
{
1718+
SWSS_LOG_INFO("Route add failed for %s", ipPrefix.to_string().c_str());
1719+
break;
1720+
}
1721+
else if (op == DEL_COMMAND && !del_route(vr_id, pfx))
1722+
{
1723+
SWSS_LOG_INFO("Route del failed for %s", ipPrefix.to_string().c_str());
1724+
break;
1725+
}
16341726
}
1635-
else if (op == DEL_COMMAND && !del_route(vr_id, pfx))
1727+
else
16361728
{
1637-
SWSS_LOG_INFO("Route del failed for %s", ipPrefix.to_string().c_str());
1638-
break;
1729+
NextHopGroupKey nhg(nhg_str);
1730+
if (!setAndDeleteRoutesWithRouteOrch(vr_id, ipPrefix, nhg, op))
1731+
{
1732+
return false;
1733+
}
16391734
}
16401735
}
16411736

16421737
if (op == SET_COMMAND)
16431738
{
1644-
vrf_obj->addRoute(ipPrefix, nh);
1739+
vrf_obj->addRoute(ipPrefix, nh, is_subnet);
16451740
}
16461741
else
16471742
{
1648-
vrf_obj->removeRoute(ipPrefix);
1743+
vrf_obj->removeRoute(ipPrefix, is_subnet);
16491744
}
16501745

16511746
return true;

orchagent/vnetorch.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ class VNetVrfObject : public VNetObject
204204
bool updateObj(vector<sai_attribute_t>&);
205205

206206
bool addRoute(IpPrefix& ipPrefix, NextHopGroupKey& nexthops);
207-
bool addRoute(IpPrefix& ipPrefix, nextHop& nh);
208-
bool removeRoute(IpPrefix& ipPrefix);
207+
bool addRoute(IpPrefix& ipPrefix, nextHop& nh, bool increaseRefCount = true);
208+
bool removeRoute(IpPrefix& ipPrefix, bool decreaseRefCount = true);
209209

210210
void addProfile(IpPrefix& ipPrefix, string& profile);
211211
void removeProfile(IpPrefix& ipPrefix);
@@ -501,6 +501,9 @@ class VNetRouteOrch : public Orch2, public Subject, public Observer
501501
void createSubnetDecapTerm(const IpPrefix &ipPrefix);
502502
void removeSubnetDecapTerm(const IpPrefix &ipPrefix);
503503

504+
bool setAndDeleteRoutesWithRouteOrch(const sai_object_id_t vr_id, const IpPrefix& ipPrefix,
505+
const NextHopGroupKey& nhg, const string& op);
506+
504507
template<typename T>
505508
bool doRouteTask(const string& vnet, IpPrefix& ipPrefix, NextHopGroupKey& nexthops, string& op, string& profile,
506509
const string& monitoring, NextHopGroupKey& nexthops_secondary, const IpPrefix& adv_prefix,

0 commit comments

Comments
 (0)