Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exp wt 202405 #1

Closed
wants to merge 13 commits into from
3 changes: 2 additions & 1 deletion orchagent/nexthopgroupkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ class NextHopGroupKey

NextHopGroupKey(const std::string &nexthops, const std::string &weights)
{
SWSS_LOG_ERROR("Received weights in NextHopGroupKey: %s", weights.c_str());
m_overlay_nexthops = false;
m_srv6_nexthops = false;
std::vector<std::string> nhv = tokenize(nexthops, NHG_DELIMITER);
std::vector<std::string> wtv = tokenize(weights, NHG_DELIMITER);
bool set_weight = wtv.size() == nhv.size();
for (uint32_t i = 0; i < nhv.size(); i++)
{
NextHopKey nh(nhv[i]);
NextHopKey nh(nhv[i]);
nh.weight = set_weight? (uint32_t)std::stoi(wtv[i]) : 0;
m_nexthops.insert(nh);
}
Expand Down
248 changes: 151 additions & 97 deletions orchagent/routeorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,47 +403,56 @@ bool RouteOrch::validnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t&

/* get updated nhkey with possible weight */
auto nhkey = nhopgroup->first.getNextHops().find(nexthop);

nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID;
nhgm_attr.value.oid = nhopgroup->second.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(nexthop);
nhgm_attrs.push_back(nhgm_attr);

if (nhkey->weight)
size_t member_ratio = 1;

if(nhkey->weight)
{
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT;
nhgm_attr.value.s32 = nhkey->weight;
nhgm_attrs.push_back(nhgm_attr);
member_ratio = nhkey->weight/nhopgroup->second.weight_offset;
SWSS_LOG_ERROR("Weight %u, offset %u, ratio %lu", nhkey->weight, nhopgroup->second.weight_offset, member_ratio);
}

if (m_switchOrch->checkOrderedEcmpEnable())
for(size_t j = 0; j < member_ratio; j++)
{
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID;
nhgm_attr.value.u32 = nhopgroup->second.nhopgroup_members[nexthop].seq_id;
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID;
nhgm_attr.value.oid = nhopgroup->second.next_hop_group_id;
nhgm_attrs.push_back(nhgm_attr);
}

status = sai_next_hop_group_api->create_next_hop_group_member(&nexthop_id, gSwitchId,
(uint32_t)nhgm_attrs.size(),
nhgm_attrs.data());
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID;
nhgm_attr.value.oid = m_neighOrch->getNextHopId(nexthop);
nhgm_attrs.push_back(nhgm_attr);

if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to add next hop member to group %" PRIx64 ": %d\n",
nhopgroup->second.next_hop_group_id, status);
task_process_status handle_status = handleSaiCreateStatus(SAI_API_NEXT_HOP_GROUP, status);
if (handle_status != task_success)
if (nhkey->weight)
{
return parseHandleSaiStatusFailure(handle_status);
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT;
nhgm_attr.value.s32 = 1;
nhgm_attrs.push_back(nhgm_attr);
}

if (m_switchOrch->checkOrderedEcmpEnable())
{
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID;
nhgm_attr.value.u32 = nhopgroup->second.nhopgroup_members[nexthop][j].seq_id;
nhgm_attrs.push_back(nhgm_attr);
}
}

++count;
gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);
nhopgroup->second.nhopgroup_members[nexthop].next_hop_id = nexthop_id;
status = sai_next_hop_group_api->create_next_hop_group_member(&nexthop_id, gSwitchId,
(uint32_t)nhgm_attrs.size(),
nhgm_attrs.data());

if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to add next hop member to group %" PRIx64 ": %d\n",
nhopgroup->second.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);
}
}

++count;
gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);
nhopgroup->second.nhopgroup_members[nexthop][j].next_hop_id = nexthop_id;
}
}

if (!m_fgNhgOrch->validNextHopInNextHopGroup(nexthop))
Expand Down Expand Up @@ -471,22 +480,25 @@ bool RouteOrch::invalidnexthopinNextHopGroup(const NextHopKey &nexthop, uint32_t
continue;
}

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

if (status != SAI_STATUS_SUCCESS)
for(size_t j = 0 ; j < nhopgroup->second.nhopgroup_members[nexthop].size(); j++)
{
SWSS_LOG_ERROR("Failed to remove next hop member %" PRIx64 " from group %" PRIx64 ": %d\n",
nexthop_id, nhopgroup->second.next_hop_group_id, status);
task_process_status handle_status = handleSaiRemoveStatus(SAI_API_NEXT_HOP_GROUP, status);
if (handle_status != task_success)
nexthop_id = nhopgroup->second.nhopgroup_members[nexthop][j].next_hop_id;
status = sai_next_hop_group_api->remove_next_hop_group_member(nexthop_id);

if (status != SAI_STATUS_SUCCESS)
{
return parseHandleSaiStatusFailure(handle_status);
SWSS_LOG_ERROR("Failed to remove next hop member %" PRIx64 " from group %" PRIx64 ": %d\n",
nexthop_id, nhopgroup->second.next_hop_group_id, status);
task_process_status handle_status = handleSaiRemoveStatus(SAI_API_NEXT_HOP_GROUP, status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
}
}

++count;
gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);
++count;
gCrmOrch->decCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);
}
}

if (!m_fgNhgOrch->invalidNextHopInNextHopGroup(nexthop))
Expand Down Expand Up @@ -655,9 +667,13 @@ void RouteOrch::doTask(Consumer& consumer)
if (fvField(i) == "blackhole")
blackhole = fvValue(i) == "true";

if (fvField(i) == "weight")
if (fvField(i) == "weight") {
weights = fvValue(i);

if(!weights.empty())
{
SWSS_LOG_ERROR("Weight %s received", weights.c_str());
}
}
if (fvField(i) == "nexthop_group")
nhg_index = fvValue(i);

Expand Down Expand Up @@ -839,6 +855,10 @@ void RouteOrch::doTask(Consumer& consumer)
}

nhg = NextHopGroupKey(nhg_str, weights);
if(!weights.empty())
{
SWSS_LOG_ERROR("UCMP: weights: %s", weights.c_str());
}
}
else
{
Expand Down Expand Up @@ -1291,6 +1311,7 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops)
set<NextHopKey> next_hop_set = nexthops.getNextHops();
std::map<sai_object_id_t, NextHopKey> nhopgroup_members_set;
std::map<sai_object_id_t, set<NextHopKey>> nhopgroup_shared_set;
vector<uint32_t> weights;

/* Assert each IP address exists in m_syncdNextHops table,
* and add the corresponding next_hop_id to next_hop_ids. */
Expand Down Expand Up @@ -1325,6 +1346,11 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops)
if (nhopgroup_members_set.find(next_hop_id) == nhopgroup_members_set.end())
{
nhopgroup_members_set[next_hop_id] = it;
if(nhopgroup_members_set[next_hop_id].weight)
{
weights.push_back(nhopgroup_members_set[next_hop_id].weight + 1);
SWSS_LOG_ERROR("Next hop member weight: %u", nhopgroup_members_set[next_hop_id].weight);
}
}
else
{
Expand Down Expand Up @@ -1365,74 +1391,100 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops)
next_hop_group_entry.next_hop_group_id = next_hop_group_id;

size_t npid_count = next_hop_ids.size();
vector<sai_object_id_t> nhgm_ids(npid_count);
uint32_t weight_offset = 1;

if(weights.size() > 0)
{
weight_offset = weights[0];
for(size_t i = 1; i < weights.size(); i++)
{
weight_offset = std::__gcd(weight_offset, weights[i]);
if (weight_offset == 1)
break;
}
}
SWSS_LOG_ERROR("Nexthops size: %lu, Weights size: %lu, GCD computed: %u\n", npid_count, weights.size(), weight_offset);
next_hop_group_entry.weight_offset = weight_offset;

std::map<sai_object_id_t, std::vector<NextHopGroupMemberEntry>> nhgm_ids;
uint32_t seq_id = 0;
for (size_t i = 0; i < npid_count; i++)
{
auto nhid = next_hop_ids[i];
auto weight = nhopgroup_members_set[nhid].weight;
auto weight = (nhopgroup_members_set[nhid].weight + 1)/weight_offset;
sai_object_id_t nhgm_id;
SWSS_LOG_ERROR("Weight: %u\n", weight);
for(size_t j = 0; j < weight; j++)
{
// Create a next hop group member
vector<sai_attribute_t> nhgm_attrs;

// Create a next hop group member
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 = next_hop_group_id;
nhgm_attrs.push_back(nhgm_attr);

sai_attribute_t nhgm_attr;
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID;
nhgm_attr.value.oid = 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 = nhid;
nhgm_attrs.push_back(nhgm_attr);

nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID;
nhgm_attr.value.oid = nhid;
nhgm_attrs.push_back(nhgm_attr);
if (weight)
{
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT;
nhgm_attr.value.s32 = 1;
nhgm_attrs.push_back(nhgm_attr);
}

if (weight)
{
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_WEIGHT;
nhgm_attr.value.s32 = weight;
nhgm_attrs.push_back(nhgm_attr);
}
if (m_switchOrch->checkOrderedEcmpEnable())
{
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID;
nhgm_attr.value.u32 = ((uint32_t)seq_id) + 1; // To make non-zero sequence id
nhgm_attrs.push_back(nhgm_attr);
}

if (m_switchOrch->checkOrderedEcmpEnable())
{
nhgm_attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_SEQUENCE_ID;
nhgm_attr.value.u32 = ((uint32_t)i) + 1; // To make non-zero sequence id
nhgm_attrs.push_back(nhgm_attr);
gNextHopGroupMemberBulker.create_entry(&nhgm_id,
(uint32_t)nhgm_attrs.size(),
nhgm_attrs.data());
NextHopGroupMemberEntry entry = {nhgm_id, seq_id};
nhgm_ids[nhid].push_back(entry);
}

gNextHopGroupMemberBulker.create_entry(&nhgm_ids[i],
(uint32_t)nhgm_attrs.size(),
nhgm_attrs.data());
}

gNextHopGroupMemberBulker.flush();

for (size_t i = 0; i < npid_count; i++)
{
auto nhid = next_hop_ids[i];
auto nhgm_id = nhgm_ids[i];
if (nhgm_id == SAI_NULL_OBJECT_ID)
for(size_t j = 0; j < nhgm_ids[nhid].size(); j++)
{
// TODO: do we need to clean up?
SWSS_LOG_ERROR("Failed to create next hop group %" PRIx64 " member %" PRIx64 ": %d\n",
next_hop_group_id, nhgm_ids[i], status);
return false;
}
auto nhgm_id = nhgm_ids[nhid][j].next_hop_id;
auto seq_id = nhgm_ids[nhid][j].seq_id;
NextHopGroupMemberEntry entry = {nhgm_id, seq_id};
if (nhgm_id == SAI_NULL_OBJECT_ID)
{
// TODO: do we need to clean up?
SWSS_LOG_ERROR("Failed to create next hop group %" PRIx64 " member %" PRIx64 ": %d\n",
next_hop_group_id, nhgm_id, status);
return false;
}

gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);
gCrmOrch->incCrmResUsedCounter(CrmResourceType::CRM_NEXTHOP_GROUP_MEMBER);

// Save the membership into next hop structure
if (nhopgroup_shared_set.find(nhid) != nhopgroup_shared_set.end())
{
auto it = nhopgroup_shared_set[nhid].begin();
next_hop_group_entry.nhopgroup_members[*it].next_hop_id = nhgm_id;
next_hop_group_entry.nhopgroup_members[*it].seq_id = (uint32_t)i + 1;
nhopgroup_shared_set[nhid].erase(it);
if (nhopgroup_shared_set[nhid].empty())
// Save the membership into next hop structure
if (nhopgroup_shared_set.find(nhid) != nhopgroup_shared_set.end())
{
nhopgroup_shared_set.erase(nhid);
auto it = nhopgroup_shared_set[nhid].begin();
next_hop_group_entry.nhopgroup_members[*it].push_back(entry);
nhopgroup_shared_set[nhid].erase(it);
if (nhopgroup_shared_set[nhid].empty())
{
nhopgroup_shared_set.erase(nhid);
}
}
else
{
next_hop_group_entry.nhopgroup_members[nhopgroup_members_set.find(nhid)->second].push_back(entry);
}
}
else
{
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;
}
}

Expand Down Expand Up @@ -1476,13 +1528,15 @@ bool RouteOrch::removeNextHopGroup(const NextHopGroupKey &nexthops)
{
if (m_neighOrch->isNextHopFlagSet(nhop->first, NHFLAGS_IFDOWN))
{
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);
for(size_t i =0 ; i < nhop->second.size(); i++)
SWSS_LOG_WARN("NHFLAGS_IFDOWN set for next hop group member %s with next_hop_ids %" PRIx64,
nhop->first.to_string().c_str(), nhop->second[i].next_hop_id);
nhop = nhgm.erase(nhop);
continue;
}

next_hop_ids.push_back(nhop->second.next_hop_id);
for(size_t i =0 ; i < nhop->second.size(); i++)
next_hop_ids.push_back(nhop->second[i].next_hop_id);
nhop = nhgm.erase(nhop);
}

Expand Down
5 changes: 3 additions & 2 deletions orchagent/routeorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
struct NextHopGroupMemberEntry
{
sai_object_id_t next_hop_id; // next hop sai oid
uint32_t seq_id; // Sequence Id of nexthop in the group
uint32_t seq_id; // Sequence Id of nexthop in the group
};

typedef std::map<NextHopKey, NextHopGroupMemberEntry> NextHopGroupMembers;
typedef std::map<NextHopKey, vector<NextHopGroupMemberEntry>> NextHopGroupMembers;

struct NhgBase;

Expand All @@ -40,6 +40,7 @@ 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>
uint32_t weight_offset;
};

struct NextHopUpdate
Expand Down