@@ -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+
15281614template <>
15291615bool 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 ;
0 commit comments