From 8de8eddf714cceb118340ea7aac1df8748b1a11c Mon Sep 17 00:00:00 2001 From: Yue Gao Date: Wed, 25 Mar 2026 07:16:09 -0700 Subject: [PATCH 1/4] Implement neighbour crm counter Signed-off-by: Yue Gao --- vslib/vpp/SwitchVpp.cpp | 72 +++++++++++++++++++++++++++++++++++++---- vslib/vpp/SwitchVpp.h | 5 +++ 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/vslib/vpp/SwitchVpp.cpp b/vslib/vpp/SwitchVpp.cpp index d5ef30a4e4..5f9179fa5c 100644 --- a/vslib/vpp/SwitchVpp.cpp +++ b/vslib/vpp/SwitchVpp.cpp @@ -894,7 +894,21 @@ sai_status_t SwitchVpp::create( if (object_type == SAI_OBJECT_TYPE_NEIGHBOR_ENTRY) { - return addIpNbr(serializedObjectId, switch_id, attr_count, attr_list); + sai_status_t status = addIpNbr(serializedObjectId, switch_id, attr_count, attr_list); + if (status == SAI_STATUS_SUCCESS) + { + if (isIPv4Neighbor(serializedObjectId)) + { + m_ipv4_neighbor_count++; + SWSS_LOG_DEBUG("CRM: IPv4 neighbor created, count: %u", m_ipv4_neighbor_count); + } + else + { + m_ipv6_neighbor_count++; + SWSS_LOG_DEBUG("CRM: IPv6 neighbor created, count: %u", m_ipv6_neighbor_count); + } + } + return status; } if (object_type == SAI_OBJECT_TYPE_ACL_ENTRY) @@ -1180,7 +1194,22 @@ sai_status_t SwitchVpp::remove( if (object_type == SAI_OBJECT_TYPE_NEIGHBOR_ENTRY) { - return removeIpNbr(serializedObjectId); + bool ipv4 = isIPv4Neighbor(serializedObjectId); + sai_status_t status = removeIpNbr(serializedObjectId); + if (status == SAI_STATUS_SUCCESS) + { + if (ipv4) + { + if (m_ipv4_neighbor_count > 0) m_ipv4_neighbor_count--; + SWSS_LOG_DEBUG("CRM: IPv4 neighbor removed, count: %u", m_ipv4_neighbor_count); + } + else + { + if (m_ipv6_neighbor_count > 0) m_ipv6_neighbor_count--; + SWSS_LOG_DEBUG("CRM: IPv6 neighbor removed, count: %u", m_ipv6_neighbor_count); + } + } + return status; } if (object_type == SAI_OBJECT_TYPE_ACL_ENTRY) @@ -2065,8 +2094,21 @@ void SwitchVpp::loadCrmProfileValues() m_vppMaxFdbEntries = (uint32_t)std::stoul(it->second); } - SWSS_LOG_NOTICE("CRM: profile loaded (IPv4=%u, IPv6=%u, FDB=%u)", - m_vppMaxIPv4RouteEntries, m_vppMaxIPv6RouteEntries, m_vppMaxFdbEntries); + it = profileMap.find("SAI_VPP_MAX_IPV4_NEIGHBOR_ENTRIES"); + if (it != profileMap.end()) + { + m_vppMaxIPv4NeighborEntries = (uint32_t)std::stoul(it->second); + } + + it = profileMap.find("SAI_VPP_MAX_IPV6_NEIGHBOR_ENTRIES"); + if (it != profileMap.end()) + { + m_vppMaxIPv6NeighborEntries = (uint32_t)std::stoul(it->second); + } + + SWSS_LOG_NOTICE("CRM: profile loaded (IPv4Route=%u, IPv6Route=%u, FDB=%u, IPv4Nbr=%u, IPv6Nbr=%u)", + m_vppMaxIPv4RouteEntries, m_vppMaxIPv6RouteEntries, m_vppMaxFdbEntries, + m_vppMaxIPv4NeighborEntries, m_vppMaxIPv6NeighborEntries); } sai_status_t SwitchVpp::set_static_crm_values() @@ -2091,12 +2133,18 @@ sai_status_t SwitchVpp::set_static_crm_values() attr.value.u32 = m_vppMaxFdbEntries; CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - // For remaining resources (nexthop, neighbor, nhg, etc.), use base class defaults + attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY; + attr.value.u32 = m_vppMaxIPv4NeighborEntries; + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY; + attr.value.u32 = m_vppMaxIPv6NeighborEntries; + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + // For remaining resources (nexthop, nhg, etc.), use base class defaults std::map remaining_resources = { { SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY, m_maxIPv4NextHopEntries }, { SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY, m_maxIPv6NextHopEntries }, - { SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY, m_maxIPv4NeighborEntries }, - { SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY, m_maxIPv6NeighborEntries }, { SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY, m_maxNextHopGroupMemberEntries }, { SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY, m_maxNextHopGroupEntries }, { SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY, m_maxSNATEntries }, @@ -2181,6 +2229,16 @@ sai_status_t SwitchVpp::refresh_read_only( ? (m_vppMaxFdbEntries - m_fdb_entry_count) : 0; return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); + case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY: + attr.value.u32 = (m_vppMaxIPv4NeighborEntries > m_ipv4_neighbor_count) + ? (m_vppMaxIPv4NeighborEntries - m_ipv4_neighbor_count) : 0; + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); + + case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY: + attr.value.u32 = (m_vppMaxIPv6NeighborEntries > m_ipv6_neighbor_count) + ? (m_vppMaxIPv6NeighborEntries - m_ipv6_neighbor_count) : 0; + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); + default: break; } diff --git a/vslib/vpp/SwitchVpp.h b/vslib/vpp/SwitchVpp.h index ccbac0a4ad..dc4bf02f4a 100644 --- a/vslib/vpp/SwitchVpp.h +++ b/vslib/vpp/SwitchVpp.h @@ -967,13 +967,18 @@ namespace saivs uint32_t m_vppMaxIPv4RouteEntries = m_maxIPv4RouteEntries; uint32_t m_vppMaxIPv6RouteEntries = m_maxIPv6RouteEntries; uint32_t m_vppMaxFdbEntries = m_maxFdbEntries; + uint32_t m_vppMaxIPv4NeighborEntries = m_maxIPv4NeighborEntries; + uint32_t m_vppMaxIPv6NeighborEntries = m_maxIPv6NeighborEntries; // CRM resource tracking counters uint32_t m_ipv4_route_count = 0; uint32_t m_ipv6_route_count = 0; uint32_t m_fdb_entry_count = 0; + uint32_t m_ipv4_neighbor_count = 0; + uint32_t m_ipv6_neighbor_count = 0; bool isIPv4Route(const std::string &serializedObjectId); + bool isIPv4Neighbor(const std::string &serializedObjectId); void loadCrmProfileValues(); From cb90329c0187e3c1768f17a0c081fdab9a0d1727 Mon Sep 17 00:00:00 2001 From: Yue Gao Date: Wed, 25 Mar 2026 07:45:28 -0700 Subject: [PATCH 2/4] Implement nh and nhgroup crm counters Signed-off-by: Yue Gao --- vslib/vpp/SwitchVpp.cpp | 164 +++++++++++++++++++++++++++++++++++++--- vslib/vpp/SwitchVpp.h | 8 ++ 2 files changed, 161 insertions(+), 11 deletions(-) diff --git a/vslib/vpp/SwitchVpp.cpp b/vslib/vpp/SwitchVpp.cpp index 5f9179fa5c..ffe12432f5 100644 --- a/vslib/vpp/SwitchVpp.cpp +++ b/vslib/vpp/SwitchVpp.cpp @@ -884,12 +884,41 @@ sai_status_t SwitchVpp::create( if (object_type == SAI_OBJECT_TYPE_NEXT_HOP) { - return createNexthop(serializedObjectId, switch_id, attr_count, attr_list); + sai_status_t status = createNexthop(serializedObjectId, switch_id, attr_count, attr_list); + if (status == SAI_STATUS_SUCCESS) + { + bool ipv4 = true; + for (uint32_t i = 0; i < attr_count; i++) + { + if (attr_list[i].id == SAI_NEXT_HOP_ATTR_IP) + { + ipv4 = (attr_list[i].value.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4); + break; + } + } + if (ipv4) + { + m_ipv4_nexthop_count++; + SWSS_LOG_DEBUG("CRM: IPv4 nexthop created, count: %u", m_ipv4_nexthop_count); + } + else + { + m_ipv6_nexthop_count++; + SWSS_LOG_DEBUG("CRM: IPv6 nexthop created, count: %u", m_ipv6_nexthop_count); + } + } + return status; } if (object_type == SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER) { - return createNexthopGroupMember(serializedObjectId, switch_id, attr_count, attr_list); + sai_status_t status = createNexthopGroupMember(serializedObjectId, switch_id, attr_count, attr_list); + if (status == SAI_STATUS_SUCCESS) + { + m_nexthop_group_member_count++; + SWSS_LOG_DEBUG("CRM: NHG member created, count: %u", m_nexthop_group_member_count); + } + return status; } if (object_type == SAI_OBJECT_TYPE_NEIGHBOR_ENTRY) @@ -995,6 +1024,17 @@ sai_status_t SwitchVpp::create( return createLagMember(object_id, switch_id, attr_count, attr_list); } + if (object_type == SAI_OBJECT_TYPE_NEXT_HOP_GROUP) + { + sai_status_t status = create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list); + if (status == SAI_STATUS_SUCCESS) + { + m_nexthop_group_count++; + SWSS_LOG_DEBUG("CRM: NHG created, count: %u", m_nexthop_group_count); + } + return status; + } + return create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list); } @@ -1184,12 +1224,44 @@ sai_status_t SwitchVpp::remove( if (object_type == SAI_OBJECT_TYPE_NEXT_HOP) { - return removeNexthop(serializedObjectId); + // Determine IP family before remove (object still exists) + bool ipv4 = true; + auto nh_obj = get_sai_object(SAI_OBJECT_TYPE_NEXT_HOP, serializedObjectId); + if (nh_obj) + { + sai_attribute_t ip_attr; + ip_attr.id = SAI_NEXT_HOP_ATTR_IP; + if (nh_obj->get_attr(ip_attr) == SAI_STATUS_SUCCESS) + { + ipv4 = (ip_attr.value.ipaddr.addr_family == SAI_IP_ADDR_FAMILY_IPV4); + } + } + sai_status_t status = removeNexthop(serializedObjectId); + if (status == SAI_STATUS_SUCCESS) + { + if (ipv4) + { + if (m_ipv4_nexthop_count > 0) m_ipv4_nexthop_count--; + SWSS_LOG_DEBUG("CRM: IPv4 nexthop removed, count: %u", m_ipv4_nexthop_count); + } + else + { + if (m_ipv6_nexthop_count > 0) m_ipv6_nexthop_count--; + SWSS_LOG_DEBUG("CRM: IPv6 nexthop removed, count: %u", m_ipv6_nexthop_count); + } + } + return status; } if (object_type == SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER) { - return removeNexthopGroupMember(serializedObjectId); + sai_status_t status = removeNexthopGroupMember(serializedObjectId); + if (status == SAI_STATUS_SUCCESS) + { + if (m_nexthop_group_member_count > 0) m_nexthop_group_member_count--; + SWSS_LOG_DEBUG("CRM: NHG member removed, count: %u", m_nexthop_group_member_count); + } + return status; } if (object_type == SAI_OBJECT_TYPE_NEIGHBOR_ENTRY) @@ -1284,6 +1356,17 @@ sai_status_t SwitchVpp::remove( return bfd_session_del(serializedObjectId); } + if (object_type == SAI_OBJECT_TYPE_NEXT_HOP_GROUP) + { + sai_status_t status = remove_internal(object_type, serializedObjectId); + if (status == SAI_STATUS_SUCCESS) + { + if (m_nexthop_group_count > 0) m_nexthop_group_count--; + SWSS_LOG_DEBUG("CRM: NHG removed, count: %u", m_nexthop_group_count); + } + return status; + } + return remove_internal(object_type, serializedObjectId); } @@ -2106,9 +2189,36 @@ void SwitchVpp::loadCrmProfileValues() m_vppMaxIPv6NeighborEntries = (uint32_t)std::stoul(it->second); } - SWSS_LOG_NOTICE("CRM: profile loaded (IPv4Route=%u, IPv6Route=%u, FDB=%u, IPv4Nbr=%u, IPv6Nbr=%u)", + it = profileMap.find("SAI_VPP_MAX_IPV4_NEXTHOP_ENTRIES"); + if (it != profileMap.end()) + { + m_vppMaxIPv4NextHopEntries = (uint32_t)std::stoul(it->second); + } + + it = profileMap.find("SAI_VPP_MAX_IPV6_NEXTHOP_ENTRIES"); + if (it != profileMap.end()) + { + m_vppMaxIPv6NextHopEntries = (uint32_t)std::stoul(it->second); + } + + it = profileMap.find("SAI_VPP_MAX_NEXTHOP_GROUP_ENTRIES"); + if (it != profileMap.end()) + { + m_vppMaxNextHopGroupEntries = (uint32_t)std::stoul(it->second); + } + + it = profileMap.find("SAI_VPP_MAX_NEXTHOP_GROUP_MEMBER_ENTRIES"); + if (it != profileMap.end()) + { + m_vppMaxNextHopGroupMemberEntries = (uint32_t)std::stoul(it->second); + } + + SWSS_LOG_NOTICE("CRM: profile loaded (IPv4Route=%u, IPv6Route=%u, FDB=%u, " + "IPv4Nbr=%u, IPv6Nbr=%u, IPv4NH=%u, IPv6NH=%u, NHG=%u, NHGMbr=%u)", m_vppMaxIPv4RouteEntries, m_vppMaxIPv6RouteEntries, m_vppMaxFdbEntries, - m_vppMaxIPv4NeighborEntries, m_vppMaxIPv6NeighborEntries); + m_vppMaxIPv4NeighborEntries, m_vppMaxIPv6NeighborEntries, + m_vppMaxIPv4NextHopEntries, m_vppMaxIPv6NextHopEntries, + m_vppMaxNextHopGroupEntries, m_vppMaxNextHopGroupMemberEntries); } sai_status_t SwitchVpp::set_static_crm_values() @@ -2141,12 +2251,24 @@ sai_status_t SwitchVpp::set_static_crm_values() attr.value.u32 = m_vppMaxIPv6NeighborEntries; CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - // For remaining resources (nexthop, nhg, etc.), use base class defaults + attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY; + attr.value.u32 = m_vppMaxIPv4NextHopEntries; + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY; + attr.value.u32 = m_vppMaxIPv6NextHopEntries; + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + attr.id = SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY; + attr.value.u32 = m_vppMaxNextHopGroupEntries; + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + attr.id = SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY; + attr.value.u32 = m_vppMaxNextHopGroupMemberEntries; + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + + // For remaining resources, use base class defaults std::map remaining_resources = { - { SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY, m_maxIPv4NextHopEntries }, - { SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY, m_maxIPv6NextHopEntries }, - { SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY, m_maxNextHopGroupMemberEntries }, - { SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY, m_maxNextHopGroupEntries }, { SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY, m_maxSNATEntries }, { SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY, m_maxDNATEntries }, { SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY, m_maxIPMCEntries }, @@ -2239,6 +2361,26 @@ sai_status_t SwitchVpp::refresh_read_only( ? (m_vppMaxIPv6NeighborEntries - m_ipv6_neighbor_count) : 0; return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); + case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY: + attr.value.u32 = (m_vppMaxIPv4NextHopEntries > m_ipv4_nexthop_count) + ? (m_vppMaxIPv4NextHopEntries - m_ipv4_nexthop_count) : 0; + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); + + case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY: + attr.value.u32 = (m_vppMaxIPv6NextHopEntries > m_ipv6_nexthop_count) + ? (m_vppMaxIPv6NextHopEntries - m_ipv6_nexthop_count) : 0; + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); + + case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY: + attr.value.u32 = (m_vppMaxNextHopGroupEntries > m_nexthop_group_count) + ? (m_vppMaxNextHopGroupEntries - m_nexthop_group_count) : 0; + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); + + case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY: + attr.value.u32 = (m_vppMaxNextHopGroupMemberEntries > m_nexthop_group_member_count) + ? (m_vppMaxNextHopGroupMemberEntries - m_nexthop_group_member_count) : 0; + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); + default: break; } diff --git a/vslib/vpp/SwitchVpp.h b/vslib/vpp/SwitchVpp.h index dc4bf02f4a..6596b783ac 100644 --- a/vslib/vpp/SwitchVpp.h +++ b/vslib/vpp/SwitchVpp.h @@ -969,6 +969,10 @@ namespace saivs uint32_t m_vppMaxFdbEntries = m_maxFdbEntries; uint32_t m_vppMaxIPv4NeighborEntries = m_maxIPv4NeighborEntries; uint32_t m_vppMaxIPv6NeighborEntries = m_maxIPv6NeighborEntries; + uint32_t m_vppMaxIPv4NextHopEntries = m_maxIPv4NextHopEntries; + uint32_t m_vppMaxIPv6NextHopEntries = m_maxIPv6NextHopEntries; + uint32_t m_vppMaxNextHopGroupEntries = m_maxNextHopGroupEntries; + uint32_t m_vppMaxNextHopGroupMemberEntries = m_maxNextHopGroupMemberEntries; // CRM resource tracking counters uint32_t m_ipv4_route_count = 0; @@ -976,6 +980,10 @@ namespace saivs uint32_t m_fdb_entry_count = 0; uint32_t m_ipv4_neighbor_count = 0; uint32_t m_ipv6_neighbor_count = 0; + uint32_t m_ipv4_nexthop_count = 0; + uint32_t m_ipv6_nexthop_count = 0; + uint32_t m_nexthop_group_count = 0; + uint32_t m_nexthop_group_member_count = 0; bool isIPv4Route(const std::string &serializedObjectId); bool isIPv4Neighbor(const std::string &serializedObjectId); From 6a48cc6364fe08377cd3cd25706a23e3c7d86554 Mon Sep 17 00:00:00 2001 From: Yue Gao Date: Wed, 25 Mar 2026 09:15:06 -0700 Subject: [PATCH 3/4] Implement crm counters to track neighbor, nh and nh group/member Signed-off-by: Yue Gao --- vslib/Makefile.am | 1 + vslib/vpp/CRMTracker.cpp | 267 ++++++++++++++++++++++++++++++++++++++ vslib/vpp/CRMTracker.h | 87 +++++++++++++ vslib/vpp/SwitchVpp.cpp | 270 ++++----------------------------------- vslib/vpp/SwitchVpp.h | 25 +--- 5 files changed, 382 insertions(+), 268 deletions(-) create mode 100644 vslib/vpp/CRMTracker.cpp create mode 100644 vslib/vpp/CRMTracker.h diff --git a/vslib/Makefile.am b/vslib/Makefile.am index 0bbfb46c90..88bdcf6de2 100644 --- a/vslib/Makefile.am +++ b/vslib/Makefile.am @@ -75,6 +75,7 @@ libSaiVS_a_SOURCES = \ if USE_VPP libSaiVS_a_SOURCES +=\ + vpp/CRMTracker.cpp \ vpp/SaiObjectDB.cpp \ vpp/SwitchVpp.cpp \ vpp/SwitchVppAcl.cpp \ diff --git a/vslib/vpp/CRMTracker.cpp b/vslib/vpp/CRMTracker.cpp new file mode 100644 index 0000000000..fa16b4c528 --- /dev/null +++ b/vslib/vpp/CRMTracker.cpp @@ -0,0 +1,267 @@ +#include "CRMTracker.h" + +using namespace saivs; + +CRMTracker::CRMTracker() +{ + SWSS_LOG_ENTER(); +} + +void CRMTracker::loadProfileValues( + const std::map& profileMap) +{ + SWSS_LOG_ENTER(); + + if (profileMap.empty()) + { + SWSS_LOG_NOTICE("CRM: profile map is empty, using defaults"); + return; + } + + static const std::pair keys[] = { + { "SAI_VPP_MAX_IPV4_ROUTE_ENTRIES", &CRMTracker::m_maxIPv4RouteEntries }, + { "SAI_VPP_MAX_IPV6_ROUTE_ENTRIES", &CRMTracker::m_maxIPv6RouteEntries }, + { "SAI_VPP_MAX_FDB_ENTRIES", &CRMTracker::m_maxFdbEntries }, + { "SAI_VPP_MAX_IPV4_NEIGHBOR_ENTRIES", &CRMTracker::m_maxIPv4NeighborEntries }, + { "SAI_VPP_MAX_IPV6_NEIGHBOR_ENTRIES", &CRMTracker::m_maxIPv6NeighborEntries }, + { "SAI_VPP_MAX_IPV4_NEXTHOP_ENTRIES", &CRMTracker::m_maxIPv4NextHopEntries }, + { "SAI_VPP_MAX_IPV6_NEXTHOP_ENTRIES", &CRMTracker::m_maxIPv6NextHopEntries }, + { "SAI_VPP_MAX_NEXTHOP_GROUP_ENTRIES", &CRMTracker::m_maxNextHopGroupEntries }, + { "SAI_VPP_MAX_NEXTHOP_GROUP_MEMBER_ENTRIES", &CRMTracker::m_maxNextHopGroupMemberEntries }, + }; + + for (const auto& kv : keys) + { + auto it = profileMap.find(kv.first); + if (it != profileMap.end()) + { + this->*(kv.second) = (uint32_t)std::stoul(it->second); + } + } + + SWSS_LOG_NOTICE("CRM: profile loaded (IPv4Route=%u, IPv6Route=%u, FDB=%u, " + "IPv4Nbr=%u, IPv6Nbr=%u, IPv4NH=%u, IPv6NH=%u, NHG=%u, NHGMbr=%u)", + m_maxIPv4RouteEntries, m_maxIPv6RouteEntries, m_maxFdbEntries, + m_maxIPv4NeighborEntries, m_maxIPv6NeighborEntries, + m_maxIPv4NextHopEntries, m_maxIPv6NextHopEntries, + m_maxNextHopGroupEntries, m_maxNextHopGroupMemberEntries); +} + +std::vector CRMTracker::getInitialValues() const +{ + SWSS_LOG_ENTER(); + + return { + { SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY, m_maxIPv4RouteEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY, m_maxIPv6RouteEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY, m_maxFdbEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY, m_maxIPv4NeighborEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY, m_maxIPv6NeighborEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY, m_maxIPv4NextHopEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY, m_maxIPv6NextHopEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY, m_maxNextHopGroupEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY, m_maxNextHopGroupMemberEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY, m_maxSNATEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY, m_maxDNATEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY, m_maxIPMCEntries }, + { SAI_SWITCH_ATTR_AVAILABLE_DOUBLE_NAT_ENTRY, m_maxDoubleNATEntries }, + }; +} + +bool CRMTracker::handles(sai_switch_attr_t attr_id) const +{ + switch (attr_id) + { + case SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY: + case SAI_SWITCH_ATTR_AVAILABLE_DOUBLE_NAT_ENTRY: + return true; + default: + return false; + } +} + +uint32_t CRMTracker::getAvailable(sai_switch_attr_t attr_id) const +{ + SWSS_LOG_ENTER(); + + uint32_t max_val = 0; + uint32_t used = 0; + + switch (attr_id) + { + case SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY: + max_val = m_maxIPv4RouteEntries; used = m_ipv4RouteCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY: + max_val = m_maxIPv6RouteEntries; used = m_ipv6RouteCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY: + max_val = m_maxFdbEntries; used = m_fdbCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY: + max_val = m_maxIPv4NeighborEntries; used = m_ipv4NeighborCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY: + max_val = m_maxIPv6NeighborEntries; used = m_ipv6NeighborCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY: + max_val = m_maxIPv4NextHopEntries; used = m_ipv4NexthopCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY: + max_val = m_maxIPv6NextHopEntries; used = m_ipv6NexthopCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY: + max_val = m_maxNextHopGroupEntries; used = m_nhgCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY: + max_val = m_maxNextHopGroupMemberEntries; used = m_nhgMemberCount; break; + case SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY: + max_val = m_maxSNATEntries; used = 0; break; + case SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY: + max_val = m_maxDNATEntries; used = 0; break; + case SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY: + max_val = m_maxIPMCEntries; used = 0; break; + case SAI_SWITCH_ATTR_AVAILABLE_DOUBLE_NAT_ENTRY: + max_val = m_maxDoubleNATEntries; used = 0; break; + default: + SWSS_LOG_WARN("CRM: getAvailable called with unhandled attr %d", attr_id); + return 0; + } + + return (max_val > used) ? (max_val - used) : 0; +} + +// Route tracking + +void CRMTracker::onRouteCreated(bool ipv4) +{ + if (ipv4) + { + m_ipv4RouteCount++; + SWSS_LOG_DEBUG("CRM: IPv4 route created, count: %u", m_ipv4RouteCount); + } + else + { + m_ipv6RouteCount++; + SWSS_LOG_DEBUG("CRM: IPv6 route created, count: %u", m_ipv6RouteCount); + } +} + +void CRMTracker::onRouteRemoved(bool ipv4) +{ + if (ipv4) + { + if (m_ipv4RouteCount > 0) m_ipv4RouteCount--; + SWSS_LOG_DEBUG("CRM: IPv4 route removed, count: %u", m_ipv4RouteCount); + } + else + { + if (m_ipv6RouteCount > 0) m_ipv6RouteCount--; + SWSS_LOG_DEBUG("CRM: IPv6 route removed, count: %u", m_ipv6RouteCount); + } +} + +// FDB tracking + +void CRMTracker::onFdbCreated() +{ + m_fdbCount++; + SWSS_LOG_DEBUG("CRM: FDB entry created, count: %u", m_fdbCount); +} + +void CRMTracker::onFdbRemoved() +{ + if (m_fdbCount > 0) m_fdbCount--; + SWSS_LOG_DEBUG("CRM: FDB entry removed, count: %u", m_fdbCount); +} + +// Neighbor tracking + +void CRMTracker::onNeighborCreated(bool ipv4) +{ + if (ipv4) + { + m_ipv4NeighborCount++; + SWSS_LOG_DEBUG("CRM: IPv4 neighbor created, count: %u", m_ipv4NeighborCount); + } + else + { + m_ipv6NeighborCount++; + SWSS_LOG_DEBUG("CRM: IPv6 neighbor created, count: %u", m_ipv6NeighborCount); + } +} + +void CRMTracker::onNeighborRemoved(bool ipv4) +{ + if (ipv4) + { + if (m_ipv4NeighborCount > 0) m_ipv4NeighborCount--; + SWSS_LOG_DEBUG("CRM: IPv4 neighbor removed, count: %u", m_ipv4NeighborCount); + } + else + { + if (m_ipv6NeighborCount > 0) m_ipv6NeighborCount--; + SWSS_LOG_DEBUG("CRM: IPv6 neighbor removed, count: %u", m_ipv6NeighborCount); + } +} + +// Nexthop tracking + +void CRMTracker::onNexthopCreated(bool ipv4) +{ + if (ipv4) + { + m_ipv4NexthopCount++; + SWSS_LOG_DEBUG("CRM: IPv4 nexthop created, count: %u", m_ipv4NexthopCount); + } + else + { + m_ipv6NexthopCount++; + SWSS_LOG_DEBUG("CRM: IPv6 nexthop created, count: %u", m_ipv6NexthopCount); + } +} + +void CRMTracker::onNexthopRemoved(bool ipv4) +{ + if (ipv4) + { + if (m_ipv4NexthopCount > 0) m_ipv4NexthopCount--; + SWSS_LOG_DEBUG("CRM: IPv4 nexthop removed, count: %u", m_ipv4NexthopCount); + } + else + { + if (m_ipv6NexthopCount > 0) m_ipv6NexthopCount--; + SWSS_LOG_DEBUG("CRM: IPv6 nexthop removed, count: %u", m_ipv6NexthopCount); + } +} + +// Nexthop group tracking + +void CRMTracker::onNhgCreated() +{ + m_nhgCount++; + SWSS_LOG_DEBUG("CRM: NHG created, count: %u", m_nhgCount); +} + +void CRMTracker::onNhgRemoved() +{ + if (m_nhgCount > 0) m_nhgCount--; + SWSS_LOG_DEBUG("CRM: NHG removed, count: %u", m_nhgCount); +} + +// Nexthop group member tracking + +void CRMTracker::onNhgMemberCreated() +{ + m_nhgMemberCount++; + SWSS_LOG_DEBUG("CRM: NHG member created, count: %u", m_nhgMemberCount); +} + +void CRMTracker::onNhgMemberRemoved() +{ + if (m_nhgMemberCount > 0) m_nhgMemberCount--; + SWSS_LOG_DEBUG("CRM: NHG member removed, count: %u", m_nhgMemberCount); +} diff --git a/vslib/vpp/CRMTracker.h b/vslib/vpp/CRMTracker.h new file mode 100644 index 0000000000..748dfbd427 --- /dev/null +++ b/vslib/vpp/CRMTracker.h @@ -0,0 +1,87 @@ +#pragma once + +extern "C" { +#include "sai.h" +} + +#include "swss/logger.h" + +#include +#include +#include + +namespace saivs +{ + struct CRMInitValue + { + sai_switch_attr_t attr_id; + uint32_t value; + }; + + class CRMTracker + { + public: + + CRMTracker(); + + void loadProfileValues(const std::map& profileMap); + + std::vector getInitialValues() const; + + uint32_t getAvailable(sai_switch_attr_t attr_id) const; + + bool handles(sai_switch_attr_t attr_id) const; + + // Route tracking + void onRouteCreated(bool ipv4); + void onRouteRemoved(bool ipv4); + + // FDB tracking + void onFdbCreated(); + void onFdbRemoved(); + + // Neighbor tracking + void onNeighborCreated(bool ipv4); + void onNeighborRemoved(bool ipv4); + + // Nexthop tracking + void onNexthopCreated(bool ipv4); + void onNexthopRemoved(bool ipv4); + + // Nexthop group tracking + void onNhgCreated(); + void onNhgRemoved(); + + // Nexthop group member tracking + void onNhgMemberCreated(); + void onNhgMemberRemoved(); + + private: + + // Configurable limits (defaults from SwitchStateBase) + uint32_t m_maxIPv4RouteEntries = 100000; + uint32_t m_maxIPv6RouteEntries = 10000; + uint32_t m_maxFdbEntries = 800; + uint32_t m_maxIPv4NeighborEntries = 4000; + uint32_t m_maxIPv6NeighborEntries = 2000; + uint32_t m_maxIPv4NextHopEntries = 32000; + uint32_t m_maxIPv6NextHopEntries = 32000; + uint32_t m_maxNextHopGroupEntries = 400; + uint32_t m_maxNextHopGroupMemberEntries = 16000; + uint32_t m_maxSNATEntries = 100; + uint32_t m_maxDNATEntries = 100; + uint32_t m_maxIPMCEntries = 100; + uint32_t m_maxDoubleNATEntries = 50; + + // Usage counters + uint32_t m_ipv4RouteCount = 0; + uint32_t m_ipv6RouteCount = 0; + uint32_t m_fdbCount = 0; + uint32_t m_ipv4NeighborCount = 0; + uint32_t m_ipv6NeighborCount = 0; + uint32_t m_ipv4NexthopCount = 0; + uint32_t m_ipv6NexthopCount = 0; + uint32_t m_nhgCount = 0; + uint32_t m_nhgMemberCount = 0; + }; +} diff --git a/vslib/vpp/SwitchVpp.cpp b/vslib/vpp/SwitchVpp.cpp index ffe12432f5..b06473daeb 100644 --- a/vslib/vpp/SwitchVpp.cpp +++ b/vslib/vpp/SwitchVpp.cpp @@ -852,16 +852,7 @@ sai_status_t SwitchVpp::create( sai_status_t status = addIpRoute(serializedObjectId, switch_id, attr_count, attr_list); if (status == SAI_STATUS_SUCCESS) { - if (isIPv4Route(serializedObjectId)) - { - m_ipv4_route_count++; - SWSS_LOG_DEBUG("CRM: IPv4 route created, count: %u", m_ipv4_route_count); - } - else - { - m_ipv6_route_count++; - SWSS_LOG_DEBUG("CRM: IPv6 route created, count: %u", m_ipv6_route_count); - } + m_crmTracker.onRouteCreated(isIPv4Route(serializedObjectId)); } return status; } @@ -896,16 +887,7 @@ sai_status_t SwitchVpp::create( break; } } - if (ipv4) - { - m_ipv4_nexthop_count++; - SWSS_LOG_DEBUG("CRM: IPv4 nexthop created, count: %u", m_ipv4_nexthop_count); - } - else - { - m_ipv6_nexthop_count++; - SWSS_LOG_DEBUG("CRM: IPv6 nexthop created, count: %u", m_ipv6_nexthop_count); - } + m_crmTracker.onNexthopCreated(ipv4); } return status; } @@ -915,8 +897,7 @@ sai_status_t SwitchVpp::create( sai_status_t status = createNexthopGroupMember(serializedObjectId, switch_id, attr_count, attr_list); if (status == SAI_STATUS_SUCCESS) { - m_nexthop_group_member_count++; - SWSS_LOG_DEBUG("CRM: NHG member created, count: %u", m_nexthop_group_member_count); + m_crmTracker.onNhgMemberCreated(); } return status; } @@ -926,16 +907,7 @@ sai_status_t SwitchVpp::create( sai_status_t status = addIpNbr(serializedObjectId, switch_id, attr_count, attr_list); if (status == SAI_STATUS_SUCCESS) { - if (isIPv4Neighbor(serializedObjectId)) - { - m_ipv4_neighbor_count++; - SWSS_LOG_DEBUG("CRM: IPv4 neighbor created, count: %u", m_ipv4_neighbor_count); - } - else - { - m_ipv6_neighbor_count++; - SWSS_LOG_DEBUG("CRM: IPv6 neighbor created, count: %u", m_ipv6_neighbor_count); - } + m_crmTracker.onNeighborCreated(isIPv4Neighbor(serializedObjectId)); } return status; } @@ -1000,8 +972,7 @@ sai_status_t SwitchVpp::create( sai_status_t status = FdbEntryadd(serializedObjectId, switch_id, attr_count, attr_list); if (status == SAI_STATUS_SUCCESS) { - m_fdb_entry_count++; - SWSS_LOG_DEBUG("CRM: FDB entry created, count: %u", m_fdb_entry_count); + m_crmTracker.onFdbCreated(); } return status; } @@ -1029,8 +1000,7 @@ sai_status_t SwitchVpp::create( sai_status_t status = create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list); if (status == SAI_STATUS_SUCCESS) { - m_nexthop_group_count++; - SWSS_LOG_DEBUG("CRM: NHG created, count: %u", m_nexthop_group_count); + m_crmTracker.onNhgCreated(); } return status; } @@ -1189,16 +1159,7 @@ sai_status_t SwitchVpp::remove( sai_status_t status = removeIpRoute(serializedObjectId); if (status == SAI_STATUS_SUCCESS) { - if (wasIPv4) - { - if (m_ipv4_route_count > 0) m_ipv4_route_count--; - SWSS_LOG_DEBUG("CRM: IPv4 route removed, count: %u", m_ipv4_route_count); - } - else - { - if (m_ipv6_route_count > 0) m_ipv6_route_count--; - SWSS_LOG_DEBUG("CRM: IPv6 route removed, count: %u", m_ipv6_route_count); - } + m_crmTracker.onRouteRemoved(wasIPv4); } return status; } @@ -1239,16 +1200,7 @@ sai_status_t SwitchVpp::remove( sai_status_t status = removeNexthop(serializedObjectId); if (status == SAI_STATUS_SUCCESS) { - if (ipv4) - { - if (m_ipv4_nexthop_count > 0) m_ipv4_nexthop_count--; - SWSS_LOG_DEBUG("CRM: IPv4 nexthop removed, count: %u", m_ipv4_nexthop_count); - } - else - { - if (m_ipv6_nexthop_count > 0) m_ipv6_nexthop_count--; - SWSS_LOG_DEBUG("CRM: IPv6 nexthop removed, count: %u", m_ipv6_nexthop_count); - } + m_crmTracker.onNexthopRemoved(ipv4); } return status; } @@ -1258,8 +1210,7 @@ sai_status_t SwitchVpp::remove( sai_status_t status = removeNexthopGroupMember(serializedObjectId); if (status == SAI_STATUS_SUCCESS) { - if (m_nexthop_group_member_count > 0) m_nexthop_group_member_count--; - SWSS_LOG_DEBUG("CRM: NHG member removed, count: %u", m_nexthop_group_member_count); + m_crmTracker.onNhgMemberRemoved(); } return status; } @@ -1270,16 +1221,7 @@ sai_status_t SwitchVpp::remove( sai_status_t status = removeIpNbr(serializedObjectId); if (status == SAI_STATUS_SUCCESS) { - if (ipv4) - { - if (m_ipv4_neighbor_count > 0) m_ipv4_neighbor_count--; - SWSS_LOG_DEBUG("CRM: IPv4 neighbor removed, count: %u", m_ipv4_neighbor_count); - } - else - { - if (m_ipv6_neighbor_count > 0) m_ipv6_neighbor_count--; - SWSS_LOG_DEBUG("CRM: IPv6 neighbor removed, count: %u", m_ipv6_neighbor_count); - } + m_crmTracker.onNeighborRemoved(ipv4); } return status; } @@ -1346,8 +1288,7 @@ sai_status_t SwitchVpp::remove( sai_status_t status = FdbEntrydel(serializedObjectId); if (status == SAI_STATUS_SUCCESS) { - if (m_fdb_entry_count > 0) m_fdb_entry_count--; - SWSS_LOG_DEBUG("CRM: FDB entry removed, count: %u", m_fdb_entry_count); + m_crmTracker.onFdbRemoved(); } return status; } @@ -1361,8 +1302,7 @@ sai_status_t SwitchVpp::remove( sai_status_t status = remove_internal(object_type, serializedObjectId); if (status == SAI_STATUS_SUCCESS) { - if (m_nexthop_group_count > 0) m_nexthop_group_count--; - SWSS_LOG_DEBUG("CRM: NHG removed, count: %u", m_nexthop_group_count); + m_crmTracker.onNhgRemoved(); } return status; } @@ -2146,139 +2086,27 @@ bool SwitchVpp::isIPv4Route( return route_entry.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV4; } -void SwitchVpp::loadCrmProfileValues() +bool SwitchVpp::isIPv4Neighbor( + const std::string &serializedObjectId) { SWSS_LOG_ENTER(); - const auto &profileMap = m_switchConfig->m_profileMap; - - if (profileMap.empty()) - { - SWSS_LOG_NOTICE("CRM: profile map is empty, using defaults (IPv4=%u, IPv6=%u, FDB=%u)", - m_vppMaxIPv4RouteEntries, m_vppMaxIPv6RouteEntries, m_vppMaxFdbEntries); - return; - } - - auto it = profileMap.find("SAI_VPP_MAX_IPV4_ROUTE_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxIPv4RouteEntries = (uint32_t)std::stoul(it->second); - } - - it = profileMap.find("SAI_VPP_MAX_IPV6_ROUTE_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxIPv6RouteEntries = (uint32_t)std::stoul(it->second); - } - - it = profileMap.find("SAI_VPP_MAX_FDB_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxFdbEntries = (uint32_t)std::stoul(it->second); - } - - it = profileMap.find("SAI_VPP_MAX_IPV4_NEIGHBOR_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxIPv4NeighborEntries = (uint32_t)std::stoul(it->second); - } - - it = profileMap.find("SAI_VPP_MAX_IPV6_NEIGHBOR_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxIPv6NeighborEntries = (uint32_t)std::stoul(it->second); - } - - it = profileMap.find("SAI_VPP_MAX_IPV4_NEXTHOP_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxIPv4NextHopEntries = (uint32_t)std::stoul(it->second); - } - - it = profileMap.find("SAI_VPP_MAX_IPV6_NEXTHOP_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxIPv6NextHopEntries = (uint32_t)std::stoul(it->second); - } - - it = profileMap.find("SAI_VPP_MAX_NEXTHOP_GROUP_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxNextHopGroupEntries = (uint32_t)std::stoul(it->second); - } - - it = profileMap.find("SAI_VPP_MAX_NEXTHOP_GROUP_MEMBER_ENTRIES"); - if (it != profileMap.end()) - { - m_vppMaxNextHopGroupMemberEntries = (uint32_t)std::stoul(it->second); - } - - SWSS_LOG_NOTICE("CRM: profile loaded (IPv4Route=%u, IPv6Route=%u, FDB=%u, " - "IPv4Nbr=%u, IPv6Nbr=%u, IPv4NH=%u, IPv6NH=%u, NHG=%u, NHGMbr=%u)", - m_vppMaxIPv4RouteEntries, m_vppMaxIPv6RouteEntries, m_vppMaxFdbEntries, - m_vppMaxIPv4NeighborEntries, m_vppMaxIPv6NeighborEntries, - m_vppMaxIPv4NextHopEntries, m_vppMaxIPv6NextHopEntries, - m_vppMaxNextHopGroupEntries, m_vppMaxNextHopGroupMemberEntries); + sai_neighbor_entry_t neighbor_entry; + sai_deserialize_neighbor_entry(serializedObjectId, neighbor_entry); + return neighbor_entry.ip_address.addr_family == SAI_IP_ADDR_FAMILY_IPV4; } sai_status_t SwitchVpp::set_static_crm_values() { SWSS_LOG_ENTER(); - // Load configurable CRM limits from sai_vpp.profile - loadCrmProfileValues(); + m_crmTracker.loadProfileValues(m_switchConfig->m_profileMap); - // Override the base class static values with our configurable ones sai_attribute_t attr; - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY; - attr.value.u32 = m_vppMaxIPv4RouteEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY; - attr.value.u32 = m_vppMaxIPv6RouteEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY; - attr.value.u32 = m_vppMaxFdbEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY; - attr.value.u32 = m_vppMaxIPv4NeighborEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY; - attr.value.u32 = m_vppMaxIPv6NeighborEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY; - attr.value.u32 = m_vppMaxIPv4NextHopEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY; - attr.value.u32 = m_vppMaxIPv6NextHopEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY; - attr.value.u32 = m_vppMaxNextHopGroupEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - attr.id = SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY; - attr.value.u32 = m_vppMaxNextHopGroupMemberEntries; - CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); - - // For remaining resources, use base class defaults - std::map remaining_resources = { - { SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY, m_maxSNATEntries }, - { SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY, m_maxDNATEntries }, - { SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY, m_maxIPMCEntries }, - { SAI_SWITCH_ATTR_AVAILABLE_DOUBLE_NAT_ENTRY, m_maxDoubleNATEntries } - }; - - for (auto const &resource: remaining_resources) + for (const auto& v : m_crmTracker.getInitialValues()) { - attr.id = resource.first; - attr.value.u32 = resource.second; + attr.id = v.attr_id; + attr.value.u32 = v.value; CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); } @@ -2329,61 +2157,13 @@ sai_status_t SwitchVpp::refresh_read_only( } // Dynamic CRM resource availability: return max - used - if (meta->objecttype == SAI_OBJECT_TYPE_SWITCH) + if (meta->objecttype == SAI_OBJECT_TYPE_SWITCH && + m_crmTracker.handles((sai_switch_attr_t)meta->attrid)) { sai_attribute_t attr; attr.id = meta->attrid; - - switch (meta->attrid) - { - case SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY: - attr.value.u32 = (m_vppMaxIPv4RouteEntries > m_ipv4_route_count) - ? (m_vppMaxIPv4RouteEntries - m_ipv4_route_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - case SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY: - attr.value.u32 = (m_vppMaxIPv6RouteEntries > m_ipv6_route_count) - ? (m_vppMaxIPv6RouteEntries - m_ipv6_route_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - case SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY: - attr.value.u32 = (m_vppMaxFdbEntries > m_fdb_entry_count) - ? (m_vppMaxFdbEntries - m_fdb_entry_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY: - attr.value.u32 = (m_vppMaxIPv4NeighborEntries > m_ipv4_neighbor_count) - ? (m_vppMaxIPv4NeighborEntries - m_ipv4_neighbor_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY: - attr.value.u32 = (m_vppMaxIPv6NeighborEntries > m_ipv6_neighbor_count) - ? (m_vppMaxIPv6NeighborEntries - m_ipv6_neighbor_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - case SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY: - attr.value.u32 = (m_vppMaxIPv4NextHopEntries > m_ipv4_nexthop_count) - ? (m_vppMaxIPv4NextHopEntries - m_ipv4_nexthop_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - case SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY: - attr.value.u32 = (m_vppMaxIPv6NextHopEntries > m_ipv6_nexthop_count) - ? (m_vppMaxIPv6NextHopEntries - m_ipv6_nexthop_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY: - attr.value.u32 = (m_vppMaxNextHopGroupEntries > m_nexthop_group_count) - ? (m_vppMaxNextHopGroupEntries - m_nexthop_group_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY: - attr.value.u32 = (m_vppMaxNextHopGroupMemberEntries > m_nexthop_group_member_count) - ? (m_vppMaxNextHopGroupMemberEntries - m_nexthop_group_member_count) : 0; - return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); - - default: - break; - } + attr.value.u32 = m_crmTracker.getAvailable((sai_switch_attr_t)meta->attrid); + return set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr); } // For all other cases, delegate to the base class implementation diff --git a/vslib/vpp/SwitchVpp.h b/vslib/vpp/SwitchVpp.h index 6596b783ac..e5624b7cab 100644 --- a/vslib/vpp/SwitchVpp.h +++ b/vslib/vpp/SwitchVpp.h @@ -8,6 +8,7 @@ #include "TunnelManager.h" #include "SwitchVppNexthop.h" #include "SwitchVppAcl.h" +#include "CRMTracker.h" #include "vppxlate/SaiVppXlate.h" @@ -963,33 +964,11 @@ namespace saivs std::map> m_hostif_info_map; - // CRM resource limits (configurable via profile map from -p argument) - uint32_t m_vppMaxIPv4RouteEntries = m_maxIPv4RouteEntries; - uint32_t m_vppMaxIPv6RouteEntries = m_maxIPv6RouteEntries; - uint32_t m_vppMaxFdbEntries = m_maxFdbEntries; - uint32_t m_vppMaxIPv4NeighborEntries = m_maxIPv4NeighborEntries; - uint32_t m_vppMaxIPv6NeighborEntries = m_maxIPv6NeighborEntries; - uint32_t m_vppMaxIPv4NextHopEntries = m_maxIPv4NextHopEntries; - uint32_t m_vppMaxIPv6NextHopEntries = m_maxIPv6NextHopEntries; - uint32_t m_vppMaxNextHopGroupEntries = m_maxNextHopGroupEntries; - uint32_t m_vppMaxNextHopGroupMemberEntries = m_maxNextHopGroupMemberEntries; - - // CRM resource tracking counters - uint32_t m_ipv4_route_count = 0; - uint32_t m_ipv6_route_count = 0; - uint32_t m_fdb_entry_count = 0; - uint32_t m_ipv4_neighbor_count = 0; - uint32_t m_ipv6_neighbor_count = 0; - uint32_t m_ipv4_nexthop_count = 0; - uint32_t m_ipv6_nexthop_count = 0; - uint32_t m_nexthop_group_count = 0; - uint32_t m_nexthop_group_member_count = 0; + CRMTracker m_crmTracker; bool isIPv4Route(const std::string &serializedObjectId); bool isIPv4Neighbor(const std::string &serializedObjectId); - void loadCrmProfileValues(); - virtual sai_status_t set_static_crm_values() override; // SRv6 object tracking for CRM From f687e25cf462e5ad37fb54c37d9d1eae33489520 Mon Sep 17 00:00:00 2001 From: Yue Gao Date: Wed, 25 Mar 2026 11:25:41 -0700 Subject: [PATCH 4/4] Fix unit test due to missing SWSS_LOG_ENTER Signed-off-by: Yue Gao --- vslib/vpp/CRMTracker.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/vslib/vpp/CRMTracker.cpp b/vslib/vpp/CRMTracker.cpp index fa16b4c528..cb90111c1e 100644 --- a/vslib/vpp/CRMTracker.cpp +++ b/vslib/vpp/CRMTracker.cpp @@ -70,6 +70,8 @@ std::vector CRMTracker::getInitialValues() const bool CRMTracker::handles(sai_switch_attr_t attr_id) const { + SWSS_LOG_ENTER(); + switch (attr_id) { case SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY: @@ -138,6 +140,8 @@ uint32_t CRMTracker::getAvailable(sai_switch_attr_t attr_id) const void CRMTracker::onRouteCreated(bool ipv4) { + SWSS_LOG_ENTER(); + if (ipv4) { m_ipv4RouteCount++; @@ -152,6 +156,8 @@ void CRMTracker::onRouteCreated(bool ipv4) void CRMTracker::onRouteRemoved(bool ipv4) { + SWSS_LOG_ENTER(); + if (ipv4) { if (m_ipv4RouteCount > 0) m_ipv4RouteCount--; @@ -168,12 +174,16 @@ void CRMTracker::onRouteRemoved(bool ipv4) void CRMTracker::onFdbCreated() { + SWSS_LOG_ENTER(); + m_fdbCount++; SWSS_LOG_DEBUG("CRM: FDB entry created, count: %u", m_fdbCount); } void CRMTracker::onFdbRemoved() { + SWSS_LOG_ENTER(); + if (m_fdbCount > 0) m_fdbCount--; SWSS_LOG_DEBUG("CRM: FDB entry removed, count: %u", m_fdbCount); } @@ -182,6 +192,8 @@ void CRMTracker::onFdbRemoved() void CRMTracker::onNeighborCreated(bool ipv4) { + SWSS_LOG_ENTER(); + if (ipv4) { m_ipv4NeighborCount++; @@ -196,6 +208,8 @@ void CRMTracker::onNeighborCreated(bool ipv4) void CRMTracker::onNeighborRemoved(bool ipv4) { + SWSS_LOG_ENTER(); + if (ipv4) { if (m_ipv4NeighborCount > 0) m_ipv4NeighborCount--; @@ -212,6 +226,8 @@ void CRMTracker::onNeighborRemoved(bool ipv4) void CRMTracker::onNexthopCreated(bool ipv4) { + SWSS_LOG_ENTER(); + if (ipv4) { m_ipv4NexthopCount++; @@ -226,6 +242,8 @@ void CRMTracker::onNexthopCreated(bool ipv4) void CRMTracker::onNexthopRemoved(bool ipv4) { + SWSS_LOG_ENTER(); + if (ipv4) { if (m_ipv4NexthopCount > 0) m_ipv4NexthopCount--; @@ -242,12 +260,16 @@ void CRMTracker::onNexthopRemoved(bool ipv4) void CRMTracker::onNhgCreated() { + SWSS_LOG_ENTER(); + m_nhgCount++; SWSS_LOG_DEBUG("CRM: NHG created, count: %u", m_nhgCount); } void CRMTracker::onNhgRemoved() { + SWSS_LOG_ENTER(); + if (m_nhgCount > 0) m_nhgCount--; SWSS_LOG_DEBUG("CRM: NHG removed, count: %u", m_nhgCount); } @@ -256,12 +278,16 @@ void CRMTracker::onNhgRemoved() void CRMTracker::onNhgMemberCreated() { + SWSS_LOG_ENTER(); + m_nhgMemberCount++; SWSS_LOG_DEBUG("CRM: NHG member created, count: %u", m_nhgMemberCount); } void CRMTracker::onNhgMemberRemoved() { + SWSS_LOG_ENTER(); + if (m_nhgMemberCount > 0) m_nhgMemberCount--; SWSS_LOG_DEBUG("CRM: NHG member removed, count: %u", m_nhgMemberCount); }