vslib/RealObjectIdManager.cpp (292 lines of code) (raw):

#include "RealObjectIdManager.h" #include "meta/sai_serialize.h" #include "swss/logger.h" extern "C" { #include "saimetadata.h" } #define SAI_OBJECT_ID_BITS_SIZE (8 * sizeof(sai_object_id_t)) static_assert(SAI_OBJECT_ID_BITS_SIZE == 64, "sai_object_id_t must have 64 bits"); static_assert(sizeof(sai_object_id_t) == sizeof(uint64_t), "SAI object ID size should be uint64_t"); #define SAI_VS_OID_RESERVED_BITS_SIZE ( 8 ) #define SAI_VS_SWITCH_INDEX_BITS_SIZE ( 8 ) #define SAI_VS_SWITCH_INDEX_MAX ( (1ULL << SAI_VS_SWITCH_INDEX_BITS_SIZE) - 1 ) #define SAI_VS_SWITCH_INDEX_MASK (SAI_VS_SWITCH_INDEX_MAX) #define SAI_VS_GLOBAL_CONTEXT_BITS_SIZE ( 8 ) #define SAI_VS_GLOBAL_CONTEXT_MAX ( (1ULL << SAI_VS_GLOBAL_CONTEXT_BITS_SIZE) - 1 ) #define SAI_VS_GLOBAL_CONTEXT_MASK (SAI_VS_GLOBAL_CONTEXT_MAX) #define SAI_VS_OBJECT_TYPE_BITS_SIZE ( 8 ) #define SAI_VS_OBJECT_TYPE_MAX ( (1ULL << SAI_VS_OBJECT_TYPE_BITS_SIZE) - 1 ) #define SAI_VS_OBJECT_TYPE_MASK (SAI_VS_OBJECT_TYPE_MAX) #define SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE ( 1 ) #define SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_MAX ( (1ULL << SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE) - 1 ) #define SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_MASK (SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_MAX) #define SAI_VS_OBJECT_INDEX_BITS_SIZE ( 31 ) #define SAI_VS_OBJECT_INDEX_MAX ( (1ULL << SAI_VS_OBJECT_INDEX_BITS_SIZE) - 1 ) #define SAI_VS_OBJECT_INDEX_MASK (SAI_VS_OBJECT_INDEX_MAX) #define SAI_VS_OBJECT_ID_BITS_SIZE ( \ SAI_VS_OID_RESERVED_BITS_SIZE + \ SAI_VS_GLOBAL_CONTEXT_BITS_SIZE + \ SAI_VS_SWITCH_INDEX_BITS_SIZE + \ SAI_VS_OBJECT_TYPE_BITS_SIZE + \ SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE + \ SAI_VS_OBJECT_INDEX_BITS_SIZE ) static_assert(SAI_VS_OBJECT_ID_BITS_SIZE == SAI_OBJECT_ID_BITS_SIZE, "vs object id size must be equal to SAI object id size"); /* * This condition must be met, since we need to be able to encode SAI object * type in object id on defined number of bits. */ static_assert(SAI_OBJECT_TYPE_MAX < 256, "object type must be possible to encode on 1 byte"); static_assert((SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END - SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START) < 256, "extensions object type must be possible to encode on 1 byte"); /* * Current OBJECT ID format: * * bits 63..56 - reserved (must be zero) * bits 55..48 - global context * bits 47..40 - switch index * bits 49..32 - SAI object type * bits 31..31 - object type extension flag * bits 30..0 - object index * * So large number of bits is required, otherwise we would need to have map of * OID to some struct that will have all those values. But having all this * information in OID itself is more convenient. * * To be backward compatible with previous sairedis, we will still encode base * object type on bit's 49..32, and extensions which will now start from range * 0x20000000, will be encoded from 0x0, but extensions flag will be set to 1. * * For example SAI_OBJECT_TYPE_VIRTUAL_ROUTER oid will be encoded as 0x0300000001 * SAI_OBJECT_TYPE_DASH_ACL_GROUP oid will be encoded as 0x000380000000 */ #define SAI_VS_GET_OBJECT_INDEX(oid) \ ( ((uint64_t)oid) & ( SAI_VS_OBJECT_INDEX_MASK ) ) #define SAI_VS_GET_OBJECT_TYPE_EXTENSIONS_FLAG(oid) \ ( (((uint64_t)oid) >> (SAI_VS_OBJECT_INDEX_BITS_SIZE) ) & ( SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_MAX ) ) #define SAI_VS_GET_OBJECT_TYPE(oid) \ ( (((uint64_t)oid) >> ( SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE + SAI_VS_OBJECT_INDEX_BITS_SIZE) ) & ( SAI_VS_OBJECT_TYPE_MASK ) ) #define SAI_VS_GET_SWITCH_INDEX(oid) \ ( (((uint64_t)oid) >> ( SAI_VS_OBJECT_TYPE_BITS_SIZE + SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE + SAI_VS_OBJECT_INDEX_BITS_SIZE) ) & ( SAI_VS_SWITCH_INDEX_MASK ) ) #define SAI_VS_GET_GLOBAL_CONTEXT(oid) \ ( (((uint64_t)oid) >> ( SAI_VS_SWITCH_INDEX_BITS_SIZE + SAI_VS_OBJECT_TYPE_BITS_SIZE + SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE + SAI_VS_OBJECT_INDEX_BITS_SIZE) ) & ( SAI_VS_GLOBAL_CONTEXT_MASK ) ) #define SAI_VS_TEST_OID (0x01234567f9abcdef) static_assert(SAI_VS_GET_GLOBAL_CONTEXT(SAI_VS_TEST_OID) == 0x23, "test global context"); static_assert(SAI_VS_GET_SWITCH_INDEX(SAI_VS_TEST_OID) == 0x45, "test switch index"); static_assert(SAI_VS_GET_OBJECT_TYPE(SAI_VS_TEST_OID) == 0x67, "test object type"); static_assert(SAI_VS_GET_OBJECT_INDEX(SAI_VS_TEST_OID) == 0x79abcdef, "test object index"); static_assert(SAI_VS_GET_OBJECT_TYPE_EXTENSIONS_FLAG(SAI_VS_TEST_OID) == 0x1, "test object type extensions flag"); using namespace saivs; RealObjectIdManager::RealObjectIdManager( _In_ uint32_t globalContext, _In_ std::shared_ptr<SwitchConfigContainer> container): m_globalContext(globalContext), m_container(container) { SWSS_LOG_ENTER(); if (globalContext > SAI_VS_GLOBAL_CONTEXT_MAX) { SWSS_LOG_THROW("specified globalContext(0x%x) > maximum global context 0x%llx", globalContext, SAI_VS_GLOBAL_CONTEXT_MAX); } if (container == nullptr) { SWSS_LOG_THROW("switch config container cannot be nullptr"); } } sai_object_id_t RealObjectIdManager::saiSwitchIdQuery( _In_ sai_object_id_t objectId) const { SWSS_LOG_ENTER(); if (objectId == SAI_NULL_OBJECT_ID) { return SAI_NULL_OBJECT_ID; } sai_object_type_t objectType = saiObjectTypeQuery(objectId); if (objectType == SAI_OBJECT_TYPE_NULL) { SWSS_LOG_THROW("invalid object type of oid %s", sai_serialize_object_id(objectId).c_str()); } if (objectType == SAI_OBJECT_TYPE_SWITCH) { return objectId; } // NOTE: we could also check: // - if object id has correct global context // - if object id has existing switch index // but then this method can't be made static uint32_t switchIndex = (uint32_t)SAI_VS_GET_SWITCH_INDEX(objectId); return constructObjectId(SAI_OBJECT_TYPE_SWITCH, switchIndex, switchIndex, m_globalContext); } sai_object_type_t RealObjectIdManager::saiObjectTypeQuery( _In_ sai_object_id_t objectId) const { SWSS_LOG_ENTER(); if (objectId == SAI_NULL_OBJECT_ID) { return SAI_OBJECT_TYPE_NULL; } sai_object_type_t objectType = SAI_VS_GET_OBJECT_TYPE_EXTENSIONS_FLAG(objectId) ? (sai_object_type_t)(SAI_VS_GET_OBJECT_TYPE(objectId) + SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START) : (sai_object_type_t)(SAI_VS_GET_OBJECT_TYPE(objectId)); if (sai_metadata_is_object_type_valid(objectType) == false) { SWSS_LOG_ERROR("invalid object id %s", sai_serialize_object_id(objectId).c_str()); /* * We can't throw here, since it would give no meaningful message. * Throwing at one level up is better. */ return SAI_OBJECT_TYPE_NULL; } // NOTE: we could also check: // - if object id has correct global context // - if object id has existing switch index // but then this method can't be made static return objectType; } void RealObjectIdManager::clear() { SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("clearing switch index set"); m_switchIndexes.clear(); m_indexer.clear(); } void RealObjectIdManager::releaseSwitchIndex( _In_ uint32_t index) { SWSS_LOG_ENTER(); auto it = m_switchIndexes.find(index); if (it == m_switchIndexes.end()) { SWSS_LOG_THROW("switch index 0x%x is invalid! programming error", index); } m_switchIndexes.erase(it); SWSS_LOG_DEBUG("released switch index 0x%x", index); } sai_object_id_t RealObjectIdManager::allocateNewObjectId( _In_ sai_object_type_t objectType, _In_ sai_object_id_t switchId) { SWSS_LOG_ENTER(); if (sai_metadata_is_object_type_valid(objectType) == false) { SWSS_LOG_THROW("invalid objct type: %d", objectType); } if (objectType == SAI_OBJECT_TYPE_SWITCH) { SWSS_LOG_THROW("this function can't be used to allocate switch id"); } sai_object_type_t switchObjectType = saiObjectTypeQuery(switchId); if (switchObjectType != SAI_OBJECT_TYPE_SWITCH) { SWSS_LOG_THROW("object type of switch %s is %s, should be SWITCH", sai_serialize_object_id(switchId).c_str(), sai_serialize_object_type(switchObjectType).c_str()); } uint32_t switchIndex = (uint32_t)SAI_VS_GET_SWITCH_INDEX(switchId); // count from zero uint64_t objectIndex = m_indexer[objectType]++; // allocation ! if (objectIndex > SAI_VS_OBJECT_INDEX_MAX) { SWSS_LOG_THROW("no more object indexes available, given: 0x%lx but limit is 0x%llx", objectIndex, SAI_VS_OBJECT_INDEX_MAX); } sai_object_id_t objectId = constructObjectId(objectType, switchIndex, objectIndex, m_globalContext); SWSS_LOG_DEBUG("created RID %s", sai_serialize_object_id(objectId).c_str()); return objectId; } sai_object_id_t RealObjectIdManager::allocateNewSwitchObjectId( _In_ const std::string& hardwareInfo) { SWSS_LOG_ENTER(); auto config = m_container->getConfig(hardwareInfo); if (config == nullptr) { SWSS_LOG_ERROR("no switch config for hardware info: '%s'", hardwareInfo.c_str()); return SAI_NULL_OBJECT_ID; } uint32_t switchIndex = config->m_switchIndex; if (switchIndex > SAI_VS_SWITCH_INDEX_MAX) { SWSS_LOG_THROW("switch index %u > %llu (max)", switchIndex, SAI_VS_SWITCH_INDEX_MAX); } m_switchIndexes.insert(switchIndex); sai_object_id_t objectId = constructObjectId(SAI_OBJECT_TYPE_SWITCH, switchIndex, switchIndex, m_globalContext); SWSS_LOG_NOTICE("created SWITCH RID %s for hwinfo: '%s'", sai_serialize_object_id(objectId).c_str(), hardwareInfo.c_str()); return objectId; } void RealObjectIdManager::releaseObjectId( _In_ sai_object_id_t objectId) { SWSS_LOG_ENTER(); if (saiObjectTypeQuery(objectId) == SAI_OBJECT_TYPE_SWITCH) { releaseSwitchIndex((uint32_t)SAI_VS_GET_SWITCH_INDEX(objectId)); } } sai_object_id_t RealObjectIdManager::constructObjectId( _In_ sai_object_type_t objectType, _In_ uint32_t switchIndex, _In_ uint64_t objectIndex, _In_ uint32_t globalContext) { SWSS_LOG_ENTER(); if (sai_metadata_is_object_type_valid(objectType) == false) { SWSS_LOG_THROW("FATAL: invalid object type (0x%x), logic error, this is a bug!", objectType); } uint64_t extensionsFlag = (uint64_t)objectType >= SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START; objectType = extensionsFlag ? (sai_object_type_t)(objectType - SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START) : objectType; return (sai_object_id_t)( ((uint64_t)globalContext << ( SAI_VS_SWITCH_INDEX_BITS_SIZE + SAI_VS_OBJECT_TYPE_BITS_SIZE + SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE + SAI_VS_OBJECT_INDEX_BITS_SIZE )) | ((uint64_t)switchIndex << ( SAI_VS_OBJECT_TYPE_BITS_SIZE + SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE + SAI_VS_OBJECT_INDEX_BITS_SIZE )) | ((uint64_t)objectType << ( SAI_VS_OBJECT_TYPE_EXTENSIONS_FLAG_BITS_SIZE + SAI_VS_OBJECT_INDEX_BITS_SIZE)) | ((uint64_t)extensionsFlag << (SAI_VS_OBJECT_INDEX_BITS_SIZE)) | objectIndex); } sai_object_id_t RealObjectIdManager::switchIdQuery( _In_ sai_object_id_t objectId) { SWSS_LOG_ENTER(); if (objectId == SAI_NULL_OBJECT_ID) { return SAI_NULL_OBJECT_ID; } sai_object_type_t objectType = objectTypeQuery(objectId); if (objectType == SAI_OBJECT_TYPE_NULL) { SWSS_LOG_ERROR("invalid object type of oid %s", sai_serialize_object_id(objectId).c_str()); return SAI_NULL_OBJECT_ID; } if (objectType == SAI_OBJECT_TYPE_SWITCH) { return objectId; } uint32_t switchIndex = (uint32_t)SAI_VS_GET_SWITCH_INDEX(objectId); uint32_t globalContext = (uint32_t)SAI_VS_GET_GLOBAL_CONTEXT(objectId); return constructObjectId(SAI_OBJECT_TYPE_SWITCH, switchIndex, switchIndex, globalContext); } sai_object_type_t RealObjectIdManager::objectTypeQuery( _In_ sai_object_id_t objectId) { SWSS_LOG_ENTER(); if (objectId == SAI_NULL_OBJECT_ID) { return SAI_OBJECT_TYPE_NULL; } sai_object_type_t objectType = SAI_VS_GET_OBJECT_TYPE_EXTENSIONS_FLAG(objectId) ? (sai_object_type_t)(SAI_VS_GET_OBJECT_TYPE(objectId) + SAI_OBJECT_TYPE_EXTENSIONS_RANGE_START) : (sai_object_type_t)(SAI_VS_GET_OBJECT_TYPE(objectId)); if (!sai_metadata_is_object_type_valid(objectType)) { SWSS_LOG_ERROR("invalid object id %s", sai_serialize_object_id(objectId).c_str()); return SAI_OBJECT_TYPE_NULL; } return objectType; } uint32_t RealObjectIdManager::getSwitchIndex( _In_ sai_object_id_t objectId) { SWSS_LOG_ENTER(); auto switchId = switchIdQuery(objectId); return SAI_VS_GET_SWITCH_INDEX(switchId); } void RealObjectIdManager::updateWarmBootObjectIndex( _In_ sai_object_id_t oid) { SWSS_LOG_ENTER(); sai_object_type_t objectType = objectTypeQuery(oid); if (objectType == SAI_OBJECT_TYPE_NULL) { SWSS_LOG_THROW("invalid object type on warm boot object: %s", sai_serialize_object_id(oid).c_str()); } if (objectType == SAI_OBJECT_TYPE_SWITCH) { uint32_t switchIndex = (uint32_t)SAI_VS_GET_SWITCH_INDEX(oid); m_switchIndexes.insert(switchIndex); } uint64_t index = SAI_VS_GET_OBJECT_INDEX(oid); if (m_indexer[objectType] <= index) { uint64_t prev = m_indexer[objectType]; m_indexer[objectType] = index + 1; // +1 since this will be next object number SWSS_LOG_DEBUG("update %s:%s real id to from %lu to %lu", sai_serialize_object_type(objectType).c_str(), sai_serialize_object_id(oid).c_str(), prev, index + 1); } }