From 1b6fc2e6e44de61af12c078e77511b21be05ef17 Mon Sep 17 00:00:00 2001 From: Dmytro Shevchuk <68949102+dmytroxshevchuk@users.noreply.github.com> Date: Fri, 23 Oct 2020 22:53:05 +0300 Subject: [PATCH] [syncd] Add supports of bulk api in syncd (#656) --- saiplayer/SaiPlayer.cpp | 435 ++++++++++++++++++++- saiplayer/SaiPlayer.h | 14 + syncd/CommandLineOptions.cpp | 2 + syncd/CommandLineOptions.h | 2 + syncd/CommandLineOptionsParser.cpp | 15 +- syncd/Syncd.cpp | 489 +++++++++++++++++++++++- syncd/Syncd.h | 32 ++ syncd/VendorSai.cpp | 93 ++++- syncd/scripts/syncd_init_common.sh | 3 + tests/BCM56850.pl | 24 +- tests/BCM56850/bulk_fdb.rec | 10 + tests/BCM56850/bulk_object.rec | 9 + tests/BCM56850/bulk_route.rec | 10 + vslib/inc/SwitchStateBase.h | 25 +- vslib/src/SwitchStateBase.cpp | 136 +++++++ vslib/src/VirtualSwitchSaiInterface.cpp | 12 +- 16 files changed, 1273 insertions(+), 38 deletions(-) create mode 100644 tests/BCM56850/bulk_fdb.rec create mode 100644 tests/BCM56850/bulk_object.rec create mode 100644 tests/BCM56850/bulk_route.rec diff --git a/saiplayer/SaiPlayer.cpp b/saiplayer/SaiPlayer.cpp index 43797d8cd035..1798aadbce32 100644 --- a/saiplayer/SaiPlayer.cpp +++ b/saiplayer/SaiPlayer.cpp @@ -33,6 +33,33 @@ using namespace saimeta; using namespace sairediscommon; using namespace std::placeholders; +#define CALL_BULK_CREATE_API_WITH_TIMER(entry) \ + SWSS_LOG_INFO("executing BULK create "#entry", count = %zu ", entries.size()); \ + static PerformanceIntervalTimer timer("SaiPlayer::handle_bulk_entry::bulkCreate("#entry")"); \ + timer.start(); \ + status = m_sai->bulkCreate(object_count, entries.data(), attr_counts.data(), \ + attr_lists.data(), mode, statuses.data()); \ + timer.stop(); \ + timer.inc(entries.size()); + +#define CALL_BULK_REMOVE_API_WITH_TIMER(entry) \ + SWSS_LOG_INFO("executing BULK remove ", entry,", count = %zu ", entries.size()); \ + static PerformanceIntervalTimer timer("SaiPlayer::handle_bulk_entry::bulkRemove("#entry")"); \ + timer.start(); \ + status = m_sai->bulkRemove(object_count, entries.data(), \ + mode, statuses.data()); \ + timer.stop(); \ + timer.inc(entries.size()); + +#define CALL_BULK_SET_API_WITH_TIMER(entry) \ + SWSS_LOG_INFO("executing BULK set ", entry,", count = %zu ", entries.size()); \ + static PerformanceIntervalTimer timer("SaiPlayer::handle_bulk_entry::bulkSet("#entry")"); \ + timer.start(); \ + status = m_sai->bulkSet(object_count, entries.data(), \ + attr_lists.data(), mode, statuses.data()); \ + timer.stop(); \ + timer.inc(entries.size()); + SaiPlayer::SaiPlayer( _In_ std::shared_ptr sai, _In_ std::shared_ptr cmd): @@ -1327,6 +1354,361 @@ sai_status_t SaiPlayer::handle_bulk_generic( } } +sai_status_t SaiPlayer::handle_bulk_entry( + _In_ const std::vector &object_ids, + _In_ sai_object_type_t object_type, + _In_ sai_common_api_t api, + _In_ const std::vector> &attributes, + _Out_ std::vector& statuses) +{ + SWSS_LOG_ENTER(); + + sai_bulk_op_error_mode_t mode = SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR; // TODO we need to get that from recording + + uint32_t object_count = (uint32_t) object_ids.size(); + + sai_status_t status = SAI_STATUS_SUCCESS; + + if (api == SAI_COMMON_API_BULK_CREATE) + { + std::vector attr_counts(object_count); + std::vector attr_lists(object_count); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + attr_counts[idx] = attributes[idx]->get_attr_count(); + attr_lists[idx] = attributes[idx]->get_attr_list(); + } + + switch (object_type) + { + case SAI_OBJECT_TYPE_ROUTE_ENTRY: + { + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_route_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].vr_id = translate_local_to_redis(entries[it].vr_id); + } + + CALL_BULK_CREATE_API_WITH_TIMER("route_entry"); + + } + break; + + case SAI_OBJECT_TYPE_FDB_ENTRY: + { + + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_fdb_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].bv_id = translate_local_to_redis(entries[it].bv_id); + } + + CALL_BULK_CREATE_API_WITH_TIMER("fdb_entry"); + + } + break; + + case SAI_OBJECT_TYPE_NAT_ENTRY: + { + + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_nat_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].vr_id = translate_local_to_redis(entries[it].vr_id); + } + + CALL_BULK_CREATE_API_WITH_TIMER("nat_entry"); + + } + break; + + default: + SWSS_LOG_THROW("api %s is not supported in bulk", sai_serialize_common_api(api).c_str()); + } + } + else if (api == SAI_COMMON_API_BULK_REMOVE) + { + switch (object_type) + { + case SAI_OBJECT_TYPE_ROUTE_ENTRY: + { + + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_route_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].vr_id = translate_local_to_redis(entries[it].vr_id); + } + + CALL_BULK_REMOVE_API_WITH_TIMER("route_entry"); + + } + break; + + case SAI_OBJECT_TYPE_FDB_ENTRY: + { + + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_fdb_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].bv_id = translate_local_to_redis(entries[it].bv_id); + } + + CALL_BULK_REMOVE_API_WITH_TIMER("fdb_entry"); + + } + break; + + case SAI_OBJECT_TYPE_NAT_ENTRY: + { + + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_nat_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].vr_id = translate_local_to_redis(entries[it].vr_id); + } + + CALL_BULK_REMOVE_API_WITH_TIMER("nat_entry"); + + } + break; + + default: + SWSS_LOG_THROW("api %s is not supported in bulk", sai_serialize_common_api(api).c_str()); + + } + } + else if (api == SAI_COMMON_API_BULK_SET) + { + std::vector attr_lists; + + for (size_t it = 0; it < object_count; it++) + { + attr_lists.push_back(attributes[it]->get_attr_list()[0]); + } + switch (object_type) + { + case SAI_OBJECT_TYPE_ROUTE_ENTRY: + { + + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_route_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].vr_id = translate_local_to_redis(entries[it].vr_id); + } + + CALL_BULK_SET_API_WITH_TIMER("route_entry"); + + } + break; + + case SAI_OBJECT_TYPE_FDB_ENTRY: + { + + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_fdb_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].bv_id = translate_local_to_redis(entries[it].bv_id); + } + + CALL_BULK_SET_API_WITH_TIMER("fdb_entry"); + + } + break; + + case SAI_OBJECT_TYPE_NAT_ENTRY: + { + + std::vector entries(object_count); + + for (size_t it = 0; it < object_count; it++) + { + sai_deserialize_nat_entry(object_ids[it], entries[it]); + + entries[it].switch_id = translate_local_to_redis(entries[it].switch_id); + entries[it].vr_id = translate_local_to_redis(entries[it].vr_id); + } + + CALL_BULK_SET_API_WITH_TIMER("nat_entry"); + + } + break; + + default: + SWSS_LOG_THROW("api %s is not supported in bulk", sai_serialize_common_api(api).c_str()); + } + } + else + { + SWSS_LOG_THROW("api %s is not supported in bulk", sai_serialize_common_api(api).c_str()); + } + + return status; +} + +sai_status_t SaiPlayer::handle_bulk_object( + _In_ sai_object_type_t object_type, + _In_ const std::vector &object_ids, + _In_ sai_common_api_t api, + _In_ const std::vector> &attributes, + _Out_ std::vector &statuses) +{ + SWSS_LOG_ENTER(); + + if (!object_ids.size()) + { + SWSS_LOG_ERROR("Object ids is empty in handle bulk generic"); + return SAI_STATUS_FAILURE; + } + + sai_status_t status; + + uint32_t object_count = (uint32_t) object_ids.size(); + + std::vector local_ids(object_count); + + sai_bulk_op_error_mode_t mode = SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR; // TODO we need to get that from recording + + SWSS_LOG_DEBUG("generic %s for %s:%s", + sai_serialize_common_api(api).c_str(), + sai_serialize_object_type(object_type).c_str(), + object_ids[0].c_str()); + + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_object_id(object_ids[it], local_ids[it]); + } + + switch (api) + { + case SAI_COMMON_API_BULK_CREATE: + + { + sai_object_id_t switch_id = m_sai->switchIdQuery(local_ids[0]); + std::vector ids(object_count); + + for (uint32_t it = 0; it < object_count; it++) + { + if (m_sai->switchIdQuery(local_ids[it]) != switch_id || + switch_id == SAI_NULL_OBJECT_ID) + { + SWSS_LOG_THROW("invalid switch_id translated from VID %s", + sai_serialize_object_id(local_ids[it]).c_str()); + } + } + + std::vector attr_counts(object_count); + + std::vector attr_lists(object_count); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + attr_counts[idx] = attributes[idx]->get_attr_count(); + attr_lists[idx] = attributes[idx]->get_attr_list(); + } + + switch_id = translate_local_to_redis(switch_id); + + status = m_sai->bulkCreate(object_type, + switch_id, + object_count, + attr_counts.data(), + attr_lists.data(), + mode, + ids.data(), + statuses.data()); + + if (status == SAI_STATUS_SUCCESS) + { + for (uint32_t it = 0; it < object_count; it++) + { + match_redis_with_rec(ids[it], local_ids[it]); + + SWSS_LOG_INFO("saved VID %s to RID %s", + sai_serialize_object_id(local_ids[it]).c_str(), + sai_serialize_object_id(ids[it]).c_str()); + } + } + + return status; + } + break; + + case SAI_COMMON_API_BULK_REMOVE: + + { + std::vector ids(object_count); + + for (uint32_t it = 0; it < object_count; it++) + { + ids[it] = translate_local_to_redis(local_ids[it]); + } + + status = m_sai->bulkRemove(object_type, object_count, ids.data(), mode, statuses.data()); + } + break; + + case SAI_COMMON_API_BULK_SET: + + { + std::vector ids(object_count); + + for (uint32_t it = 0; it < object_count; it++) + { + ids[it] = translate_local_to_redis(local_ids[it]); + } + + std::vector attr_list; + + // route can have multiple attributes, so we need to handle them all + for (const auto &alist: attributes) + { + attr_list.push_back(alist->get_attr_list()[0]); + } + + status = m_sai->bulkSet(object_type, object_count, ids.data(), attr_list.data(), mode, statuses.data()); + } + break; + + default: + SWSS_LOG_THROW("generic other apis not implemented"); + } + + return status; +} + void SaiPlayer::processBulk( _In_ sai_common_api_t api, _In_ const std::string &line) @@ -1362,7 +1744,11 @@ void SaiPlayer::processBulk( std::vector> attributes; - std::vector expectedStatuses; + std::vector statuses(fields.size()); + + // TODO currently we expect all bulk API will always succeed in sync mode + // we will need to update that, needs to be obtained from recording file + std::vector expectedStatuses(fields.size(), SAI_STATUS_SUCCESS); for (size_t idx = 1; idx < fields.size(); ++idx) { @@ -1375,10 +1761,6 @@ void SaiPlayer::processBulk( object_ids.push_back(str_object_id); - // TODO currently we expect all bulk API will always succeed in sync mode - // we will need to update that, needs to be obtained from recording file - expectedStatuses.push_back(SAI_STATUS_SUCCESS); - std::vector entries; // attributes per object id // skip front object_id and back status @@ -1416,29 +1798,50 @@ void SaiPlayer::processBulk( attributes.push_back(list); } - sai_status_t status; + sai_status_t status = SAI_STATUS_SUCCESS; + + auto info = sai_metadata_get_object_type_info(object_type); switch (object_type) { case SAI_OBJECT_TYPE_ROUTE_ENTRY: - status = handle_bulk_route(object_ids, api, attributes, expectedStatuses); - break; - - case SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MEMBER: - status = handle_bulk_generic(object_type, object_ids, api, attributes, expectedStatuses); + case SAI_OBJECT_TYPE_FDB_ENTRY: + case SAI_OBJECT_TYPE_NAT_ENTRY: + status = handle_bulk_entry(object_ids, object_type, api, attributes, statuses); break; default: - SWSS_LOG_THROW("bulk op for %s is not supported yet, FIXME", - sai_serialize_object_type(object_type).c_str()); + if (info->isnonobjectid) + { + SWSS_LOG_THROW("object %s is non object id, but not handled, FIXME", + sai_serialize_object_type(object_type).c_str()); + } + + status = handle_bulk_object(object_type, object_ids, api, attributes, statuses); + break; } - // TODO currently bulk API assume that always succeed, but this may not be - // the case when using synchronous mode, so this needs to be updated if (status != SAI_STATUS_SUCCESS) { - SWSS_LOG_THROW("failed to execute bulk api, FIXME"); + SWSS_LOG_ERROR("handle bulk executed with failure, status = %s", sai_serialize_status(status)); + } + + // even if API will fail, we will need to compare all statuses for each entry + + for (size_t i = 0; i < statuses.size(); ++i) + { + if (statuses[i] != expectedStatuses[i]) + { + /* + * If expected statuses are different than received, throw + * exception since data don't match. + */ + SWSS_LOG_THROW("expected status is %s but returned is %s on %s", + sai_serialize_status(expectedStatuses[i]).c_str(), + sai_serialize_status(statuses[i]).c_str(), + object_ids[i].c_str()); + } } } diff --git a/saiplayer/SaiPlayer.h b/saiplayer/SaiPlayer.h index 42f9528841e9..148d7b2c1c34 100644 --- a/saiplayer/SaiPlayer.h +++ b/saiplayer/SaiPlayer.h @@ -52,6 +52,20 @@ namespace saiplayer _In_ const std::vector> &attributes, _In_ const std::vector &recorded_statuses); + sai_status_t handle_bulk_object( + _In_ sai_object_type_t object_type, + _In_ const std::vector &object_ids, + _In_ sai_common_api_t api, + _In_ const std::vector> &attributes, + _Out_ std::vector &statuses); + + sai_status_t handle_bulk_entry( + _In_ const std::vector &object_ids, + _In_ sai_object_type_t object_type, + _In_ sai_common_api_t api, + _In_ const std::vector> &attributes, + _Out_ std::vector &statuses); + std::vector tokenize( _In_ std::string input, _In_ const std::string &delim); diff --git a/syncd/CommandLineOptions.cpp b/syncd/CommandLineOptions.cpp index 8af89d925e65..7ed084bdbf68 100644 --- a/syncd/CommandLineOptions.cpp +++ b/syncd/CommandLineOptions.cpp @@ -18,6 +18,7 @@ CommandLineOptions::CommandLineOptions() m_enableUnittests = false; m_enableConsistencyCheck = false; m_enableSyncMode = false; + m_enableSaiBulkSupport = false; m_startType = SAI_START_TYPE_COLD_BOOT; @@ -51,6 +52,7 @@ std::string CommandLineOptions::getCommandLineString() const ss << " EnableUnittests=" << (m_enableUnittests ? "YES" : "NO"); ss << " EnableConsistencyCheck=" << (m_enableConsistencyCheck ? "YES" : "NO"); ss << " EnableSyncMode=" << (m_enableSyncMode ? "YES" : "NO"); + ss << " EnableSaiBulkSuport=" << (m_enableSaiBulkSupport ? "YES" : "NO"); ss << " StartType=" << startTypeToString(m_startType); ss << " ProfileMapFile=" << m_profileMapFile; ss << " GlobalContext=" << m_globalContext; diff --git a/syncd/CommandLineOptions.h b/syncd/CommandLineOptions.h index 473e38c47751..c0636afcbb8a 100644 --- a/syncd/CommandLineOptions.h +++ b/syncd/CommandLineOptions.h @@ -68,6 +68,8 @@ namespace syncd bool m_enableSyncMode; + bool m_enableSaiBulkSupport; + sai_start_type_t m_startType; std::string m_profileMapFile; diff --git a/syncd/CommandLineOptionsParser.cpp b/syncd/CommandLineOptionsParser.cpp index a3a645ef6ae4..fe3474b8bf9d 100644 --- a/syncd/CommandLineOptionsParser.cpp +++ b/syncd/CommandLineOptionsParser.cpp @@ -17,9 +17,9 @@ std::shared_ptr CommandLineOptionsParser::parseCommandLine( auto options = std::make_shared(); #ifdef SAITHRIFT - const char* const optstring = "dp:t:g:x:b:uSUCsrm:h"; + const char* const optstring = "dp:t:g:x:b:uSUCslrm:h"; #else - const char* const optstring = "dp:t:g:x:b:uSUCsh"; + const char* const optstring = "dp:t:g:x:b:uSUCslh"; #endif // SAITHRIFT while(true) @@ -34,6 +34,7 @@ std::shared_ptr CommandLineOptionsParser::parseCommandLine( { "enableUnittests", no_argument, 0, 'U' }, { "enableConsistencyCheck", no_argument, 0, 'C' }, { "syncMode", no_argument, 0, 's' }, + { "enableSaiBulkSupport", no_argument, 0, 'l' }, { "globalContext", required_argument, 0, 'g' }, { "contextContig", required_argument, 0, 'x' }, { "breakConfig", required_argument, 0, 'b' }, @@ -94,6 +95,10 @@ std::shared_ptr CommandLineOptionsParser::parseCommandLine( options->m_enableSyncMode = true; break; + case 'l': + options->m_enableSaiBulkSupport = true; + break; + case 'g': options->m_globalContext = (uint32_t)std::stoul(optarg); break; @@ -138,9 +143,9 @@ void CommandLineOptionsParser::printUsage() SWSS_LOG_ENTER(); #ifdef SAITHRIFT - std::cout << "Usage: syncd [-d] [-p profile] [-t type] [-u] [-S] [-U] [-C] [-s] [-g idx] [-x contextConfig] [-b breakConfig] [-r] [-m portmap] [-h]" << std::endl; + std::cout << "Usage: syncd [-d] [-p profile] [-t type] [-u] [-S] [-U] [-C] [-s] [-l] [-g idx] [-x contextConfig] [-b breakConfig] [-r] [-m portmap] [-h]" << std::endl; #else - std::cout << "Usage: syncd [-d] [-p profile] [-t type] [-u] [-S] [-U] [-C] [-s] [-g idx] [-x contextConfig] [-b breakConfig] [-h]" << std::endl; + std::cout << "Usage: syncd [-d] [-p profile] [-t type] [-u] [-S] [-U] [-C] [-s] [-l] [-g idx] [-x contextConfig] [-b breakConfig] [-h]" << std::endl; #endif // SAITHRIFT std::cout << " -d --diag" << std::endl; @@ -159,6 +164,8 @@ void CommandLineOptionsParser::printUsage() std::cout << " Enable consisteny check DB vs ASIC after comparison logic" << std::endl; std::cout << " -s --syncMode" << std::endl; std::cout << " Enable synchronous mode" << std::endl; + std::cout << " -l --enableBulk" << std::endl; + std::cout << " Enable SAI Bulk support" << std::endl; std::cout << " -g --globalContext" << std::endl; std::cout << " Global context index to load from context config file" << std::endl; std::cout << " -x --contextConfig" << std::endl; diff --git a/syncd/Syncd.cpp b/syncd/Syncd.cpp index 30395ef35d8b..f1393a162468 100644 --- a/syncd/Syncd.cpp +++ b/syncd/Syncd.cpp @@ -797,6 +797,296 @@ sai_status_t Syncd::processBulkQuadEventInInitViewMode( } } +sai_status_t Syncd::processBulkCreateEntry( + _In_ sai_object_type_t objectType, + _In_ const std::vector& objectIds, + _In_ const std::vector>& attributes, + _Out_ std::vector& statuses) +{ + SWSS_LOG_ENTER(); + sai_status_t status = SAI_STATUS_SUCCESS; + + uint32_t object_count = (uint32_t) objectIds.size(); + + if (!object_count) + { + SWSS_LOG_ERROR("container with objectIds is empty in processBulkCreateEntry"); + return SAI_STATUS_FAILURE; + } + + sai_bulk_op_error_mode_t mode = SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR; + + std::vector attr_counts(object_count); + std::vector attr_lists(object_count); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + attr_counts[idx] = attributes[idx]->get_attr_count(); + attr_lists[idx] = attributes[idx]->get_attr_list(); + } + + switch (objectType) + { + case SAI_OBJECT_TYPE_ROUTE_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_route_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].vr_id = m_translator->translateVidToRid(entries[it].vr_id); + } + + status = m_vendorSai->bulkCreate( + object_count, + entries.data(), + attr_counts.data(), + attr_lists.data(), + mode, + statuses.data()); + + } + break; + + case SAI_OBJECT_TYPE_FDB_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_fdb_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].bv_id = m_translator->translateVidToRid(entries[it].bv_id); + } + + status = m_vendorSai->bulkCreate( + object_count, + entries.data(), + attr_counts.data(), + attr_lists.data(), + mode, + statuses.data()); + + } + break; + + case SAI_OBJECT_TYPE_NAT_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_nat_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].vr_id = m_translator->translateVidToRid(entries[it].vr_id); + } + + status = m_vendorSai->bulkCreate( + object_count, + entries.data(), + attr_counts.data(), + attr_lists.data(), + mode, + statuses.data()); + + } + break; + + default: + return SAI_STATUS_NOT_SUPPORTED; + } + + return status; +} + +sai_status_t Syncd::processBulkRemoveEntry( + _In_ sai_object_type_t objectType, + _In_ const std::vector& objectIds, + _Out_ std::vector& statuses) +{ + SWSS_LOG_ENTER(); + + sai_status_t status = SAI_STATUS_SUCCESS; + + uint32_t object_count = (uint32_t) objectIds.size(); + + if (!object_count) + { + SWSS_LOG_ERROR("container with objectIds is empty in processBulkRemoveEntry"); + return SAI_STATUS_FAILURE; + } + + sai_bulk_op_error_mode_t mode = SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR; + + switch (objectType) + { + case SAI_OBJECT_TYPE_ROUTE_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_route_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].vr_id = m_translator->translateVidToRid(entries[it].vr_id); + } + + status = m_vendorSai->bulkRemove( + object_count, + entries.data(), + mode, + statuses.data()); + + } + break; + + case SAI_OBJECT_TYPE_FDB_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_fdb_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].bv_id = m_translator->translateVidToRid(entries[it].bv_id); + } + + status = m_vendorSai->bulkRemove( + object_count, + entries.data(), + mode, + statuses.data()); + + } + break; + + case SAI_OBJECT_TYPE_NAT_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_nat_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].vr_id = m_translator->translateVidToRid(entries[it].vr_id); + } + + status = m_vendorSai->bulkRemove( + object_count, + entries.data(), + mode, + statuses.data()); + + } + break; + + default: + return SAI_STATUS_NOT_SUPPORTED; + } + + return status; +} + +sai_status_t Syncd::processBulkSetEntry( + _In_ sai_object_type_t objectType, + _In_ const std::vector& objectIds, + _In_ const std::vector>& attributes, + _Out_ std::vector& statuses) +{ + SWSS_LOG_ENTER(); + + sai_status_t status = SAI_STATUS_SUCCESS; + + std::vector attr_lists; + + uint32_t object_count = (uint32_t) objectIds.size(); + + if (!object_count) + { + SWSS_LOG_ERROR("container with objectIds is empty in processBulkSetEntry"); + return SAI_STATUS_FAILURE; + } + + sai_bulk_op_error_mode_t mode = SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR; + + for (uint32_t it = 0; it < object_count; it++) + { + attr_lists.push_back(attributes[it]->get_attr_list()[0]); + } + + switch (objectType) + { + case SAI_OBJECT_TYPE_ROUTE_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_route_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].vr_id = m_translator->translateVidToRid(entries[it].vr_id); + } + + status = m_vendorSai->bulkSet( + object_count, + entries.data(), + attr_lists.data(), + mode, + statuses.data()); + + } + break; + + case SAI_OBJECT_TYPE_FDB_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_fdb_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].bv_id = m_translator->translateVidToRid(entries[it].bv_id); + } + + status = m_vendorSai->bulkSet( + object_count, + entries.data(), + attr_lists.data(), + mode, + statuses.data()); + + } + break; + + case SAI_OBJECT_TYPE_NAT_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_nat_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + entries[it].vr_id = m_translator->translateVidToRid(entries[it].vr_id); + } + + status = m_vendorSai->bulkSet( + object_count, + entries.data(), + attr_lists.data(), + mode, + statuses.data()); + + } + break; + + default: + return SAI_STATUS_NOT_SUPPORTED; + } + + return status; +} + sai_status_t Syncd::processBulkEntry( _In_ sai_object_type_t objectType, _In_ const std::vector& objectIds, @@ -813,12 +1103,42 @@ sai_status_t Syncd::processBulkEntry( SWSS_LOG_THROW("passing oid object to bulk non obejct id operation"); } - // vendor SAI don't bulk API yet, so execute one by one - std::vector statuses(objectIds.size()); sai_status_t all = SAI_STATUS_SUCCESS; + if (m_commandLineOptions->m_enableSaiBulkSupport) + { + switch (api) + { + case SAI_COMMON_API_BULK_CREATE: + all = processBulkCreateEntry(objectType, objectIds, attributes, statuses); + break; + + case SAI_COMMON_API_BULK_REMOVE: + all = processBulkRemoveEntry(objectType, objectIds, statuses); + break; + + case SAI_COMMON_API_BULK_SET: + all = processBulkSetEntry(objectType, objectIds, attributes, statuses); + break; + + default: + SWSS_LOG_ERROR("api %s is not supported in bulk", sai_serialize_common_api(api).c_str()); + all = SAI_STATUS_NOT_SUPPORTED; + } + + if (all != SAI_STATUS_NOT_SUPPORTED && all != SAI_STATUS_NOT_IMPLEMENTED) + { + sendApiResponse(api, all, (uint32_t)objectIds.size(), statuses.data()); + syncUpdateRedisBulkQuadEvent(api, statuses, objectType, objectIds, strAttributes); + + return all; + } + } + + // vendor SAI don't bulk API yet, so execute one by one + for (size_t idx = 0; idx < objectIds.size(); ++idx) { sai_object_meta_key_t metaKey; @@ -930,6 +1250,141 @@ sai_status_t Syncd::processEntry( } } +sai_status_t Syncd::processBulkOidCreate( + _In_ sai_object_type_t objectType, + _In_ sai_bulk_op_error_mode_t mode, + _In_ const std::vector& objectIds, + _In_ const std::vector>& attributes, + _Out_ std::vector& statuses) +{ + SWSS_LOG_ENTER(); + + sai_status_t status = SAI_STATUS_SUCCESS; + uint32_t object_count = (uint32_t)objectIds.size(); + + if (!object_count) + { + SWSS_LOG_ERROR("container with objectIds is empty in processBulkOidCreate"); + return SAI_STATUS_FAILURE; + } + + std::vector objectVids(object_count); + + std::vector attr_counts(object_count); + std::vector attr_lists(object_count); + + for (size_t idx = 0; idx < object_count; idx++) + { + sai_deserialize_object_id(objectIds[idx], objectVids[idx]); + + attr_counts[idx] = attributes[idx]->get_attr_count(); + attr_lists[idx] = attributes[idx]->get_attr_list(); + } + + sai_object_id_t switchRid = SAI_NULL_OBJECT_ID; + + sai_object_id_t switchVid = VidManager::switchIdQuery(objectVids.front()); + switchRid = m_translator->translateVidToRid(switchVid); + + + std::vector objectRids(object_count); + + status = m_vendorSai->bulkCreate( + objectType, + switchRid, + object_count, + attr_counts.data(), + attr_lists.data(), + mode, + objectRids.data(), + statuses.data()); + + if (status == SAI_STATUS_NOT_IMPLEMENTED || status == SAI_STATUS_NOT_SUPPORTED) + { + SWSS_LOG_ERROR("bulkCreate api is not implemented or not supported, object_type = %u", objectType); + return status; + } + + /* + * Object was created so new object id was generated we need to save + * virtual id's to redis db. + */ + for (size_t idx = 0; idx < object_count; idx++) + { + if (statuses[idx] == SAI_STATUS_SUCCESS) + { + m_translator->insertRidAndVid(objectRids[idx], objectVids[idx]); + SWSS_LOG_INFO("saved VID %s to RID %s", + sai_serialize_object_id(objectVids[idx]).c_str(), + sai_serialize_object_id(objectRids[idx]).c_str()); + } + } + + return status; +} + +sai_status_t Syncd::processBulkOidRemove( + _In_ sai_object_type_t objectType, + _In_ sai_bulk_op_error_mode_t mode, + _In_ const std::vector& objectIds, + _Out_ std::vector& statuses) +{ + SWSS_LOG_ENTER(); + + sai_status_t status = SAI_STATUS_SUCCESS; + uint32_t object_count = (uint32_t)objectIds.size(); + + if (!object_count) + { + SWSS_LOG_ERROR("container with objectIds is empty in processBulkOidRemove"); + return SAI_STATUS_FAILURE; + } + + std::vector objectVids(object_count); + std::vector objectRids(object_count); + + for (size_t idx = 0; idx < object_count; idx++) + { + sai_deserialize_object_id(objectIds[idx], objectVids[idx]); + objectRids[idx] = m_translator->translateVidToRid(objectVids[idx]); + } + + status = m_vendorSai->bulkRemove( + objectType, + (uint32_t)object_count, + objectVids.data(), + mode, + statuses.data()); + + if (status == SAI_STATUS_NOT_IMPLEMENTED || status == SAI_STATUS_NOT_SUPPORTED) + { + SWSS_LOG_ERROR("bulkRemove api is not implemented or not supported, object_type = %u", objectType); + return status; + } + + /* + * remove all related objects from REDIS DB and also from existing + * object references since at this point they are no longer valid + */ + sai_object_id_t switchVid; + for (size_t idx = 0; idx < object_count; idx++) + { + if (statuses[idx] == SAI_STATUS_SUCCESS) + { + m_translator->eraseRidAndVid(objectRids[idx], objectVids[idx]); + + switchVid = VidManager::switchIdQuery(objectVids[idx]); + + if (m_switches.at(switchVid)->isDiscoveredRid(objectRids[idx])) + { + m_switches.at(switchVid)->removeExistingObjectReference(objectRids[idx]); + } + } + } + + return status; +} + sai_status_t Syncd::processBulkOid( _In_ sai_object_type_t objectType, _In_ const std::vector& objectIds, @@ -946,12 +1401,38 @@ sai_status_t Syncd::processBulkOid( SWSS_LOG_THROW("passing non object id to bulk oid obejct operation"); } - // vendor SAI don't bulk API yet, so execute one by one - std::vector statuses(objectIds.size()); sai_status_t all = SAI_STATUS_SUCCESS; + if (m_commandLineOptions->m_enableSaiBulkSupport) + { + sai_bulk_op_error_mode_t mode = SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR; + + switch (api) + { + case SAI_COMMON_API_BULK_CREATE: + all = processBulkOidCreate(objectType, mode, objectIds, attributes, statuses); + break; + + case SAI_COMMON_API_BULK_REMOVE: + all = processBulkOidRemove(objectType, mode, objectIds, statuses); + break; + + default: + all = SAI_STATUS_NOT_SUPPORTED; + SWSS_LOG_ERROR("api %s is not supported in bulk mode", sai_serialize_common_api(api).c_str()); + } + + if (all != SAI_STATUS_NOT_SUPPORTED && all != SAI_STATUS_NOT_IMPLEMENTED) + { + sendApiResponse(api, all, (uint32_t)objectIds.size(), statuses.data()); + syncUpdateRedisBulkQuadEvent(api, statuses, objectType, objectIds, strAttributes); + + return all; + } + } + for (size_t idx = 0; idx < objectIds.size(); ++idx) { sai_status_t status = SAI_STATUS_FAILURE; diff --git a/syncd/Syncd.h b/syncd/Syncd.h index 6aea2e527481..e13df9f63efc 100644 --- a/syncd/Syncd.h +++ b/syncd/Syncd.h @@ -163,6 +163,23 @@ namespace syncd _In_ const std::vector> &attributes, _In_ const std::vector>& strAttributes); + sai_status_t processBulkCreateEntry( + _In_ sai_object_type_t objectType, + _In_ const std::vector& objectIds, + _In_ const std::vector>& attributes, + _Out_ std::vector& statuses); + + sai_status_t processBulkRemoveEntry( + _In_ sai_object_type_t objectType, + _In_ const std::vector& objectIds, + _Out_ std::vector& statuses); + + sai_status_t processBulkSetEntry( + _In_ sai_object_type_t objectType, + _In_ const std::vector& objectIds, + _In_ const std::vector>& attributes, + _Out_ std::vector& statuses); + sai_status_t processBulkQuadEventInInitViewMode( _In_ sai_object_type_t objectType, _In_ const std::vector &object_ids, @@ -200,6 +217,21 @@ namespace syncd _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); + private: // process bulk oid + + sai_status_t processBulkOidCreate( + _In_ sai_object_type_t objectType, + _In_ sai_bulk_op_error_mode_t mode, + _In_ const std::vector& objectIds, + _In_ const std::vector>& attributes, + _Out_ std::vector& statuses); + + sai_status_t processBulkOidRemove( + _In_ sai_object_type_t objectType, + _In_ sai_bulk_op_error_mode_t mode, + _In_ const std::vector& objectIds, + _Out_ std::vector& statuses); + private: // process quad in init view mode sai_status_t processQuadInInitViewModeCreate( diff --git a/syncd/VendorSai.cpp b/syncd/VendorSai.cpp index ed16bec78bbf..03b92e6cbc68 100644 --- a/syncd/VendorSai.cpp +++ b/syncd/VendorSai.cpp @@ -663,7 +663,13 @@ sai_status_t VendorSai::bulkCreate( default: SWSS_LOG_ERROR("not implemented, FIXME"); - return SAI_STATUS_FAILURE; + return SAI_STATUS_NOT_IMPLEMENTED; + } + + if (!ptr) + { + SWSS_LOG_ERROR("create bulk not supported from SAI, object_type = %s", sai_serialize_object_type(object_type).c_str()); + return SAI_STATUS_NOT_SUPPORTED; } return ptr(switch_id, @@ -716,7 +722,13 @@ sai_status_t VendorSai::bulkRemove( default: SWSS_LOG_ERROR("not implemented, FIXME"); - return SAI_STATUS_FAILURE; + return SAI_STATUS_NOT_IMPLEMENTED; + } + + if (!ptr) + { + SWSS_LOG_ERROR("remove bulk not supported from SAI, object_type = %s", sai_serialize_object_type(object_type).c_str()); + return SAI_STATUS_NOT_SUPPORTED; } return ptr(object_count, object_id, mode, object_statuses); @@ -753,6 +765,12 @@ sai_status_t VendorSai::bulkCreate( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); + if (!m_apis.route_api->create_route_entries) + { + SWSS_LOG_ERROR("create_route_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + return m_apis.route_api->create_route_entries( object_count, entries, @@ -774,9 +792,19 @@ sai_status_t VendorSai::bulkCreate( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); - SWSS_LOG_ERROR("not supported by SAI"); + if (!m_apis.fdb_api->create_fdb_entries) + { + SWSS_LOG_ERROR("create_fdb_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } - return SAI_STATUS_NOT_SUPPORTED; + return m_apis.fdb_api->create_fdb_entries( + object_count, + entries, + attr_count, + attr_list, + mode, + object_statuses); } sai_status_t VendorSai::bulkCreate( @@ -791,6 +819,12 @@ sai_status_t VendorSai::bulkCreate( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); + if (!m_apis.nat_api->create_nat_entries) + { + SWSS_LOG_ERROR("create_nat_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + return m_apis.nat_api->create_nat_entries( object_count, entries, @@ -811,6 +845,13 @@ sai_status_t VendorSai::bulkRemove( MUTEX(); SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.route_api->remove_route_entries) + { + SWSS_LOG_ERROR("remove_route_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + return m_apis.route_api->remove_route_entries( object_count, entries, @@ -829,9 +870,17 @@ sai_status_t VendorSai::bulkRemove( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); - SWSS_LOG_ERROR("not supported by SAI"); + if (!m_apis.fdb_api->remove_fdb_entries) + { + SWSS_LOG_ERROR("remove_fdb_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } - return SAI_STATUS_NOT_SUPPORTED; + return m_apis.fdb_api->remove_fdb_entries( + object_count, + entries, + mode, + object_statuses);; } sai_status_t VendorSai::bulkRemove( @@ -843,6 +892,13 @@ sai_status_t VendorSai::bulkRemove( MUTEX(); SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.nat_api->remove_nat_entries) + { + SWSS_LOG_ERROR("remove_nat_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + return m_apis.nat_api->remove_nat_entries( object_count, entries, @@ -863,6 +919,12 @@ sai_status_t VendorSai::bulkSet( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); + if (!m_apis.route_api->set_route_entries_attribute) + { + SWSS_LOG_ERROR("set_route_entries_attribute is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + return m_apis.route_api->set_route_entries_attribute( object_count, entries, @@ -882,9 +944,18 @@ sai_status_t VendorSai::bulkSet( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); - SWSS_LOG_ERROR("not supported by SAI"); + if (!m_apis.fdb_api->set_fdb_entries_attribute) + { + SWSS_LOG_ERROR("set_fdb_entries_attribute is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } - return SAI_STATUS_NOT_SUPPORTED; + return m_apis.fdb_api->set_fdb_entries_attribute( + object_count, + entries, + attr_list, + mode, + object_statuses);; } sai_status_t VendorSai::bulkSet( @@ -898,6 +969,12 @@ sai_status_t VendorSai::bulkSet( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); + if (!m_apis.nat_api->set_nat_entries_attribute) + { + SWSS_LOG_ERROR("set_nat_entries_attribute is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + return m_apis.nat_api->set_nat_entries_attribute( object_count, entries, diff --git a/syncd/scripts/syncd_init_common.sh b/syncd/scripts/syncd_init_common.sh index 3e1b73987cd8..bded9d754a9f 100755 --- a/syncd/scripts/syncd_init_common.sh +++ b/syncd/scripts/syncd_init_common.sh @@ -24,6 +24,9 @@ fi # Use temporary view between init and apply CMD_ARGS+=" -u" +# Use bulk api`s in SAI +CMD_ARGS+=" -l" + # Set synchronous mode if it is enabled in CONFIG_DB SYNC_MODE=$(sonic-cfggen -d -v DEVICE_METADATA.localhost.synchronous_mode) if [ "$SYNC_MODE" == "enable" ]; then diff --git a/tests/BCM56850.pl b/tests/BCM56850.pl index b06878baecd5..abaad58d88ec 100755 --- a/tests/BCM56850.pl +++ b/tests/BCM56850.pl @@ -563,10 +563,29 @@ sub test_brcm_buffer_pool_zmq play("-m", "-p", "$utils::DIR/vsprofile_ctx_zmq.ini", "full_buffer_second.rec",0); } +sub test_bulk_route +{ + fresh_start; + + play "bulk_route.rec" +} + +sub test_bulk_fdb +{ + fresh_start; + + play "bulk_fdb.rec" +} + +sub test_bulk_object +{ + fresh_start; + + play "bulk_object.rec" +} # RUN TESTS test_brcm_buffer_pool_zmq; - test_brcm_acl_limit; test_sync_brcm_warm_boot_port_remove; test_brcm_warm_boot_port_remove; @@ -580,6 +599,9 @@ sub test_brcm_buffer_pool_zmq test_ntf; test_acl_mask; test_empty_lag_buffer_acl; +test_bulk_route; +test_bulk_fdb; +test_bulk_object; test_brcm_config_acl; test_brcm_warm_wred_queue; test_brcm_warm_boot_full_empty; diff --git a/tests/BCM56850/bulk_fdb.rec b/tests/BCM56850/bulk_fdb.rec new file mode 100644 index 000000000000..fddbaca43822 --- /dev/null +++ b/tests/BCM56850/bulk_fdb.rec @@ -0,0 +1,10 @@ +2017-06-14.01:55:46.541806|#|recording on: ./sairedis.2017-06-14.01:55:46.541389.rec +2017-06-14.01:55:46.543987|a|INIT_VIEW +2017-06-14.01:55:46.551164|A|SAI_STATUS_SUCCESS +2017-06-14.01:55:46.555975|c|SAI_OBJECT_TYPE_SWITCH:oid:0x21000000000000|SAI_SWITCH_ATTR_INIT_SWITCH=true|SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY=0x417890|SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY=0x4179f0|SAI_SWITCH_ATTR_SWITCH_SHUTDOWN_REQUEST_NOTIFY=0x417b50 +2017-06-14.01:55:56.555975|c|SAI_OBJECT_TYPE_BRIDGE:oid:0x39000000000018|SAI_BRIDGE_ATTR_TYPE=SAI_BRIDGE_TYPE_1D +2017-06-14.01:56:06.105336|C|SAI_OBJECT_TYPE_FDB_ENTRY||{"mac":"11-11-11-11-11-11","switch_id":"oid:0x21000000000000","bvid":"oid:0x39000000000018"}|SAI_FDB_ENTRY_ATTR_TYPE=SAI_FDB_ENTRY_TYPE_STATIC||{"mac":"11-11-11-11-11-12","switch_id":"oid:0x21000000000000","bvid":"oid:0x39000000000018"}|SAI_FDB_ENTRY_ATTR_TYPE=SAI_FDB_ENTRY_TYPE_STATIC +2017-06-14.01:56:06.205336|S|SAI_OBJECT_TYPE_FDB_ENTRY||{"mac":"11-11-11-11-11-11","switch_id":"oid:0x21000000000000","bvid":"oid:0x39000000000018"}|SAI_FDB_ENTRY_ATTR_TYPE=SAI_FDB_ENTRY_TYPE_STATIC||{"mac":"11-11-11-11-11-12","switch_id":"oid:0x21000000000000","bvid":"oid:0x39000000000018"}|SAI_FDB_ENTRY_ATTR_TYPE=SAI_FDB_ENTRY_TYPE_STATIC +2017-06-14.01:56:06.205336|R|SAI_OBJECT_TYPE_FDB_ENTRY||{"mac":"11-11-11-11-11-11","switch_id":"oid:0x21000000000000","bvid":"oid:0x39000000000018"}||{"mac":"11-11-11-11-11-12","switch_id":"oid:0x21000000000000","bvid":"oid:0x39000000000018"} +2017-06-14.01:56:06.151337|a|APPLY_VIEW +2017-06-14.01:56:06.156740|A|SAI_STATUS_SUCCESS diff --git a/tests/BCM56850/bulk_object.rec b/tests/BCM56850/bulk_object.rec new file mode 100644 index 000000000000..eacbbb9dacb2 --- /dev/null +++ b/tests/BCM56850/bulk_object.rec @@ -0,0 +1,9 @@ +2017-06-14.01:55:46.541806|#|recording on: ./sairedis.2017-06-14.01:55:46.541389.rec +2017-06-14.01:55:46.543987|a|INIT_VIEW +2017-06-14.01:55:46.551164|A|SAI_STATUS_SUCCESS +2017-06-14.01:55:46.555975|c|SAI_OBJECT_TYPE_SWITCH:oid:0x21000000000000|SAI_SWITCH_ATTR_INIT_SWITCH=true|SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY=0x417890|SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY=0x4179f0|SAI_SWITCH_ATTR_SWITCH_SHUTDOWN_REQUEST_NOTIFY=0x417b50 +2017-06-14.01:55:56.555975|C|SAI_OBJECT_TYPE_NEXT_HOP_GROUP||oid:0x5000000000005|SAI_NEXT_HOP_GROUP_ATTR_TYPE=SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP||oid:0x5000000000006|SAI_NEXT_HOP_GROUP_ATTR_TYPE=SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP||oid:0x5000000000007|SAI_NEXT_HOP_GROUP_ATTR_TYPE=SAI_NEXT_HOP_GROUP_TYPE_DYNAMIC_UNORDERED_ECMP +2017-06-14.01:55:56.555975|S|SAI_OBJECT_TYPE_NEXT_HOP_GROUP||oid:0x5000000000005|SAI_NEXT_HOP_GROUP_ATTR_SET_SWITCHOVER=true||oid:0x5000000000006|SAI_NEXT_HOP_GROUP_ATTR_SET_SWITCHOVER=true||oid:0x5000000000007|SAI_NEXT_HOP_GROUP_ATTR_SET_SWITCHOVER=true +2017-06-14.01:55:56.555975|R|SAI_OBJECT_TYPE_NEXT_HOP_GROUP||oid:0x5000000000005||oid:0x5000000000006||oid:0x5000000000007 +2017-06-14.01:56:06.151337|a|APPLY_VIEW +2017-06-14.01:56:06.156740|A|SAI_STATUS_SUCCESS diff --git a/tests/BCM56850/bulk_route.rec b/tests/BCM56850/bulk_route.rec new file mode 100644 index 000000000000..c174463a1bf1 --- /dev/null +++ b/tests/BCM56850/bulk_route.rec @@ -0,0 +1,10 @@ +2017-06-14.01:55:46.541806|#|recording on: ./sairedis.2017-06-14.01:55:46.541389.rec +2017-06-14.01:55:46.543987|a|INIT_VIEW +2017-06-14.01:55:46.551164|A|SAI_STATUS_SUCCESS +2017-06-14.01:55:46.555975|c|SAI_OBJECT_TYPE_SWITCH:oid:0x21000000000000|SAI_SWITCH_ATTR_INIT_SWITCH=true|SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY=0x417890|SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY=0x4179f0|SAI_SWITCH_ATTR_SWITCH_SHUTDOWN_REQUEST_NOTIFY=0x417b50 +2017-06-14.01:56:05.508992|c|SAI_OBJECT_TYPE_VIRTUAL_ROUTER:oid:0x3000000000004 +2017-06-14.01:56:06.105336|C|SAI_OBJECT_TYPE_ROUTE_ENTRY||{"dest":"40.0.0.1/10","switch_id":"oid:0x21000000000000","vr":"oid:0x3000000000004"}|SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID=oid:0x0||{"dest":"41.0.0.1/10","switch_id":"oid:0x21000000000000","vr":"oid:0x3000000000004"}|SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID=oid:0x0 +2017-06-14.01:56:06.205336|S|SAI_OBJECT_TYPE_ROUTE_ENTRY||{"dest":"40.0.0.1/10","switch_id":"oid:0x21000000000000","vr":"oid:0x3000000000004"}|SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID=oid:0x0||{"dest":"41.0.0.1/10","switch_id":"oid:0x21000000000000","vr":"oid:0x3000000000004"}|SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID=oid:0x0 +2017-06-14.01:56:06.205336|R|SAI_OBJECT_TYPE_ROUTE_ENTRY||{"dest":"40.0.0.1/10","switch_id":"oid:0x21000000000000","vr":"oid:0x3000000000004"}||{"dest":"41.0.0.1/10","switch_id":"oid:0x21000000000000","vr":"oid:0x3000000000004"} +2017-06-14.01:56:06.151337|a|APPLY_VIEW +2017-06-14.01:56:06.156740|A|SAI_STATUS_SUCCESS \ No newline at end of file diff --git a/vslib/inc/SwitchStateBase.h b/vslib/inc/SwitchStateBase.h index 1c7a6054f358..78b1c7e4bc11 100644 --- a/vslib/inc/SwitchStateBase.h +++ b/vslib/inc/SwitchStateBase.h @@ -10,6 +10,7 @@ #include #include +#include #define SAI_VS_FDB_INFO "SAI_VS_FDB_INFO" @@ -192,6 +193,28 @@ namespace saivs _In_ uint32_t attr_count, _Out_ sai_attribute_t *attr_list); + virtual sai_status_t bulkCreate( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _In_ const std::vector &serialized_object_ids, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + + virtual sai_status_t bulkRemove( + _In_ sai_object_type_t object_type, + _In_ const std::vector &serialized_object_ids, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + + virtual sai_status_t bulkSet( + _In_ sai_object_type_t object_type, + _In_ const std::vector &serialized_object_ids, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + protected: virtual sai_status_t remove_internal( @@ -334,7 +357,7 @@ namespace saivs sai_status_t removeHostif( _In_ sai_object_id_t objectId); - + sai_status_t vs_remove_hostif_tap_interface( _In_ sai_object_id_t hostif_id); diff --git a/vslib/src/SwitchStateBase.cpp b/vslib/src/SwitchStateBase.cpp index 9bd0a68b3833..5268111b4553 100644 --- a/vslib/src/SwitchStateBase.cpp +++ b/vslib/src/SwitchStateBase.cpp @@ -629,6 +629,142 @@ sai_status_t SwitchStateBase::get( return final_status; } +sai_status_t SwitchStateBase::bulkCreate( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _In_ const std::vector &serialized_object_ids, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + uint32_t object_count = (uint32_t) serialized_object_ids.size(); + + if (!object_count || !attr_count || !attr_list || !object_statuses) + { + SWSS_LOG_ERROR("Invalid arguments"); + return SAI_STATUS_FAILURE; + } + + sai_status_t status = SAI_STATUS_SUCCESS; + uint32_t it; + + for (it = 0; it < object_count; it++) + { + object_statuses[it] = create_internal(object_type, serialized_object_ids[it], switch_id, attr_count[it], attr_list[it]); + + if (object_statuses[it] != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to create object with type = %u", object_type); + + status = SAI_STATUS_FAILURE; + + if (mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { + break; + } + } + } + + while (++it < object_count) + { + object_statuses[it] = SAI_STATUS_NOT_EXECUTED; + } + + return status; +} + +sai_status_t SwitchStateBase::bulkRemove( + _In_ sai_object_type_t object_type, + _In_ const std::vector &serialized_object_ids, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + uint32_t object_count = (uint32_t) serialized_object_ids.size(); + + if (!object_count || !object_statuses) + { + SWSS_LOG_ERROR("Invalid arguments"); + return SAI_STATUS_FAILURE; + } + + sai_status_t status = SAI_STATUS_SUCCESS; + uint32_t it; + + for (it = 0; it < object_count; it++) + { + object_statuses[it] = remove_internal(object_type, serialized_object_ids[it]); + + if (object_statuses[it] != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to remove object with type = %u", object_type); + + status = SAI_STATUS_FAILURE; + + if (mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { + break; + } + } + } + + while (++it < object_count) + { + object_statuses[it] = SAI_STATUS_NOT_EXECUTED; + } + + return status; +} + +sai_status_t SwitchStateBase::bulkSet( + _In_ sai_object_type_t object_type, + _In_ const std::vector &serialized_object_ids, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + uint32_t object_count = (uint32_t) serialized_object_ids.size(); + + if (!object_count || !attr_list || !object_statuses) + { + SWSS_LOG_ERROR("Invalid arguments"); + return SAI_STATUS_FAILURE; + } + + sai_status_t status = SAI_STATUS_SUCCESS; + uint32_t it; + + for (it = 0; it < object_count; it++) + { + object_statuses[it] = set_internal(object_type, serialized_object_ids[it], &attr_list[it]); + + if (object_statuses[it] != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Failed to set attribute for object with type = %u", object_type); + + status = SAI_STATUS_FAILURE; + + if (mode == SAI_BULK_OP_ERROR_MODE_STOP_ON_ERROR) + { + break; + } + } + } + + while (++it < object_count) + { + object_statuses[it] = SAI_STATUS_NOT_EXECUTED; + } + + return status; +} + static int get_default_gw_mac_address( _Out_ sai_mac_t& mac) { diff --git a/vslib/src/VirtualSwitchSaiInterface.cpp b/vslib/src/VirtualSwitchSaiInterface.cpp index 0ae11d968737..2b00a4cf2f6a 100644 --- a/vslib/src/VirtualSwitchSaiInterface.cpp +++ b/vslib/src/VirtualSwitchSaiInterface.cpp @@ -980,7 +980,9 @@ sai_status_t VirtualSwitchSaiInterface::bulkRemove( { SWSS_LOG_ENTER(); - return SAI_STATUS_NOT_IMPLEMENTED; + auto ss = m_switchStateMap.at(switchId); + + return ss->bulkRemove(object_type, serialized_object_ids, mode, object_statuses); } sai_status_t VirtualSwitchSaiInterface::bulkRemove( @@ -1147,7 +1149,9 @@ sai_status_t VirtualSwitchSaiInterface::bulkSet( { SWSS_LOG_ENTER(); - return SAI_STATUS_NOT_IMPLEMENTED; + auto ss = m_switchStateMap.at(switchId); + + return ss->bulkSet(object_type, serialized_object_ids, attr_list, mode, object_statuses); } sai_status_t VirtualSwitchSaiInterface::bulkCreate( @@ -1192,9 +1196,9 @@ sai_status_t VirtualSwitchSaiInterface::bulkCreate( { SWSS_LOG_ENTER(); - // support mode ! + auto ss = m_switchStateMap.at(switchId); - return SAI_STATUS_NOT_IMPLEMENTED; + return ss->bulkCreate(switchId, object_type, serialized_object_ids, attr_count, attr_list, mode, object_statuses);; } sai_status_t VirtualSwitchSaiInterface::bulkCreate(