Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
72b5825
Changes
abdosi Nov 24, 2024
e3b48ae
More changes
abdosi Nov 24, 2024
9c5c2e7
Added UT
abdosi Nov 25, 2024
126c201
Fix indenation and missed file changes
abdosi Nov 25, 2024
4751f41
Fix indenation
abdosi Nov 25, 2024
1fef1c2
Fix
abdosi Nov 25, 2024
de8e979
Fixed flaky test case
abdosi Nov 26, 2024
b374597
Merge remote-tracking branch 'upstream/master' into default-route
abdosi Nov 26, 2024
540dd52
Merge branch 'master' into default-route
prsunny Nov 27, 2024
de037d5
Merge branch 'master' into default-route
abdosi Nov 28, 2024
8d2d008
Update test_nhg.py
abdosi Nov 29, 2024
a90ba41
Revert "Update test_nhg.py"
abdosi Nov 29, 2024
d9272ee
More changes
abdosi Nov 29, 2024
0c6ec8b
Merge branch 'master' into default-route
prsunny Dec 2, 2024
5985e34
Fix
abdosi Dec 6, 2024
780d69d
Merge branch 'default-route' of https://github.com/abdosi/sonic-swss …
abdosi Dec 6, 2024
d65732d
Merge branch 'master' into default-route
abdosi Dec 10, 2024
a6d1c77
Merge remote-tracking branch 'upstream/master' into default-route
abdosi Dec 11, 2024
409b268
Address review comment
abdosi Dec 11, 2024
7718dfa
Add the test case back
abdosi Dec 11, 2024
eb74abe
Merge branch 'master' into default-route
abdosi Dec 18, 2024
33cdc81
Merge remote-tracking branch 'upstream/master' into default-route
abdosi Jan 23, 2025
ca0f0b9
Fix the nexthop delete SAI error after default swap.
abdosi Jan 23, 2025
32f19a9
Ehnahnce UT to handle port toggle case
abdosi Jan 24, 2025
40759b9
Merge remote-tracking branch 'upstream/master' into default-route
abdosi Feb 21, 2025
a9ccf72
Merge remote-tracking branch 'upstream/master' into default-route
abdosi Mar 22, 2025
b5fdeda
Address Review Comments
abdosi Mar 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 176 additions & 6 deletions orchagent/routeorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,71 @@ void RouteOrch::detach(Observer *observer, const IpAddress& dstAddr, sai_object_
}
}

void RouteOrch::updateDefaultRouteSwapSet(const NextHopGroupKey default_nhg_key, std::set<NextHopKey>& active_default_route_nhops)
{
std::set<NextHopKey> current_default_route_nhops;
current_default_route_nhops.clear();

if (default_nhg_key.getSize() == 1)
{
current_default_route_nhops.insert(*default_nhg_key.getNextHops().begin());
}
else
{
auto nhgm = m_syncdNextHopGroups[default_nhg_key].nhopgroup_members;
for (auto nhop = nhgm.begin(); nhop != nhgm.end(); ++nhop)
{
current_default_route_nhops.insert(nhop->first);
}
}

active_default_route_nhops.clear();
std::copy(current_default_route_nhops.begin(), current_default_route_nhops.end(), std::inserter(active_default_route_nhops, active_default_route_nhops.begin()));
}

bool RouteOrch::addDefaultRouteNexthopsInNextHopGroup(NextHopGroupEntry& original_next_hop_group, std::set<NextHopKey>& default_route_next_hop_set)
{
/* In the function we update the member of existing NexthopGroup to the Default Route Nexthop's */
SWSS_LOG_ENTER();
sai_object_id_t nexthop_group_member_id;
sai_status_t status;

for (auto it : default_route_next_hop_set)
{
vector<sai_attribute_t> nhgm_attrs;
sai_attribute_t nhgm_attr;
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID;
nhgm_attr.value.oid = original_next_hop_group.next_hop_group_id;
nhgm_attrs.push_back(nhgm_attr);

nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID;
nhgm_attr.value.oid = m_neighOrch->getNextHopId(it);
nhgm_attrs.push_back(nhgm_attr);

status = sai_next_hop_group_api->create_next_hop_group_member(&nexthop_group_member_id, gSwitchId,
(uint32_t)nhgm_attrs.size(),
nhgm_attrs.data());

if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Default Route Swap Failed to add next hop member to group %" PRIx64 ": %d\n",
original_next_hop_group.next_hop_group_id, status);
task_process_status handle_status = handleSaiCreateStatus(SAI_API_NEXT_HOP_GROUP, status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
}
// Increment the Default Route Active NH Reference Count
m_neighOrch->increaseNextHopRefCount(it);
gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);
original_next_hop_group.default_route_nhopgroup_members[it].next_hop_id = nexthop_group_member_id;
original_next_hop_group.default_route_nhopgroup_members[it].seq_id = 0;
original_next_hop_group.is_default_route_nh_swap = true;
}
return true;
}

bool RouteOrch::validnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t& count)
{
SWSS_LOG_ENTER();
Expand All @@ -400,6 +465,13 @@ bool RouteOrch::validnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t&
continue;
}

// Route NHOP Group is swapped by default route nh memeber . do not add Nexthop again.
// Wait for Nexthop Group Cleanup
if (nhopgroup->second.is_default_route_nh_swap)
{
continue;
}

vector<sai_attribute_t> nhgm_attrs;
sai_attribute_t nhgm_attr;

Expand Down Expand Up @@ -446,6 +518,9 @@ bool RouteOrch::validnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t&
++count;
gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);
nhopgroup->second.nhopgroup_members[nexthop].next_hop_id = nexthop_id;
/* Keep the count of number of nexthop members are present in Nexthop Group
* when the links became active again*/
nhopgroup->second.nh_member_install_count++;
}

if (!m_fgNhgOrch->validNextHopInNextHopGroup(nexthop))
Expand Down Expand Up @@ -473,6 +548,14 @@ bool RouteOrch::invalidnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t
continue;
}

// Route NHOP Group is already swapped by default route nh memeber . do not delete actual nexthop again.

if (nhopgroup->second.is_default_route_nh_swap)
{
continue;
}


nexthop_id = nhopgroup->second.nhopgroup_members[nexthop].next_hop_id;
status = sai_next_hop_group_api->remove_next_hop_group_member(nexthop_id);

Expand All @@ -486,7 +569,24 @@ bool RouteOrch::invalidnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t
return parseHandleSaiStatusFailure(handle_status);
}
}

// Reduce the member install count when links down
if (nhopgroup->second.nh_member_install_count)
{
nhopgroup->second.nh_member_install_count--;
}
// Nexthop Group member count has become zero so swap it's memebers with default route
// nexthop's if this route is eligible for such a swap
if (nhopgroup->second.nh_member_install_count == 0 && nhopgroup->second.eligible_for_default_route_nh_swap && !nhopgroup->second.is_default_route_nh_swap)
{
if(nexthop.ip_address.isV4())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if at this time the default route from bgp is not present. will the v4_active_default_route_nhops have the drop port?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arlakshm : if no default route than existing behavior will happen where nexthop group will not have any members which will cause drop as expected.

{
addDefaultRouteNexthopsInNextHopGroup(nhopgroup->second, v4_active_default_route_nhops);
}
else
{
addDefaultRouteNexthopsInNextHopGroup(nhopgroup->second, v6_active_default_route_nhops);
}
}
++count;
gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);
}
Expand Down Expand Up @@ -638,6 +738,7 @@ void RouteOrch::doTask(Consumer& consumer)
bool srv6_seg = false;
bool srv6_vpn = false;
bool srv6_nh = false;
bool fallback_to_default_route = false;

for (auto i : kfvFieldsValues(t))
{
Expand Down Expand Up @@ -683,6 +784,9 @@ void RouteOrch::doTask(Consumer& consumer)
ctx.protocol = fvValue(i);
}

if (fvField(i) == "fallback_to_default_route")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

who sets this attribute?

Copy link
Copy Markdown
Contributor Author

@abdosi abdosi Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@prsunny : it is being done here: #3353

fallback_to_default_route = fvValue(i) == "true";

if (fvField(i) == "vpn_sid") {
srv6_vpn_sids = fvValue(i);
srv6_nh = true;
Expand All @@ -707,6 +811,7 @@ void RouteOrch::doTask(Consumer& consumer)
continue;
}

ctx.fallback_to_default_route = fallback_to_default_route;
ctx.nhg_index = nhg_index;
ctx.context_index = context_index;

Expand Down Expand Up @@ -1003,6 +1108,8 @@ void RouteOrch::doTask(Consumer& consumer)
// Go through the bulker results
auto it_prev = consumer.m_toSync.begin();
m_bulkNhgReducedRefCnt.clear();
NextHopGroupKey v4_default_nhg_key;
NextHopGroupKey v6_default_nhg_key;
m_bulkSrv6NhgReducedVec.clear();

while (it_prev != it)
Expand Down Expand Up @@ -1068,6 +1175,20 @@ void RouteOrch::doTask(Consumer& consumer)
it_prev = consumer.m_toSync.erase(it_prev);
else
it_prev++;

// Save the Default Route of Default VRF to be used for
// enabling fallback to it as needed
if (ip_prefix.isDefaultRoute() && vrf_id == gVirtualRouterId)
{
if (ip_prefix.isV4())
Comment on lines +1182 to +1183
Copy link
Copy Markdown
Contributor

@arlakshm arlakshm Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation #Resolved

{
v4_default_nhg_key = getSyncdRouteNhgKey(gVirtualRouterId, ip_prefix);
}
else
{
v6_default_nhg_key = getSyncdRouteNhgKey(gVirtualRouterId, ip_prefix);
}
}
}
}
else if (op == DEL_COMMAND)
Expand All @@ -1089,16 +1210,31 @@ void RouteOrch::doTask(Consumer& consumer)
}
else if (m_syncdNextHopGroups[it_nhg.first].ref_count == 0)
{
removeNextHopGroup(it_nhg.first);
// Pass the flag to indicate if the NextHop Group as Default Route NH Members as swapped.
removeNextHopGroup(it_nhg.first, m_syncdNextHopGroups[it_nhg.first].is_default_route_nh_swap);
}
}

/* Reduce reference for srv6 next hop group */
/* Later delete for increase refcnt early */
if (!m_bulkSrv6NhgReducedVec.empty())
{
m_srv6Orch->removeSrv6Nexthops(m_bulkSrv6NhgReducedVec);
}
/* No Update to Default Route so we can return */
if (!(v4_default_nhg_key.getSize()) && !(v6_default_nhg_key.getSize()))
{
return;
}
/* Update to v4 Default Route so update the data structure */
if (v4_default_nhg_key.getSize())
{
updateDefaultRouteSwapSet(v4_default_nhg_key, v4_active_default_route_nhops);
}
/* Update to v6 Default Route so update the data structure */
if (v6_default_nhg_key.getSize())
{
updateDefaultRouteSwapSet(v6_default_nhg_key, v6_active_default_route_nhops);
}
}
}

Expand Down Expand Up @@ -1397,6 +1533,7 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops)

NextHopGroupEntry next_hop_group_entry;
next_hop_group_entry.next_hop_group_id = next_hop_group_id;
next_hop_group_entry.nh_member_install_count = 0;

size_t npid_count = next_hop_ids.size();
vector<sai_object_id_t> nhgm_ids(npid_count);
Expand Down Expand Up @@ -1467,6 +1604,8 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops)
{
next_hop_group_entry.nhopgroup_members[nhopgroup_members_set.find(nhid)->second].next_hop_id = nhgm_id;
next_hop_group_entry.nhopgroup_members[nhopgroup_members_set.find(nhid)->second].seq_id = ((uint32_t)i) + 1;
/* Keep the count of number of nexthop members are present in Nexthop Group*/
next_hop_group_entry.nh_member_install_count++;
}
}

Expand All @@ -1484,7 +1623,7 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops)
return true;
}

bool RouteOrch::removeNextHopGroup(const NextHopGroupKey &nexthops)
bool RouteOrch::removeNextHopGroup(const NextHopGroupKey &nexthops, const bool is_default_route_nh_swap)
{
SWSS_LOG_ENTER();

Expand All @@ -1505,10 +1644,15 @@ bool RouteOrch::removeNextHopGroup(const NextHopGroupKey &nexthops)
SWSS_LOG_NOTICE("Delete next hop group %s", nexthops.to_string().c_str());

vector<sai_object_id_t> next_hop_ids;
auto& nhgm = next_hop_group_entry->second.nhopgroup_members;
/* If the NexthopGroup is the one that has been swapped with default route members
* than when deleting such Nexthop Group we have to remove default route nexthop group members */
auto& nhgm = is_default_route_nh_swap ? next_hop_group_entry->second.default_route_nhopgroup_members : next_hop_group_entry->second.nhopgroup_members;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comment on where the second.nhopgroup_members gets cleaned up

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@prsunny comments added to major code points.

for (auto nhop = nhgm.begin(); nhop != nhgm.end();)
{
if (m_neighOrch->isNextHopFlagSet(nhop->first, NHFLAGS_IFDOWN))
/* This check we skip for Nexthop Group that has been swapped
* as Nexthop Group Members are not original member which are already removed
* as part of API invalidnexthopinNextHopGroup */
if (m_neighOrch->isNextHopFlagSet(nhop->first, NHFLAGS_IFDOWN) && (!is_default_route_nh_swap))
{
SWSS_LOG_WARN("NHFLAGS_IFDOWN set for next hop group member %s with next_hop_id %" PRIx64,
nhop->first.to_string().c_str(), nhop->second.next_hop_id);
Expand Down Expand Up @@ -1587,6 +1731,16 @@ bool RouteOrch::removeNextHopGroup(const NextHopGroupKey &nexthops)
}
}

// Decrement Nexthop Reference Count for Default Route NH Member used as swapped
if (is_default_route_nh_swap)
{
auto& nhgm = next_hop_group_entry->second.default_route_nhopgroup_members;
for (auto nhop = nhgm.begin(); nhop != nhgm.end(); ++nhop)
{
m_neighOrch->decreaseNextHopRefCount(nhop->first);
}
}

m_syncdNextHopGroups.erase(nexthops);

return true;
Expand Down Expand Up @@ -2008,6 +2162,13 @@ bool RouteOrch::addRoute(RouteBulkContext& ctx, const NextHopGroupKey &nextHops)
/* Return false since the original route is not successfully added */
return false;
}
else
{
/* Nexthop Creation Successful. So the save the state if eligible to fallback to default route
* based on APP_DB value for the route. Also initialize the present to False as swap did not happen */
m_syncdNextHopGroups[nextHops].eligible_for_default_route_nh_swap = ctx.fallback_to_default_route;
m_syncdNextHopGroups[nextHops].is_default_route_nh_swap = false;
}
}

next_hop_id = m_syncdNextHopGroups[nextHops].next_hop_group_id;
Expand Down Expand Up @@ -2610,6 +2771,15 @@ bool RouteOrch::removeRoutePost(const RouteBulkContext& ctx)
updateDefRouteState(ipPrefix.to_string());

SWSS_LOG_INFO("Set route %s next hop ID to NULL", ipPrefix.to_string().c_str());

if (ipPrefix.isV4())
{
v4_active_default_route_nhops.clear();
}
else
{
v6_active_default_route_nhops.clear();
}
}
else
{
Expand Down
16 changes: 14 additions & 2 deletions orchagent/routeorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ struct NextHopGroupEntry
sai_object_id_t next_hop_group_id; // next hop group id
int ref_count; // reference count
NextHopGroupMembers nhopgroup_members; // ids of members indexed by <ip_address, if_alias>
NextHopGroupMembers default_route_nhopgroup_members; // ids of members indexed by <ip_address, if_alias>
uint32_t nh_member_install_count;
bool eligible_for_default_route_nh_swap;
bool is_default_route_nh_swap;
};

struct NextHopUpdate
Expand Down Expand Up @@ -125,6 +129,7 @@ struct RouteBulkContext
bool excp_intfs_flag;
// using_temp_nhg will track if the NhgOrch's owned NHG is temporary or not
bool using_temp_nhg;
bool fallback_to_default_route;
std::vector<string> ipv;
std::vector<string> alsv;
std::vector<string> vni_labelv;
Expand All @@ -136,7 +141,8 @@ struct RouteBulkContext
bool is_set; // True if set operation

RouteBulkContext(const std::string& key, bool is_set)
: key(key), excp_intfs_flag(false), using_temp_nhg(false), is_set(is_set)
: key(key), excp_intfs_flag(false), using_temp_nhg(false), is_set(is_set),
fallback_to_default_route(false)
{
}

Expand All @@ -155,6 +161,7 @@ struct RouteBulkContext
using_temp_nhg = false;
key.clear();
protocol.clear();
fallback_to_default_route = false;
}
};

Expand Down Expand Up @@ -206,12 +213,13 @@ class RouteOrch : public Orch, public Subject
bool isRefCounterZero(const NextHopGroupKey&) const;

bool addNextHopGroup(const NextHopGroupKey&);
bool removeNextHopGroup(const NextHopGroupKey&);
bool removeNextHopGroup(const NextHopGroupKey&, const bool is_default_route_nh_swap=false);

void addNextHopRoute(const NextHopKey&, const RouteKey&);
void removeNextHopRoute(const NextHopKey&, const RouteKey&);
bool updateNextHopRoutes(const NextHopKey&, uint32_t&);
bool getRoutesForNexthop(std::set<RouteKey>&, const NextHopKey&);
bool swapnexthopinNextHopGroup(sai_object_id_t next_hop_group_id, sai_object_id_t default_next_hop_id);

bool validnexthopinNextHopGroup(const NextHopKey&, uint32_t&);
bool invalidnexthopinNextHopGroup(const NextHopKey&, uint32_t&);
Expand Down Expand Up @@ -251,6 +259,8 @@ class RouteOrch : public Orch, public Subject
unsigned int m_maxNextHopGroupCount;
bool m_resync;

std::set<NextHopKey> v4_active_default_route_nhops;
std::set<NextHopKey> v6_active_default_route_nhops;
shared_ptr<DBConnector> m_stateDb;
unique_ptr<swss::Table> m_stateDefaultRouteTb;

Expand Down Expand Up @@ -296,6 +306,8 @@ class RouteOrch : public Orch, public Subject
bool isVipRoute(const IpPrefix &ipPrefix, const NextHopGroupKey &nextHops);
void createVipRouteSubnetDecapTerm(const IpPrefix &ipPrefix);
void removeVipRouteSubnetDecapTerm(const IpPrefix &ipPrefix);
bool addDefaultRouteNexthopsInNextHopGroup(NextHopGroupEntry& original_next_hop_group, std::set<NextHopKey>& default_route_next_hop_set);
void updateDefaultRouteSwapSet(const NextHopGroupKey default_nhg_key, std::set<NextHopKey>& active_default_route_nhops);
void incNhgRefCount(const std::string& nhg_index, const std::string &context_index = "");
void decNhgRefCount(const std::string& nhg_index, const std::string &context_index = "");
};
Expand Down
Loading
Loading