diff --git a/orchagent/nexthopgroupkey.h b/orchagent/nexthopgroupkey.h index d012cbe41a..8f0916b666 100644 --- a/orchagent/nexthopgroupkey.h +++ b/orchagent/nexthopgroupkey.h @@ -49,6 +49,7 @@ 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 nhv = tokenize(nexthops, NHG_DELIMITER); @@ -56,7 +57,7 @@ class NextHopGroupKey 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); } diff --git a/orchagent/routeorch.cpp b/orchagent/routeorch.cpp index 803f71bb1e..f300b8de82 100644 --- a/orchagent/routeorch.cpp +++ b/orchagent/routeorch.cpp @@ -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)) @@ -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)) @@ -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); @@ -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 { @@ -1291,6 +1311,7 @@ bool RouteOrch::addNextHopGroup(const NextHopGroupKey &nexthops) set next_hop_set = nexthops.getNextHops(); std::map nhopgroup_members_set; std::map> nhopgroup_shared_set; + vector weights; /* Assert each IP address exists in m_syncdNextHops table, * and add the corresponding next_hop_id to next_hop_ids. */ @@ -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 { @@ -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 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> 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 nhgm_attrs; - // Create a next hop group member - vector 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; } } @@ -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); } diff --git a/orchagent/routeorch.h b/orchagent/routeorch.h index 577d966a26..8eee61fe9c 100644 --- a/orchagent/routeorch.h +++ b/orchagent/routeorch.h @@ -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 NextHopGroupMembers; +typedef std::map> NextHopGroupMembers; struct NhgBase; @@ -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 + uint32_t weight_offset; }; struct NextHopUpdate