diff --git a/dash-pipeline/Makefile b/dash-pipeline/Makefile index 3a16cf365..eecf8679f 100644 --- a/dash-pipeline/Makefile +++ b/dash-pipeline/Makefile @@ -177,7 +177,7 @@ sai-headers: p4 docker-saithrift-bldr-image-exists | SAI/SAI --name build_sai-$(USER) \ -u $(HOST_USER):$(HOST_GROUP) \ -w /SAI $(DOCKER_SAITHRIFT_BLDR_IMG) \ - ./generate_dash_api.sh + make sai-meta: @echo "Generate SAI metadata..." @@ -271,7 +271,7 @@ DOCKER_RUN_SAITHRIFT_SRVR =\ run-saithrift-server: $(DOCKER_RUN_SAITHRIFT_SRVR) \ - ./saiserver + bash -c './saiserver' kill-saithrift-server: -docker kill dash-saithrift-server-$(USER) diff --git a/dash-pipeline/SAI/Makefile b/dash-pipeline/SAI/Makefile index db818adb1..90e70e664 100644 --- a/dash-pipeline/SAI/Makefile +++ b/dash-pipeline/SAI/Makefile @@ -1,19 +1,13 @@ -dashone: test.cpp - g++ \ - -I SAI/inc \ - -I SAI/experimental/ \ - -o test test.cpp saidash.cpp \ - -L/usr/local/lib/ \ - -lpthread \ - -lpiprotogrpc \ - -lpiprotobuf \ - -lprotobuf \ - -lgrpc++ \ - -lgrpc \ - -lpiall \ - -lpi_dummy \ - -lpthread \ - -labsl_synchronization \ - -g +all: copysrc + ./sai_api_gen.py \ + /bmv2/dash_pipeline.bmv2/dash_pipeline_p4rt.json \ + --ignore-tables=appliance,eni_meter,slb_decap \ + dash +copysrc: + install -CDv src/Makefile src/*h src/*cpp lib/ + +.PHONY: clean +clean: + rm -f lib/* diff --git a/dash-pipeline/SAI/generate_dash_api.sh b/dash-pipeline/SAI/generate_dash_api.sh deleted file mode 100755 index d3c73ebe2..000000000 --- a/dash-pipeline/SAI/generate_dash_api.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -./sai_api_gen.py \ - /bmv2/dash_pipeline.bmv2/dash_pipeline_p4rt.json \ - --ignore-tables=appliance,eni_meter,slb_decap \ - dash diff --git a/dash-pipeline/SAI/sai_api_gen.py b/dash-pipeline/SAI/sai_api_gen.py index 71ff6cff3..498072004 100755 --- a/dash-pipeline/SAI/sai_api_gen.py +++ b/dash-pipeline/SAI/sai_api_gen.py @@ -382,17 +382,10 @@ def write_sai_impl_files(sai_api): sai_impl_str = sai_impl_tm.render(tables = sai_api[TABLES_TAG], app_name = sai_api['app_name'], header_prefix = header_prefix) write_if_different('./lib/sai' + sai_api['app_name'].replace('_', '') + '.cpp',sai_impl_str) -def write_sai_makefile(sai_api_name_list, sai_api_full_name_list): - env = Environment(loader=FileSystemLoader('.')) - makefile_tm = env.get_template('/templates/Makefile.j2') - makefile_str = makefile_tm.render(api_names = sai_api_name_list) - - write_if_different('./lib/Makefile',makefile_str) - def write_sai_fixed_api_files(sai_api_full_name_list): env = Environment(loader=FileSystemLoader('.')) - for filename in ['utils.cpp', 'utils.h', 'saifixedapis.cpp', 'saiimpl.h', 'logger.h', 'logger.cpp', 'saidash.h', 'dashsai.h', 'dashsai.cpp', 'config.h', 'config.cpp']: + for filename in ['saifixedapis.cpp', 'saiimpl.h']: env = Environment(loader=FileSystemLoader('.'), trim_blocks=True, lstrip_blocks=True) sai_impl_tm = env.get_template('/templates/%s.j2' % filename) sai_impl_str = sai_impl_tm.render(tables = sai_api[TABLES_TAG], app_name = sai_api['app_name'], api_names = sai_api_full_name_list) @@ -555,7 +548,6 @@ def write_sai_files(sai_api): write_if_different('./SAI/experimental/saitypesextensions.h',''.join(new_lines)) -write_sai_makefile(sai_api_name_list, sai_api_full_name_list) write_sai_fixed_api_files(sai_api_full_name_list) if args.print_sai_lib: diff --git a/dash-pipeline/SAI/templates/Makefile.j2 b/dash-pipeline/SAI/src/Makefile similarity index 91% rename from dash-pipeline/SAI/templates/Makefile.j2 rename to dash-pipeline/SAI/src/Makefile index 06b200a4b..9b93dd754 100644 --- a/dash-pipeline/SAI/templates/Makefile.j2 +++ b/dash-pipeline/SAI/src/Makefile @@ -1,7 +1,3 @@ -# DASH libsai.so Makefile -# THIS MAKEFILE IS AUTO-GENERATED FROM templates/Makefile.j2 -# DO NOT MODIFY - CXXFLAGS_COMMON= CXXFLAGS_COMMON+= -ansi CXXFLAGS_COMMON+= -fPIC @@ -58,11 +54,18 @@ SAI_OBJS_PATHS=$(addprefix $(SAI_DIR)/,$(SAI_OBJS)) DASH_SAI_SRCS=$(wildcard *.cpp) DASH_SAI_OBJS=$(DASH_SAI_SRCS:.cpp=.o) -%.o: %.cpp - g++ $(SAI_INC) $(GXX_FLAGS) $(CXXFLAGS_COMMON) -c $< -o $@ - all: libsai.so +%.d: %.cpp + g++ $(SAI_INC) $(GXX_FLAGS) $(CXXFLAGS_COMMON) -M $^ -o $@ + +DEPS := $(DASH_SAI_OBJS:.o=.d) + +-include $(DEPS) + +%.o: %.cpp + g++ $(SAI_INC) $(GXX_FLAGS) $(CXXFLAGS_COMMON) -MMD -c $< -o $@ + libsai.so: $(SAI_OBJS_PATHS) $(DASH_SAI_OBJS) g++ -shared -g -o $@ $^ diff --git a/dash-pipeline/SAI/templates/config.cpp.j2 b/dash-pipeline/SAI/src/config.cpp similarity index 100% rename from dash-pipeline/SAI/templates/config.cpp.j2 rename to dash-pipeline/SAI/src/config.cpp diff --git a/dash-pipeline/SAI/templates/config.h.j2 b/dash-pipeline/SAI/src/config.h similarity index 100% rename from dash-pipeline/SAI/templates/config.h.j2 rename to dash-pipeline/SAI/src/config.h diff --git a/dash-pipeline/SAI/templates/dashsai.cpp.j2 b/dash-pipeline/SAI/src/dashsai.cpp similarity index 78% rename from dash-pipeline/SAI/templates/dashsai.cpp.j2 rename to dash-pipeline/SAI/src/dashsai.cpp index e655ad947..69dbb4b81 100644 --- a/dash-pipeline/SAI/templates/dashsai.cpp.j2 +++ b/dash-pipeline/SAI/src/dashsai.cpp @@ -6,9 +6,6 @@ using namespace dash; #define DASH_BMV2_CPU_QOS_NUMBER_OF_QUEUES 0 -#define DASH_OBJECT_SHFT 48 -#define DASH_MAKE_OID(objtype, objval) (sai_object_id_t)(((sai_object_id_t)objtype< _lock(m_tableLock); -// TODO replace DASH_MAKE_OID with ObjectIdManager - DashSai::DashSai(): m_apiInitialized(false) { DASH_LOG_ENTER(); - // those oids are constant + // TODO move to switch state - m_switchId = DASH_MAKE_OID(SAI_OBJECT_TYPE_SWITCH, 1); - m_defaultCpuPortId = DASH_MAKE_OID(SAI_OBJECT_TYPE_PORT, 64); - m_defaultVlanId = DASH_MAKE_OID(SAI_OBJECT_TYPE_VLAN, 1); - m_defaultVrfId = DASH_MAKE_OID(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, 1); - m_default1QBridgeId = DASH_MAKE_OID(SAI_OBJECT_TYPE_BRIDGE, 1); - m_defaultTrapGroup = DASH_MAKE_OID(SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP, 1); + m_switchId = SAI_OBJECT_TYPE_NULL; + m_defaultCpuPortId = SAI_OBJECT_TYPE_NULL; + m_defaultVlanId = SAI_OBJECT_TYPE_NULL; + m_defaultVrfId = SAI_OBJECT_TYPE_NULL; + m_default1QBridgeId = SAI_OBJECT_TYPE_NULL; + m_defaultTrapGroup = SAI_OBJECT_TYPE_NULL; } DashSai::~DashSai() @@ -79,22 +74,6 @@ sai_status_t DashSai::apiInitialize( DASH_LOG_NOTICE("config: %s", m_cfg->getConfigString().c_str()); - m_portList.clear(); - - for (uint32_t i = 1; i <= m_cfg->m_bmv2NumPorts; i++) - { - m_portList.push_back(DASH_MAKE_OID(SAI_OBJECT_TYPE_PORT,i)); - } - - if (m_cfg->m_bmv2NumPorts != (uint32_t)m_portList.size()) - { - DASH_LOG_ERROR("FATAL: number of ports is different: config: %u vs port list: %u", - m_cfg->m_bmv2NumPorts, - (uint32_t)m_portList.size()); - - return SAI_STATUS_FAILURE; - } - const grpc::string grpcTarget = m_cfg->m_grpcTarget; const char* test_json = m_cfg->m_pipelineJson.c_str(); const char* test_proto_json = m_cfg->m_pipelineProto.c_str(); @@ -189,6 +168,8 @@ sai_status_t DashSai::apiInitialize( config->release_p4info(); } + m_objectIdManager = std::make_shared(); + m_apiInitialized = true; return SAI_STATUS_SUCCESS; @@ -201,12 +182,10 @@ sai_status_t DashSai::apiUninitialize(void) m_cfg = nullptr; - m_portList.clear(); + m_portList.clear(); // TODO move to switch state class m_tableEntryMap.clear(); - m_nextId = 0; - m_grpcChannel = nullptr; m_stub = nullptr; @@ -215,6 +194,8 @@ sai_status_t DashSai::apiUninitialize(void) m_serviceMethodTable = nullptr; + m_objectIdManager = nullptr; + return SAI_STATUS_SUCCESS; } @@ -230,7 +211,7 @@ sai_object_type_t DashSai::objectTypeQuery( return SAI_OBJECT_TYPE_NULL; } - return sai_object_type_t(object_id >> (DASH_OBJECT_SHFT)); + return m_objectIdManager->objectTypeQuery(object_id); } sai_object_id_t DashSai::switchIdQuery( @@ -239,12 +220,7 @@ sai_object_id_t DashSai::switchIdQuery( DASH_LOG_ENTER(); DASH_CHECK_API_INITIALIZED(); - if (object_id == SAI_NULL_OBJECT_ID) - { - return SAI_NULL_OBJECT_ID; - } - - return m_switchId; + return m_objectIdManager->switchIdQuery(object_id); } sai_status_t DashSai::createSwitch( @@ -255,9 +231,44 @@ sai_status_t DashSai::createSwitch( DASH_LOG_ENTER(); DASH_CHECK_API_INITIALIZED(); + std::string hardwareInfo; + for (uint32_t i = 0; i < attr_count; i++) { DASH_LOG_WARN("attr id %d is NOT IMPLEMENTED, ignored", attr_list[i].id); + + if (attr_list[i].id == SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO) + { + DASH_LOG_WARN("attr SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO specified, but ignored, set to '%s', FIXME", + hardwareInfo.c_str()); + } + } + + // TODO add switch state and init switch method + + m_switchId = m_objectIdManager->allocateNewSwitchObjectId(hardwareInfo); + + if (m_switchId == SAI_NULL_OBJECT_ID) + { + DASH_LOG_ERROR("switch OID allocation failed"); + + return SAI_STATUS_FAILURE; + } + + // TODO move to switch state + + m_defaultCpuPortId = m_objectIdManager->allocateNewObjectId(SAI_OBJECT_TYPE_PORT, m_switchId); + m_defaultVlanId = m_objectIdManager->allocateNewObjectId(SAI_OBJECT_TYPE_VLAN, m_switchId); + m_defaultVrfId = m_objectIdManager->allocateNewObjectId(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, m_switchId); + m_default1QBridgeId = m_objectIdManager->allocateNewObjectId(SAI_OBJECT_TYPE_BRIDGE, m_switchId); + m_defaultTrapGroup = m_objectIdManager->allocateNewObjectId(SAI_OBJECT_TYPE_HOSTIF_TRAP_GROUP, m_switchId); + + m_portList.clear(); + + for (uint32_t i = 1; i <= m_cfg->m_bmv2NumPorts; i++) + { + // TODO in switch state must be internally calling create on this object + m_portList.push_back(m_objectIdManager->allocateNewObjectId(SAI_OBJECT_TYPE_PORT, m_switchId)); } *switch_id = m_switchId; @@ -280,6 +291,8 @@ sai_status_t DashSai::removeSwitch( return SAI_STATUS_INVALID_PARAMETER; } + m_objectIdManager->releaseObjectId(switch_id); + // dummy switch remove DASH_LOG_NOTICE("removing switch: 0x%lx", switch_id); @@ -459,7 +472,15 @@ sai_status_t DashSai::getPortAttribute( attr->value.s32 = SAI_PORT_OPER_STATUS_UP; - DASH_LOG_NOTICE("[%d] setting SAI_PORT_ATTR_OPER_STATUS=SAI_PORT_OPER_STATUS_UP for port %lx", i, port_id); + DASH_LOG_NOTICE("[%d] setting SAI_PORT_ATTR_OPER_STATUS=SAI_PORT_OPER_STATUS_UP for port 0x%lx", i, port_id); + + break; + + case SAI_PORT_ATTR_PORT_VLAN_ID: + + attr->value.u16 = 1; + + DASH_LOG_NOTICE("[%d] setting SAI_PORT_ATTR_PORT_VLAN_ID=1 for port 0x%lx", i, port_id); break; @@ -600,6 +621,7 @@ bool DashSai::insertInTable( return true; } +// TODO needs to be converted to create (with attributes) sai_object_id_t DashSai::getNextObjectId( _In_ sai_object_type_t objectType) { @@ -612,7 +634,14 @@ sai_object_id_t DashSai::getNextObjectId( return SAI_NULL_OBJECT_ID; } - return DASH_MAKE_OID(objectType, ++m_nextId); + if (m_switchId == SAI_NULL_OBJECT_ID) + { + DASH_LOG_ERROR("switch is not created, create switch first"); + + return SAI_NULL_OBJECT_ID; + } + + return m_objectIdManager->allocateNewObjectId(objectType, m_switchId); } bool DashSai::removeFromTable( @@ -655,3 +684,76 @@ bool DashSai::removeFromTable( return retCode == grpc::StatusCode::OK; } + +// QUAD generic api implementation + +sai_status_t DashSai::create( + _In_ sai_object_type_t objectType, + _Out_ sai_object_id_t* objectId, + _In_ sai_object_id_t switchId, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + if (objectType == SAI_OBJECT_TYPE_SWITCH) + return createSwitch(objectId, attr_count, attr_list); + + *objectId = m_objectIdManager->allocateNewObjectId(objectType, m_switchId); + + DASH_LOG_WARN("creating dummy object for object type %d: 0x%lx", objectType, *objectId); + + return SAI_STATUS_SUCCESS; +} + +sai_status_t DashSai::remove( + _In_ sai_object_type_t objectType, + _In_ sai_object_id_t objectId) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + if (objectType == SAI_OBJECT_TYPE_SWITCH) + return removeSwitch(objectId); + + DASH_LOG_WARN("dummy remove: 0x%lx", objectId); + + return SAI_STATUS_SUCCESS; +} + +sai_status_t DashSai::set( + _In_ sai_object_type_t objectType, + _In_ sai_object_id_t objectId, + _In_ const sai_attribute_t *attr) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + if (objectType == SAI_OBJECT_TYPE_SWITCH) + return setSwitchAttribute(objectId, attr); + + DASH_LOG_WARN("dummy set: 0x%lx, attr id: %d", objectId, attr->id); + + return SAI_STATUS_SUCCESS; +} + +sai_status_t DashSai::get( + _In_ sai_object_type_t objectType, + _In_ sai_object_id_t objectId, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + DASH_CHECK_API_INITIALIZED(); + + if (objectType == SAI_OBJECT_TYPE_PORT) + return getPortAttribute(objectId, attr_count, attr_list); + + if (objectType == SAI_OBJECT_TYPE_SWITCH) + return getSwitchAttribute(objectId, attr_count, attr_list); + + DASH_LOG_ERROR("not implemented for object type %d", objectType); + + return SAI_STATUS_NOT_IMPLEMENTED; +} diff --git a/dash-pipeline/SAI/templates/dashsai.h.j2 b/dash-pipeline/SAI/src/dashsai.h similarity index 74% rename from dash-pipeline/SAI/templates/dashsai.h.j2 rename to dash-pipeline/SAI/src/dashsai.h index 2783461e3..53736eee7 100644 --- a/dash-pipeline/SAI/templates/dashsai.h.j2 +++ b/dash-pipeline/SAI/src/dashsai.h @@ -2,6 +2,7 @@ #include "utils.h" #include "config.h" +#include "objectidmanager.h" namespace dash { @@ -26,7 +27,31 @@ namespace dash sai_object_id_t switchIdQuery( _In_ sai_object_id_t object_id); - public: // QUAD api implementation + public: // QUAD generic api implementation + + sai_status_t create( + _In_ sai_object_type_t objectType, + _Out_ sai_object_id_t* objectId, + _In_ sai_object_id_t switchId, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + + sai_status_t remove( + _In_ sai_object_type_t objectType, + _In_ sai_object_id_t objectId); + + sai_status_t set( + _In_ sai_object_type_t objectType, + _In_ sai_object_id_t objectId, + _In_ const sai_attribute_t *attr); + + sai_status_t get( + _In_ sai_object_type_t objectType, + _In_ sai_object_id_t objectId, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + + private: // QUAD api implementation // switch @@ -111,5 +136,7 @@ namespace dash std::shared_ptr m_grpcChannel; std::unique_ptr m_stub; + + std::shared_ptr m_objectIdManager; }; } diff --git a/dash-pipeline/SAI/templates/logger.cpp.j2 b/dash-pipeline/SAI/src/logger.cpp similarity index 100% rename from dash-pipeline/SAI/templates/logger.cpp.j2 rename to dash-pipeline/SAI/src/logger.cpp diff --git a/dash-pipeline/SAI/templates/logger.h.j2 b/dash-pipeline/SAI/src/logger.h similarity index 100% rename from dash-pipeline/SAI/templates/logger.h.j2 rename to dash-pipeline/SAI/src/logger.h diff --git a/dash-pipeline/SAI/src/objectidmanager.cpp b/dash-pipeline/SAI/src/objectidmanager.cpp new file mode 100644 index 000000000..d9d2b2b00 --- /dev/null +++ b/dash-pipeline/SAI/src/objectidmanager.cpp @@ -0,0 +1,308 @@ +#include "objectidmanager.h" +#include "logger.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 DASH_OID_RESERVED_BITS_SIZE ( 8 ) + +#define DASH_OBJECT_TYPE_BITS_SIZE ( 8 ) +#define DASH_OBJECT_TYPE_MASK ( (1ULL << DASH_OBJECT_TYPE_BITS_SIZE) - 1 ) +#define DASH_OBJECT_TYPE_MAX (DASH_OBJECT_TYPE_MASK) + +#define DASH_SWITCH_INDEX_BITS_SIZE ( 8 ) +#define DASH_SWITCH_INDEX_MASK ( (1ULL << DASH_SWITCH_INDEX_BITS_SIZE) - 1 ) +#define DASH_SWITCH_INDEX_MAX (DASH_SWITCH_INDEX_MASK) + +#define DASH_OBJECT_INDEX_BITS_SIZE ( 40 ) +#define DASH_OBJECT_INDEX_MASK ( (1ULL << DASH_OBJECT_INDEX_BITS_SIZE) - 1 ) +#define DASH_OBJECT_INDEX_MAX (DASH_OBJECT_INDEX_MASK) + +#define DASH_OBJECT_ID_BITS_SIZE (DASH_OID_RESERVED_BITS_SIZE + DASH_OBJECT_TYPE_BITS_SIZE + DASH_SWITCH_INDEX_BITS_SIZE + DASH_OBJECT_INDEX_BITS_SIZE) + +static_assert(DASH_OBJECT_ID_BITS_SIZE == SAI_OBJECT_ID_BITS_SIZE, "dash object id size must be equal to SAI object id size"); + +static_assert(DASH_OBJECT_TYPE_MAX == 0xff, "invalid object type max size"); +static_assert(DASH_SWITCH_INDEX_MAX == 0xff, "invalid switch index max size"); +static_assert(DASH_OBJECT_INDEX_MAX == 0xffffffffff, "invalid object index max"); + +/* + * 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_EXTENSIONS_RANGE_END < DASH_OBJECT_TYPE_MAX, "dash max object type value must be greater than supported SAI max objeect type value"); + +/* + * Current OBJECT ID format: + * + * bits 63..56 - reserved (must be zero) + * bits 55..48 - SAI object type + * bits 47..40 - switch index + * bits 39..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. + */ + +#define DASH_GET_OBJECT_INDEX(oid) \ + ( ((uint64_t)oid) & ( DASH_OBJECT_INDEX_MASK ) ) + +#define DASH_GET_SWITCH_INDEX(oid) \ + ( (((uint64_t)oid) >> ( DASH_OBJECT_INDEX_BITS_SIZE) ) & ( DASH_SWITCH_INDEX_MASK ) ) + +#define DASH_GET_OBJECT_TYPE(oid) \ + ( (((uint64_t)oid) >> ( DASH_SWITCH_INDEX_BITS_SIZE + DASH_OBJECT_INDEX_BITS_SIZE ) ) & ( DASH_OBJECT_TYPE_MASK ) ) + +#define DASH_TEST_OID (0x0123456789abcdef) + +static_assert(DASH_GET_OBJECT_TYPE(DASH_TEST_OID) == 0x23, "test object type"); +static_assert(DASH_GET_SWITCH_INDEX(DASH_TEST_OID) == 0x45, "test switch index"); +static_assert(DASH_GET_OBJECT_INDEX(DASH_TEST_OID) == 0x6789abcdef, "test object index"); + +using namespace dash; + +sai_object_id_t ObjectIdManager::saiSwitchIdQuery( + _In_ sai_object_id_t objectId) const +{ + DASH_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) + { + DASH_LOG_ERROR("invalid object type of oid 0x%lx", objectId); + + return SAI_NULL_OBJECT_ID; + } + + if (objectType == SAI_OBJECT_TYPE_SWITCH) + { + return objectId; + } + + uint32_t switchIndex = (uint32_t)DASH_GET_SWITCH_INDEX(objectId); + + return constructObjectId(SAI_OBJECT_TYPE_SWITCH, switchIndex, switchIndex); +} + +sai_object_type_t ObjectIdManager::saiObjectTypeQuery( + _In_ sai_object_id_t objectId) const +{ + DASH_LOG_ENTER(); + + if (objectId == SAI_NULL_OBJECT_ID) + { + return SAI_OBJECT_TYPE_NULL; + } + + sai_object_type_t objectType = (sai_object_type_t)(DASH_GET_OBJECT_TYPE(objectId)); + + if (objectType == SAI_OBJECT_TYPE_NULL || objectType >= (sai_object_type_t)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END) + { + DASH_LOG_ERROR("invalid object id 0x%lx", objectId); + + return SAI_OBJECT_TYPE_NULL; + } + + return objectType; +} + +void ObjectIdManager::clear() +{ + DASH_LOG_ENTER(); + + DASH_LOG_NOTICE("clearing switch index set"); + + m_switchIndexes.clear(); + m_indexer.clear(); +} + +void ObjectIdManager::releaseSwitchIndex( + _In_ uint32_t index) +{ + DASH_LOG_ENTER(); + + auto it = m_switchIndexes.find(index); + + if (it == m_switchIndexes.end()) + { + DASH_LOG_ERROR("switch index 0x%x is invalid! programming error", index); + return; + } + + m_switchIndexes.erase(it); + + DASH_LOG_NOTICE("released switch index 0x%x", index); +} + +sai_object_id_t ObjectIdManager::allocateNewObjectId( + _In_ sai_object_type_t objectType, + _In_ sai_object_id_t switchId) +{ + DASH_LOG_ENTER(); + + if ((objectType <= SAI_OBJECT_TYPE_NULL) || (objectType >= (sai_object_type_t)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END)) + { + DASH_LOG_ERROR("invalid objct type: %d", objectType); + + return SAI_NULL_OBJECT_ID; + } + + if (objectType == SAI_OBJECT_TYPE_SWITCH) + { + DASH_LOG_ERROR("this function can't be used to allocate switch id"); + + return SAI_NULL_OBJECT_ID; + } + + sai_object_type_t switchObjectType = saiObjectTypeQuery(switchId); + + if (switchObjectType != SAI_OBJECT_TYPE_SWITCH) + { + DASH_LOG_ERROR("object type of switch 0x%lx is %d, should be SWITCH", switchId, switchObjectType); + + return SAI_NULL_OBJECT_ID; + } + + uint32_t switchIndex = (uint32_t)DASH_GET_SWITCH_INDEX(switchId); + + // count from zero + uint64_t objectIndex = m_indexer[objectType]++; // allocation ! + + if (objectIndex > DASH_OBJECT_INDEX_MAX) + { + DASH_LOG_ERROR("no more object indexes available, given: 0x%lx but limit is 0x%llx", + objectIndex, + DASH_OBJECT_INDEX_MAX); + + return SAI_NULL_OBJECT_ID; + } + + sai_object_id_t objectId = constructObjectId(objectType, switchIndex, objectIndex); + + DASH_LOG_INFO("allocated new object id 0x%lx", objectId); + + return objectId; +} + +sai_object_id_t ObjectIdManager::allocateNewSwitchObjectId( + _In_ const std::string& hardwareInfo) +{ + DASH_LOG_ENTER(); + + // TODO currently we support only empty hardware info and 1 switch + + if (hardwareInfo.size()) + { + DASH_LOG_ERROR("hardware info is '%s', not supported yet, switch OID allocation failed, FIXME", hardwareInfo.c_str()); + + return SAI_NULL_OBJECT_ID; + } + + uint32_t switchIndex = 0; // for empty hardware info + + if (switchIndex > DASH_SWITCH_INDEX_MAX) + { + DASH_LOG_ERROR("switch index %u > %llu (max)", switchIndex, DASH_SWITCH_INDEX_MAX); + + return SAI_NULL_OBJECT_ID; + } + + if (m_switchIndexes.find(switchIndex) != m_switchIndexes.end()) + { + DASH_LOG_ERROR("switch with index %d is alrady allocated, programming error!", switchIndex); + + return SAI_NULL_OBJECT_ID; + } + + m_switchIndexes.insert(switchIndex); + + sai_object_id_t objectId = constructObjectId(SAI_OBJECT_TYPE_SWITCH, switchIndex, switchIndex); + + DASH_LOG_NOTICE("allocated switch OID 0x%lx for hwinfo: '%s'", objectId, hardwareInfo.c_str()); + + return objectId; +} + +void ObjectIdManager::releaseObjectId( + _In_ sai_object_id_t objectId) +{ + DASH_LOG_ENTER(); + + if (saiObjectTypeQuery(objectId) == SAI_OBJECT_TYPE_SWITCH) + { + releaseSwitchIndex((uint32_t)DASH_GET_SWITCH_INDEX(objectId)); + } +} + +sai_object_id_t ObjectIdManager::constructObjectId( + _In_ sai_object_type_t objectType, + _In_ uint32_t switchIndex, + _In_ uint64_t objectIndex) +{ + DASH_LOG_ENTER(); + + return (sai_object_id_t)( + (((uint64_t)objectType & DASH_OBJECT_TYPE_MASK)<< ( DASH_SWITCH_INDEX_BITS_SIZE + DASH_OBJECT_INDEX_BITS_SIZE))| + (((uint64_t)switchIndex & DASH_SWITCH_INDEX_MASK)<< ( DASH_OBJECT_INDEX_BITS_SIZE )) | + (objectIndex & DASH_OBJECT_INDEX_MASK)); +} + +sai_object_id_t ObjectIdManager::switchIdQuery( + _In_ sai_object_id_t objectId) +{ + DASH_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) + { + DASH_LOG_ERROR("invalid object type of oid 0x%lx", objectId); + + return SAI_NULL_OBJECT_ID; + } + + if (objectType == SAI_OBJECT_TYPE_SWITCH) + { + return objectId; + } + + uint32_t switchIndex = (uint32_t)DASH_GET_SWITCH_INDEX(objectId); + + return constructObjectId(SAI_OBJECT_TYPE_SWITCH, switchIndex, switchIndex); +} + +sai_object_type_t ObjectIdManager::objectTypeQuery( + _In_ sai_object_id_t objectId) +{ + DASH_LOG_ENTER(); + + if (objectId == SAI_NULL_OBJECT_ID) + { + return SAI_OBJECT_TYPE_NULL; + } + + sai_object_type_t objectType = (sai_object_type_t)(DASH_GET_OBJECT_TYPE(objectId)); + + if (objectType == SAI_OBJECT_TYPE_NULL || objectType >= (sai_object_type_t)SAI_OBJECT_TYPE_EXTENSIONS_RANGE_END) + { + DASH_LOG_ERROR("invalid object id 0x%lx", objectId); + + return SAI_OBJECT_TYPE_NULL; + } + + return objectType; +} diff --git a/dash-pipeline/SAI/src/objectidmanager.h b/dash-pipeline/SAI/src/objectidmanager.h new file mode 100644 index 000000000..d824f6832 --- /dev/null +++ b/dash-pipeline/SAI/src/objectidmanager.h @@ -0,0 +1,134 @@ +#pragma once + +extern "C" { +#include +#include +} + +#include +#include + +namespace dash +{ + class ObjectIdManager + { + public: + + ObjectIdManager() = default; + ~ObjectIdManager() = default; + + public: + + /** + * @brief Switch id query. + * + * Return switch object id for given object if. If object type is + * switch, it will return input value. + * + * Returns SAI_NULL_OBJECT_ID if input value is invalid. + * + * For SAI_NULL_OBJECT_ID input will return SAI_NULL_OBJECT_ID. + */ + sai_object_id_t saiSwitchIdQuery( + _In_ sai_object_id_t objectId) const; + + /** + * @brief Object type query. + * + * Returns object type for input object id. If object id is invalid + * then returns SAI_OBJECT_TYPE_NULL. + */ + sai_object_type_t saiObjectTypeQuery( + _In_ sai_object_id_t objectId) const; + + /** + * @brief Clear switch index set. + * + * New switch index allocation will start from the beginning. + */ + void clear(); + + /** + * @brief Allocate new object id on a given switch. + * + * Method can't be used to allocate switch object id. + * + * Returns SAI_NULL_OBJECT_ID if there are no more available + * switch indexes. + */ + sai_object_id_t allocateNewObjectId( + _In_ sai_object_type_t objectType, + _In_ sai_object_id_t switchId); + + /** + * @brief Allocate new switch object id. + * + * Return SAI_NULL_OBJECT_ID if allocation failed. + */ + sai_object_id_t allocateNewSwitchObjectId( + _In_ const std::string& hardwareInfo); + + /** + * @brief Release allocated object id. + * + * If object type is switch, then switch index will be released. + */ + void releaseObjectId( + _In_ sai_object_id_t objectId); + + public: + + /** + * @brief Switch id query. + * + * Return switch object id for given object if. If object type is + * switch, it will return input value. + * + * Return SAI_NULL_OBJECT_ID if given object id has invalid object type. + */ + static sai_object_id_t switchIdQuery( + _In_ sai_object_id_t objectId); + + /** + * @brief Object type query. + * + * Returns object type for input object id. If object id is invalid + * then returns SAI_OBJECT_TYPE_NULL. + */ + static sai_object_type_t objectTypeQuery( + _In_ sai_object_id_t objectId); + + private: + + /** + * @brief Release given switch index. + */ + void releaseSwitchIndex( + _In_ uint32_t index); + + /** + * @brief Construct object id. + * + * Using all input parameters to construct object id. + */ + static sai_object_id_t constructObjectId( + _In_ sai_object_type_t objectType, + _In_ uint32_t switchIndex, + _In_ uint64_t objectIndex); + + private: + + /** + * @brief Set of allocated switch indexes. + */ + std::set m_switchIndexes; + + /** + * @brief Object index indexer map. + * + * Each object type have its own starting index from zero for easy + * count how many objects of each type there are allocated. + */ + std::map m_indexer; + }; +} diff --git a/dash-pipeline/SAI/src/sai_dash_hostif.cpp b/dash-pipeline/SAI/src/sai_dash_hostif.cpp new file mode 100644 index 000000000..fc5b2da52 --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_hostif.cpp @@ -0,0 +1,21 @@ +#include "saiimpl.h" + +DASH_GENERIC_QUAD(HOSTIF,hostif); +DASH_GENERIC_QUAD(HOSTIF_TABLE_ENTRY,hostif_table_entry); +DASH_GENERIC_QUAD(HOSTIF_TRAP_GROUP,hostif_trap_group); +DASH_GENERIC_QUAD(HOSTIF_TRAP,hostif_trap); +DASH_GENERIC_QUAD(HOSTIF_USER_DEFINED_TRAP,hostif_user_defined_trap); + +sai_hostif_api_t dash_sai_hostif_api_impl = { + + DASH_GENERIC_QUAD_API(hostif) + DASH_GENERIC_QUAD_API(hostif_table_entry) + DASH_GENERIC_QUAD_API(hostif_trap_group) + DASH_GENERIC_QUAD_API(hostif_trap) + DASH_GENERIC_QUAD_API(hostif_user_defined_trap) + + .recv_hostif_packet = 0, + .send_hostif_packet = 0, + .allocate_hostif_packet = 0, + .free_hostif_packet = 0, +}; diff --git a/dash-pipeline/SAI/src/sai_dash_neighbor.cpp b/dash-pipeline/SAI/src/sai_dash_neighbor.cpp new file mode 100644 index 000000000..b52ddff33 --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_neighbor.cpp @@ -0,0 +1,58 @@ +#include "saiimpl.h" + +static sai_status_t dash_create_neighbor_entry( + _In_ const sai_neighbor_entry_t *neighbor_entry, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + + DASH_LOG_WARN("dummy create"); + + return SAI_STATUS_SUCCESS; +} + +static sai_status_t dash_remove_neighbor_entry( + _In_ const sai_neighbor_entry_t *neighbor_entry) +{ + DASH_LOG_ENTER(); + + DASH_LOG_WARN("dummy remove"); + + return SAI_STATUS_SUCCESS; +} + +static sai_status_t dash_set_neighbor_entry_attribute( + _In_ const sai_neighbor_entry_t *neighbor_entry, + _In_ const sai_attribute_t *attr) +{ + DASH_LOG_ENTER(); + + DASH_LOG_WARN("dummy set"); + + return SAI_STATUS_SUCCESS; +} + +static sai_status_t dash_get_neighbor_entry_attribute( + _In_ const sai_neighbor_entry_t *neighbor_entry, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + + DASH_LOG_ERROR("not implemented"); + + return SAI_STATUS_NOT_IMPLEMENTED; +} + +sai_neighbor_api_t dash_sai_neighbor_api_impl = { + + DASH_GENERIC_QUAD_API(neighbor_entry) + + .remove_all_neighbor_entries = 0, + + .create_neighbor_entries = 0, + .remove_neighbor_entries = 0, + .set_neighbor_entries_attribute = 0, + .get_neighbor_entries_attribute = 0, +}; diff --git a/dash-pipeline/SAI/src/sai_dash_next_hop.cpp b/dash-pipeline/SAI/src/sai_dash_next_hop.cpp new file mode 100644 index 000000000..f12d6e6a1 --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_next_hop.cpp @@ -0,0 +1,13 @@ +#include "saiimpl.h" + +DASH_GENERIC_QUAD(NEXT_HOP,next_hop); + +sai_next_hop_api_t dash_sai_next_hop_api_impl = { + + DASH_GENERIC_QUAD_API(next_hop) + + .create_next_hops = 0, + .remove_next_hops = 0, + .set_next_hops_attribute = 0, + .get_next_hops_attribute = 0, +}; diff --git a/dash-pipeline/SAI/src/sai_dash_policer.cpp b/dash-pipeline/SAI/src/sai_dash_policer.cpp new file mode 100644 index 000000000..409369c06 --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_policer.cpp @@ -0,0 +1,9 @@ +#include "saiimpl.h" + +DASH_GENERIC_QUAD(POLICER,policer); + +sai_policer_api_t dash_sai_policer_api_impl = { + + DASH_GENERIC_QUAD_API(policer) + DASH_GENERIC_STATS_API(policer) +}; diff --git a/dash-pipeline/SAI/src/sai_dash_port.cpp b/dash-pipeline/SAI/src/sai_dash_port.cpp new file mode 100644 index 000000000..c863fc5c7 --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_port.cpp @@ -0,0 +1,36 @@ +#include "saiimpl.h" + +DASH_GENERIC_QUAD(PORT,port); + +sai_port_api_t dash_sai_port_api_impl = { + + DASH_GENERIC_QUAD_API(port) + + .get_port_stats = 0, + .get_port_stats_ext = 0, + .clear_port_stats = 0, + .clear_port_all_stats = 0, + .create_port_pool = 0, + .remove_port_pool = 0, + .set_port_pool_attribute = 0, + .get_port_pool_attribute = 0, + .get_port_pool_stats = 0, + .get_port_pool_stats_ext = 0, + .clear_port_pool_stats = 0, + .create_port_connector = 0, + .remove_port_connector = 0, + .set_port_connector_attribute = 0, + .get_port_connector_attribute = 0, + .create_port_serdes = 0, + .remove_port_serdes = 0, + .set_port_serdes_attribute = 0, + .get_port_serdes_attribute = 0, + .create_ports = 0, + .remove_ports = 0, + .set_ports_attribute = 0, + .get_ports_attribute = 0, + .create_port_serdess = 0, + .remove_port_serdess = 0, + .set_port_serdess_attribute = 0, + .get_port_serdess_attribute = 0, +}; diff --git a/dash-pipeline/SAI/src/sai_dash_router_interface.cpp b/dash-pipeline/SAI/src/sai_dash_router_interface.cpp new file mode 100644 index 000000000..5f8a45c51 --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_router_interface.cpp @@ -0,0 +1,9 @@ +#include "saiimpl.h" + +DASH_GENERIC_QUAD(ROUTER_INTERFACE,router_interface); + +sai_router_interface_api_t dash_sai_router_interface_api_impl = { + + DASH_GENERIC_QUAD_API(router_interface) + DASH_GENERIC_STATS_API(router_interface) +}; diff --git a/dash-pipeline/SAI/src/sai_dash_switch.cpp b/dash-pipeline/SAI/src/sai_dash_switch.cpp new file mode 100644 index 000000000..5c200e79e --- /dev/null +++ b/dash-pipeline/SAI/src/sai_dash_switch.cpp @@ -0,0 +1,35 @@ +#include "saiimpl.h" + +DASH_GENERIC_QUAD(SWITCH,switch); + +static sai_status_t dash_create_switch_uniq( + _Out_ sai_object_id_t *switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list) +{ + DASH_LOG_ENTER(); + + return dash_create_switch( + switch_id, + SAI_NULL_OBJECT_ID, // no switch id since we create switch + attr_count, + attr_list); +} + +sai_switch_api_t dash_sai_switch_api_impl = { + .create_switch = dash_create_switch_uniq, + .remove_switch = dash_remove_switch, + .set_switch_attribute = dash_set_switch_attribute, + .get_switch_attribute = dash_get_switch_attribute, + .get_switch_stats = 0, + .get_switch_stats_ext = 0, + .clear_switch_stats = 0, + .switch_mdio_read = 0, + .switch_mdio_write = 0, + .create_switch_tunnel = 0, + .remove_switch_tunnel = 0, + .set_switch_tunnel_attribute = 0, + .get_switch_tunnel_attribute = 0, + .switch_mdio_cl22_read = 0, + .switch_mdio_cl22_write = 0, +}; diff --git a/dash-pipeline/SAI/templates/saidash.h.j2 b/dash-pipeline/SAI/src/saidash.h similarity index 100% rename from dash-pipeline/SAI/templates/saidash.h.j2 rename to dash-pipeline/SAI/src/saidash.h diff --git a/dash-pipeline/SAI/templates/utils.cpp.j2 b/dash-pipeline/SAI/src/utils.cpp similarity index 100% rename from dash-pipeline/SAI/templates/utils.cpp.j2 rename to dash-pipeline/SAI/src/utils.cpp diff --git a/dash-pipeline/SAI/templates/utils.h.j2 b/dash-pipeline/SAI/src/utils.h similarity index 100% rename from dash-pipeline/SAI/templates/utils.h.j2 rename to dash-pipeline/SAI/src/utils.h diff --git a/dash-pipeline/SAI/templates/saiapi.cpp.j2 b/dash-pipeline/SAI/templates/saiapi.cpp.j2 index 7db54710d..a9289436b 100644 --- a/dash-pipeline/SAI/templates/saiapi.cpp.j2 +++ b/dash-pipeline/SAI/templates/saiapi.cpp.j2 @@ -42,6 +42,13 @@ static sai_status_t dash_sai_create_{{ table.name }}( //matchedParams = 0; objId = dashSai->getNextObjectId((sai_object_type_t)SAI_OBJECT_TYPE_{{ table.name | upper }}); + if (objId == SAI_NULL_OBJECT_ID) + { + DASH_LOG_ERROR("getNextObjectId failed for SAI_OBJECT_TYPE_{{ table.name | upper }}"); + // TODO clean resources + return SAI_STATUS_FAILURE; + } + matchActionEntry->set_table_id(tableId); {% if table['keys'] | length== 1 %} @@ -54,10 +61,13 @@ static sai_status_t dash_sai_create_{{ table.name }}( {% else %} // SAI object table with multiple P4 table keys // Copy P4 table keys from appropriate SAI attributes - for (uint32_t i = 0; i < attr_count; i++) { - switch(attr_list[i].id) { + for (uint32_t i = 0; i < attr_count; i++) + { + switch(attr_list[i].id) + { {% for key in table['keys'] %} - case SAI_{{ table.name | upper }}_ATTR_{{ key.sai_key_name | upper }}: { + case SAI_{{ table.name | upper }}_ATTR_{{ key.sai_key_name | upper }}: + { auto mf = matchActionEntry->add_match(); mf->set_field_id({{key.id}}); {% if key.match_type == 'exact' %} @@ -102,17 +112,20 @@ static sai_status_t dash_sai_create_{{ table.name }}( {% if table['keys'] | selectattr('match_type', 'ne', 'exact') | list | length > 0 %} {% if table['keys'] | selectattr('match_type', 'eq', 'lpm') | list | length == 0 %} // Table has non lpm ternary keys - add priority field - case SAI_{{ table.name | upper }}_ATTR_PRIORITY: { + case SAI_{{ table.name | upper }}_ATTR_PRIORITY: + { matchActionEntry->set_priority(attr_list[i].value.u32); break; } {% endif %} {% endif %} + default: + DASH_LOG_ERROR("attribute [%d] %d not supported yet", i, attr_list[i].id); + break; } } {% endif %} - // If there is only one action, simply set it. // Else, search in the attrs. {% if table.actions|length == 1 %} @@ -122,31 +135,41 @@ static sai_status_t dash_sai_create_{{ table.name }}( {% endfor %} {% else %} // Search the action - for (uint32_t i = 0; i < attr_count; i++) { + for (uint32_t i = 0; i < attr_count; i++) + { if (SAI_{{ table.name | upper }}_ATTR_ACTION == attr_list[i].id) { - switch(attr_list[i].value.s32) { + switch(attr_list[i].value.s32) + { {% for action in table.actions %} - case SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }}: { + case SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }}: + { actionId = {{action.id}}; //expectedParams = {{ action.params|length }}; break; } {% endfor %} + default: + DASH_LOG_ERROR("attribute value [%d] %d not supported yet", i, attr_list[i].value.s32); + break; } // only one action break; } } {% endif %} + action->set_action_id(actionId); - for (uint32_t i = 0; i < attr_count; i++) { - switch(attr_list[i].id) { + for (uint32_t i = 0; i < attr_count; i++) + { + switch(attr_list[i].id) + { {% for param in table.actionParams %} {% if param.skipattr == 'true' %} {% else %} - case SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}: { + case SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}: + { auto param = action->add_params(); param->set_param_id({{param.id}}); {{param.field}}SetVal(attr_list[i].value, param, {{param.bitwidth}}); @@ -164,6 +187,9 @@ static sai_status_t dash_sai_create_{{ table.name }}( } {% endif %} {% endfor %} + default: + DASH_LOG_ERROR("attribute [%d] %d not supported yet", i, attr_list[i].id); + break; } } @@ -198,14 +224,17 @@ static sai_status_t dash_sai_create_{{ table.name }}s( sai_status_t agg_status = SAI_STATUS_SUCCESS; - for (uint32_t i = 0; i < object_count; i++) { + for (uint32_t i = 0; i < object_count; i++) + { object_statuses[i] = dash_sai_create_{{ table.name }}(&object_id[i], switch_id, attr_count[i], attr_list[i]); - if (object_statuses[i] != SAI_STATUS_SUCCESS) { + if (object_statuses[i] != SAI_STATUS_SUCCESS) + { agg_status = SAI_STATUS_FAILURE; } - if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) { + if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { return agg_status; } } @@ -213,7 +242,8 @@ static sai_status_t dash_sai_create_{{ table.name }}s( return agg_status; } -static sai_status_t dash_sai_remove_{{ table.name }}(_In_ sai_object_id_t {{ table.name }}_id) +static sai_status_t dash_sai_remove_{{ table.name }}( + _In_ sai_object_id_t {{ table.name }}_id) { DASH_LOG_ENTER(); @@ -235,14 +265,17 @@ static sai_status_t dash_sai_remove_{{ table.name }}s( sai_status_t agg_status = SAI_STATUS_SUCCESS; - for (uint32_t i = 0; i < object_count; i++) { + for (uint32_t i = 0; i < object_count; i++) + { object_statuses[i] = dash_sai_remove_{{ table.name }}(object_id[i]); - if (object_statuses[i] != SAI_STATUS_SUCCESS) { + if (object_statuses[i] != SAI_STATUS_SUCCESS) + { agg_status = SAI_STATUS_FAILURE; } - if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) { + if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { return agg_status; } } @@ -330,15 +363,21 @@ static sai_status_t dash_sai_create_{{ table.name }}( {% endfor %} {% else %} // Search the action - for (uint32_t i = 0; i < attr_count; i++) { - switch(attr_list[i].value.s32) { + for (uint32_t i = 0; i < attr_count; i++) + { + switch(attr_list[i].value.s32) + { {% for action in table.actions %} - case SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }}: { + case SAI_{{ table.name | upper }}_ACTION_{{ action.name | upper }}: + { actionId = {{action.id}}; //expectedParams = {{ action.params|length }}; break; } {% endfor %} + default: + DASH_LOG_ERROR("attribute value [%d] %d not supported yet", i, attr_list[i].value.s32); + break; } // only one action break; @@ -346,12 +385,15 @@ static sai_status_t dash_sai_create_{{ table.name }}( {% endif %} action->set_action_id(actionId); - for (uint32_t i = 0; i < attr_count; i++) { - switch(attr_list[i].id) { + for (uint32_t i = 0; i < attr_count; i++) + { + switch(attr_list[i].id) + { {% for param in table.actionParams %} {% if param.skipattr == 'true' %} {% else %} - case SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}: { + case SAI_{{ table.name | upper }}_ATTR_{{ param.name | upper }}: + { auto param = action->add_params(); param->set_param_id({{param.id}}); {{param.field}}SetVal(attr_list[i].value, param, {{param.bitwidth}}); @@ -369,6 +411,9 @@ static sai_status_t dash_sai_create_{{ table.name }}( } {% endif %} {% endfor %} + default: + DASH_LOG_ERROR("attribute [%d] %d not supported yet", i, attr_list[i].id); + break; } } @@ -379,7 +424,9 @@ static sai_status_t dash_sai_create_{{ table.name }}( //} // TODO: ternaly needs to set priority retCode = dashSai->mutateTableEntry(matchActionEntry, p4::v1::Update_Type_INSERT); - if (grpc::StatusCode::OK == retCode) { + + if (grpc::StatusCode::OK == retCode) + { return SAI_STATUS_SUCCESS; } ErrRet: @@ -398,20 +445,22 @@ static sai_status_t dash_sai_create_{{ table.name | replace("entry", "entries") sai_status_t agg_status = SAI_STATUS_SUCCESS; - for (uint32_t i = 0; i < object_count; i++) { + for (uint32_t i = 0; i < object_count; i++) + { object_statuses[i] = dash_sai_create_{{ table.name }}(&{{ table.name }}[i], attr_count[i], attr_list[i]); - if (object_statuses[i] != SAI_STATUS_SUCCESS) { + if (object_statuses[i] != SAI_STATUS_SUCCESS) + { agg_status = SAI_STATUS_FAILURE; } - if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) { + if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { return agg_status; } } return agg_status; - } static sai_status_t dash_sai_remove_{{ table.name }}( @@ -422,7 +471,7 @@ static sai_status_t dash_sai_remove_{{ table.name }}( std::shared_ptr matchActionEntry = std::make_shared(); pi_p4_id_t tableId = {{table.id}}; matchActionEntry->set_table_id(tableId); - auto tableEntry = {{ table.name }}; + auto tableEntry = {{ table.name }}; grpc::StatusCode retCode; {% for key in table['keys'] %} @@ -480,14 +529,17 @@ static sai_status_t dash_sai_remove_{{ table.name | replace("entry", "entries") sai_status_t agg_status = SAI_STATUS_SUCCESS; - for (uint32_t i = 0; i < object_count; i++) { + for (uint32_t i = 0; i < object_count; i++) + { object_statuses[i] = dash_sai_remove_{{ table.name }}(&{{ table.name }}[i]); - if (object_statuses[i] != SAI_STATUS_SUCCESS) { + if (object_statuses[i] != SAI_STATUS_SUCCESS) + { agg_status = SAI_STATUS_FAILURE; } - if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) { + if (agg_status == SAI_STATUS_FAILURE && mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { return agg_status; } } @@ -551,7 +603,7 @@ sai_{{ app_name }}_api_t dash_sai_{{ app_name }}_api_impl = { {% for table in tables %} {% if table.name in registered_group %}{% continue %}{% endif %} {% do registered_group.append( table.name ) %} - .create_{{ table.name }} = dash_sai_create_{{ table.name }}, + .create_{{ table.name }} = dash_sai_create_{{ table.name }}, .remove_{{ table.name }} = dash_sai_remove_{{ table.name }}, .set_{{ table.name }}_attribute = dash_sai_set_{{ table.name }}_attribute, .get_{{ table.name }}_attribute = dash_sai_get_{{ table.name }}_attribute, diff --git a/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 b/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 index fbe659edc..8ae3750c3 100644 --- a/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 +++ b/dash-pipeline/SAI/templates/saifixedapis.cpp.j2 @@ -10,104 +10,7 @@ std::shared_ptr dashSai = std::make_shared(); -static sai_status_t dash_sai_create_switch( - _Out_ sai_object_id_t *switch_id, - _In_ uint32_t attr_count, - _In_ const sai_attribute_t *attr_list) -{ - DASH_LOG_ENTER(); - - return dashSai->createSwitch(switch_id, attr_count, attr_list); -} - -static sai_status_t dash_sai_get_switch_attribute( - _In_ sai_object_id_t switch_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list) -{ - DASH_LOG_ENTER(); - - return dashSai->getSwitchAttribute(switch_id, attr_count, attr_list); -} - -static sai_status_t dash_sai_remove_switch( - _In_ sai_object_id_t switch_id) -{ - DASH_LOG_ENTER(); - - return dashSai->removeSwitch(switch_id); -} - -static sai_status_t dash_sai_set_switch_attribute( - _In_ sai_object_id_t switch_id, - _In_ const sai_attribute_t *attr) -{ - DASH_LOG_ENTER(); - - return dashSai->setSwitchAttribute(switch_id, attr); -} - -sai_switch_api_t dash_sai_switch_api_impl = { - .create_switch = dash_sai_create_switch, - .remove_switch = dash_sai_remove_switch, - .set_switch_attribute = dash_sai_set_switch_attribute, - .get_switch_attribute = dash_sai_get_switch_attribute, - .get_switch_stats = 0, - .get_switch_stats_ext = 0, - .clear_switch_stats = 0, - .switch_mdio_read = 0, - .switch_mdio_write = 0, - .create_switch_tunnel = 0, - .remove_switch_tunnel = 0, - .set_switch_tunnel_attribute = 0, - .get_switch_tunnel_attribute = 0, - .switch_mdio_cl22_read = 0, - .switch_mdio_cl22_write = 0, -}; - -static sai_status_t dash_sai_get_port_attribute( - _In_ sai_object_id_t port_id, - _In_ uint32_t attr_count, - _Inout_ sai_attribute_t *attr_list) -{ - DASH_LOG_ENTER(); - - return dashSai->getPortAttribute(port_id, attr_count, attr_list); -} - -sai_port_api_t dash_sai_port_api_impl = { - .create_port = 0, - .remove_port = 0, - .set_port_attribute = 0, - .get_port_attribute = dash_sai_get_port_attribute, - .get_port_stats = 0, - .get_port_stats_ext = 0, - .clear_port_stats = 0, - .clear_port_all_stats = 0, - .create_port_pool = 0, - .remove_port_pool = 0, - .set_port_pool_attribute = 0, - .get_port_pool_attribute = 0, - .get_port_pool_stats = 0, - .get_port_pool_stats_ext = 0, - .clear_port_pool_stats = 0, - .create_port_connector = 0, - .remove_port_connector = 0, - .set_port_connector_attribute = 0, - .get_port_connector_attribute = 0, - .create_port_serdes = 0, - .remove_port_serdes = 0, - .set_port_serdes_attribute = 0, - .get_port_serdes_attribute = 0, - .create_ports = 0, - .remove_ports = 0, - .set_ports_attribute = 0, - .get_ports_attribute = 0, - .create_port_serdess = 0, - .remove_port_serdess = 0, - .set_port_serdess_attribute = 0, - .get_port_serdess_attribute = 0, -}; +#define API(A,api) case SAI_API_ ## A: *api_method_table = (void*)&dash_sai_ ## api ## _api_impl; break; sai_status_t sai_api_query( _In_ sai_api_t api, @@ -115,14 +18,15 @@ sai_status_t sai_api_query( { DASH_LOG_ENTER(); - switch((int)api) { - case SAI_API_SWITCH: - *api_method_table = (void *)&dash_sai_switch_api_impl; - break; - - case SAI_API_PORT: - *api_method_table = (void *)&dash_sai_port_api_impl; - break; + switch((int)api) + { + API(HOSTIF,hostif); + API(NEIGHBOR,neighbor); + API(NEXT_HOP,next_hop); + API(POLICER,policer); + API(PORT,port); + API(ROUTER_INTERFACE,router_interface); + API(SWITCH,switch); {% for api in api_names %} case SAI_API_{{ api | upper }}: diff --git a/dash-pipeline/SAI/templates/saiimpl.h.j2 b/dash-pipeline/SAI/templates/saiimpl.h.j2 index a0dad0c4e..052a0a3ac 100644 --- a/dash-pipeline/SAI/templates/saiimpl.h.j2 +++ b/dash-pipeline/SAI/templates/saiimpl.h.j2 @@ -4,11 +4,92 @@ #define DASH_PRIVATE __attribute__((visibility("hidden"))) -DASH_PRIVATE extern sai_switch_api_t dash_sai_switch_api_impl; -DASH_PRIVATE extern sai_port_api_t dash_sai_port_api_impl; +DASH_PRIVATE extern sai_hostif_api_t dash_sai_hostif_api_impl; +DASH_PRIVATE extern sai_neighbor_api_t dash_sai_neighbor_api_impl; +DASH_PRIVATE extern sai_next_hop_api_t dash_sai_next_hop_api_impl; +DASH_PRIVATE extern sai_policer_api_t dash_sai_policer_api_impl; +DASH_PRIVATE extern sai_port_api_t dash_sai_port_api_impl; +DASH_PRIVATE extern sai_router_interface_api_t dash_sai_router_interface_api_impl; +DASH_PRIVATE extern sai_switch_api_t dash_sai_switch_api_impl; {% for api in api_names %} DASH_PRIVATE extern sai_{{ api }}_api_t dash_sai_{{ api }}_api_impl; {% endfor %} DASH_PRIVATE extern std::shared_ptr dashSai; + +// QUAD OID + +#define DASH_CREATE(OT,ot) \ + static sai_status_t dash_create_ ## ot( \ + _Out_ sai_object_id_t *object_id, \ + _In_ sai_object_id_t switch_id, \ + _In_ uint32_t attr_count, \ + _In_ const sai_attribute_t *attr_list) \ +{ \ + DASH_LOG_ENTER(); \ + return dashSai->create( \ + (sai_object_type_t)SAI_OBJECT_TYPE_ ## OT, \ + object_id, \ + switch_id, \ + attr_count, \ + attr_list); \ +} + +#define DASH_REMOVE(OT,ot) \ + static sai_status_t dash_remove_ ## ot( \ + _In_ sai_object_id_t object_id) \ +{ \ + DASH_LOG_ENTER(); \ + return dashSai->remove( \ + (sai_object_type_t)SAI_OBJECT_TYPE_ ## OT, \ + object_id); \ +} + +#define DASH_SET(OT,ot) \ + static sai_status_t dash_set_ ## ot ## _attribute( \ + _In_ sai_object_id_t object_id, \ + _In_ const sai_attribute_t *attr) \ +{ \ + DASH_LOG_ENTER(); \ + return dashSai->set( \ + (sai_object_type_t)SAI_OBJECT_TYPE_ ## OT, \ + object_id, \ + attr); \ +} + +#define DASH_GET(OT,ot) \ + static sai_status_t dash_get_ ## ot ## _attribute( \ + _In_ sai_object_id_t object_id, \ + _In_ uint32_t attr_count, \ + _Inout_ sai_attribute_t *attr_list) \ +{ \ + DASH_LOG_ENTER(); \ + return dashSai->get( \ + (sai_object_type_t)SAI_OBJECT_TYPE_ ## OT, \ + object_id, \ + attr_count, \ + attr_list); \ +} + +// QUAD DECLARE + +#define DASH_GENERIC_QUAD(OT,ot) \ + DASH_CREATE(OT,ot); \ + DASH_REMOVE(OT,ot); \ + DASH_SET(OT,ot); \ + DASH_GET(OT,ot); + +// QUAD API + +#define DASH_GENERIC_QUAD_API(ot) \ + dash_create_ ## ot, \ + dash_remove_ ## ot, \ + dash_set_ ## ot ##_attribute, \ + dash_get_ ## ot ##_attribute, + +#define DASH_GENERIC_STATS_API(ot) \ + .get_ ## ot ## _stats = 0, \ + .get_ ## ot ## _stats_ext = 0, \ + .clear_ ## ot ## _stats = 0, + diff --git a/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp b/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp index bebef12d1..fe08170cd 100644 --- a/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp +++ b/dash-pipeline/tests/libsai/vnet_out/vnet_out.cpp @@ -31,6 +31,18 @@ int main(int argc, char **argv) return 1; } + sai_switch_api_t *switch_api; + status = sai_api_query((sai_api_t)SAI_API_SWITCH, (void**)&switch_api); + QUERY_STATUS_CHECK(status, SAI_API_SWITCH); + + status = switch_api->create_switch(&switch_id, 0, NULL); + + if (status != SAI_STATUS_SUCCESS) + { + std::cout << "Failed to create switch" << std::endl; + return 1; + } + sai_dash_direction_lookup_api_t *dash_direction_lookup_api; status = sai_api_query((sai_api_t)SAI_API_DASH_DIRECTION_LOOKUP, (void**)&dash_direction_lookup_api); QUERY_STATUS_CHECK(status, SAI_API_DASH_DIRECTION_LOOKUP);