diff --git a/vslib/Makefile.am b/vslib/Makefile.am index 69ef2384..a62e1dee 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 00000000..cb90111c --- /dev/null +++ b/vslib/vpp/CRMTracker.cpp @@ -0,0 +1,293 @@ +#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 +{ + SWSS_LOG_ENTER(); + + 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) +{ + SWSS_LOG_ENTER(); + + 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) +{ + SWSS_LOG_ENTER(); + + 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() +{ + 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); +} + +// Neighbor tracking + +void CRMTracker::onNeighborCreated(bool ipv4) +{ + SWSS_LOG_ENTER(); + + 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) +{ + SWSS_LOG_ENTER(); + + 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) +{ + SWSS_LOG_ENTER(); + + 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) +{ + SWSS_LOG_ENTER(); + + 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() +{ + 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); +} + +// Nexthop group member tracking + +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); +} diff --git a/vslib/vpp/CRMTracker.h b/vslib/vpp/CRMTracker.h new file mode 100644 index 00000000..748dfbd4 --- /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 4f60ba6c..712791f0 100644 --- a/vslib/vpp/SwitchVpp.cpp +++ b/vslib/vpp/SwitchVpp.cpp @@ -865,16 +865,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; } @@ -897,17 +888,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; + } + } + m_crmTracker.onNexthopCreated(ipv4); + } + 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_crmTracker.onNhgMemberCreated(); + } + return status; } 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) + { + m_crmTracker.onNeighborCreated(isIPv4Neighbor(serializedObjectId)); + } + return status; } if (object_type == SAI_OBJECT_TYPE_ACL_ENTRY) @@ -970,8 +985,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; } @@ -994,6 +1008,16 @@ 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_crmTracker.onNhgCreated(); + } + return status; + } + return create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list); } @@ -1148,16 +1172,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; } @@ -1183,17 +1198,45 @@ 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) + { + m_crmTracker.onNexthopRemoved(ipv4); + } + 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) + { + m_crmTracker.onNhgMemberRemoved(); + } + return status; } 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) + { + m_crmTracker.onNeighborRemoved(ipv4); + } + return status; } if (object_type == SAI_OBJECT_TYPE_ACL_ENTRY) @@ -1258,8 +1301,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; } @@ -1268,6 +1310,16 @@ 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) + { + m_crmTracker.onNhgRemoved(); + } + return status; + } + return remove_internal(object_type, serializedObjectId); } @@ -2047,81 +2099,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); - } - - SWSS_LOG_NOTICE("CRM: profile loaded (IPv4=%u, IPv6=%u, FDB=%u)", - m_vppMaxIPv4RouteEntries, m_vppMaxIPv6RouteEntries, m_vppMaxFdbEntries); + 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)); - - // For remaining resources (nexthop, neighbor, 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 }, - { 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)); } @@ -2172,31 +2170,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); - - 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 30d4961b..2285b796 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" @@ -974,19 +975,10 @@ 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; - - // 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; + CRMTracker m_crmTracker; bool isIPv4Route(const std::string &serializedObjectId); - - void loadCrmProfileValues(); + bool isIPv4Neighbor(const std::string &serializedObjectId); virtual sai_status_t set_static_crm_values() override;