From 98bb52ebe92dd47edf0bb12321886df2388e026f Mon Sep 17 00:00:00 2001 From: Stepan Blyshchak <38952541+stepanblyschak@users.noreply.github.com> Date: Tue, 10 Dec 2024 13:24:47 +0200 Subject: [PATCH] [syncd] Implement bulk set support (#1422) Added support for bulk set SAI API for port, PG and queue objects. This allows orchagent to configure those objects in bulk improving configuration time. --- syncd/Syncd.cpp | 58 +++++++++++ syncd/Syncd.h | 7 ++ syncd/VendorSai.cpp | 33 +++++- syncd/tests/TestSyncdBrcm.cpp | 179 +++++++++++++++++++++++++++++++++ tests/BCM56850.pl | 10 +- tests/BCM56850/bulk_object.rec | 11 ++ 6 files changed, 295 insertions(+), 3 deletions(-) diff --git a/syncd/Syncd.cpp b/syncd/Syncd.cpp index 9c2533c3a..e7efff34e 100644 --- a/syncd/Syncd.cpp +++ b/syncd/Syncd.cpp @@ -2024,6 +2024,60 @@ sai_status_t Syncd::processBulkOidCreate( return status; } +sai_status_t Syncd::processBulkOidSet( + _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 = static_cast(objectIds.size()); + + if (!object_count) + { + SWSS_LOG_ERROR("container with objectIds is empty in processBulkOidSet"); + return SAI_STATUS_FAILURE; + } + + std::vector objectVids(object_count); + std::vector objectRids(object_count); + + std::vector attr_list(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]); + + const auto attr_count = attributes[idx]->get_attr_count(); + if (attr_count != 1) + { + SWSS_LOG_THROW("bulkSet api requires one attribute per object"); + } + + attr_list[idx] = *attributes[idx]->get_attr_list(); + } + + status = m_vendorSai->bulkSet( + objectType, + object_count, + objectRids.data(), + attr_list.data(), + mode, + statuses.data()); + + if (status == SAI_STATUS_NOT_IMPLEMENTED || status == SAI_STATUS_NOT_SUPPORTED) + { + SWSS_LOG_ERROR("bulkSet api is not implemented or not supported, object_type = %s", + sai_serialize_object_type(objectType).c_str()); + } + + return status; +} + sai_status_t Syncd::processBulkOidRemove( _In_ sai_object_type_t objectType, _In_ sai_bulk_op_error_mode_t mode, @@ -2128,6 +2182,10 @@ sai_status_t Syncd::processBulkOid( all = processBulkOidCreate(objectType, mode, objectIds, attributes, statuses); break; + case SAI_COMMON_API_BULK_SET: + all = processBulkOidSet(objectType, mode, objectIds, attributes, statuses); + break; + case SAI_COMMON_API_BULK_REMOVE: all = processBulkOidRemove(objectType, mode, objectIds, statuses); break; diff --git a/syncd/Syncd.h b/syncd/Syncd.h index 06eb84a62..7cbd0575c 100644 --- a/syncd/Syncd.h +++ b/syncd/Syncd.h @@ -242,6 +242,13 @@ namespace syncd _In_ const std::vector>& attributes, _Out_ std::vector& statuses); + sai_status_t processBulkOidSet( + _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, diff --git a/syncd/VendorSai.cpp b/syncd/VendorSai.cpp index c0cb5683a..4e6ee2d8b 100644 --- a/syncd/VendorSai.cpp +++ b/syncd/VendorSai.cpp @@ -606,9 +606,38 @@ sai_status_t VendorSai::bulkSet( SWSS_LOG_ENTER(); VENDOR_CHECK_API_INITIALIZED(); - SWSS_LOG_ERROR("not supported by SAI"); + sai_bulk_object_set_attribute_fn ptr; - return SAI_STATUS_NOT_SUPPORTED; + switch (object_type) + { + case SAI_OBJECT_TYPE_PORT: + ptr = m_apis.port_api->set_ports_attribute; + break; + + case SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP: + ptr = m_apis.buffer_api->set_ingress_priority_groups_attribute; + break; + + case SAI_OBJECT_TYPE_QUEUE: + ptr = m_apis.queue_api->set_queues_attribute; + break; + + default: + SWSS_LOG_ERROR("not implemented %s, FIXME", sai_serialize_object_type(object_type).c_str()); + return SAI_STATUS_NOT_IMPLEMENTED; + } + + if (!ptr) + { + SWSS_LOG_INFO("create 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, + attr_list, + mode, + object_statuses); } sai_status_t VendorSai::bulkGet( diff --git a/syncd/tests/TestSyncdBrcm.cpp b/syncd/tests/TestSyncdBrcm.cpp index 892a3ca0e..7a6e44424 100644 --- a/syncd/tests/TestSyncdBrcm.cpp +++ b/syncd/tests/TestSyncdBrcm.cpp @@ -389,3 +389,182 @@ TEST_F(SyncdBrcmTest, neighborBulkTest) ASSERT_EQ(status, SAI_STATUS_SUCCESS); } } + +TEST_F(SyncdBrcmTest, portBufferBulkSet) +{ + sai_object_id_t switchId; + sai_attribute_t attrs[1]; + + struct + { + std::vector oids; + std::vector attrs; + std::vector statuses; + + void resize(size_t size) + { + SWSS_LOG_ENTER(); + + oids.resize(size); + attrs.resize(size); + statuses.resize(size, SAI_STATUS_NOT_EXECUTED); + } + } ports, pgs, queues; + + // init view + + attrs[0].id = SAI_REDIS_SWITCH_ATTR_NOTIFY_SYNCD; + attrs[0].value.s32 = SAI_REDIS_NOTIFY_SYNCD_INIT_VIEW; + + auto status = m_sairedis->set(SAI_OBJECT_TYPE_SWITCH, SAI_NULL_OBJECT_ID, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + // create switch + + attrs[0].id = SAI_SWITCH_ATTR_INIT_SWITCH; + attrs[0].value.booldata = true; + + status = m_sairedis->create(SAI_OBJECT_TYPE_SWITCH, &switchId, SAI_NULL_OBJECT_ID, 1, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + attrs[0].id = SAI_SWITCH_ATTR_PORT_NUMBER; + status = m_sairedis->get(SAI_OBJECT_TYPE_SWITCH, switchId, 1, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + ports.resize(attrs[0].value.u32); + + ASSERT_TRUE(ports.oids.size() > 1); + + attrs[0].id = SAI_SWITCH_ATTR_PORT_LIST; + attrs[0].value.objlist.count = static_cast(ports.oids.size()); + attrs[0].value.objlist.list = ports.oids.data(); + status = m_sairedis->get(SAI_OBJECT_TYPE_SWITCH, switchId, 1, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + // Set port admin status in bulk + + for (size_t i = 0; i < ports.oids.size(); i++) + { + ports.attrs[i].id = SAI_PORT_ATTR_ADMIN_STATE; + ports.attrs[i].value.booldata = true; + } + + status = m_sairedis->bulkSet(SAI_OBJECT_TYPE_PORT, static_cast(ports.oids.size()), ports.oids.data(), + ports.attrs.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, ports.statuses.data()); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + for (size_t i = 0; i < ports.oids.size(); i++) + { + ASSERT_EQ(ports.statuses[i], SAI_STATUS_SUCCESS); + } + + // Create buffer pool + + std::array buffer_pool_attrs; + sai_object_id_t buffer_pool; + + buffer_pool_attrs[0].id = SAI_BUFFER_POOL_ATTR_THRESHOLD_MODE; + buffer_pool_attrs[0].value.u32 = SAI_BUFFER_POOL_THRESHOLD_MODE_DYNAMIC; + + buffer_pool_attrs[1].id = SAI_BUFFER_POOL_ATTR_SIZE; + buffer_pool_attrs[1].value.u32 = 47218432; + + buffer_pool_attrs[2].id = SAI_BUFFER_POOL_ATTR_TYPE; + buffer_pool_attrs[2].value.u32 = SAI_BUFFER_POOL_TYPE_INGRESS; + + buffer_pool_attrs[3].id = SAI_BUFFER_POOL_ATTR_XOFF_SIZE; + buffer_pool_attrs[3].value.u32 = 17708800; + + status = m_sairedis->create(SAI_OBJECT_TYPE_BUFFER_POOL, &buffer_pool, switchId, + static_cast(buffer_pool_attrs.size()), buffer_pool_attrs.data()); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + // Create buffer profile + + std::array buffer_profile_attrs; + sai_object_id_t buffer_profile; + + buffer_profile_attrs[0].id = SAI_BUFFER_PROFILE_ATTR_POOL_ID; + buffer_profile_attrs[0].value.oid = buffer_pool; + + buffer_profile_attrs[1].id = SAI_BUFFER_PROFILE_ATTR_THRESHOLD_MODE; + buffer_profile_attrs[1].value.u32 = SAI_BUFFER_PROFILE_THRESHOLD_MODE_DYNAMIC; + + buffer_profile_attrs[2].id = SAI_BUFFER_PROFILE_ATTR_SHARED_DYNAMIC_TH; + buffer_profile_attrs[2].value.s8 = -8; + + buffer_profile_attrs[3].id = SAI_BUFFER_PROFILE_ATTR_RESERVED_BUFFER_SIZE; + buffer_profile_attrs[3].value.u64 = 6755399441055744; + + status = m_sairedis->create(SAI_OBJECT_TYPE_BUFFER_PROFILE, &buffer_profile, switchId, + static_cast(buffer_profile_attrs.size()), buffer_profile_attrs.data()); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + // Priority group configuration + + attrs[0].id = SAI_PORT_ATTR_NUMBER_OF_INGRESS_PRIORITY_GROUPS; + status = m_sairedis->get(SAI_OBJECT_TYPE_PORT, ports.oids[0], 1, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + pgs.resize(attrs[0].value.u32); + + attrs[0].id = SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST; + attrs[0].value.objlist.count = static_cast(pgs.oids.size()); + attrs[0].value.objlist.list = pgs.oids.data(); + + status = m_sairedis->get(SAI_OBJECT_TYPE_PORT, ports.oids[0], 1, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + for (size_t i = 0; i < pgs.oids.size(); i++) + { + pgs.attrs[i].id = SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE; + pgs.attrs[i].value.oid = buffer_profile; + } + + status = m_sairedis->bulkSet(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, static_cast(pgs.oids.size()), pgs.oids.data(), + pgs.attrs.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, pgs.statuses.data()); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + for (size_t i = 0; i < pgs.oids.size(); i++) + { + ASSERT_EQ(pgs.statuses[i], SAI_STATUS_SUCCESS); + } + + // Queue configuration + + attrs[0].id = SAI_PORT_ATTR_QOS_NUMBER_OF_QUEUES; + status = m_sairedis->get(SAI_OBJECT_TYPE_PORT, ports.oids[0], 1, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + queues.resize(attrs[0].value.u32); + + attrs[0].id = SAI_PORT_ATTR_QOS_QUEUE_LIST; + attrs[0].value.objlist.count = static_cast(queues.oids.size()); + attrs[0].value.objlist.list = queues.oids.data(); + + status = m_sairedis->get(SAI_OBJECT_TYPE_PORT, ports.oids[0], 1, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + for (size_t i = 0; i < queues.oids.size(); i++) + { + queues.attrs[i].id = SAI_QUEUE_ATTR_BUFFER_PROFILE_ID; + queues.attrs[i].value.oid = buffer_profile; + } + + status = m_sairedis->bulkSet(SAI_OBJECT_TYPE_QUEUE, static_cast(queues.oids.size()), queues.oids.data(), + queues.attrs.data(), SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, queues.statuses.data()); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); + + for (size_t i = 0; i < queues.oids.size(); i++) + { + ASSERT_EQ(queues.statuses[i], SAI_STATUS_SUCCESS); + } + + // apply view + + attrs[0].id = SAI_REDIS_SWITCH_ATTR_NOTIFY_SYNCD; + attrs[0].value.s32 = SAI_REDIS_NOTIFY_SYNCD_APPLY_VIEW; + + status = m_sairedis->set(SAI_OBJECT_TYPE_SWITCH, SAI_NULL_OBJECT_ID, attrs); + ASSERT_EQ(status, SAI_STATUS_SUCCESS); +} \ No newline at end of file diff --git a/tests/BCM56850.pl b/tests/BCM56850.pl index bca5fc4ce..6b9c66c85 100755 --- a/tests/BCM56850.pl +++ b/tests/BCM56850.pl @@ -594,13 +594,20 @@ sub test_bulk_fdb play "bulk_fdb.rec" } -sub test_bulk_object +sub test_emulated_bulk_object { fresh_start; play "bulk_object.rec" } +sub test_bulk_object +{ + fresh_start_bulk; + + play "bulk_object.rec" +} + sub test_depreacated_enums { fresh_start; @@ -899,6 +906,7 @@ sub test_neighbor_next_hop test_bulk_route; test_bulk_neighbor; test_bulk_fdb; +test_emulated_bulk_object; test_bulk_object; test_brcm_config_acl; test_brcm_warm_wred_queue; diff --git a/tests/BCM56850/bulk_object.rec b/tests/BCM56850/bulk_object.rec index eacbbb9da..781c1fa28 100644 --- a/tests/BCM56850/bulk_object.rec +++ b/tests/BCM56850/bulk_object.rec @@ -2,6 +2,17 @@ 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 +2018-11-05.23:55:47.743415|g|SAI_OBJECT_TYPE_SWITCH:oid:0x21000000000000|SAI_SWITCH_ATTR_PORT_LIST=32:oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0 +2018-11-05.23:55:47.749126|G|SAI_STATUS_SUCCESS|SAI_SWITCH_ATTR_PORT_LIST=32:oid:0x1000000000002,oid:0x1000000000003,oid:0x1000000000004,oid:0x1000000000005,oid:0x1000000000006,oid:0x1000000000007,oid:0x1000000000008,oid:0x1000000000009,oid:0x100000000000a,oid:0x100000000000b,oid:0x100000000000c,oid:0x100000000000d,oid:0x100000000000e,oid:0x100000000000f,oid:0x1000000000010,oid:0x1000000000011,oid:0x1000000000012,oid:0x1000000000013,oid:0x1000000000014,oid:0x1000000000015,oid:0x1000000000016,oid:0x1000000000017,oid:0x1000000000018,oid:0x1000000000019,oid:0x100000000001a,oid:0x100000000001b,oid:0x100000000001c,oid:0x100000000001d,oid:0x100000000001e,oid:0x100000000001f,oid:0x1000000000020,oid:0x1000000000021 +2017-06-14.01:55:56.555975|S|SAI_OBJECT_TYPE_PORT||oid:0x1000000000002|SAI_PORT_ATTR_ADMIN_STATE=true||oid:0x1000000000003|SAI_PORT_ATTR_ADMIN_STATE=false||oid:0x1000000000004|SAI_PORT_ATTR_ADMIN_STATE=true +2017-06-14.01:55:56.555975|c|SAI_OBJECT_TYPE_BUFFER_POOL:oid:0x1800000000038a|SAI_BUFFER_POOL_ATTR_THRESHOLD_MODE=SAI_BUFFER_POOL_THRESHOLD_MODE_DYNAMIC|SAI_BUFFER_POOL_ATTR_SIZE=47218432|SAI_BUFFER_POOL_ATTR_TYPE=SAI_BUFFER_POOL_TYPE_INGRESS|SAI_BUFFER_POOL_ATTR_XOFF_SIZE=17708800 +2017-06-14.01:55:56.555975|c|SAI_OBJECT_TYPE_BUFFER_PROFILE:oid:0x1900000000044a|SAI_BUFFER_PROFILE_ATTR_POOL_ID=oid:0x1800000000038a|SAI_BUFFER_PROFILE_ATTR_THRESHOLD_MODE=SAI_BUFFER_PROFILE_THRESHOLD_MODE_DYNAMIC|SAI_BUFFER_PROFILE_ATTR_RESERVED_BUFFER_SIZE=6755399441055744|SAI_BUFFER_PROFILE_ATTR_SHARED_DYNAMIC_TH=-8 +2017-06-14.01:55:56.555975|g|SAI_OBJECT_TYPE_PORT:oid:0x1000000000002|SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST=8:oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0 +2017-06-14.01:55:56.555975|G|SAI_STATUS_SUCCESS|SAI_PORT_ATTR_INGRESS_PRIORITY_GROUP_LIST=8:oid:0x1a00000000018a,oid:0x1a00000000018b,oid:0x1a00000000018c,oid:0x1a00000000018d,oid:0x1a00000000018e,oid:0x1a00000000018f,oid:0x1a000000000190,oid:0x1a000000000191 +2017-06-14.01:55:56.555975|S|SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP||oid:0x1a00000000018a|SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE=oid:0x1900000000044a||oid:0x1a00000000018b|SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE=oid:0x1900000000044a||oid:0x1a00000000018c|SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE=oid:0x1900000000044a +2017-06-14.01:55:56.555975|g|SAI_OBJECT_TYPE_PORT:oid:0x1000000000002|SAI_PORT_ATTR_QOS_QUEUE_LIST=20:oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0,oid:0x0 +2017-06-14.01:55:56.555975|G|SAI_STATUS_SUCCESS|SAI_PORT_ATTR_QOS_QUEUE_LIST=20:oid:0x15000000000582,oid:0x15000000000583,oid:0x15000000000584,oid:0x15000000000585,oid:0x15000000000586,oid:0x15000000000587,oid:0x15000000000588,oid:0x15000000000589,oid:0x1500000000058a,oid:0x1500000000058b,oid:0x1500000000058e,oid:0x1500000000058f,oid:0x15000000000590,oid:0x15000000000591,oid:0x15000000000592,oid:0x15000000000593,oid:0x15000000000594,oid:0x15000000000595,oid:0x15000000000596,oid:0x15000000000597 +2017-06-14.01:55:56.555975|S|SAI_OBJECT_TYPE_QUEUE||oid:0x15000000000582|SAI_QUEUE_ATTR_BUFFER_PROFILE_ID=oid:0x1900000000044a||oid:0x15000000000583|SAI_QUEUE_ATTR_BUFFER_PROFILE_ID=oid:0x1900000000044a||oid:0x15000000000584|SAI_QUEUE_ATTR_BUFFER_PROFILE_ID=oid:0x1900000000044a 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