From 0d3749d3a93fd7e59ebb83b49fa1d7e2a56d6cf4 Mon Sep 17 00:00:00 2001 From: abdosi <58047199+abdosi@users.noreply.github.com> Date: Fri, 9 Apr 2021 07:58:34 -0700 Subject: [PATCH] Moved SAI Header to git tag v1.8.1 (#816) What I did: Moved the SAI header to v1.8.1. 7cd3a7ed84db3fc9cec13496a5339b6fe1888bb7 (HEAD, tag: v1.8.1, origin/v1.8) Update SAI version to V1.8.1 (#1218) 5913e4cdd0c9c7ae859baa2e18086327b39a94da Fix error when compiling Broadcom SAI with v1.8.0 (#1216) 5a98bc3c7e86c01f3cf702054f9af7c7c5ca6daf (HEAD, tag: v1.8.0, origin/master, origin/HEAD, master) Update version to 1.8.0 (#1207) b3244ceceb45184ffe37da55bb9a98ef126050ce saineighbor.h: Updated SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_INDEX and deprecated SAI_NEIGHBOR_ENTRY_ATTR_ENCAP_IMPOSE_INDEX (#1202) 8731ca6e09c7ba99b0b009e5821d80598e216756 Add source/dest/double NAPT entry available attributes (#1194) f053d899feb9517f2db43ee462589a30572b5ed1 Add switch attributes for hash offset configuration. (#1195) 13e5cd6940f9a0da1878d00f08e5941e09f16e7f PRBS RX State Data Type (#1179) 9755845a06525a3c17f03e7b936a70783e8ef068 Packet header based VRF classification (#1185) 2369ecb59fff1a5cae948d41eea06bf8b71330b2 SAI versioning (#1183) 744279839c176e68b19734657975e3f5ec6f1a32 Replaced SAI_SWITCH_ATTR_MACSEC_OBJECT_ID with SAI_SWITCH_ATTR_MACSEC_OBJECT_LIST (#1199) 584c724864fe565357e82d097ddcc7363bddefac [CI] Set up CI&PR with Azure Pipelines (#1200) 08192237963174cc60edae9b4812a39c43b291fd Add attribute to query available packet DMA pool size (#1198) f092ef1e3ce695fc3f9552721025695312b961a2 Add IPv6 flow label hash attribute. (#1192) cbc9562bb7a8f2c3a79702b99be55f3b3afa6957 Override VRF (#1186) 1eb35afdb2146baf40e6c2b8f2f8bfe99075eaee Add SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO format for GB MDIO sysfs access (#1171) b2d4c9a57c7f00b2632c35ca5eb3dd6480f7916a Switch scoped tunnel attributes (#1173) 96adc95bf8316e1905143d9ecd21f32a43e80d7f Enhancements for MPLS support (#1181) 3dcf1f2028da4060b345ad78e8a0c87d225bf5d0 Support for ACL extensions in metadata (#1178) 24076be95b871e8f82ecaeb908cad951dc68896c [meta] Add support for allow empty list tag (#1190) a2b3344cdde0bf5a4f8e98e1c676a658c0c615b0 spell check fixes (#1189) bf4271bab6e8884bd96050bcba44e3134adaaec3 Do not call sai_metadata_sai get APIs before checking if they are allocated (#1182) 5d5784dc3dbfc713c92ae7d2c472680b837bb002 [macsec]: Separate XPN configuration attribute from read-only attribute (#1169) 6d5a9bf5ad17cb82621cabbe2449524320930606 [macsec]: add SAI_MACSEC_ATTR_SUPPORTED_CIPHER_SUITE_LIST (#1172) e72c8f3a0cc543cb228554be82c97a63db917740 [meta] Print each tool version in Makefile (#1177) 8f19677da88c7494d563ef7c5acb0529ecbd0b6e [meta] Add check for START, END and RANBE_BASE enums (#1175) 24ad7906f145930b2e25682b6248909289d39e72 [meta] Create sai_switch_pointers_t struct (#1174) 4f5f84df3fcd0e146707df41d3e2837c48f7c760 Tunnel loopback packet action as resource (#1163) 8a0e82c57aa0e22e696158735516904e7dc14052 [meta] Add create only oid attribute check on switch object (#1170) 14cf50772e478551920963ecf11f4fd019a0c106 Remove obsolete stub folder (#1168) f14f406340e4f5f1b1d674f6fdd5fd861a54c877 [meta] Use safer calloc for integer overflow check (#1166) Also this PR include changes of this #815 SAI commit b2d4c9a57c7f00b2632c35ca5eb3dd6480f7916a Switch scoped tunnel attributes (#1173) needed change in sai_redis_switch.cpp and sai_vs_switch.cpp for compilation. How I verify: Verify Build is fine of libsairedis*.deb, syncd*.deb, swss*.deb Co-authored-by: Ann Pokora --- SAI | 2 +- lib/inc/RedisRemoteSaiInterface.h | 3 + lib/inc/Sai.h | 3 + lib/inc/SaiInterface.h | 3 + lib/src/RedisRemoteSaiInterface.cpp | 76 ++++++++ lib/src/Sai.cpp | 3 + lib/src/SaiInterface.cpp | 12 ++ lib/src/sai_redis_mpls.cpp | 2 + lib/src/sai_redis_switch.cpp | 3 + meta/DummySaiInterface.cpp | 45 +++++ meta/DummySaiInterface.h | 3 + meta/Meta.cpp | 178 ++++++++++++++++++ meta/Meta.h | 3 + meta/MetaKeyHasher.cpp | 24 +++ meta/saiserialize.cpp | 20 ++ saiplayer/SaiPlayer.cpp | 36 ++++ saiplayer/SaiPlayer.h | 6 + syncd/AsicView.cpp | 13 ++ syncd/AsicView.h | 1 + syncd/BestCandidateFinder.cpp | 82 ++++++++ syncd/BestCandidateFinder.h | 3 + syncd/ComparisonLogic.cpp | 4 + syncd/SingleReiniter.cpp | 40 ++++ syncd/SingleReiniter.h | 3 + syncd/Syncd.cpp | 64 +++++++ syncd/VendorSai.cpp | 75 ++++++++ syncd/VendorSai.h | 3 + .../test_macsec_p2p_establishment.rec | 4 +- tests/aspell.en.pws | 3 + vslib/inc/Sai.h | 3 + vslib/inc/VirtualSwitchSaiInterface.h | 3 + vslib/src/Sai.cpp | 3 + vslib/src/SwitchStateBaseMACsec.cpp | 4 +- vslib/src/VirtualSwitchSaiInterface.cpp | 66 +++++++ vslib/src/sai_vs_mpls.cpp | 2 + vslib/src/sai_vs_switch.cpp | 6 +- 36 files changed, 798 insertions(+), 6 deletions(-) diff --git a/SAI b/SAI index c0bdac2b8801..7cd3a7ed84db 160000 --- a/SAI +++ b/SAI @@ -1 +1 @@ -Subproject commit c0bdac2b8801fddf60be74f011ffb8410c0c253f +Subproject commit 7cd3a7ed84db3fc9cec13496a5339b6fe1888bb7 diff --git a/lib/inc/RedisRemoteSaiInterface.h b/lib/inc/RedisRemoteSaiInterface.h index 4927e2321a99..fbf198932fc6 100644 --- a/lib/inc/RedisRemoteSaiInterface.h +++ b/lib/inc/RedisRemoteSaiInterface.h @@ -185,18 +185,21 @@ namespace sairedis public: // bulk create ENTRY SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(fdb_entry); + SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(inseg_entry); SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(nat_entry); SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(route_entry); public: // bulk remove ENTRY SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(fdb_entry); + SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(inseg_entry); SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(nat_entry); SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(route_entry); public: // bulk set ENTRY SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_SET_ENTRY(fdb_entry); + SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_SET_ENTRY(inseg_entry); SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_SET_ENTRY(nat_entry); SAIREDIS_REDISREMOTESAIINTERFACE_DECLARE_BULK_SET_ENTRY(route_entry); diff --git a/lib/inc/Sai.h b/lib/inc/Sai.h index 1ea13bac08a1..4dd3944eb4e6 100644 --- a/lib/inc/Sai.h +++ b/lib/inc/Sai.h @@ -177,18 +177,21 @@ namespace sairedis public: // bulk create ENTRY SAIREDIS_SAI_DECLARE_BULK_CREATE_ENTRY(fdb_entry); + SAIREDIS_SAI_DECLARE_BULK_CREATE_ENTRY(inseg_entry); SAIREDIS_SAI_DECLARE_BULK_CREATE_ENTRY(nat_entry); SAIREDIS_SAI_DECLARE_BULK_CREATE_ENTRY(route_entry); public: // bulk remove ENTRY SAIREDIS_SAI_DECLARE_BULK_REMOVE_ENTRY(fdb_entry); + SAIREDIS_SAI_DECLARE_BULK_REMOVE_ENTRY(inseg_entry); SAIREDIS_SAI_DECLARE_BULK_REMOVE_ENTRY(nat_entry); SAIREDIS_SAI_DECLARE_BULK_REMOVE_ENTRY(route_entry); public: // bulk set ENTRY SAIREDIS_SAI_DECLARE_BULK_SET_ENTRY(fdb_entry); + SAIREDIS_SAI_DECLARE_BULK_SET_ENTRY(inseg_entry); SAIREDIS_SAI_DECLARE_BULK_SET_ENTRY(nat_entry); SAIREDIS_SAI_DECLARE_BULK_SET_ENTRY(route_entry); diff --git a/lib/inc/SaiInterface.h b/lib/inc/SaiInterface.h index 5ce7f727f1d2..69ceb61b6808 100644 --- a/lib/inc/SaiInterface.h +++ b/lib/inc/SaiInterface.h @@ -168,18 +168,21 @@ namespace sairedis public: // bulk create ENTRY SAIREDIS_SAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(fdb_entry); + SAIREDIS_SAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(inseg_entry); SAIREDIS_SAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(nat_entry); SAIREDIS_SAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(route_entry); public: // bulk remove ENTRY SAIREDIS_SAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(fdb_entry); + SAIREDIS_SAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(inseg_entry); SAIREDIS_SAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(nat_entry); SAIREDIS_SAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(route_entry); public: // bulk set ENTRY SAIREDIS_SAIINTERFACE_DECLARE_BULK_SET_ENTRY(fdb_entry); + SAIREDIS_SAIINTERFACE_DECLARE_BULK_SET_ENTRY(inseg_entry); SAIREDIS_SAIINTERFACE_DECLARE_BULK_SET_ENTRY(nat_entry); SAIREDIS_SAIINTERFACE_DECLARE_BULK_SET_ENTRY(route_entry); diff --git a/lib/src/RedisRemoteSaiInterface.cpp b/lib/src/RedisRemoteSaiInterface.cpp index 7507f7866a1c..48301e1c3bc5 100644 --- a/lib/src/RedisRemoteSaiInterface.cpp +++ b/lib/src/RedisRemoteSaiInterface.cpp @@ -1410,6 +1410,24 @@ sai_status_t RedisRemoteSaiInterface::bulkRemove( return bulkRemove(SAI_OBJECT_TYPE_NAT_ENTRY, serializedObjectIds, mode, object_statuses); } +sai_status_t RedisRemoteSaiInterface::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + std::vector serializedObjectIds; + + for (uint32_t idx = 0; idx < object_count; idx++) + { + serializedObjectIds.emplace_back(sai_serialize_inseg_entry(inseg_entry[idx])); + } + + return bulkRemove(SAI_OBJECT_TYPE_INSEG_ENTRY, serializedObjectIds, mode, object_statuses); +} + sai_status_t RedisRemoteSaiInterface::bulkRemove( _In_ uint32_t object_count, _In_ const sai_fdb_entry_t *fdb_entry, @@ -1486,6 +1504,25 @@ sai_status_t RedisRemoteSaiInterface::bulkSet( return bulkSet(SAI_OBJECT_TYPE_NAT_ENTRY, serializedObjectIds, attr_list, mode, object_statuses); } +sai_status_t RedisRemoteSaiInterface::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + std::vector serializedObjectIds; + + for (uint32_t idx = 0; idx < object_count; idx++) + { + serializedObjectIds.emplace_back(sai_serialize_inseg_entry(inseg_entry[idx])); + } + + return bulkSet(SAI_OBJECT_TYPE_INSEG_ENTRY, serializedObjectIds, attr_list, mode, object_statuses); +} + sai_status_t RedisRemoteSaiInterface::bulkSet( _In_ uint32_t object_count, _In_ const sai_fdb_entry_t *fdb_entry, @@ -1714,6 +1751,45 @@ sai_status_t RedisRemoteSaiInterface::bulkCreate( object_statuses); } +sai_status_t RedisRemoteSaiInterface::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t* inseg_entry, + _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(); + + // TODO support mode + + static PerformanceIntervalTimer timer("RedisRemoteSaiInterface::bulkCreate(inseg_entry)"); + + timer.start(); + + std::vector serialized_object_ids; + + // on create vid is put in db by syncd + for (uint32_t idx = 0; idx < object_count; idx++) + { + std::string str_object_id = sai_serialize_inseg_entry(inseg_entry[idx]); + serialized_object_ids.push_back(str_object_id); + } + + auto status = bulkCreate( + SAI_OBJECT_TYPE_INSEG_ENTRY, + serialized_object_ids, + attr_count, + attr_list, + mode, + object_statuses); + + timer.stop(); + + timer.inc(object_count); + + return status; +} sai_status_t RedisRemoteSaiInterface::bulkCreate( _In_ uint32_t object_count, diff --git a/lib/src/Sai.cpp b/lib/src/Sai.cpp index 1bb9fbff1eac..411ad37a8d38 100644 --- a/lib/src/Sai.cpp +++ b/lib/src/Sai.cpp @@ -505,6 +505,7 @@ sai_status_t Sai::bulkCreate( \ DECLARE_BULK_CREATE_ENTRY(ROUTE_ENTRY,route_entry) DECLARE_BULK_CREATE_ENTRY(FDB_ENTRY,fdb_entry); +DECLARE_BULK_CREATE_ENTRY(INSEG_ENTRY,inseg_entry); DECLARE_BULK_CREATE_ENTRY(NAT_ENTRY,nat_entry) @@ -530,6 +531,7 @@ sai_status_t Sai::bulkRemove( \ DECLARE_BULK_REMOVE_ENTRY(ROUTE_ENTRY,route_entry) DECLARE_BULK_REMOVE_ENTRY(FDB_ENTRY,fdb_entry); +DECLARE_BULK_REMOVE_ENTRY(INSEG_ENTRY,inseg_entry); DECLARE_BULK_REMOVE_ENTRY(NAT_ENTRY,nat_entry) // BULK SET @@ -556,6 +558,7 @@ sai_status_t Sai::bulkSet( \ DECLARE_BULK_SET_ENTRY(ROUTE_ENTRY,route_entry); DECLARE_BULK_SET_ENTRY(FDB_ENTRY,fdb_entry); +DECLARE_BULK_SET_ENTRY(INSEG_ENTRY,inseg_entry); DECLARE_BULK_SET_ENTRY(NAT_ENTRY,nat_entry); // NON QUAD API diff --git a/lib/src/SaiInterface.cpp b/lib/src/SaiInterface.cpp index 7e1c5a8c6664..cd7a2296fdee 100644 --- a/lib/src/SaiInterface.cpp +++ b/lib/src/SaiInterface.cpp @@ -40,6 +40,9 @@ sai_status_t SaiInterface::create( case SAI_OBJECT_TYPE_NAT_ENTRY: return create(&metaKey.objectkey.key.nat_entry, attr_count, attr_list); + case SAI_OBJECT_TYPE_INSEG_ENTRY: + return create(&metaKey.objectkey.key.inseg_entry, attr_count, attr_list); + default: SWSS_LOG_ERROR("object type %s not implemented, FIXME", info->objecttypename); @@ -81,6 +84,9 @@ sai_status_t SaiInterface::remove( case SAI_OBJECT_TYPE_NAT_ENTRY: return remove(&metaKey.objectkey.key.nat_entry); + case SAI_OBJECT_TYPE_INSEG_ENTRY: + return remove(&metaKey.objectkey.key.inseg_entry); + default: SWSS_LOG_ERROR("object type %s not implemented, FIXME", info->objecttypename); @@ -123,6 +129,9 @@ sai_status_t SaiInterface::set( case SAI_OBJECT_TYPE_NAT_ENTRY: return set(&metaKey.objectkey.key.nat_entry, attr); + case SAI_OBJECT_TYPE_INSEG_ENTRY: + return set(&metaKey.objectkey.key.inseg_entry, attr); + default: SWSS_LOG_ERROR("object type %s not implemented, FIXME", info->objecttypename); @@ -166,6 +175,9 @@ sai_status_t SaiInterface::get( case SAI_OBJECT_TYPE_NAT_ENTRY: return get(&metaKey.objectkey.key.nat_entry, attr_count, attr_list); + case SAI_OBJECT_TYPE_INSEG_ENTRY: + return get(&metaKey.objectkey.key.inseg_entry, attr_count, attr_list); + default: SWSS_LOG_ERROR("object type %s not implemented, FIXME", info->objecttypename); diff --git a/lib/src/sai_redis_mpls.cpp b/lib/src/sai_redis_mpls.cpp index e03671e2dbd3..70eef8ae8a66 100644 --- a/lib/src/sai_redis_mpls.cpp +++ b/lib/src/sai_redis_mpls.cpp @@ -1,8 +1,10 @@ #include "sai_redis.h" REDIS_GENERIC_QUAD_ENTRY(INSEG_ENTRY,inseg_entry); +REDIS_BULK_QUAD_ENTRY(INSEG_ENTRY,inseg_entry); const sai_mpls_api_t redis_mpls_api = { REDIS_GENERIC_QUAD_API(inseg_entry) + REDIS_BULK_QUAD_API(inseg_entry) }; diff --git a/lib/src/sai_redis_switch.cpp b/lib/src/sai_redis_switch.cpp index 00617eecd7be..3d1f97494a71 100644 --- a/lib/src/sai_redis_switch.cpp +++ b/lib/src/sai_redis_switch.cpp @@ -26,6 +26,7 @@ static sai_status_t redis_switch_mdio_write( REDIS_GENERIC_QUAD(SWITCH,switch); REDIS_GENERIC_STATS(SWITCH,switch); +REDIS_GENERIC_QUAD(SWITCH_TUNNEL,switch_tunnel); static sai_status_t redis_create_switch_uniq( _Out_ sai_object_id_t *switch_id, @@ -52,4 +53,6 @@ const sai_switch_api_t redis_switch_api = { redis_switch_mdio_read, redis_switch_mdio_write, + + REDIS_GENERIC_QUAD_API(switch_tunnel) }; diff --git a/meta/DummySaiInterface.cpp b/meta/DummySaiInterface.cpp index 3f32f9229512..53b573e88586 100644 --- a/meta/DummySaiInterface.cpp +++ b/meta/DummySaiInterface.cpp @@ -258,6 +258,20 @@ sai_status_t DummySaiInterface::bulkRemove( return m_status; } +sai_status_t DummySaiInterface::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + for (uint32_t idx = 0; idx < object_count; idx++) + object_statuses[idx] = m_status; + + return m_status; +} + sai_status_t DummySaiInterface::bulkRemove( _In_ uint32_t object_count, _In_ const sai_fdb_entry_t *fdb_entry, @@ -319,6 +333,21 @@ sai_status_t DummySaiInterface::bulkSet( return m_status; } +sai_status_t DummySaiInterface::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + for (uint32_t idx = 0; idx < object_count; idx++) + object_statuses[idx] = m_status; + + return m_status; +} + sai_status_t DummySaiInterface::bulkSet( _In_ uint32_t object_count, _In_ const sai_fdb_entry_t *fdb_entry, @@ -384,6 +413,22 @@ sai_status_t DummySaiInterface::bulkCreate( return m_status; } +sai_status_t DummySaiInterface::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _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(); + + for (uint32_t idx = 0; idx < object_count; idx++) + object_statuses[idx] = m_status; + + return m_status; +} + sai_status_t DummySaiInterface::bulkCreate( _In_ uint32_t object_count, _In_ const sai_nat_entry_t *nat_entry, diff --git a/meta/DummySaiInterface.h b/meta/DummySaiInterface.h index b0d801233899..d248da1bd457 100644 --- a/meta/DummySaiInterface.h +++ b/meta/DummySaiInterface.h @@ -176,18 +176,21 @@ namespace saimeta public: // bulk create ENTRY SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(fdb_entry); + SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(inseg_entry); SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(nat_entry); SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(route_entry); public: // bulk remove ENTRY SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(fdb_entry); + SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(inseg_entry); SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(nat_entry); SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(route_entry); public: // bulk set ENTRY SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_SET_ENTRY(fdb_entry); + SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_SET_ENTRY(inseg_entry); SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_SET_ENTRY(nat_entry); SAIMETA_DUMMYSAIINTERFACE_DECLARE_BULK_SET_ENTRY(route_entry); diff --git a/meta/Meta.cpp b/meta/Meta.cpp index 192fe1a77d83..923857ae572f 100644 --- a/meta/Meta.cpp +++ b/meta/Meta.cpp @@ -2319,6 +2319,65 @@ sai_status_t Meta::bulkRemove( return status; } +sai_status_t Meta::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + // all objects must be same type and come from the same switch + // TODO check multiple switches + + PARAMETER_CHECK_IF_NOT_NULL(object_statuses); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + object_statuses[idx] = SAI_STATUS_NOT_EXECUTED; + } + + //PARAMETER_CHECK_OBJECT_TYPE_VALID(object_type); + PARAMETER_CHECK_POSITIVE(object_count); + PARAMETER_CHECK_IF_NOT_NULL(inseg_entry); + + if (sai_metadata_get_enum_value_name(&sai_metadata_enum_sai_stats_mode_t, mode) == nullptr) + { + SWSS_LOG_ERROR("mode vlaue %d is not in range on %s", mode, sai_metadata_enum_sai_stats_mode_t.name); + + return SAI_STATUS_INVALID_PARAMETER; + } + + std::vector vmk; + + for (uint32_t idx = 0; idx < object_count; idx++) + { + sai_status_t status = meta_sai_validate_inseg_entry(&inseg_entry[idx], false); + + CHECK_STATUS_SUCCESS(status); + + sai_object_meta_key_t meta_key = { .objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY, .objectkey = { .key = { .inseg_entry = inseg_entry[idx] } } }; + + vmk.push_back(meta_key); + + status = meta_generic_validation_remove(meta_key); + + CHECK_STATUS_SUCCESS(status); + } + + auto status = m_implementation->bulkRemove(object_count, inseg_entry, mode, object_statuses); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + if (object_statuses[idx] == SAI_STATUS_SUCCESS) + { + meta_generic_validation_post_remove(vmk[idx]); + } + } + + return status; +} + sai_status_t Meta::bulkSet( _In_ sai_object_type_t object_type, _In_ uint32_t object_count, @@ -2555,6 +2614,64 @@ sai_status_t Meta::bulkSet( return status; } +sai_status_t Meta::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + PARAMETER_CHECK_IF_NOT_NULL(object_statuses); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + object_statuses[idx] = SAI_STATUS_NOT_EXECUTED; + } + + //PARAMETER_CHECK_OBJECT_TYPE_VALID(object_type); + PARAMETER_CHECK_POSITIVE(object_count); + PARAMETER_CHECK_IF_NOT_NULL(inseg_entry); + PARAMETER_CHECK_IF_NOT_NULL(attr_list); + + if (sai_metadata_get_enum_value_name(&sai_metadata_enum_sai_stats_mode_t, mode) == nullptr) + { + SWSS_LOG_ERROR("mode vlaue %d is not in range on %s", mode, sai_metadata_enum_sai_stats_mode_t.name); + + return SAI_STATUS_INVALID_PARAMETER; + } + + std::vector vmk; + + for (uint32_t idx = 0; idx < object_count; idx++) + { + sai_status_t status = meta_sai_validate_inseg_entry(&inseg_entry[idx], false); + + CHECK_STATUS_SUCCESS(status); + + sai_object_meta_key_t meta_key = { .objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY, .objectkey = { .key = { .inseg_entry = inseg_entry[idx] } } }; + + vmk.push_back(meta_key); + + status = meta_generic_validation_set(meta_key, &attr_list[idx]); + + CHECK_STATUS_SUCCESS(status); + } + + auto status = m_implementation->bulkSet(object_count, inseg_entry, attr_list, mode, object_statuses); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + if (object_statuses[idx] == SAI_STATUS_SUCCESS) + { + meta_generic_validation_post_set(vmk[idx], &attr_list[idx]); + } + } + + return status; +} + sai_status_t Meta::bulkCreate( _In_ sai_object_type_t object_type, _In_ sai_object_id_t switchId, @@ -2760,6 +2877,67 @@ sai_status_t Meta::bulkCreate( return status; } + +sai_status_t Meta::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _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(); + + PARAMETER_CHECK_IF_NOT_NULL(object_statuses); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + object_statuses[idx] = SAI_STATUS_NOT_EXECUTED; + } + + //PARAMETER_CHECK_OBJECT_TYPE_VALID(object_type); + PARAMETER_CHECK_POSITIVE(object_count); + PARAMETER_CHECK_IF_NOT_NULL(inseg_entry); + PARAMETER_CHECK_IF_NOT_NULL(attr_count); + PARAMETER_CHECK_IF_NOT_NULL(attr_list); + + if (sai_metadata_get_enum_value_name(&sai_metadata_enum_sai_stats_mode_t, mode) == nullptr) + { + SWSS_LOG_ERROR("mode vlaue %d is not in range on %s", mode, sai_metadata_enum_sai_stats_mode_t.name); + + return SAI_STATUS_INVALID_PARAMETER; + } + + std::vector vmk; + + for (uint32_t idx = 0; idx < object_count; idx++) + { + sai_status_t status = meta_sai_validate_inseg_entry(&inseg_entry[idx], true); + + CHECK_STATUS_SUCCESS(status); + + sai_object_meta_key_t meta_key = { .objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY, .objectkey = { .key = { .inseg_entry = inseg_entry[idx] } } }; + + vmk.push_back(meta_key); + + status = meta_generic_validation_create(meta_key, inseg_entry[idx].switch_id, attr_count[idx], attr_list[idx]); + + CHECK_STATUS_SUCCESS(status); + } + + auto status = m_implementation->bulkCreate(object_count, inseg_entry, attr_count, attr_list, mode, object_statuses); + + for (uint32_t idx = 0; idx < object_count; idx++) + { + if (object_statuses[idx] == SAI_STATUS_SUCCESS) + { + meta_generic_validation_post_create(vmk[idx], inseg_entry[idx].switch_id, attr_count[idx], attr_list[idx]); + } + } + + return status; +} + sai_status_t Meta::bulkCreate( _In_ uint32_t object_count, _In_ const sai_nat_entry_t *nat_entry, diff --git a/meta/Meta.h b/meta/Meta.h index 3af662b6e0c1..629bfab8849a 100644 --- a/meta/Meta.h +++ b/meta/Meta.h @@ -183,18 +183,21 @@ namespace saimeta public: // bulk create ENTRY SAIREDIS_META_DECLARE_BULK_CREATE_ENTRY(fdb_entry); + SAIREDIS_META_DECLARE_BULK_CREATE_ENTRY(inseg_entry); SAIREDIS_META_DECLARE_BULK_CREATE_ENTRY(nat_entry); SAIREDIS_META_DECLARE_BULK_CREATE_ENTRY(route_entry); public: // bulk remove ENTRY SAIREDIS_META_DECLARE_BULK_REMOVE_ENTRY(fdb_entry); + SAIREDIS_META_DECLARE_BULK_REMOVE_ENTRY(inseg_entry); SAIREDIS_META_DECLARE_BULK_REMOVE_ENTRY(nat_entry); SAIREDIS_META_DECLARE_BULK_REMOVE_ENTRY(route_entry); public: // bulk set ENTRY SAIREDIS_META_DECLARE_BULK_SET_ENTRY(fdb_entry); + SAIREDIS_META_DECLARE_BULK_SET_ENTRY(inseg_entry); SAIREDIS_META_DECLARE_BULK_SET_ENTRY(nat_entry); SAIREDIS_META_DECLARE_BULK_SET_ENTRY(route_entry); diff --git a/meta/MetaKeyHasher.cpp b/meta/MetaKeyHasher.cpp index be98064842e2..1da4d8585a12 100644 --- a/meta/MetaKeyHasher.cpp +++ b/meta/MetaKeyHasher.cpp @@ -88,6 +88,16 @@ static bool operator==( a.data.mask.l4_dst_port == b.data.mask.l4_dst_port; } +static bool operator==( + _In_ const sai_inseg_entry_t& a, + _In_ const sai_inseg_entry_t& b) +{ + // SWSS_LOG_ENTER(); // disabled for performance reasons + + return a.switch_id == b.switch_id && + a.label == b.label; +} + bool MetaKeyHasher::operator()( _In_ const sai_object_meta_key_t& a, _In_ const sai_object_meta_key_t& b) const @@ -114,6 +124,9 @@ bool MetaKeyHasher::operator()( if (a.objecttype == SAI_OBJECT_TYPE_NAT_ENTRY) return a.objectkey.key.nat_entry == b.objectkey.key.nat_entry; + if (a.objecttype == SAI_OBJECT_TYPE_INSEG_ENTRY) + return a.objectkey.key.inseg_entry == b.objectkey.key.inseg_entry; + SWSS_LOG_THROW("not implemented: %s", sai_serialize_object_meta_key(a).c_str()); } @@ -190,6 +203,14 @@ static inline std::size_t sai_get_hash( return ne.data.key.src_ip ^ ne.data.key.dst_ip; } +static inline std::size_t sai_get_hash( + _In_ const sai_inseg_entry_t& ie) +{ + // SWSS_LOG_ENTER(); // disabled for performance reasons + + return ie.label; +} + std::size_t MetaKeyHasher::operator()( _In_ const sai_object_meta_key_t& k) const { @@ -217,6 +238,9 @@ std::size_t MetaKeyHasher::operator()( case SAI_OBJECT_TYPE_NAT_ENTRY: return sai_get_hash(k.objectkey.key.nat_entry); + case SAI_OBJECT_TYPE_INSEG_ENTRY: + return sai_get_hash(k.objectkey.key.inseg_entry); + default: SWSS_LOG_THROW("not handled: %s", sai_serialize_object_type(k.objecttype).c_str()); } diff --git a/meta/saiserialize.cpp b/meta/saiserialize.cpp index 53651ac7a253..3662705a35e5 100644 --- a/meta/saiserialize.cpp +++ b/meta/saiserialize.cpp @@ -1934,6 +1934,10 @@ std::string sai_serialize_object_meta_key( key = sai_serialize_nat_entry(meta_key.objectkey.key.nat_entry); break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + key = sai_serialize_inseg_entry(meta_key.objectkey.key.inseg_entry); + break; + default: if (meta->isnonobjectid) @@ -3217,6 +3221,18 @@ void sai_deserialize_route_entry( EXPECT("}"); } +void sai_deserialize_inseg_entry( + _In_ const std::string &s, + _Out_ sai_inseg_entry_t& inseg_entry) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + sai_deserialize_object_id(j["switch_id"], inseg_entry.switch_id); + sai_deserialize_number(j["label"], inseg_entry.label); +} + void sai_deserialize_nat_entry_key( _In_ const json& j, _Out_ sai_nat_entry_key_t& nat_entry_key) @@ -3348,6 +3364,10 @@ void sai_deserialize_object_meta_key( sai_deserialize_nat_entry(str_object_id, meta_key.objectkey.key.nat_entry); break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + sai_deserialize_inseg_entry(str_object_id, meta_key.objectkey.key.inseg_entry); + break; + default: if (meta->isnonobjectid) diff --git a/saiplayer/SaiPlayer.cpp b/saiplayer/SaiPlayer.cpp index b4995574f35c..cbce49cf0fe7 100644 --- a/saiplayer/SaiPlayer.cpp +++ b/saiplayer/SaiPlayer.cpp @@ -639,6 +639,38 @@ sai_status_t SaiPlayer::handle_route( } } +sai_status_t SaiPlayer::handle_inseg( + _In_ const std::string &str_object_id, + _In_ sai_common_api_t api, + _In_ uint32_t attr_count, + _In_ sai_attribute_t *attr_list) +{ + SWSS_LOG_ENTER(); + + sai_inseg_entry_t inseg_entry; + sai_deserialize_inseg_entry(str_object_id, inseg_entry); + + inseg_entry.switch_id = translate_local_to_redis(inseg_entry.switch_id); + + switch(api) + { + case SAI_COMMON_API_CREATE: + return sai_metadata_sai_mpls_api->create_inseg_entry(&inseg_entry, attr_count, attr_list); + + case SAI_COMMON_API_REMOVE: + return sai_metadata_sai_mpls_api->remove_inseg_entry(&inseg_entry); + + case SAI_COMMON_API_SET: + return sai_metadata_sai_mpls_api->set_inseg_entry_attribute(&inseg_entry, attr_list); + + case SAI_COMMON_API_GET: + return sai_metadata_sai_mpls_api->get_inseg_entry_attribute(&inseg_entry, attr_count, attr_list); + + default: + SWSS_LOG_THROW("inseg other apis not implemented"); + } +} + void SaiPlayer::update_notifications_pointers( _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list) @@ -2002,6 +2034,10 @@ int SaiPlayer::replay() status = handle_route(str_object_id, api, attr_count, attr_list); break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + status = handle_inseg(str_object_id, api, attr_count, attr_list); + break; + default: if (info->isnonobjectid) diff --git a/saiplayer/SaiPlayer.h b/saiplayer/SaiPlayer.h index 148d7b2c1c34..74f01a0ab563 100644 --- a/saiplayer/SaiPlayer.h +++ b/saiplayer/SaiPlayer.h @@ -117,6 +117,12 @@ namespace saiplayer _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); + sai_status_t handle_inseg( + _In_ const std::string &str_object_id, + _In_ sai_common_api_t api, + _In_ uint32_t attr_count, + _In_ sai_attribute_t *attr_list); + void match_redis_with_rec( _In_ sai_object_type_t object_type, _In_ uint32_t get_attr_count, diff --git a/syncd/AsicView.cpp b/syncd/AsicView.cpp index 61af425613f2..c5c35cc41c14 100644 --- a/syncd/AsicView.cpp +++ b/syncd/AsicView.cpp @@ -109,6 +109,11 @@ void AsicView::fromDump( m_soNatEntries[o->m_str_object_id] = o; break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + sai_deserialize_inseg_entry(o->m_str_object_id, o->m_meta_key.objectkey.key.inseg_entry); + m_soInsegs[o->m_str_object_id] = o; + break; + default: if (o->m_info->isnonobjectid) @@ -696,6 +701,10 @@ void AsicView::asicCreateObject( m_soNatEntries[currentObj->m_str_object_id] = currentObj; break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + m_soInsegs[currentObj->m_str_object_id] = currentObj; + break; + default: SWSS_LOG_THROW("unsupported object type: %s", @@ -840,6 +849,10 @@ void AsicView::asicRemoveObject( m_soNatEntries.erase(currentObj->m_str_object_id); break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + m_soInsegs.erase(currentObj->m_str_object_id); + break; + default: SWSS_LOG_THROW("unsupported object type: %s", diff --git a/syncd/AsicView.h b/syncd/AsicView.h index 132c2d632fdd..89102b95445c 100644 --- a/syncd/AsicView.h +++ b/syncd/AsicView.h @@ -276,6 +276,7 @@ namespace syncd StrObjectIdToSaiObjectHash m_soNeighbors; StrObjectIdToSaiObjectHash m_soRoutes; StrObjectIdToSaiObjectHash m_soNatEntries; + StrObjectIdToSaiObjectHash m_soInsegs; StrObjectIdToSaiObjectHash m_soOids; StrObjectIdToSaiObjectHash m_soAll; diff --git a/syncd/BestCandidateFinder.cpp b/syncd/BestCandidateFinder.cpp index d82ae8b856ad..05d469b419cc 100644 --- a/syncd/BestCandidateFinder.cpp +++ b/syncd/BestCandidateFinder.cpp @@ -2172,6 +2172,85 @@ std::shared_ptr BestCandidateFinder::findCurrentBestMatchForRouteEntry( currentRouteObj->getObjectStatus()); } +/** + * @brief Find current best match for inseg. + * + * For Inseg we don't need to iterate via all current insegs, we can do + * dictionary lookup, but we need to do smart trick, since temporary object was + * processed we just need to check whether VID in inseg_entry struct is + * matched/final and it has RID assigned from current view. If, RID exists, we + * can use that RID to get VID of current view, exchange in inseg_entry struct + * and do dictionary lookup on serialized inseg_entry. + * + * With this approach for many entries this is the quickest possible way. In + * case when RID doesn't exist, that means we have invalid inseg entry, so we + * must return null. + * + * @param currentView Current view. + * @param temporaryView Temporary view. + * @param temporaryObj Temporary object. + * + * @return Best match object if found or nullptr. + */ +std::shared_ptr BestCandidateFinder::findCurrentBestMatchForInsegEntry( + _In_ const std::shared_ptr &temporaryObj) +{ + SWSS_LOG_ENTER(); + + /* + * Make a copy here to not destroy object data, later + * on this data should be read only. + */ + + sai_object_meta_key_t mk = temporaryObj->m_meta_key; + + if (!exchangeTemporaryVidToCurrentVid(mk)) + { + /* + * Not all oids inside struct object were translated, so there is no + * matching object in current view, we need to return null. + */ + + return nullptr; + } + + std::string str_inseg_entry = sai_serialize_inseg_entry(mk.objectkey.key.inseg_entry); + + /* + * Now when we have serialized inseg entry with temporary vr_id VID + * replaced to current vr_id VID we can do dictionary lookup for inseg. + */ + auto currentInsegIt = m_currentView.m_soInsegs.find(str_inseg_entry); + + if (currentInsegIt == m_currentView.m_soInsegs.end()) + { + SWSS_LOG_DEBUG("unable to find inseg entry %s in current asic view", str_inseg_entry.c_str()); + + return nullptr; + } + + /* + * We found the same inseg entry in current view! Just one extra check + * of object status if it's not processed yet. + */ + + auto currentInsegObj = currentInsegIt->second; + + if (currentInsegObj->getObjectStatus() == SAI_OBJECT_STATUS_NOT_PROCESSED) + { + return currentInsegObj; + } + + /* + * If we are here, that means this inseg was already processed, which + * can indicate a bug or somehow duplicated entries. + */ + + SWSS_LOG_THROW("found inseg entry %s in current view, but it status is %d, FATAL", + str_inseg_entry.c_str(), + currentInsegObj->getObjectStatus()); +} + /** * @brief Find current best match for FDB. * @@ -2412,6 +2491,9 @@ std::shared_ptr BestCandidateFinder::findCurrentBestMatch( case SAI_OBJECT_TYPE_NAT_ENTRY: return findCurrentBestMatchForNatEntry(temporaryObj); + case SAI_OBJECT_TYPE_INSEG_ENTRY: + return findCurrentBestMatchForInsegEntry(temporaryObj); + /* * We can have special case for switch since we know there should * be only one switch. diff --git a/syncd/BestCandidateFinder.h b/syncd/BestCandidateFinder.h index 2114749b79b8..482eb161c104 100644 --- a/syncd/BestCandidateFinder.h +++ b/syncd/BestCandidateFinder.h @@ -129,6 +129,9 @@ namespace syncd std::shared_ptr findCurrentBestMatchForNatEntry( _In_ const std::shared_ptr &temporaryObj); + std::shared_ptr findCurrentBestMatchForInsegEntry( + _In_ const std::shared_ptr &temporaryObj); + private: bool exchangeTemporaryVidToCurrentVid( diff --git a/syncd/ComparisonLogic.cpp b/syncd/ComparisonLogic.cpp index 33df6489d05b..af69bd596578 100644 --- a/syncd/ComparisonLogic.cpp +++ b/syncd/ComparisonLogic.cpp @@ -962,6 +962,10 @@ void ComparisonLogic::createNewObjectFromTemporaryObject( currentObj->m_str_object_id = sai_serialize_nat_entry(currentObj->m_meta_key.objectkey.key.nat_entry); break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + currentObj->m_str_object_id = sai_serialize_inseg_entry(currentObj->m_meta_key.objectkey.key.inseg_entry); + break; + default: SWSS_LOG_THROW("unexpected non object id type: %s", diff --git a/syncd/SingleReiniter.cpp b/syncd/SingleReiniter.cpp index b710ee740be2..f757ba515c1d 100644 --- a/syncd/SingleReiniter.cpp +++ b/syncd/SingleReiniter.cpp @@ -58,6 +58,7 @@ std::shared_ptr SingleReiniter::hardReinit() processOids(); processRoutes(true); processRoutes(false); + processInsegs(); processNatEntries(); #ifdef ENABLE_PERF @@ -485,6 +486,45 @@ void SingleReiniter::processRoutes( } } +void SingleReiniter::processInsegs() +{ + SWSS_LOG_ENTER(); + + for (auto &kv: m_insegs) + { + const std::string &strInsegEntry = kv.first; + const std::string &asicKey = kv.second; + + sai_object_meta_key_t meta_key; + + meta_key.objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY; + + sai_deserialize_inseg_entry(strInsegEntry, meta_key.objectkey.key.inseg_entry); + + processStructNonObjectIds(meta_key); + + std::shared_ptr list = m_attributesLists[asicKey]; + + sai_attribute_t *attrList = list->get_attr_list(); + + uint32_t attrCount = list->get_attr_count(); + + processAttributesForOids(SAI_OBJECT_TYPE_INSEG_ENTRY, attrCount, attrList); + + sai_status_t status = sai_metadata_sai_mpls_api-> + create_inseg_entry(&meta_key.objectkey.key.inseg_entry, attrCount, attrList); + + if (status != SAI_STATUS_SUCCESS) + { + listFailedAttributes(SAI_OBJECT_TYPE_INSEG_ENTRY, attrCount, attrList); + + SWSS_LOG_THROW("failed to create_inseg_entry %s: %s", + strInsegEntry.c_str(), + sai_serialize_status(status).c_str()); + } + } +} + void SingleReiniter::processNatEntries() { SWSS_LOG_ENTER(); diff --git a/syncd/SingleReiniter.h b/syncd/SingleReiniter.h index 177af364e835..3da2351e2009 100644 --- a/syncd/SingleReiniter.h +++ b/syncd/SingleReiniter.h @@ -66,6 +66,8 @@ namespace syncd void processNatEntries(); + void processInsegs(); + sai_object_id_t processSingleVid( _In_ sai_object_id_t vid); @@ -116,6 +118,7 @@ namespace syncd StringHash m_routes; StringHash m_neighbors; StringHash m_nats; + StringHash m_insegs; std::vector m_asicKeys; diff --git a/syncd/Syncd.cpp b/syncd/Syncd.cpp index 24b6b7cab9ca..59dafd65da3d 100644 --- a/syncd/Syncd.cpp +++ b/syncd/Syncd.cpp @@ -969,6 +969,27 @@ sai_status_t Syncd::processBulkCreateEntry( } break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_inseg_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_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; } @@ -1057,6 +1078,25 @@ sai_status_t Syncd::processBulkRemoveEntry( } break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_inseg_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + } + + status = m_vendorSai->bulkRemove( + object_count, + entries.data(), + mode, + statuses.data()); + + } + break; + default: return SAI_STATUS_NOT_SUPPORTED; } @@ -1156,6 +1196,26 @@ sai_status_t Syncd::processBulkSetEntry( } break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + { + std::vector entries(object_count); + for (uint32_t it = 0; it < object_count; it++) + { + sai_deserialize_inseg_entry(objectIds[it], entries[it]); + + entries[it].switch_id = m_translator->translateVidToRid(entries[it].switch_id); + } + + status = m_vendorSai->bulkSet( + object_count, + entries.data(), + attr_lists.data(), + mode, + statuses.data()); + + } + break; + default: return SAI_STATUS_NOT_SUPPORTED; } @@ -1231,6 +1291,10 @@ sai_status_t Syncd::processBulkEntry( sai_deserialize_fdb_entry(objectIds[idx], metaKey.objectkey.key.fdb_entry); break; + case SAI_OBJECT_TYPE_INSEG_ENTRY: + sai_deserialize_inseg_entry(objectIds[idx], metaKey.objectkey.key.inseg_entry); + break; + default: SWSS_LOG_THROW("object %s not implemented, FIXME", sai_serialize_object_type(objectType).c_str()); } diff --git a/syncd/VendorSai.cpp b/syncd/VendorSai.cpp index a50dbaa8f789..39a9f1865879 100644 --- a/syncd/VendorSai.cpp +++ b/syncd/VendorSai.cpp @@ -807,6 +807,33 @@ sai_status_t VendorSai::bulkCreate( object_statuses); } +sai_status_t VendorSai::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t* entries, + _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) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.mpls_api->create_inseg_entries) + { + SWSS_LOG_INFO("create_inseg_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.mpls_api->create_inseg_entries( + object_count, + entries, + attr_count, + attr_list, + mode, + object_statuses); +} + sai_status_t VendorSai::bulkCreate( _In_ uint32_t object_count, _In_ const sai_nat_entry_t* entries, @@ -883,6 +910,29 @@ sai_status_t VendorSai::bulkRemove( object_statuses);; } +sai_status_t VendorSai::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *entries, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.mpls_api->remove_inseg_entries) + { + SWSS_LOG_INFO("remove_inseg_entries is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.mpls_api->remove_inseg_entries( + object_count, + entries, + mode, + object_statuses);; +} + sai_status_t VendorSai::bulkRemove( _In_ uint32_t object_count, _In_ const sai_nat_entry_t *entries, @@ -958,6 +1008,31 @@ sai_status_t VendorSai::bulkSet( object_statuses);; } +sai_status_t VendorSai::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *entries, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + MUTEX(); + SWSS_LOG_ENTER(); + VENDOR_CHECK_API_INITIALIZED(); + + if (!m_apis.mpls_api->set_inseg_entries_attribute) + { + SWSS_LOG_INFO("set_inseg_entries_attribute is not supported"); + return SAI_STATUS_NOT_SUPPORTED; + } + + return m_apis.mpls_api->set_inseg_entries_attribute( + object_count, + entries, + attr_list, + mode, + object_statuses);; +} + sai_status_t VendorSai::bulkSet( _In_ uint32_t object_count, _In_ const sai_nat_entry_t *entries, diff --git a/syncd/VendorSai.h b/syncd/VendorSai.h index 0c91eaf83bcd..73459080b2e3 100644 --- a/syncd/VendorSai.h +++ b/syncd/VendorSai.h @@ -173,18 +173,21 @@ namespace syncd public: // bulk create ENTRY SYNCD_VENDORSAI_DECLARE_BULK_CREATE_ENTRY(fdb_entry); + SYNCD_VENDORSAI_DECLARE_BULK_CREATE_ENTRY(inseg_entry); SYNCD_VENDORSAI_DECLARE_BULK_CREATE_ENTRY(nat_entry); SYNCD_VENDORSAI_DECLARE_BULK_CREATE_ENTRY(route_entry); public: // bulk remove ENTRY SYNCD_VENDORSAI_DECLARE_BULK_REMOVE_ENTRY(fdb_entry); + SYNCD_VENDORSAI_DECLARE_BULK_REMOVE_ENTRY(inseg_entry); SYNCD_VENDORSAI_DECLARE_BULK_REMOVE_ENTRY(nat_entry); SYNCD_VENDORSAI_DECLARE_BULK_REMOVE_ENTRY(route_entry); public: // bulk set ENTRY SYNCD_VENDORSAI_DECLARE_BULK_SET_ENTRY(fdb_entry); + SYNCD_VENDORSAI_DECLARE_BULK_SET_ENTRY(inseg_entry); SYNCD_VENDORSAI_DECLARE_BULK_SET_ENTRY(nat_entry); SYNCD_VENDORSAI_DECLARE_BULK_SET_ENTRY(route_entry); diff --git a/tests/BCM56850/test_macsec_p2p_establishment.rec b/tests/BCM56850/test_macsec_p2p_establishment.rec index c397896ef2b3..8eb2ba400294 100644 --- a/tests/BCM56850/test_macsec_p2p_establishment.rec +++ b/tests/BCM56850/test_macsec_p2p_establishment.rec @@ -69,8 +69,8 @@ 2021-02-04.14:32:44.652603|c|SAI_OBJECT_TYPE_MACSEC_FLOW:oid:0x5a000000000633|SAI_MACSEC_FLOW_ATTR_MACSEC_DIRECTION=SAI_MACSEC_DIRECTION_INGRESS 2021-02-04.14:32:44.656090|c|SAI_OBJECT_TYPE_MACSEC_SC:oid:0x5b000000000634|SAI_MACSEC_SC_ATTR_MACSEC_DIRECTION=SAI_MACSEC_DIRECTION_INGRESS|SAI_MACSEC_SC_ATTR_FLOW_ID=oid:0x5a000000000633|SAI_MACSEC_SC_ATTR_MACSEC_SCI=72294895074694398|SAI_MACSEC_SC_ATTR_ENCRYPTION_ENABLE=true|SAI_MACSEC_SC_ATTR_MACSEC_EXPLICIT_SCI_ENABLE=false|SAI_MACSEC_SC_ATTR_MACSEC_CIPHER_SUITE=SAI_MACSEC_CIPHER_SUITE_GCM_AES_128 2021-02-04.14:32:44.658292|c|SAI_OBJECT_TYPE_ACL_ENTRY:oid:0x8000000000635|SAI_ACL_ENTRY_ATTR_TABLE_ID=oid:0x700000000062e|SAI_ACL_ENTRY_ATTR_PRIORITY=2|SAI_ACL_ENTRY_ATTR_ADMIN_STATE=true|SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION=SAI_PACKET_ACTION_DROP -2021-02-04.14:32:46.658586|c|SAI_OBJECT_TYPE_MACSEC_SA:oid:0x5c000000000636|SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION=SAI_MACSEC_DIRECTION_EGRESS|SAI_MACSEC_SA_ATTR_SC_ID=oid:0x5b000000000631|SAI_MACSEC_SA_ATTR_AN=0|SAI_MACSEC_SA_ATTR_SAK=00000000000000000000000000000000BCF9AD8CE37694552ECF8AB895169604|SAI_MACSEC_SA_ATTR_SALT=000000000000000000000000|SAI_MACSEC_SA_ATTR_MACSEC_SSCI=0|SAI_MACSEC_SA_ATTR_AUTH_KEY=E6BCBC29D9BB2A4E9297A11976D1FFBA|SAI_MACSEC_SA_ATTR_XPN=1 -2021-02-04.14:32:46.663929|c|SAI_OBJECT_TYPE_MACSEC_SA:oid:0x5c000000000637|SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION=SAI_MACSEC_DIRECTION_INGRESS|SAI_MACSEC_SA_ATTR_SC_ID=oid:0x5b000000000634|SAI_MACSEC_SA_ATTR_AN=0|SAI_MACSEC_SA_ATTR_SAK=00000000000000000000000000000000BCF9AD8CE37694552ECF8AB895169604|SAI_MACSEC_SA_ATTR_SALT=000000000000000000000000|SAI_MACSEC_SA_ATTR_MACSEC_SSCI=0|SAI_MACSEC_SA_ATTR_AUTH_KEY=E6BCBC29D9BB2A4E9297A11976D1FFBA|SAI_MACSEC_SA_ATTR_MINIMUM_XPN=1 +2021-02-04.14:32:46.658586|c|SAI_OBJECT_TYPE_MACSEC_SA:oid:0x5c000000000636|SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION=SAI_MACSEC_DIRECTION_EGRESS|SAI_MACSEC_SA_ATTR_SC_ID=oid:0x5b000000000631|SAI_MACSEC_SA_ATTR_AN=0|SAI_MACSEC_SA_ATTR_SAK=00000000000000000000000000000000BCF9AD8CE37694552ECF8AB895169604|SAI_MACSEC_SA_ATTR_SALT=000000000000000000000000|SAI_MACSEC_SA_ATTR_MACSEC_SSCI=0|SAI_MACSEC_SA_ATTR_AUTH_KEY=E6BCBC29D9BB2A4E9297A11976D1FFBA|SAI_MACSEC_SA_ATTR_CONFIGURED_EGRESS_XPN=1 +2021-02-04.14:32:46.663929|c|SAI_OBJECT_TYPE_MACSEC_SA:oid:0x5c000000000637|SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION=SAI_MACSEC_DIRECTION_INGRESS|SAI_MACSEC_SA_ATTR_SC_ID=oid:0x5b000000000634|SAI_MACSEC_SA_ATTR_AN=0|SAI_MACSEC_SA_ATTR_SAK=00000000000000000000000000000000BCF9AD8CE37694552ECF8AB895169604|SAI_MACSEC_SA_ATTR_SALT=000000000000000000000000|SAI_MACSEC_SA_ATTR_MACSEC_SSCI=0|SAI_MACSEC_SA_ATTR_AUTH_KEY=E6BCBC29D9BB2A4E9297A11976D1FFBA|SAI_MACSEC_SA_ATTR_MINIMUM_INGRESS_XPN=1 2021-02-04.14:32:46.666605|s|SAI_OBJECT_TYPE_ACL_ENTRY:oid:0x8000000000632|SAI_ACL_ENTRY_ATTR_ACTION_MACSEC_FLOW=oid:0x5a000000000630 2021-02-04.14:32:46.751694|s|SAI_OBJECT_TYPE_ACL_ENTRY:oid:0x8000000000632|SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION=disabled 2021-02-04.14:32:46.752433|s|SAI_OBJECT_TYPE_ACL_ENTRY:oid:0x8000000000635|SAI_ACL_ENTRY_ATTR_ACTION_MACSEC_FLOW=oid:0x5a000000000633 diff --git a/tests/aspell.en.pws b/tests/aspell.en.pws index 8ba60363ae45..0810854f5e14 100644 --- a/tests/aspell.en.pws +++ b/tests/aspell.en.pws @@ -121,6 +121,9 @@ init INIT inout INSEG +Inseg +insegs +inseg ip IP ipc diff --git a/vslib/inc/Sai.h b/vslib/inc/Sai.h index 599380fb6a97..515a6e4a2f5a 100644 --- a/vslib/inc/Sai.h +++ b/vslib/inc/Sai.h @@ -180,18 +180,21 @@ namespace saivs public: // bulk create ENTRY SAIVS_SAI_DECLARE_BULK_CREATE_ENTRY(fdb_entry); + SAIVS_SAI_DECLARE_BULK_CREATE_ENTRY(inseg_entry); SAIVS_SAI_DECLARE_BULK_CREATE_ENTRY(nat_entry); SAIVS_SAI_DECLARE_BULK_CREATE_ENTRY(route_entry); public: // bulk remove ENTRY SAIVS_SAI_DECLARE_BULK_REMOVE_ENTRY(fdb_entry); + SAIVS_SAI_DECLARE_BULK_REMOVE_ENTRY(inseg_entry); SAIVS_SAI_DECLARE_BULK_REMOVE_ENTRY(nat_entry); SAIVS_SAI_DECLARE_BULK_REMOVE_ENTRY(route_entry); public: // bulk set ENTRY SAIVS_SAI_DECLARE_BULK_SET_ENTRY(fdb_entry); + SAIVS_SAI_DECLARE_BULK_SET_ENTRY(inseg_entry); SAIVS_SAI_DECLARE_BULK_SET_ENTRY(nat_entry); SAIVS_SAI_DECLARE_BULK_SET_ENTRY(route_entry); diff --git a/vslib/inc/VirtualSwitchSaiInterface.h b/vslib/inc/VirtualSwitchSaiInterface.h index 6a7ced16897e..508159042d22 100644 --- a/vslib/inc/VirtualSwitchSaiInterface.h +++ b/vslib/inc/VirtualSwitchSaiInterface.h @@ -180,18 +180,21 @@ namespace saivs public: // bulk create ENTRY SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(fdb_entry); + SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(inseg_entry); SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(nat_entry); SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_CREATE_ENTRY(route_entry); public: // bulk remove ENTRY SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(fdb_entry); + SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(inseg_entry); SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(nat_entry); SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_REMOVE_ENTRY(route_entry); public: // bulk set ENTRY SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_SET_ENTRY(fdb_entry); + SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_SET_ENTRY(inseg_entry); SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_SET_ENTRY(nat_entry); SAIVS_VIRTUALSWITCHSAIINTERFACE_DECLARE_BULK_SET_ENTRY(route_entry); diff --git a/vslib/src/Sai.cpp b/vslib/src/Sai.cpp index 654014f67172..a674f502b3f1 100644 --- a/vslib/src/Sai.cpp +++ b/vslib/src/Sai.cpp @@ -643,6 +643,7 @@ sai_status_t Sai::bulkCreate( \ DECLARE_BULK_CREATE_ENTRY(ROUTE_ENTRY,route_entry) DECLARE_BULK_CREATE_ENTRY(FDB_ENTRY,fdb_entry); +DECLARE_BULK_CREATE_ENTRY(INSEG_ENTRY,inseg_entry); DECLARE_BULK_CREATE_ENTRY(NAT_ENTRY,nat_entry) @@ -667,6 +668,7 @@ sai_status_t Sai::bulkRemove( \ DECLARE_BULK_REMOVE_ENTRY(ROUTE_ENTRY,route_entry) DECLARE_BULK_REMOVE_ENTRY(FDB_ENTRY,fdb_entry); +DECLARE_BULK_REMOVE_ENTRY(INSEG_ENTRY,inseg_entry); DECLARE_BULK_REMOVE_ENTRY(NAT_ENTRY,nat_entry) // BULK SET @@ -692,6 +694,7 @@ sai_status_t Sai::bulkSet( \ DECLARE_BULK_SET_ENTRY(ROUTE_ENTRY,route_entry); DECLARE_BULK_SET_ENTRY(FDB_ENTRY,fdb_entry); +DECLARE_BULK_SET_ENTRY(INSEG_ENTRY,inseg_entry); DECLARE_BULK_SET_ENTRY(NAT_ENTRY,nat_entry); // NON QUAD API diff --git a/vslib/src/SwitchStateBaseMACsec.cpp b/vslib/src/SwitchStateBaseMACsec.cpp index ae5b8895e888..bf091e17eb25 100644 --- a/vslib/src/SwitchStateBaseMACsec.cpp +++ b/vslib/src/SwitchStateBaseMACsec.cpp @@ -564,11 +564,11 @@ sai_status_t SwitchStateBase::loadMACsecAttrFromMACsecSA( if (macsecAttr.m_direction == SAI_MACSEC_DIRECTION_EGRESS) { - SAI_METADATA_GET_ATTR_BY_ID(attr, SAI_MACSEC_SA_ATTR_XPN, attrCount, attrList); + SAI_METADATA_GET_ATTR_BY_ID(attr, SAI_MACSEC_SA_ATTR_CONFIGURED_EGRESS_XPN, attrCount, attrList); } else { - SAI_METADATA_GET_ATTR_BY_ID(attr, SAI_MACSEC_SA_ATTR_MINIMUM_XPN, attrCount, attrList); + SAI_METADATA_GET_ATTR_BY_ID(attr, SAI_MACSEC_SA_ATTR_MINIMUM_INGRESS_XPN, attrCount, attrList); } macsecAttr.m_pn = attr->value.u64; diff --git a/vslib/src/VirtualSwitchSaiInterface.cpp b/vslib/src/VirtualSwitchSaiInterface.cpp index abebb27c6762..8b70171c8237 100644 --- a/vslib/src/VirtualSwitchSaiInterface.cpp +++ b/vslib/src/VirtualSwitchSaiInterface.cpp @@ -1046,6 +1046,24 @@ sai_status_t VirtualSwitchSaiInterface::bulkRemove( return bulkRemove(nat_entry->switch_id, SAI_OBJECT_TYPE_NAT_ENTRY, serializedObjectIds, mode, object_statuses); } +sai_status_t VirtualSwitchSaiInterface::bulkRemove( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + std::vector serializedObjectIds; + + for (uint32_t idx = 0; idx < object_count; idx++) + { + serializedObjectIds.emplace_back(sai_serialize_inseg_entry(inseg_entry[idx])); + } + + return bulkRemove(inseg_entry->switch_id, SAI_OBJECT_TYPE_INSEG_ENTRY, serializedObjectIds, mode, object_statuses); +} + sai_status_t VirtualSwitchSaiInterface::bulkRemove( _In_ uint32_t object_count, _In_ const sai_fdb_entry_t *fdb_entry, @@ -1124,6 +1142,25 @@ sai_status_t VirtualSwitchSaiInterface::bulkSet( return bulkSet(nat_entry->switch_id, SAI_OBJECT_TYPE_NAT_ENTRY, serializedObjectIds, attr_list, mode, object_statuses); } +sai_status_t VirtualSwitchSaiInterface::bulkSet( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses) +{ + SWSS_LOG_ENTER(); + + std::vector serializedObjectIds; + + for (uint32_t idx = 0; idx < object_count; idx++) + { + serializedObjectIds.emplace_back(sai_serialize_inseg_entry(inseg_entry[idx])); + } + + return bulkSet(inseg_entry->switch_id, SAI_OBJECT_TYPE_INSEG_ENTRY, serializedObjectIds, attr_list, mode, object_statuses); +} + sai_status_t VirtualSwitchSaiInterface::bulkSet( _In_ uint32_t object_count, _In_ const sai_fdb_entry_t *fdb_entry, @@ -1263,6 +1300,35 @@ sai_status_t VirtualSwitchSaiInterface::bulkCreate( object_statuses); } +sai_status_t VirtualSwitchSaiInterface::bulkCreate( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t* inseg_entry, + _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(); + + std::vector serialized_object_ids; + + // on create vid is put in db by syncd + for (uint32_t idx = 0; idx < object_count; idx++) + { + std::string str_object_id = sai_serialize_inseg_entry(inseg_entry[idx]); + serialized_object_ids.push_back(str_object_id); + } + + return bulkCreate( + inseg_entry->switch_id, + SAI_OBJECT_TYPE_INSEG_ENTRY, + serialized_object_ids, + attr_count, + attr_list, + mode, + object_statuses); +} + sai_status_t VirtualSwitchSaiInterface::bulkCreate( _In_ uint32_t object_count, _In_ const sai_nat_entry_t* nat_entry, diff --git a/vslib/src/sai_vs_mpls.cpp b/vslib/src/sai_vs_mpls.cpp index efa294b59630..2058c4e48245 100644 --- a/vslib/src/sai_vs_mpls.cpp +++ b/vslib/src/sai_vs_mpls.cpp @@ -1,8 +1,10 @@ #include "sai_vs.h" VS_GENERIC_QUAD_ENTRY(INSEG_ENTRY,inseg_entry); +VS_BULK_QUAD_ENTRY(INSEG_ENTRY,inseg_entry); const sai_mpls_api_t vs_mpls_api = { VS_GENERIC_QUAD_API(inseg_entry) + VS_BULK_QUAD_API(inseg_entry) }; diff --git a/vslib/src/sai_vs_switch.cpp b/vslib/src/sai_vs_switch.cpp index 67cdecb0bbbb..ff2809750ceb 100644 --- a/vslib/src/sai_vs_switch.cpp +++ b/vslib/src/sai_vs_switch.cpp @@ -2,6 +2,7 @@ VS_GENERIC_QUAD(SWITCH,switch); VS_GENERIC_STATS(SWITCH,switch); +VS_GENERIC_QUAD(SWITCH_TUNNEL,switch_tunnel); static sai_status_t vs_create_switch_uniq( _Out_ sai_object_id_t *switch_id, @@ -51,5 +52,8 @@ const sai_switch_api_t vs_switch_api = { VS_GENERIC_STATS_API(switch) vs_mdio_read, - vs_mdio_write + vs_mdio_write, + + VS_GENERIC_QUAD_API(switch_tunnel) + };