diff --git a/.azure-pipelines/build-swss-template.yml b/.azure-pipelines/build-swss-template.yml index 9a0098c43..6c1c3173d 100644 --- a/.azure-pipelines/build-swss-template.yml +++ b/.azure-pipelines/build-swss-template.yml @@ -50,10 +50,6 @@ jobs: sudo apt-get install -y libzmq5 libzmq3-dev sudo apt-get install -qq -y \ libhiredis-dev \ - libnl-3-dev \ - libnl-genl-3-dev \ - libnl-route-3-dev \ - libnl-nf-3-dev \ swig3.0 sudo apt-get install -y libdbus-1-3 sudo apt-get install -y libteam-dev \ @@ -73,7 +69,24 @@ jobs: inputs: artifact: ${{ parameters.sairedis_artifact_name }} displayName: "Download sonic sairedis deb packages" + - task: DownloadPipelineArtifact@2 + inputs: + source: specific + project: build + pipeline: 1 + artifact: sonic-buildimage.vs + runVersion: 'latestFromBranch' + runBranch: 'refs/heads/master' + displayName: "Download sonic buildimage" - script: | + sudo dpkg -i target/debs/buster/libnl-3-200_*.deb + sudo dpkg -i target/debs/buster/libnl-3-dev_*.deb + sudo dpkg -i target/debs/buster/libnl-genl-3-200_*.deb + sudo dpkg -i target/debs/buster/libnl-genl-3-dev_*.deb + sudo dpkg -i target/debs/buster/libnl-route-3-200_*.deb + sudo dpkg -i target/debs/buster/libnl-route-3-dev_*.deb + sudo dpkg -i target/debs/buster/libnl-nf-3-200_*.deb + sudo dpkg -i target/debs/buster/libnl-nf-3-dev_*.deb sudo dpkg -i libswsscommon_1.0.0_${{ parameters.arch }}.deb sudo dpkg -i libswsscommon-dev_1.0.0_${{ parameters.arch }}.deb sudo dpkg -i libsaivs_*.deb @@ -84,7 +97,7 @@ jobs: sudo dpkg -i libsaimetadata-dev_*.deb sudo dpkg -i syncd-vs_*.deb workingDirectory: $(Pipeline.Workspace) - displayName: "Install sonic swss common and sairedis" + displayName: "Install libnl3, sonic swss common, and sairedis" - checkout: sonic-swss path: s submodules: true diff --git a/.azure-pipelines/build-template.yml b/.azure-pipelines/build-template.yml index 2432d375e..8fc68c31c 100644 --- a/.azure-pipelines/build-template.yml +++ b/.azure-pipelines/build-template.yml @@ -33,6 +33,10 @@ parameters: type: boolean default: false +- name: archive_gcov + type: boolean + default: false + jobs: - job: displayName: ${{ parameters.arch }} @@ -97,20 +101,48 @@ jobs: - checkout: self submodules: true - script: | + set -ex ./autogen.sh - fakeroot dpkg-buildpackage -b -us -uc -Tbinary-syncd-vs -j$(nproc) && cp ../*.deb . - displayName: "Compile sonic sairedis" + fakeroot debian/rules DEB_CONFIGURE_EXTRA_FLAGS='--enable-code-coverage' CFLAGS="" CXXFLAGS="" binary-syncd-vs && cp ../*.deb . + displayName: "Compile sonic sairedis with coverage enabled" - script: | sudo cp azsyslog.conf /etc/rsyslog.conf sudo service rsyslog restart displayName: "Update rsyslog.conf" - ${{ if eq(parameters.run_unit_test, true) }}: - script: | + set -ex + git clone https://github.com/Spacetown/gcovr.git + cd gcovr/ + git checkout origin/recursive_search_file + sudo pip3 install setuptools + sudo python3 setup.py install + cd .. + sudo rm -rf gcovr + displayName: "Install gcovr 5.0 with recursive fix" + - script: | + set -ex make check + gcovr --version + gcovr -r ./ -e ".*/SAI/.*" -e ".+/json.hpp" -e "swss/.+" -e ".*/.libs/.*" -e ".*/debian/.*" --exclude-unreachable-branches --exclude-throw-branches -x -o coverage.xml displayName: "Run sonic sairedis unit tests" - publish: $(System.DefaultWorkingDirectory)/ artifact: ${{ parameters.artifact_name }} displayName: "Archive sonic sairedis debian packages" + - ${{ if eq(parameters.archive_gcov, true) }}: + - script: | + set -ex + # Install .NET CORE + curl -sSL https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add - + sudo apt-add-repository https://packages.microsoft.com/debian/10/prod + sudo apt-get update + sudo apt-get install -y dotnet-sdk-5.0 + displayName: "Install .NET CORE" + - task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: Cobertura + summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage.xml' + displayName: 'Publish test coverage' - script: | pwd sudo chmod a+r /var/log/syslog* diff --git a/.gitignore b/.gitignore index 02d2723f9..b55d71be9 100644 --- a/.gitignore +++ b/.gitignore @@ -88,8 +88,8 @@ deps/ # Executables # ############### lib/tests -vslib/tests meta/tests +saiasiccmp/saiasiccmp saidiscovery/saidiscovery saidump/saidump saiplayer/saiplayer @@ -97,10 +97,16 @@ saisdkdump/saisdkdump syncd/syncd syncd/syncd_request_shutdown tests/syncd -tests/vssyncd -saiasiccmp/saiasiccmp -tests/tests tests/testclient +tests/tests +tests/vssyncd +unittest/lib/tests +unittest/lib/testslibsairedis +unittest/meta/tests +unittest/syncd/tests +unittest/vslib/tests +unittest/vslib/testslibsaivs +vslib/tests # Temporary files # ################### diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a786b0997..49f85d5a5 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -27,6 +27,7 @@ stages: artifact_name: sonic-sairedis syslog_artifact_name: sonic-sairedis.syslog run_unit_test: true + archive_gcov: true - stage: BuildArm dependsOn: Build @@ -35,7 +36,7 @@ stages: - template: .azure-pipelines/build-template.yml parameters: arch: armhf - timeout: 180 + timeout: 240 pool: sonicbld sonic_slave: sonic-slave-buster-armhf swss_common_artifact_name: sonic-swss-common.armhf @@ -45,7 +46,7 @@ stages: - template: .azure-pipelines/build-template.yml parameters: arch: arm64 - timeout: 180 + timeout: 240 pool: sonicbld sonic_slave: sonic-slave-buster-arm64 swss_common_artifact_name: sonic-swss-common.arm64 diff --git a/debian/rules b/debian/rules index 674ba1f05..f83631959 100755 --- a/debian/rules +++ b/debian/rules @@ -69,7 +69,7 @@ binary-syncd-vs: override_dh_auto_configure: ./autogen.sh - dh_auto_configure -- $(shell cat /tmp/syncd-build) ${SWSS_COMMON_CONFIG} + dh_auto_configure -- $(DEB_CONFIGURE_EXTRA_FLAGS) $(shell cat /tmp/syncd-build) ${SWSS_COMMON_CONFIG} override_dh_install: dh_install diff --git a/lib/Switch.cpp b/lib/Switch.cpp index f16d6934d..0f909f13e 100644 --- a/lib/Switch.cpp +++ b/lib/Switch.cpp @@ -108,6 +108,11 @@ void Switch::updateNotifications( (sai_queue_pfc_deadlock_notification_fn)attr.value.ptr; break; + case SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY: + m_switchNotifications.on_bfd_session_state_change = + (sai_bfd_session_state_change_notification_fn)attr.value.ptr; + break; + default: SWSS_LOG_ERROR("pointer for %s is not handled, FIXME!", meta->attridname); break; diff --git a/lib/sairediscommon.h b/lib/sairediscommon.h index d0de3dd26..7f3eeda96 100644 --- a/lib/sairediscommon.h +++ b/lib/sairediscommon.h @@ -8,9 +8,14 @@ #define SYNCD_INIT_VIEW "INIT_VIEW" #define SYNCD_APPLY_VIEW "APPLY_VIEW" #define SYNCD_INSPECT_ASIC "SYNCD_INSPECT_ASIC" + #define ASIC_STATE_TABLE "ASIC_STATE" #define TEMP_PREFIX "TEMP_" +#define REDIS_COMMUNICATION_MODE_REDIS_ASYNC_STRING "redis_async" +#define REDIS_COMMUNICATION_MODE_REDIS_SYNC_STRING "redis_sync" +#define REDIS_COMMUNICATION_MODE_ZMQ_SYNC_STRING "zmq_sync" + /* * Asic state table commands. Those names are special and they will be used * inside swsscommon library LUA scripts to perform operations on redis diff --git a/meta/Makefile.am b/meta/Makefile.am index 58039c758..89cf12562 100644 --- a/meta/Makefile.am +++ b/meta/Makefile.am @@ -33,15 +33,17 @@ libsaimeta_la_SOURCES = \ NotificationQueuePfcDeadlock.cpp \ NotificationSwitchShutdownRequest.cpp \ NotificationSwitchStateChange.cpp \ + NotificationBfdSessionStateChange.cpp \ + NumberOidIndexGenerator.cpp \ OidRefCounter.cpp \ PerformanceIntervalTimer.cpp \ PortRelatedSet.cpp \ RedisSelectableChannel.cpp \ - SaiAttributeList.cpp \ SaiAttrWrapper.cpp \ + SaiAttributeList.cpp \ SaiInterface.cpp \ - SaiObjectCollection.cpp \ SaiObject.cpp \ + SaiObjectCollection.cpp \ SaiSerialize.cpp \ SelectableChannel.cpp \ ZeroMQSelectableChannel.cpp @@ -49,19 +51,3 @@ libsaimeta_la_SOURCES = \ libsaimeta_la_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS) libsaimeta_la_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) $(CODE_COVERAGE_CXXFLAGS) libsaimeta_la_LIBADD = -lhiredis -lswsscommon libsaimetadata.la $(CODE_COVERAGE_LIBS) - -bin_PROGRAMS = tests - -tests_SOURCES = \ - tests.cpp \ - DummySaiInterface.cpp \ - MetaTestSaiInterface.cpp \ - NumberOidIndexGenerator.cpp \ - ../lib/VirtualObjectIdManager.cpp \ - ../lib/SwitchConfig.cpp \ - ../lib/SwitchConfigContainer.cpp - -tests_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) -tests_LDADD = -lhiredis -lswsscommon -lpthread libsaimetadata.la libsaimeta.la -lzmq - -TESTS = tests diff --git a/meta/Meta.cpp b/meta/Meta.cpp index 6b391e55b..1cc05f7a5 100644 --- a/meta/Meta.cpp +++ b/meta/Meta.cpp @@ -33,6 +33,11 @@ } \ } +#define META_LOG_STATUS(status,msg) \ + if ((status) == SAI_STATUS_SUCCESS) \ + { SWSS_LOG_DEBUG(msg " status: %s", sai_serialize_status(status).c_str()); } \ + else { SWSS_LOG_ERROR(msg " status: %s", sai_serialize_status(status).c_str()); } + using namespace saimeta; Meta::Meta( @@ -101,7 +106,7 @@ void Meta::meta_init_db() SWSS_LOG_NOTICE("end"); } -bool Meta::isEmpty() +bool Meta::isEmpty() const { SWSS_LOG_ENTER(); @@ -111,6 +116,31 @@ bool Meta::isEmpty() && m_saiObjectCollection.getAllKeys().empty(); } +void Meta::dump() const +{ + SWSS_LOG_ENTER(); + + if (isEmpty() == false) + { + std::cout << "portRelatedSet: " << m_portRelatedSet.getAllPorts().size() << std::endl; + std::cout << "oids: " << m_oids.getAllOids().size() << std::endl; + std::cout << "attrKeys: " << m_attrKeys.getAllKeys().size() << std::endl; + std::cout << "saiObjectCollection: " << m_saiObjectCollection.getAllKeys().size() << std::endl; + + for (auto &oid: m_oids.getAllReferences()) + { + printf("oid: %s: count: %u\n", + sai_serialize_object_id(oid.first).c_str(), + oid.second); + } + + for (auto &mk: m_saiObjectCollection.getAllKeys()) + { + printf("objcollection: %s\n", sai_serialize_object_meta_key(mk).c_str()); + } + } +} + sai_status_t Meta::remove( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id) @@ -135,14 +165,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(object_type, object_id); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -175,14 +198,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(fdb_entry); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -215,14 +231,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(mcast_fdb_entry); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -255,14 +264,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(neighbor_entry); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -295,14 +297,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(route_entry); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -335,14 +330,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(l2mc_entry); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -375,14 +363,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(ipmc_entry); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -415,14 +396,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(nat_entry); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -455,14 +429,7 @@ sai_status_t Meta::remove( status = m_implementation->remove(inseg_entry); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("remove status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("remove status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "remove"); if (status == SAI_STATUS_SUCCESS) { @@ -537,14 +504,7 @@ sai_status_t Meta::create( status = m_implementation->create(fdb_entry, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -579,14 +539,7 @@ sai_status_t Meta::create( status = m_implementation->create(mcast_fdb_entry, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -621,14 +574,7 @@ sai_status_t Meta::create( status = m_implementation->create(neighbor_entry, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -662,14 +608,7 @@ sai_status_t Meta::create( status = m_implementation->create(route_entry, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -704,14 +643,7 @@ sai_status_t Meta::create( status = m_implementation->create(l2mc_entry, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -746,14 +678,7 @@ sai_status_t Meta::create( status = m_implementation->create(ipmc_entry, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -788,14 +713,7 @@ sai_status_t Meta::create( status = m_implementation->create(inseg_entry, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -830,14 +748,7 @@ sai_status_t Meta::create( status = m_implementation->create(nat_entry, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -913,14 +824,7 @@ sai_status_t Meta::set( status = m_implementation->set(fdb_entry, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -954,14 +858,7 @@ sai_status_t Meta::set( status = m_implementation->set(mcast_fdb_entry, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -995,14 +892,7 @@ sai_status_t Meta::set( status = m_implementation->set(neighbor_entry, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -1036,14 +926,7 @@ sai_status_t Meta::set( status = m_implementation->set(route_entry, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -1077,14 +960,7 @@ sai_status_t Meta::set( status = m_implementation->set(l2mc_entry, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -1118,14 +994,7 @@ sai_status_t Meta::set( status = m_implementation->set(ipmc_entry, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -1159,14 +1028,7 @@ sai_status_t Meta::set( status = m_implementation->set(inseg_entry, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -1199,14 +1061,7 @@ sai_status_t Meta::set( status = m_implementation->set(nat_entry, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -1584,14 +1439,7 @@ sai_status_t Meta::create( status = m_implementation->create(object_type, object_id, switch_id, attr_count, attr_list); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("create status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("create status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "create"); if (status == SAI_STATUS_SUCCESS) { @@ -1639,14 +1487,7 @@ sai_status_t Meta::set( status = m_implementation->set(object_type, object_id, attr); - if (status == SAI_STATUS_SUCCESS) - { - SWSS_LOG_DEBUG("set status: %s", sai_serialize_status(status).c_str()); - } - else - { - SWSS_LOG_ERROR("set status: %s", sai_serialize_status(status).c_str()); - } + META_LOG_STATUS(status, "set"); if (status == SAI_STATUS_SUCCESS) { @@ -1791,17 +1632,6 @@ sai_status_t Meta::flushFdbEntries( switch (md.attrvaluetype) { - case SAI_ATTR_VALUE_TYPE_UINT16: - - if (md.isvlan && (value.u16 >= 0xFFF || value.u16 == 0)) - { - META_LOG_ERROR(md, "is vlan id but has invalid id %u", value.u16); - - return SAI_STATUS_INVALID_PARAMETER; - } - - break; - case SAI_ATTR_VALUE_TYPE_INT32: if (md.isenum && !sai_metadata_is_allowed_enum_value(&md, value.s32)) @@ -1865,10 +1695,9 @@ sai_status_t Meta::flushFdbEntries( } else { - // no type specified so we need to flush static and dynamic entries + // no type specified so we need to flush dynamic only types.push_back(SAI_FDB_ENTRY_TYPE_DYNAMIC); - types.push_back(SAI_FDB_ENTRY_TYPE_STATIC); } for (auto type: types) @@ -4849,7 +4678,9 @@ sai_status_t Meta::meta_generic_validation_create( if (mdp == NULL) { - SWSS_LOG_ERROR("unable to find attribute metadata %d:%d", meta_key.objecttype, attr->id); + SWSS_LOG_ERROR("unable to find attribute metadata %s:%d", + sai_serialize_object_type(meta_key.objecttype).c_str(), + attr->id); return SAI_STATUS_FAILURE; } @@ -5501,7 +5332,9 @@ sai_status_t Meta::meta_generic_validation_set( if (mdp == NULL) { - SWSS_LOG_ERROR("unable to find attribute metadata %d:%d", meta_key.objecttype, attr->id); + SWSS_LOG_ERROR("unable to find attribute metadata %s:%d", + sai_serialize_object_type(meta_key.objecttype).c_str(), + attr->id); return SAI_STATUS_FAILURE; } @@ -6000,7 +5833,9 @@ sai_status_t Meta::meta_generic_validation_get( if (mdp == NULL) { - SWSS_LOG_ERROR("unable to find attribute metadata %d:%d", meta_key.objecttype, attr->id); + SWSS_LOG_ERROR("unable to find attribute metadata %s:%d", + sai_serialize_object_type(meta_key.objecttype).c_str(), + attr->id); return SAI_STATUS_FAILURE; } @@ -7994,6 +7829,14 @@ void Meta::meta_sai_on_switch_state_change( { SWSS_LOG_ENTER(); + if (!sai_metadata_get_enum_value_name( + &sai_metadata_enum_sai_switch_oper_status_t, + switch_oper_status)) + { + SWSS_LOG_WARN("switch oper status value (%d) not found in sai_switch_oper_status_t", + switch_oper_status); + } + auto ot = objectTypeQuery(switch_id); if (ot != SAI_OBJECT_TYPE_SWITCH) @@ -8001,6 +7844,8 @@ void Meta::meta_sai_on_switch_state_change( SWSS_LOG_WARN("switch_id %s is of type %s, but expected SAI_OBJECT_TYPE_SWITCH", sai_serialize_object_id(switch_id).c_str(), sai_serialize_object_type(ot).c_str()); + + return; } sai_object_meta_key_t switch_meta_key = { .objecttype = ot , .objectkey = { .key = { .object_id = switch_id } } }; @@ -8012,14 +7857,6 @@ void Meta::meta_sai_on_switch_state_change( } // we should not snoop switch_id, since switch id should be created directly by user - - if (!sai_metadata_get_enum_value_name( - &sai_metadata_enum_sai_switch_oper_status_t, - switch_oper_status)) - { - SWSS_LOG_WARN("switch oper status value (%d) not found in sai_switch_oper_status_t", - switch_oper_status); - } } void Meta::meta_sai_on_switch_shutdown_request( @@ -8034,6 +7871,8 @@ void Meta::meta_sai_on_switch_shutdown_request( SWSS_LOG_WARN("switch_id %s is of type %s, but expected SAI_OBJECT_TYPE_SWITCH", sai_serialize_object_id(switch_id).c_str(), sai_serialize_object_type(ot).c_str()); + + return; } sai_object_meta_key_t switch_meta_key = { .objecttype = ot , .objectkey = { .key = { .object_id = switch_id } } }; @@ -8177,6 +8016,65 @@ void Meta::meta_sai_on_queue_pfc_deadlock_notification( } } +void Meta::meta_sai_on_bfd_session_state_change_single( + _In_ const sai_bfd_session_state_notification_t& data) +{ + SWSS_LOG_ENTER(); + + auto ot = objectTypeQuery(data.bfd_session_id); + + bool valid = false; + + switch (ot) + { + // TODO hardcoded types, must advance SAI repository commit to get metadata for this + case SAI_OBJECT_TYPE_BFD_SESSION: + + valid = true; + break; + + default: + + SWSS_LOG_ERROR("data.bfd_session_id %s has unexpected type: %s, expected BFD_SESSION", + sai_serialize_object_id(data.bfd_session_id).c_str(), + sai_serialize_object_type(ot).c_str()); + break; + } + + if (valid && !m_oids.objectReferenceExists(data.bfd_session_id)) + { + SWSS_LOG_NOTICE("data.bfd_session_id new object spotted %s not present in local DB (snoop!)", + sai_serialize_object_id(data.bfd_session_id).c_str()); + + sai_object_meta_key_t key = { .objecttype = ot, .objectkey = { .key = { .object_id = data.bfd_session_id } } }; + + m_oids.objectReferenceInsert(data.bfd_session_id); + + if (!m_saiObjectCollection.objectExists(key)) + { + m_saiObjectCollection.createObject(key); + } + } +} + +void Meta::meta_sai_on_bfd_session_state_change( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data) +{ + SWSS_LOG_ENTER(); + + if (count && data == NULL) + { + SWSS_LOG_ERROR("sai_bfd_session_state_notification_t pointer is NULL but count is %u", count); + return; + } + + for (uint32_t i = 0; i < count; ++i) + { + meta_sai_on_bfd_session_state_change_single(data[i]); + } +} + int32_t Meta::getObjectReferenceCount( _In_ sai_object_id_t oid) const { diff --git a/meta/Meta.h b/meta/Meta.h index 79dc2ec49..29745b8bf 100644 --- a/meta/Meta.h +++ b/meta/Meta.h @@ -161,7 +161,9 @@ namespace saimeta void meta_init_db(); - bool isEmpty(); + bool isEmpty() const; + + void dump() const; public: // notifications @@ -184,6 +186,10 @@ namespace saimeta _In_ uint32_t count, _In_ const sai_queue_deadlock_notification_data_t *data); + void meta_sai_on_bfd_session_state_change( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data); + private: // notifications helpers void meta_sai_on_fdb_flush_event_consolidated( @@ -201,6 +207,9 @@ namespace saimeta void meta_sai_on_queue_pfc_deadlock_notification_single( _In_ const sai_queue_deadlock_notification_data_t& data); + void meta_sai_on_bfd_session_state_change_single( + _In_ const sai_bfd_session_state_notification_t& data); + private: // validation helpers sai_status_t meta_generic_validation_objlist( diff --git a/meta/MetaKeyHasher.cpp b/meta/MetaKeyHasher.cpp index a9d67dc06..cdeb68c7d 100644 --- a/meta/MetaKeyHasher.cpp +++ b/meta/MetaKeyHasher.cpp @@ -18,6 +18,17 @@ static bool operator==( memcmp(a.mac_address, b.mac_address, sizeof(a.mac_address)) == 0; } +static bool operator==( + _In_ const sai_mcast_fdb_entry_t& a, + _In_ const sai_mcast_fdb_entry_t& b) +{ + SWSS_LOG_ENTER(); + + return a.switch_id == b.switch_id && + a.bv_id == b.bv_id && + memcmp(a.mac_address, b.mac_address, sizeof(a.mac_address)) == 0; +} + static bool operator==( _In_ const sai_route_entry_t& a, _In_ const sai_route_entry_t& b) @@ -42,6 +53,88 @@ static bool operator==( memcmp(a.destination.mask.ip6, b.destination.mask.ip6, sizeof(b.destination.mask.ip6)) == 0; } + SWSS_LOG_THROW("unknown route entry IP addr family: %d", a.destination.addr_family); +} + +static bool operator==( + _In_ const sai_l2mc_entry_t& a, + _In_ const sai_l2mc_entry_t& b) +{ + // SWSS_LOG_ENTER(); // disabled for performance reasons + + bool part = a.switch_id == b.switch_id && + a.bv_id == b.bv_id && + a.type == b.type && + a.destination.addr_family == b.destination.addr_family && + a.source.addr_family == b.source.addr_family; + + if (a.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV4) + { + part &= a.destination.addr.ip4 == b.destination.addr.ip4; + } + else if (a.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV6) + { + part &= memcmp(a.destination.addr.ip6, b.destination.addr.ip6, sizeof(b.destination.addr.ip6)) == 0; + } + else + { + SWSS_LOG_THROW("unknown l2mc entry destination IP addr family: %d", a.destination.addr_family); + } + + if (a.source.addr_family == SAI_IP_ADDR_FAMILY_IPV4) + { + part &= a.source.addr.ip4 == b.source.addr.ip4; + } + else if (a.source.addr_family == SAI_IP_ADDR_FAMILY_IPV6) + { + part &= memcmp(a.source.addr.ip6, b.source.addr.ip6, sizeof(b.source.addr.ip6)) == 0; + } + else + { + SWSS_LOG_THROW("unknown l2mc entry source IP addr family: %d", a.source.addr_family); + } + + return part; +} + +static bool operator==( + _In_ const sai_ipmc_entry_t& a, + _In_ const sai_ipmc_entry_t& b) +{ + // SWSS_LOG_ENTER(); // disabled for performance reasons + + bool part = a.switch_id == b.switch_id && + a.vr_id == b.vr_id && + a.type == b.type && + a.destination.addr_family == b.destination.addr_family && + a.source.addr_family == b.source.addr_family; + + if (a.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV4) + { + part &= a.destination.addr.ip4 == b.destination.addr.ip4; + } + else if (a.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV6) + { + part &= memcmp(a.destination.addr.ip6, b.destination.addr.ip6, sizeof(b.destination.addr.ip6)) == 0; + } + else + { + SWSS_LOG_THROW("unknown l2mc entry destination IP addr family: %d", a.destination.addr_family); + } + + if (a.source.addr_family == SAI_IP_ADDR_FAMILY_IPV4) + { + part &= a.source.addr.ip4 == b.source.addr.ip4; + } + else if (a.source.addr_family == SAI_IP_ADDR_FAMILY_IPV6) + { + part &= memcmp(a.source.addr.ip6, b.source.addr.ip6, sizeof(b.source.addr.ip6)) == 0; + } + else + { + SWSS_LOG_THROW("unknown l2mc entry source IP addr family: %d", a.source.addr_family); + } + return part; } @@ -61,7 +154,7 @@ static bool operator==( if (a.ip_address.addr_family == SAI_IP_ADDR_FAMILY_IPV6) return part && memcmp(a.ip_address.addr.ip6, b.ip_address.addr.ip6, sizeof(b.ip_address.addr.ip6)) == 0; - return part; + SWSS_LOG_THROW("unknown neighbor entry IP addr family= %d", a.ip_address.addr_family); } static bool operator==( @@ -146,6 +239,16 @@ bool MetaKeyHasher::operator()( if (a.objecttype == SAI_OBJECT_TYPE_MY_SID_ENTRY) return a.objectkey.key.my_sid_entry == b.objectkey.key.my_sid_entry; + if (a.objecttype == SAI_OBJECT_TYPE_MCAST_FDB_ENTRY) + return a.objectkey.key.mcast_fdb_entry == b.objectkey.key.mcast_fdb_entry; + + if (a.objecttype == SAI_OBJECT_TYPE_L2MC_ENTRY) + return a.objectkey.key.l2mc_entry == b.objectkey.key.l2mc_entry; + + if (a.objecttype == SAI_OBJECT_TYPE_IPMC_ENTRY) + return a.objectkey.key.ipmc_entry == b.objectkey.key.ipmc_entry; + + SWSS_LOG_THROW("not implemented: %s", sai_serialize_object_meta_key(a).c_str()); } @@ -171,7 +274,7 @@ static inline std::size_t sai_get_hash( return ip6[0] ^ ip6[1] ^ ip6[2] ^ ip6[3]; } - return re.destination.addr_family; + SWSS_LOG_THROW("unknown route entry IP addr family: %d", re.destination.addr_family); } static inline std::size_t sai_get_hash( @@ -193,7 +296,7 @@ static inline std::size_t sai_get_hash( return ip6[0] ^ ip6[1] ^ ip6[2] ^ ip6[3]; } - return ne.ip_address.addr_family; + SWSS_LOG_THROW("unknown neighbor entry IP addr family= %d", ne.ip_address.addr_family); } static_assert(sizeof(uint32_t) == 4, "uint32_t expected to be 4 bytes"); @@ -241,6 +344,64 @@ static inline std::size_t sai_get_hash( return ip6[0] ^ ip6[1] ^ ip6[2] ^ ip6[3]; } +static inline std::size_t sai_get_hash( + _In_ const sai_mcast_fdb_entry_t& mfe) +{ + // SWSS_LOG_ENTER(); // disabled for performance reasons + + uint32_t data; + + // use low 4 bytes of mac address as hash value + // use memcpy instead of cast because of strict-aliasing rules + memcpy(&data, mfe.mac_address + 2, sizeof(uint32_t)); + + return data; +} + +static inline std::size_t sai_get_hash( + _In_ const sai_l2mc_entry_t& le) +{ + // SWSS_LOG_ENTER(); // disabled for performance reasons + + if (le.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV4) + { + return le.destination.addr.ip4; + } + + if (le.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV6) + { + // cast is not good enough for arm (cast align) + uint32_t ip6[4]; + memcpy(ip6, le.destination.addr.ip6, sizeof(ip6)); + + return ip6[0] ^ ip6[1] ^ ip6[2] ^ ip6[3]; + } + + SWSS_LOG_THROW("unknown l2mc entry IP addr family: %d", le.destination.addr_family); +} + +static inline std::size_t sai_get_hash( + _In_ const sai_ipmc_entry_t& ie) +{ + // SWSS_LOG_ENTER(); // disabled for performance reasons + + if (ie.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV4) + { + return ie.destination.addr.ip4; + } + + if (ie.destination.addr_family == SAI_IP_ADDR_FAMILY_IPV6) + { + // cast is not good enough for arm (cast align) + uint32_t ip6[4]; + memcpy(ip6, ie.destination.addr.ip6, sizeof(ip6)); + + return ip6[0] ^ ip6[1] ^ ip6[2] ^ ip6[3]; + } + + SWSS_LOG_THROW("unknown ipmc entry IP addr family: %d", ie.destination.addr_family); +} + std::size_t MetaKeyHasher::operator()( _In_ const sai_object_meta_key_t& k) const { @@ -274,6 +435,15 @@ std::size_t MetaKeyHasher::operator()( case SAI_OBJECT_TYPE_MY_SID_ENTRY: return sai_get_hash(k.objectkey.key.my_sid_entry); + case SAI_OBJECT_TYPE_MCAST_FDB_ENTRY: + return sai_get_hash(k.objectkey.key.mcast_fdb_entry); + + case SAI_OBJECT_TYPE_L2MC_ENTRY: + return sai_get_hash(k.objectkey.key.l2mc_entry); + + case SAI_OBJECT_TYPE_IPMC_ENTRY: + return sai_get_hash(k.objectkey.key.ipmc_entry); + default: SWSS_LOG_THROW("not handled: %s", sai_serialize_object_type(k.objecttype).c_str()); } diff --git a/meta/NotificationBfdSessionStateChange.cpp b/meta/NotificationBfdSessionStateChange.cpp new file mode 100644 index 000000000..d332c3a9f --- /dev/null +++ b/meta/NotificationBfdSessionStateChange.cpp @@ -0,0 +1,77 @@ +#include "NotificationBfdSessionStateChange.h" + +#include "swss/logger.h" + +#include "meta/sai_serialize.h" + +using namespace sairedis; + +NotificationBfdSessionStateChange::NotificationBfdSessionStateChange( + _In_ const std::string& serializedNotification): + Notification( + SAI_SWITCH_NOTIFICATION_TYPE_BFD_SESSION_STATE_CHANGE, + serializedNotification), + m_bfdSessionStateNotificationData(nullptr) +{ + SWSS_LOG_ENTER(); + + sai_deserialize_bfd_session_state_ntf( + serializedNotification, + m_count, + &m_bfdSessionStateNotificationData); +} + +NotificationBfdSessionStateChange::~NotificationBfdSessionStateChange() +{ + SWSS_LOG_ENTER(); + + sai_deserialize_free_bfd_session_state_ntf(m_count, m_bfdSessionStateNotificationData); +} + +sai_object_id_t NotificationBfdSessionStateChange::getSwitchId() const +{ + SWSS_LOG_ENTER(); + + // this notification don't contain switch id field + + return SAI_NULL_OBJECT_ID; +} + +sai_object_id_t NotificationBfdSessionStateChange::getAnyObjectId() const +{ + SWSS_LOG_ENTER(); + + if (m_bfdSessionStateNotificationData == nullptr) + { + return SAI_NULL_OBJECT_ID; + } + + for (uint32_t idx = 0; idx < m_count; idx++) + { + if (m_bfdSessionStateNotificationData[idx].bfd_session_id != SAI_NULL_OBJECT_ID) + { + return m_bfdSessionStateNotificationData[idx].bfd_session_id; + } + } + + return SAI_NULL_OBJECT_ID; +} + +void NotificationBfdSessionStateChange::processMetadata( + _In_ std::shared_ptr meta) const +{ + SWSS_LOG_ENTER(); + + meta->meta_sai_on_bfd_session_state_change(m_count, m_bfdSessionStateNotificationData); +} + +void NotificationBfdSessionStateChange::executeCallback( + _In_ const sai_switch_notifications_t& switchNotifications) const +{ + SWSS_LOG_ENTER(); + + if (switchNotifications.on_bfd_session_state_change) + { + switchNotifications.on_bfd_session_state_change(m_count, m_bfdSessionStateNotificationData); + } +} diff --git a/meta/NotificationBfdSessionStateChange.h b/meta/NotificationBfdSessionStateChange.h new file mode 100644 index 000000000..9ebd0551e --- /dev/null +++ b/meta/NotificationBfdSessionStateChange.h @@ -0,0 +1,35 @@ +#pragma once + +#include "Notification.h" + +namespace sairedis +{ + class NotificationBfdSessionStateChange: + public Notification + { + public: + + NotificationBfdSessionStateChange( + _In_ const std::string& serializedNotification); + + virtual ~NotificationBfdSessionStateChange(); + + public: + + virtual sai_object_id_t getSwitchId() const override; + + virtual sai_object_id_t getAnyObjectId() const override; + + virtual void processMetadata( + _In_ std::shared_ptr meta) const override; + + virtual void executeCallback( + _In_ const sai_switch_notifications_t& switchNotifications) const override; + + private: + + uint32_t m_count; + + sai_bfd_session_state_notification_t *m_bfdSessionStateNotificationData; + }; +} diff --git a/meta/NotificationFactory.cpp b/meta/NotificationFactory.cpp index 4ed49300e..c9adf4863 100644 --- a/meta/NotificationFactory.cpp +++ b/meta/NotificationFactory.cpp @@ -4,6 +4,7 @@ #include "NotificationQueuePfcDeadlock.h" #include "NotificationSwitchShutdownRequest.h" #include "NotificationSwitchStateChange.h" +#include "NotificationBfdSessionStateChange.h" #include "sairediscommon.h" #include "swss/logger.h" @@ -31,7 +32,8 @@ std::shared_ptr NotificationFactory::deserialize( if (name == SAI_SWITCH_NOTIFICATION_NAME_SWITCH_STATE_CHANGE) return std::make_shared(serializedNotification); - SWSS_LOG_ERROR("unknown notification: '%s', FIXME", name.c_str()); + if (name == SAI_SWITCH_NOTIFICATION_NAME_BFD_SESSION_STATE_CHANGE) + return std::make_shared(serializedNotification); - return nullptr; + SWSS_LOG_THROW("unknown notification: '%s', FIXME", name.c_str()); } diff --git a/meta/SaiAttributeList.cpp b/meta/SaiAttributeList.cpp index c89ce30e8..7338d5906 100644 --- a/meta/SaiAttributeList.cpp +++ b/meta/SaiAttributeList.cpp @@ -28,6 +28,7 @@ SaiAttributeList::SaiAttributeList( sai_deserialize_attr_id(str_attr_id, attr.id); + // TODO object type is not necessary, we can use get attr metadata from attr id name auto meta = sai_metadata_get_attr_metadata(objectType, attr.id); if (meta == NULL) @@ -64,6 +65,7 @@ SaiAttributeList::SaiAttributeList( sai_deserialize_attr_id(str_attr_id, attr.id); + // TODO object type is not necessary, we can use get attr metadata from attr id name auto meta = sai_metadata_get_attr_metadata(objectType, attr.id); if (meta == NULL) diff --git a/meta/SaiObject.cpp b/meta/SaiObject.cpp index 14ea98dde..99a986fde 100644 --- a/meta/SaiObject.cpp +++ b/meta/SaiObject.cpp @@ -11,8 +11,11 @@ SaiObject::SaiObject( m_metaKey(metaKey) { SWSS_LOG_ENTER(); - - // empty + + if (!sai_metadata_is_object_type_valid(metaKey.objecttype)) + { + SWSS_LOG_THROW("invalid object type: %d", metaKey.objecttype); + } } sai_object_type_t SaiObject::getObjectType() const diff --git a/meta/SaiSerialize.cpp b/meta/SaiSerialize.cpp index fe9068b24..e3c1651bc 100644 --- a/meta/SaiSerialize.cpp +++ b/meta/SaiSerialize.cpp @@ -1,4 +1,6 @@ #include "sai_serialize.h" +#include "sairediscommon.h" + #include "swss/tokenize.h" #pragma GCC diagnostic push @@ -155,9 +157,9 @@ sai_status_t transfer_attribute( transfer_primitive(src_attr.value.u16, dst_attr.value.u16); break; - case SAI_ATTR_VALUE_TYPE_INT16: - transfer_primitive(src_attr.value.s16, dst_attr.value.s16); - break; +// case SAI_ATTR_VALUE_TYPE_INT16: +// transfer_primitive(src_attr.value.s16, dst_attr.value.s16); +// break; case SAI_ATTR_VALUE_TYPE_UINT32: transfer_primitive(src_attr.value.u32, dst_attr.value.u32); @@ -171,9 +173,9 @@ sai_status_t transfer_attribute( transfer_primitive(src_attr.value.u64, dst_attr.value.u64); break; - case SAI_ATTR_VALUE_TYPE_INT64: - transfer_primitive(src_attr.value.s64, dst_attr.value.s64); - break; +// case SAI_ATTR_VALUE_TYPE_INT64: +// transfer_primitive(src_attr.value.s64, dst_attr.value.s64); +// break; case SAI_ATTR_VALUE_TYPE_MAC: transfer_primitive(src_attr.value.mac, dst_attr.value.mac); @@ -215,13 +217,13 @@ sai_status_t transfer_attribute( RETURN_ON_ERROR(transfer_list(src_attr.value.s8list, dst_attr.value.s8list, countOnly)); break; - case SAI_ATTR_VALUE_TYPE_UINT16_LIST: - RETURN_ON_ERROR(transfer_list(src_attr.value.u16list, dst_attr.value.u16list, countOnly)); - break; - - case SAI_ATTR_VALUE_TYPE_INT16_LIST: - RETURN_ON_ERROR(transfer_list(src_attr.value.s16list, dst_attr.value.s16list, countOnly)); - break; +// case SAI_ATTR_VALUE_TYPE_UINT16_LIST: +// RETURN_ON_ERROR(transfer_list(src_attr.value.u16list, dst_attr.value.u16list, countOnly)); +// break; +// +// case SAI_ATTR_VALUE_TYPE_INT16_LIST: +// RETURN_ON_ERROR(transfer_list(src_attr.value.s16list, dst_attr.value.s16list, countOnly)); +// break; case SAI_ATTR_VALUE_TYPE_UINT32_LIST: RETURN_ON_ERROR(transfer_list(src_attr.value.u32list, dst_attr.value.u32list, countOnly)); @@ -235,8 +237,12 @@ sai_status_t transfer_attribute( transfer_primitive(src_attr.value.u32range, dst_attr.value.u32range); break; - case SAI_ATTR_VALUE_TYPE_INT32_RANGE: - transfer_primitive(src_attr.value.s32range, dst_attr.value.s32range); +// case SAI_ATTR_VALUE_TYPE_INT32_RANGE: +// transfer_primitive(src_attr.value.s32range, dst_attr.value.s32range); +// break; + + case SAI_ATTR_VALUE_TYPE_TIMESPEC: + transfer_primitive(src_attr.value.timespec, dst_attr.value.timespec); break; case SAI_ATTR_VALUE_TYPE_VLAN_LIST: @@ -272,11 +278,11 @@ sai_status_t transfer_attribute( transfer_primitive(src_attr.value.aclfield.data.u8, dst_attr.value.aclfield.data.u8); break; - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT8: - transfer_primitive(src_attr.value.aclfield.enable, dst_attr.value.aclfield.enable); - transfer_primitive(src_attr.value.aclfield.mask.s8, dst_attr.value.aclfield.mask.s8); - transfer_primitive(src_attr.value.aclfield.data.s8, dst_attr.value.aclfield.data.s8); - break; +// case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT8: +// transfer_primitive(src_attr.value.aclfield.enable, dst_attr.value.aclfield.enable); +// transfer_primitive(src_attr.value.aclfield.mask.s8, dst_attr.value.aclfield.mask.s8); +// transfer_primitive(src_attr.value.aclfield.data.s8, dst_attr.value.aclfield.data.s8); +// break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT16: transfer_primitive(src_attr.value.aclfield.enable, dst_attr.value.aclfield.enable); @@ -284,11 +290,11 @@ sai_status_t transfer_attribute( transfer_primitive(src_attr.value.aclfield.data.u16, dst_attr.value.aclfield.data.u16); break; - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT16: - transfer_primitive(src_attr.value.aclfield.enable, dst_attr.value.aclfield.enable); - transfer_primitive(src_attr.value.aclfield.mask.s16, dst_attr.value.aclfield.mask.s16); - transfer_primitive(src_attr.value.aclfield.data.s16, dst_attr.value.aclfield.data.s16); - break; +// case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT16: +// transfer_primitive(src_attr.value.aclfield.enable, dst_attr.value.aclfield.enable); +// transfer_primitive(src_attr.value.aclfield.mask.s16, dst_attr.value.aclfield.mask.s16); +// transfer_primitive(src_attr.value.aclfield.data.s16, dst_attr.value.aclfield.data.s16); +// break; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT32: transfer_primitive(src_attr.value.aclfield.enable, dst_attr.value.aclfield.enable); @@ -354,21 +360,20 @@ sai_status_t transfer_attribute( transfer_primitive(src_attr.value.aclaction.parameter.u8, dst_attr.value.aclaction.parameter.u8); break; - case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT8: - transfer_primitive(src_attr.value.aclaction.enable, dst_attr.value.aclaction.enable); - transfer_primitive(src_attr.value.aclaction.parameter.s8, dst_attr.value.aclaction.parameter.s8); - break; +// case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT8: +// transfer_primitive(src_attr.value.aclaction.enable, dst_attr.value.aclaction.enable); +// transfer_primitive(src_attr.value.aclaction.parameter.s8, dst_attr.value.aclaction.parameter.s8); +// break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT16: transfer_primitive(src_attr.value.aclaction.enable, dst_attr.value.aclaction.enable); transfer_primitive(src_attr.value.aclaction.parameter.u16, dst_attr.value.aclaction.parameter.u16); break; - case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT16: - transfer_primitive(src_attr.value.aclaction.enable, dst_attr.value.aclaction.enable); - transfer_primitive(src_attr.value.aclaction.parameter.s16, dst_attr.value.aclaction.parameter.s16); - break; - +// case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT16: +// transfer_primitive(src_attr.value.aclaction.enable, dst_attr.value.aclaction.enable); +// transfer_primitive(src_attr.value.aclaction.parameter.s16, dst_attr.value.aclaction.parameter.s16); +// break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT32: transfer_primitive(src_attr.value.aclaction.enable, dst_attr.value.aclaction.enable); @@ -395,6 +400,11 @@ sai_status_t transfer_attribute( transfer_primitive(src_attr.value.aclaction.parameter.ip6, dst_attr.value.aclaction.parameter.ip6); break; + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IP_ADDRESS: + transfer_primitive(src_attr.value.aclaction.enable, dst_attr.value.aclaction.enable); + transfer_primitive(src_attr.value.aclaction.parameter.ipaddr, dst_attr.value.aclaction.parameter.ipaddr); + break; + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: transfer_primitive(src_attr.value.aclaction.enable, dst_attr.value.aclaction.enable); transfer_primitive(src_attr.value.aclaction.parameter.oid, dst_attr.value.aclaction.parameter.oid); @@ -414,12 +424,52 @@ sai_status_t transfer_attribute( transfer_primitive(src_attr.value.sysportconfig, dst_attr.value.sysportconfig); break; + case SAI_ATTR_VALUE_TYPE_MACSEC_AUTH_KEY: + transfer_primitive(src_attr.value.macsecauthkey, dst_attr.value.macsecauthkey); + break; + + case SAI_ATTR_VALUE_TYPE_MACSEC_SALT: + transfer_primitive(src_attr.value.macsecsalt, dst_attr.value.macsecsalt); + break; + + case SAI_ATTR_VALUE_TYPE_MACSEC_SAK: + transfer_primitive(src_attr.value.macsecsak, dst_attr.value.macsecsak); + break; + + case SAI_ATTR_VALUE_TYPE_PORT_ERR_STATUS_LIST: + RETURN_ON_ERROR(transfer_list(src_attr.value.porterror, dst_attr.value.porterror, countOnly)); + break; + + case SAI_ATTR_VALUE_TYPE_PORT_EYE_VALUES_LIST: + RETURN_ON_ERROR(transfer_list(src_attr.value.porteyevalues, dst_attr.value.porteyevalues, countOnly)); + break; + + case SAI_ATTR_VALUE_TYPE_FABRIC_PORT_REACHABILITY: + transfer_primitive(src_attr.value.reachability, dst_attr.value.reachability); + break; + + case SAI_ATTR_VALUE_TYPE_PRBS_RX_STATE: + transfer_primitive(src_attr.value.rx_state, dst_attr.value.rx_state); + break; + + case SAI_ATTR_VALUE_TYPE_SEGMENT_LIST: + RETURN_ON_ERROR(transfer_list(src_attr.value.segmentlist, dst_attr.value.segmentlist, countOnly)); + break; + + case SAI_ATTR_VALUE_TYPE_MAP_LIST: + RETURN_ON_ERROR(transfer_list(src_attr.value.maplist, dst_attr.value.maplist, countOnly)); + break; + + case SAI_ATTR_VALUE_TYPE_TLV_LIST: + RETURN_ON_ERROR(transfer_list(src_attr.value.tlvlist, dst_attr.value.tlvlist, countOnly)); + break; + case SAI_ATTR_VALUE_TYPE_SYSTEM_PORT_CONFIG_LIST: RETURN_ON_ERROR(transfer_list(src_attr.value.sysportconfiglist, dst_attr.value.sysportconfiglist, countOnly)); break; default: - return SAI_STATUS_NOT_IMPLEMENTED; + SWSS_LOG_THROW("sai attr value %s is not implemented, FIXME", sai_serialize_attr_value_type(serialization_type).c_str()); } return SAI_STATUS_SUCCESS; @@ -1316,14 +1366,14 @@ std::string sai_serialize_acl_action( case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT8: return sai_serialize_number(action.parameter.u8); - case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT8: - return sai_serialize_number(action.parameter.s8); +// case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT8: +// return sai_serialize_number(action.parameter.s8); case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT16: return sai_serialize_number(action.parameter.u16); - case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT16: - return sai_serialize_number(action.parameter.s16); +// case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT16: +// return sai_serialize_number(action.parameter.s16); case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT32: return sai_serialize_number(action.parameter.u32); @@ -1340,6 +1390,9 @@ std::string sai_serialize_acl_action( case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IPV6: return sai_serialize_ipv6(action.parameter.ip6); + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IP_ADDRESS: + return sai_serialize_ip_address(action.parameter.ipaddr); + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: return sai_serialize_object_id(action.parameter.oid); @@ -1347,7 +1400,7 @@ std::string sai_serialize_acl_action( return sai_serialize_oid_list(action.parameter.objlist, countOnly); default: - SWSS_LOG_THROW("FATAIL: invalid serialization type %d", meta.attrvaluetype); + SWSS_LOG_THROW("sai attr value %s is not implemented, FIXME", sai_serialize_attr_value_type(meta.attrvaluetype).c_str()); } } @@ -1372,14 +1425,14 @@ std::string sai_serialize_acl_field( case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT8: return sai_serialize_number(field.data.u8) + "&mask:" + sai_serialize_number(field.mask.u8, true); - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT8: - return sai_serialize_number(field.data.s8) + "&mask:" + sai_serialize_number(field.mask.s8, true); +// case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT8: +// return sai_serialize_number(field.data.s8) + "&mask:" + sai_serialize_number(field.mask.s8, true); case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT16: return sai_serialize_number(field.data.u16) + "&mask:" + sai_serialize_number(field.mask.u16, true); - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT16: - return sai_serialize_number(field.data.s16) + "&mask:" + sai_serialize_number(field.mask.s16, true); +// case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT16: +// return sai_serialize_number(field.data.s16) + "&mask:" + sai_serialize_number(field.mask.s16, true); case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT32: return sai_serialize_number(field.data.u32) + "&mask:" + sai_serialize_number(field.mask.u32, true); @@ -1409,7 +1462,7 @@ std::string sai_serialize_acl_field( return sai_serialize_number_list(field.data.u8list, countOnly) + "&mask:" + sai_serialize_number_list(field.mask.u8list, countOnly, true); default: - SWSS_LOG_THROW("FATAIL: invalid serialization type %d", meta.attrvaluetype); + SWSS_LOG_THROW("sai attr value %s is not implemented, FIXME", sai_serialize_attr_value_type(meta.attrvaluetype).c_str()); } } @@ -1577,8 +1630,8 @@ std::string sai_serialize_attr_value( case SAI_ATTR_VALUE_TYPE_UINT16: return sai_serialize_number(attr.value.u16); - case SAI_ATTR_VALUE_TYPE_INT16: - return sai_serialize_number(attr.value.s16); +// case SAI_ATTR_VALUE_TYPE_INT16: +// return sai_serialize_number(attr.value.s16); case SAI_ATTR_VALUE_TYPE_UINT32: return sai_serialize_number(attr.value.u32); @@ -1589,8 +1642,8 @@ std::string sai_serialize_attr_value( case SAI_ATTR_VALUE_TYPE_UINT64: return sai_serialize_number(attr.value.u64); - case SAI_ATTR_VALUE_TYPE_INT64: - return sai_serialize_number(attr.value.s64); +// case SAI_ATTR_VALUE_TYPE_INT64: +// return sai_serialize_number(attr.value.s64); case SAI_ATTR_VALUE_TYPE_MAC: return sai_serialize_mac(attr.value.mac); @@ -1622,11 +1675,11 @@ std::string sai_serialize_attr_value( case SAI_ATTR_VALUE_TYPE_INT8_LIST: return sai_serialize_number_list(attr.value.s8list, countOnly); - case SAI_ATTR_VALUE_TYPE_UINT16_LIST: - return sai_serialize_number_list(attr.value.u16list, countOnly); - - case SAI_ATTR_VALUE_TYPE_INT16_LIST: - return sai_serialize_number_list(attr.value.s16list, countOnly); +// case SAI_ATTR_VALUE_TYPE_UINT16_LIST: +// return sai_serialize_number_list(attr.value.u16list, countOnly); +// +// case SAI_ATTR_VALUE_TYPE_INT16_LIST: +// return sai_serialize_number_list(attr.value.s16list, countOnly); case SAI_ATTR_VALUE_TYPE_UINT32_LIST: return sai_serialize_number_list(attr.value.u32list, countOnly); @@ -1637,8 +1690,8 @@ std::string sai_serialize_attr_value( case SAI_ATTR_VALUE_TYPE_UINT32_RANGE: return sai_serialize_range(attr.value.u32range); - case SAI_ATTR_VALUE_TYPE_INT32_RANGE: - return sai_serialize_range(attr.value.s32range); +// case SAI_ATTR_VALUE_TYPE_INT32_RANGE: +// return sai_serialize_range(attr.value.s32range); case SAI_ATTR_VALUE_TYPE_VLAN_LIST: return sai_serialize_number_list(attr.value.vlanlist, countOnly); @@ -1687,6 +1740,7 @@ std::string sai_serialize_attr_value( case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IPV6: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IP_ADDRESS: return sai_serialize_acl_action(meta, attr.value.aclaction, countOnly); case SAI_ATTR_VALUE_TYPE_ACL_CAPABILITY: @@ -1710,7 +1764,7 @@ std::string sai_serialize_attr_value( return sai_serialize_system_port_config_list(meta, attr.value.sysportconfiglist, countOnly); default: - SWSS_LOG_THROW("FATAL: invalid serialization type %d", meta.attrvaluetype); + SWSS_LOG_THROW("sai attr value type %s is not implemented, FIXME", sai_serialize_attr_value_type(meta.attrvaluetype).c_str()); } } @@ -1796,6 +1850,14 @@ static json sai_serialize_json_fdb_event_notification_data( return j; } +std::string sai_serialize_bfd_session_state( + _In_ sai_bfd_session_state_t status) +{ + SWSS_LOG_ENTER(); + + return sai_serialize_enum(status, &sai_metadata_enum_sai_bfd_session_state_t); +} + std::string sai_serialize_fdb_event_ntf( _In_ uint32_t count, _In_ const sai_fdb_event_notification_data_t* fdb_event) @@ -1874,6 +1936,33 @@ std::string sai_serialize_queue_deadlock_ntf( return j.dump(); } +std::string sai_serialize_bfd_session_state_ntf( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t* bfd_session_state) +{ + SWSS_LOG_ENTER(); + + if (bfd_session_state == NULL) + { + SWSS_LOG_THROW("bfd_session_state pointer is null"); + } + + json j = json::array(); + + for (uint32_t i = 0; i < count; ++i) + { + json item; + + item["bfd_session_id"] = sai_serialize_object_id(bfd_session_state[i].bfd_session_id); + item["session_state"] = sai_serialize_bfd_session_state(bfd_session_state[i].session_state); + + j.push_back(item); + } + + // we don't need count since it can be deduced + return j.dump(); +} + json sai_serialize_nat_entry_key( _In_ const sai_nat_entry_key_t& nat_entry_key) { @@ -1967,7 +2056,7 @@ std::string sai_serialize_object_meta_key( std::string key; - if (meta_key.objecttype == SAI_OBJECT_TYPE_NULL || meta_key.objecttype >= SAI_OBJECT_TYPE_EXTENSIONS_MAX) + if (!sai_metadata_is_object_type_valid(meta_key.objecttype)) { SWSS_LOG_THROW("invalid object type value %s", sai_serialize_object_type(meta_key.objecttype).c_str()); } @@ -1995,11 +2084,23 @@ std::string sai_serialize_object_meta_key( case SAI_OBJECT_TYPE_INSEG_ENTRY: key = sai_serialize_inseg_entry(meta_key.objectkey.key.inseg_entry); break; - + case SAI_OBJECT_TYPE_MY_SID_ENTRY: key = sai_serialize_my_sid_entry(meta_key.objectkey.key.my_sid_entry); break; + case SAI_OBJECT_TYPE_L2MC_ENTRY: + key = sai_serialize_l2mc_entry(meta_key.objectkey.key.l2mc_entry); + break; + + case SAI_OBJECT_TYPE_IPMC_ENTRY: + key = sai_serialize_ipmc_entry(meta_key.objectkey.key.ipmc_entry); + break; + + case SAI_OBJECT_TYPE_MCAST_FDB_ENTRY: + key = sai_serialize_mcast_fdb_entry(meta_key.objectkey.key.mcast_fdb_entry); + break; + default: if (meta->isnonobjectid) @@ -2019,10 +2120,6 @@ std::string sai_serialize_object_meta_key( return key; } -#define SYNCD_INIT_VIEW "INIT_VIEW" -#define SYNCD_APPLY_VIEW "APPLY_VIEW" -#define SYNCD_INSPECT_ASIC "SYNCD_INSPECT_ASIC" - std::string sai_serialize( _In_ const sai_redis_notify_syncd_t& value) { @@ -2041,16 +2138,10 @@ std::string sai_serialize( default: - SWSS_LOG_WARN("unknown value on sai_redis_notify_syncd_t: %d", value); - - return std::to_string(value); + SWSS_LOG_THROW("unknown value on sai_redis_notify_syncd_t: %d", value); } } -#define REDIS_COMMUNICATION_MODE_REDIS_ASYNC_STRING "redis_async" -#define REDIS_COMMUNICATION_MODE_REDIS_SYNC_STRING "redis_sync" -#define REDIS_COMMUNICATION_MODE_ZMQ_SYNC_STRING "zmq_sync" - std::string sai_serialize_redis_communication_mode( _In_ sai_redis_communication_mode_t value) { @@ -2069,9 +2160,7 @@ std::string sai_serialize_redis_communication_mode( default: - SWSS_LOG_WARN("unknown value on sai_redis_communication_mode_t: %d", value); - - return std::to_string(value); + SWSS_LOG_THROW("unknown value on sai_redis_communication_mode_t: %d", value); } } @@ -2500,8 +2589,7 @@ void sai_deserialize_acl_resource_list( if (arr.size() != (size_t)aclresource.count) { - SWSS_LOG_ERROR("acl resource count mismatch %lu vs %u", arr.size(), aclresource.count); - throw std::runtime_error("acl resource count mismatch"); + SWSS_LOG_THROW("acl resource count mismatch %lu vs %u", arr.size(), aclresource.count); } aclresource.list = sai_alloc_n_of_ptr_type(aclresource.count, aclresource.list); @@ -2720,20 +2808,20 @@ void sai_deserialize_acl_field( sai_deserialize_number(smask, field.mask.u8, true); return; - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT8: - sai_deserialize_number(sfield, field.data.s8); - sai_deserialize_number(smask, field.mask.s8, true); - return; +// case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT8: +// sai_deserialize_number(sfield, field.data.s8); +// sai_deserialize_number(smask, field.mask.s8, true); +// return; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT16: sai_deserialize_number(sfield, field.data.u16); sai_deserialize_number(smask, field.mask.u16, true); return; - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT16: - sai_deserialize_number(sfield, field.data.s16); - sai_deserialize_number(smask, field.mask.s16, true); - return; +// case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_INT16: +// sai_deserialize_number(sfield, field.data.s16); +// sai_deserialize_number(smask, field.mask.s16, true); +// return; case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT32: sai_deserialize_number(sfield, field.data.u32); @@ -2770,12 +2858,14 @@ void sai_deserialize_acl_field( case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: return sai_deserialize_oid_list(sfield, field.data.objlist, countOnly); - /* - case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT8_LIST: - return sai_deserialize_number_list(field.data.u8list, countOnly) + "&mask:" + sai_deserialize_uint8_hex_list(field.mask.u8list, countOnly); - */ + + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_UINT8_LIST: + sai_deserialize_number_list(sfield, field.data.u8list, countOnly); + sai_deserialize_number_list(smask, field.mask.u8list, countOnly, true); + return; + default: - SWSS_LOG_THROW("FATAIL: invalid serialization type %d", meta.attrvaluetype); + SWSS_LOG_THROW("sai attr value %s is not implemented, FIXME", sai_serialize_attr_value_type(meta.attrvaluetype).c_str()); } } @@ -2803,14 +2893,14 @@ void sai_deserialize_acl_action( case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT8: return sai_deserialize_number(s, action.parameter.u8); - case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT8: - return sai_deserialize_number(s, action.parameter.s8); +// case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT8: +// return sai_deserialize_number(s, action.parameter.s8); case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT16: return sai_deserialize_number(s, action.parameter.u16); - case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT16: - return sai_deserialize_number(s, action.parameter.s16); +// case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_INT16: +// return sai_deserialize_number(s, action.parameter.s16); case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_UINT32: return sai_deserialize_number(s, action.parameter.u32); @@ -2833,8 +2923,12 @@ void sai_deserialize_acl_action( case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: return sai_deserialize_oid_list(s, action.parameter.objlist, countOnly); + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IP_ADDRESS: + sai_deserialize_ip_address(s, action.parameter.ipaddr); + return; + default: - SWSS_LOG_THROW("FATAIL: invalid serialization type %d", meta.attrvaluetype); + SWSS_LOG_THROW("sai attr value %s is not implemented, FIXME", sai_serialize_attr_value_type(meta.attrvaluetype).c_str()); } } @@ -2962,8 +3056,7 @@ void sai_deserialize_system_port_config_list( if (arr.size() != (size_t)sysportconfiglist.count) { - SWSS_LOG_ERROR("system port config list count mismatch %lu vs %u", arr.size(), sysportconfiglist.count); - throw std::runtime_error("system port config list count mismatch"); + SWSS_LOG_THROW("system port config list count mismatch %lu vs %u", arr.size(), sysportconfiglist.count); } sysportconfiglist.list = sai_alloc_n_of_ptr_type(sysportconfiglist.count, sysportconfiglist.list); @@ -3003,8 +3096,8 @@ void sai_deserialize_attr_value( case SAI_ATTR_VALUE_TYPE_UINT16: return sai_deserialize_number(s, attr.value.u16); - case SAI_ATTR_VALUE_TYPE_INT16: - return sai_deserialize_number(s, attr.value.s16); +// case SAI_ATTR_VALUE_TYPE_INT16: +// return sai_deserialize_number(s, attr.value.s16); case SAI_ATTR_VALUE_TYPE_UINT32: return sai_deserialize_number(s, attr.value.u32); @@ -3015,8 +3108,8 @@ void sai_deserialize_attr_value( case SAI_ATTR_VALUE_TYPE_UINT64: return sai_deserialize_number(s, attr.value.u64); - case SAI_ATTR_VALUE_TYPE_INT64: - return sai_deserialize_number(s, attr.value.s64); +// case SAI_ATTR_VALUE_TYPE_INT64: +// return sai_deserialize_number(s, attr.value.s64); case SAI_ATTR_VALUE_TYPE_MAC: return sai_deserialize_mac(s, attr.value.mac); @@ -3048,11 +3141,11 @@ void sai_deserialize_attr_value( case SAI_ATTR_VALUE_TYPE_INT8_LIST: return sai_deserialize_number_list(s, attr.value.s8list, countOnly); - case SAI_ATTR_VALUE_TYPE_UINT16_LIST: - return sai_deserialize_number_list(s, attr.value.u16list, countOnly); - - case SAI_ATTR_VALUE_TYPE_INT16_LIST: - return sai_deserialize_number_list(s, attr.value.s16list, countOnly); +// case SAI_ATTR_VALUE_TYPE_UINT16_LIST: +// return sai_deserialize_number_list(s, attr.value.u16list, countOnly); +// +// case SAI_ATTR_VALUE_TYPE_INT16_LIST: +// return sai_deserialize_number_list(s, attr.value.s16list, countOnly); case SAI_ATTR_VALUE_TYPE_UINT32_LIST: return sai_deserialize_number_list(s, attr.value.u32list, countOnly); @@ -3063,8 +3156,8 @@ void sai_deserialize_attr_value( case SAI_ATTR_VALUE_TYPE_UINT32_RANGE: return sai_deserialize_range(s, attr.value.u32range); - case SAI_ATTR_VALUE_TYPE_INT32_RANGE: - return sai_deserialize_range(s, attr.value.s32range); +// case SAI_ATTR_VALUE_TYPE_INT32_RANGE: +// return sai_deserialize_range(s, attr.value.s32range); case SAI_ATTR_VALUE_TYPE_VLAN_LIST: return sai_deserialize_number_list(s, attr.value.vlanlist, countOnly); @@ -3113,6 +3206,7 @@ void sai_deserialize_attr_value( case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IPV6: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IP_ADDRESS: return sai_deserialize_acl_action(s, meta, attr.value.aclaction, countOnly); case SAI_ATTR_VALUE_TYPE_ACL_CAPABILITY: @@ -3165,6 +3259,24 @@ void sai_deserialize_queue_deadlock( sai_deserialize_enum(s, &sai_metadata_enum_sai_queue_pfc_deadlock_event_type_t, (int32_t&)event); } +void sai_deserialize_ipmc_entry_type( + _In_ const std::string& s, + _Out_ sai_ipmc_entry_type_t& type) +{ + SWSS_LOG_ENTER(); + + return sai_deserialize_enum(s, &sai_metadata_enum_sai_ipmc_entry_type_t, (int32_t&)type); +} + +void sai_deserialize_l2mc_entry_type( + _In_ const std::string& s, + _Out_ sai_l2mc_entry_type_t& type) +{ + SWSS_LOG_ENTER(); + + return sai_deserialize_enum(s, &sai_metadata_enum_sai_l2mc_entry_type_t, (int32_t&)type); +} + void sai_deserialize_fdb_event( _In_ const std::string& s, _Out_ sai_fdb_event_t& event) @@ -3174,6 +3286,15 @@ void sai_deserialize_fdb_event( sai_deserialize_enum(s, &sai_metadata_enum_sai_fdb_event_t, (int32_t&)event); } +void sai_deserialize_bfd_session_state( + _In_ const std::string& s, + _Out_ sai_bfd_session_state_t& state) +{ + SWSS_LOG_ENTER(); + + sai_deserialize_enum(s, &sai_metadata_enum_sai_bfd_session_state_t, (int32_t&)state); +} + void sai_deserialize_switch_oper_status( _In_ const std::string& s, _Out_ sai_object_id_t &switch_id, @@ -3421,6 +3542,49 @@ void sai_deserialize_nat_entry( sai_deserialize_nat_entry_data(j["nat_data"], nat_entry.data); } +void sai_deserialize_ipmc_entry( + _In_ const std::string &s, + _Out_ sai_ipmc_entry_t& ipmc_entry) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + sai_deserialize_object_id(j["switch_id"], ipmc_entry.switch_id); + sai_deserialize_object_id(j["vr_id"], ipmc_entry.vr_id); + sai_deserialize_ipmc_entry_type(j["type"], ipmc_entry.type); + sai_deserialize_ip_address(j["destination"], ipmc_entry.destination); + sai_deserialize_ip_address(j["source"], ipmc_entry.source); +} + +void sai_deserialize_l2mc_entry( + _In_ const std::string &s, + _Out_ sai_l2mc_entry_t& l2mc_entry) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + sai_deserialize_object_id(j["switch_id"], l2mc_entry.switch_id); + sai_deserialize_object_id(j["bv_id"], l2mc_entry.bv_id); + sai_deserialize_l2mc_entry_type(j["type"], l2mc_entry.type); + sai_deserialize_ip_address(j["destination"], l2mc_entry.destination); + sai_deserialize_ip_address(j["source"], l2mc_entry.source); +} + +void sai_deserialize_mcast_fdb_entry( + _In_ const std::string &s, + _Out_ sai_mcast_fdb_entry_t& mcast_fdb_entry) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + sai_deserialize_object_id(j["switch_id"], mcast_fdb_entry.switch_id); + sai_deserialize_object_id(j["bv_id"], mcast_fdb_entry.bv_id); + sai_deserialize_mac(j["mac_address"], mcast_fdb_entry.mac_address); +} + void sai_deserialize_attr_id( _In_ const std::string& s, _Out_ const sai_attr_metadata_t** meta) @@ -3474,7 +3638,7 @@ void sai_deserialize_object_meta_key( sai_deserialize_object_type(str_object_type, meta_key.objecttype); - if (meta_key.objecttype == SAI_OBJECT_TYPE_NULL || meta_key.objecttype >= SAI_OBJECT_TYPE_EXTENSIONS_MAX) + if (!sai_metadata_is_object_type_valid(meta_key.objecttype)) { SWSS_LOG_THROW("invalid object type value %s", sai_serialize_object_type(meta_key.objecttype).c_str()); } @@ -3506,6 +3670,17 @@ void sai_deserialize_object_meta_key( case SAI_OBJECT_TYPE_MY_SID_ENTRY: sai_deserialize_my_sid_entry(str_object_id, meta_key.objectkey.key.my_sid_entry); break; + case SAI_OBJECT_TYPE_L2MC_ENTRY: + sai_deserialize_l2mc_entry(str_object_id, meta_key.objectkey.key.l2mc_entry); + break; + + case SAI_OBJECT_TYPE_IPMC_ENTRY: + sai_deserialize_ipmc_entry(str_object_id, meta_key.objectkey.key.ipmc_entry); + break; + + case SAI_OBJECT_TYPE_MCAST_FDB_ENTRY: + sai_deserialize_mcast_fdb_entry(str_object_id, meta_key.objectkey.key.mcast_fdb_entry); + break; default: @@ -3616,6 +3791,28 @@ void sai_deserialize_queue_deadlock_ntf( *deadlock_data = data; } +void sai_deserialize_bfd_session_state_ntf( + _In_ const std::string& s, + _Out_ uint32_t &count, + _Out_ sai_bfd_session_state_notification_t** bfd_session_state) +{ + SWSS_LOG_ENTER(); + + json j = json::parse(s); + + count = (uint32_t)j.size(); + + auto data = new sai_bfd_session_state_notification_t[count]; + + for (uint32_t i = 0; i < count; ++i) + { + sai_deserialize_object_id(j[i]["bfd_session_id"], data[i].bfd_session_id); + sai_deserialize_bfd_session_state(j[i]["session_state"], data[i].session_state); + } + + *bfd_session_state = data; +} + // deserialize free void sai_deserialize_free_attribute_value( @@ -3659,13 +3856,13 @@ void sai_deserialize_free_attribute_value( sai_free_list(attr.value.s8list); break; - case SAI_ATTR_VALUE_TYPE_UINT16_LIST: - sai_free_list(attr.value.u16list); - break; - - case SAI_ATTR_VALUE_TYPE_INT16_LIST: - sai_free_list(attr.value.s16list); - break; +// case SAI_ATTR_VALUE_TYPE_UINT16_LIST: +// sai_free_list(attr.value.u16list); +// break; +// +// case SAI_ATTR_VALUE_TYPE_INT16_LIST: +// sai_free_list(attr.value.s16list); +// break; case SAI_ATTR_VALUE_TYPE_UINT32_LIST: sai_free_list(attr.value.u32list); @@ -3736,6 +3933,7 @@ void sai_deserialize_free_attribute_value( case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IPV4: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IPV6: case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_IP_ADDRESS: break; case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: @@ -3761,7 +3959,7 @@ void sai_deserialize_free_attribute_value( break; default: - SWSS_LOG_THROW("unsupported type %d on deserialize free, FIXME", type); + SWSS_LOG_THROW("sai attr value %s is not implemented, FIXME", sai_serialize_attr_value_type(type).c_str()); } } @@ -3821,6 +4019,15 @@ void sai_deserialize_free_queue_deadlock_ntf( delete[] queue_deadlock; } +void sai_deserialize_free_bfd_session_state_ntf( + _In_ uint32_t count, + _In_ sai_bfd_session_state_notification_t* bfd_session_state) +{ + SWSS_LOG_ENTER(); + + delete[] bfd_session_state; +} + void sai_deserialize_ingress_priority_group_attr( _In_ const std::string& s, _Out_ sai_ingress_priority_group_attr_t& attr) @@ -3870,9 +4077,7 @@ void sai_deserialize( } else { - SWSS_LOG_WARN("enum %s not found in sai_redis_notify_syncd_t", s.c_str()); - - sai_deserialize_number(s, value); + SWSS_LOG_THROW("enum %s not found in sai_redis_notify_syncd_t", s.c_str()); } } diff --git a/meta/sai_serialize.h b/meta/sai_serialize.h index 92ec27470..7b317b08b 100644 --- a/meta/sai_serialize.h +++ b/meta/sai_serialize.h @@ -132,6 +132,26 @@ std::string sai_serialize_hex_binary( _In_ const void *buffer, _In_ size_t length); +void sai_deserialize_system_port_config_list( + _In_ const std::string& s, + _Out_ sai_system_port_config_list_t& sysportconfiglist, + _In_ bool countOnly); + +std::string sai_serialize_chardata( + _In_ const char data[32]); + +std::string sai_serialize_oid_list( + _In_ const sai_object_list_t &list, + _In_ bool countOnly); + +std::string sai_serialize_system_port_config_list( + _In_ const sai_attr_metadata_t &meta, + _In_ const sai_system_port_config_list_t& sysportconfiglist, + _In_ bool countOnly); + +std::string sai_serialize_queue_deadlock_event( + _In_ sai_queue_pfc_deadlock_event_type_t event); + template std::string sai_serialize_hex_binary( _In_ const T &value) @@ -208,6 +228,10 @@ std::string sai_serialize_queue_deadlock_ntf( _In_ uint32_t count, _In_ const sai_queue_deadlock_notification_data_t* deadlock_data); +std::string sai_serialize_bfd_session_state_ntf( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t* bfd_session_state); + // sairedis std::string sai_serialize( @@ -257,6 +281,14 @@ void sai_deserialize_api( _In_ const std::string& s, _Out_ sai_api_t& api); +void sai_deserialize_ipmc_entry_type( + _In_ const std::string& s, + _Out_ sai_ipmc_entry_type_t& type); + +void sai_deserialize_l2mc_entry_type( + _In_ const std::string& s, + _Out_ sai_l2mc_entry_type_t& type); + void sai_deserialize_fdb_entry( _In_ const std::string& s, _In_ sai_fdb_entry_t &fdb_entry); @@ -331,6 +363,18 @@ void sai_deserialize_my_sid_entry( _In_ const std::string& s, _Out_ sai_my_sid_entry_t& my_sid_entry); +void sai_deserialize_ipv4( + _In_ const std::string& s, + _Out_ sai_ip4_t& ipaddr); + +void sai_deserialize_ipv6( + _In_ const std::string& s, + _Out_ sai_ip6_t& ipaddr); + +void sai_deserialize_chardata( + _In_ const std::string& s, + _Out_ char chardata[32]); + // deserialize notifications void sai_deserialize_fdb_event_ntf( @@ -348,6 +392,11 @@ void sai_deserialize_queue_deadlock_ntf( _Out_ uint32_t &count, _Out_ sai_queue_deadlock_notification_data_t** deadlock_data); +void sai_deserialize_bfd_session_state_ntf( + _In_ const std::string& s, + _Out_ uint32_t &count, + _Out_ sai_bfd_session_state_notification_t** bfdsession); + // free methods void sai_deserialize_free_attribute_value( @@ -368,6 +417,10 @@ void sai_deserialize_free_queue_deadlock_ntf( _In_ uint32_t count, _In_ sai_queue_deadlock_notification_data_t* deadlock_data); +void sai_deserialize_free_bfd_session_state_ntf( + _In_ uint32_t count, + _In_ sai_bfd_session_state_notification_t* bfdsessionstate); + void sai_deserialize_ingress_priority_group_attr( _In_ const std::string& s, _Out_ sai_ingress_priority_group_attr_t& attr); diff --git a/meta/tests.cpp b/meta/tests.cpp deleted file mode 100644 index 4990fa04a..000000000 --- a/meta/tests.cpp +++ /dev/null @@ -1,4045 +0,0 @@ -#include "sai_serialize.h" - -#include "OidRefCounter.h" -#include "SaiAttrWrapper.h" -#include "AttrKeyMap.h" -#include "SaiObjectCollection.h" -#include "MetaTestSaiInterface.h" -#include "Meta.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -using namespace saimeta; - -static std::shared_ptr g_sai = std::make_shared(); -static std::shared_ptr g_meta = std::make_shared(g_sai); - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmissing-noreturn" - -sai_object_type_t sai_object_type_query( - _In_ sai_object_id_t oid) -{ - SWSS_LOG_ENTER(); - - SWSS_LOG_THROW("should not be used"); -} - -void clear_local() -{ - SWSS_LOG_ENTER(); - - g_sai = std::make_shared(); - g_meta = std::make_shared(g_sai); -} - -sai_object_id_t create_dummy_object_id( - _In_ sai_object_type_t object_type, - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t oid; - - auto status = g_sai->create(object_type, &oid, switch_id, 0, NULL); - - if (status != SAI_STATUS_SUCCESS) - { - SWSS_LOG_THROW("failed to create oid"); - } - - SWSS_LOG_DEBUG("created oid %s", sai_serialize_object_id(oid).c_str()); - - return oid; -} - -sai_object_id_t sai_switch_id_query( - _In_ sai_object_id_t oid) -{ - SWSS_LOG_ENTER(); - - SWSS_LOG_THROW("should not be used"); -} - -#pragma GCC diagnostic pop - -// META ASSERTS - -#define META_ASSERT_SUCCESS(x) \ - if (x != SAI_STATUS_SUCCESS) \ -{\ - SWSS_LOG_ERROR("expected success, line: %d", __LINE__);\ - throw;\ -} - -#define META_ASSERT_FAIL(x) \ - if (x == SAI_STATUS_SUCCESS) \ -{\ - SWSS_LOG_ERROR("expected failure, line: %d", __LINE__);\ - throw;\ -} - -#define META_ASSERT_TRUE(x) \ - if (!(x)) \ -{\ - SWSS_LOG_ERROR("assert true failed '%s', line: %d", # x, __LINE__);\ - throw;\ -} - -// SWITCH TESTS - -sai_object_id_t create_switch() -{ - SWSS_LOG_ENTER(); - - sai_attribute_t attr; - - sai_object_id_t switch_id; - - attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; - attr.value.booldata = true; - - auto status = g_meta->create(SAI_OBJECT_TYPE_SWITCH, &switch_id, SAI_NULL_OBJECT_ID, 1, &attr); - META_ASSERT_SUCCESS(status); - - return switch_id; -} - -void remove_switch( - _In_ sai_object_id_t switchId) -{ - SWSS_LOG_ENTER(); - - META_ASSERT_TRUE(g_meta->isEmpty() == false); - - SWSS_LOG_NOTICE("removing: %lX", switchId); - - auto status = g_meta->remove(SAI_OBJECT_TYPE_SWITCH, switchId); - - META_ASSERT_SUCCESS(status); - - META_ASSERT_TRUE(g_meta->isEmpty()); -} - -void test_switch_set() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - - sai_object_id_t switch_id = create_switch(); - - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, NULL); - META_ASSERT_FAIL(status); - - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_FAIL(status); - - // id outside range - attr.id = -1; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_FAIL(status); - - g_sai->setStatus(SAI_STATUS_FAILURE); - attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_FAIL(status); - g_sai->setStatus(SAI_STATUS_SUCCESS); - - attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_FAIL(status); - - attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; - attr.value.s32 = 0x1000; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_FAIL(status); - - // enum - attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; - attr.value.s32 = SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_SUCCESS(status); - - // bool - attr.id = SAI_SWITCH_ATTR_BCAST_CPU_FLOOD_ENABLE; - attr.value.booldata = SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_SUCCESS(status); - - // mac - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS; - memcpy(attr.value.mac, mac, sizeof(mac)); - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_SUCCESS(status); - - // uint8 - attr.id = SAI_SWITCH_ATTR_QOS_DEFAULT_TC; - attr.value.u8 = 0x11; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_SUCCESS(status); - - // object id with not allowed null - -// currently hash is read only -// -// // null oid -// attr.id = SAI_SWITCH_ATTR_LAG_HASH_IPV6; -// attr.value.oid = SAI_NULL_OBJECT_ID; -// status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); -// META_ASSERT_FAIL(status); -// -// // wrong object type -// attr.id = SAI_SWITCH_ATTR_LAG_HASH_IPV6; -// attr.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_LAG); -// status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); -// META_ASSERT_FAIL(status); -// -// // valid object (object must exist) -// attr.id = SAI_SWITCH_ATTR_LAG_HASH_IPV6; -// attr.value.oid = create_hash(switch_id); -// -// status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); -// META_ASSERT_SUCCESS(status); -// -// META_ASSERT_TRUE(g_meta->getObjectReferenceCount(attr.value.oid) == 1); - - // object id with allowed null - - // null oid - attr.id = SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP; - attr.value.oid = SAI_NULL_OBJECT_ID; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_SUCCESS(status); - - // wrong object - attr.id = SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP; - status = g_meta->create(SAI_OBJECT_TYPE_LAG, &attr.value.oid, switch_id, 0, NULL); - META_ASSERT_SUCCESS(status); - - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_FAIL(status); - - // good object - attr.id = SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP; - - sai_attribute_t a[2] = { }; - a[0].id = SAI_QOS_MAP_ATTR_TYPE; - a[0].value.s32 = 1; - a[1].id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST; - status = g_meta->create(SAI_OBJECT_TYPE_QOS_MAP, &attr.value.oid, switch_id, 2, a); - META_ASSERT_SUCCESS(status); - - sai_object_id_t oid = attr.value.oid; - - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_SUCCESS(status); - - META_ASSERT_TRUE(g_meta->getObjectReferenceCount(attr.value.oid) == 1); - - attr.id = SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP; - attr.value.oid = SAI_NULL_OBJECT_ID; - status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); - META_ASSERT_SUCCESS(status); - - // check if it was decreased - META_ASSERT_TRUE(g_meta->getObjectReferenceCount(oid) == 0); - - remove_switch(switch_id); -} - -void test_switch_get() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - - sai_object_id_t switch_id = create_switch(); - - attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; - status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 0, &attr); - META_ASSERT_FAIL(status); - - status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1000, &attr); - META_ASSERT_FAIL(status); - - status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, NULL); - META_ASSERT_FAIL(status); - - status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, NULL); - META_ASSERT_FAIL(status); - - status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - attr.id = -1; - status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, &attr); - META_ASSERT_FAIL(status); - - attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; - attr.value.u32 = 0; - status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - sai_attribute_t attr1; - attr1.id = SAI_SWITCH_ATTR_PORT_NUMBER; - - sai_attribute_t attr2; - attr2.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID; - sai_attribute_t list[2] = { attr1, attr2 }; - - status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 2, list); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -// FDB TESTS - -static sai_object_id_t create_bridge( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t bridge_id; - - sai_attribute_t attrs[9] = {}; - - attrs[0].id = SAI_BRIDGE_ATTR_TYPE; - attrs[0].value.s32 = SAI_BRIDGE_TYPE_1Q; - - sai_status_t status = g_meta->create(SAI_OBJECT_TYPE_BRIDGE, &bridge_id, switch_id, 1, attrs); - META_ASSERT_SUCCESS(status); - - return bridge_id; -} - -static sai_object_id_t create_port( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t port; - - static uint32_t id = 1; - id++; - sai_attribute_t attrs[9] = { }; - - uint32_t list[1] = { id }; - - attrs[0].id = SAI_PORT_ATTR_HW_LANE_LIST; - attrs[0].value.u32list.count = 1; - attrs[0].value.u32list.list = list; - - attrs[1].id = SAI_PORT_ATTR_SPEED; - attrs[1].value.u32 = 10000; - - auto status = g_meta->create(SAI_OBJECT_TYPE_PORT, &port, switch_id, 2, attrs); - META_ASSERT_SUCCESS(status); - - return port; -} - -static sai_object_id_t create_bridge_port( - _In_ sai_object_id_t switch_id, - _In_ sai_object_id_t bridge_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t bridge_port; - - sai_attribute_t attrs[9] = { }; - - auto port = create_port(switch_id); - - attrs[0].id = SAI_BRIDGE_PORT_ATTR_TYPE; - attrs[0].value.s32 = SAI_BRIDGE_PORT_TYPE_PORT; - - attrs[1].id = SAI_BRIDGE_PORT_ATTR_PORT_ID; - attrs[1].value.oid = port; - - auto status = g_meta->create(SAI_OBJECT_TYPE_BRIDGE_PORT, &bridge_port, switch_id, 2, attrs); - META_ASSERT_SUCCESS(status); - - return bridge_port; -} - -void test_fdb_entry_create() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - - sai_object_id_t switch_id = create_switch(); - - sai_fdb_entry_t fdb_entry; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - memcpy(fdb_entry.mac_address, mac, sizeof(mac)); - - fdb_entry.switch_id = switch_id; - sai_object_id_t bridge_id = create_bridge(switch_id); - fdb_entry.bv_id = bridge_id; - - sai_object_id_t port = create_bridge_port(switch_id, bridge_id); - - SWSS_LOG_NOTICE("create tests"); - - SWSS_LOG_NOTICE("zero attribute count (but there are mandatory attributes)"); - attr.id = SAI_FDB_ENTRY_ATTR_TYPE; - status = g_meta->create(&fdb_entry, 0, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->create(&fdb_entry, 1, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("fdb entry is null"); - status = g_meta->create((const sai_fdb_entry_t*)NULL, 1, &attr); - META_ASSERT_FAIL(status); - - sai_attribute_t list1[4] = { }; - - sai_attribute_t &attr1 = list1[0]; - sai_attribute_t &attr2 = list1[1]; - sai_attribute_t &attr3 = list1[2]; - sai_attribute_t &attr4 = list1[3]; - - attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; - attr1.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; - - attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; - attr2.value.oid = port; - - attr3.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; - attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; - - attr4.id = -1; - - SWSS_LOG_NOTICE("invalid attribute id"); - status = g_meta->create(&fdb_entry, 4, list1); - META_ASSERT_FAIL(status); - -// // packet action is now optional -// SWSS_LOG_NOTICE("passing optional attribute"); -// status = g_meta->create(&fdb_entry, 1, list1); -// META_ASSERT_SUCCESS(status); - - attr2.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_HASH, switch_id); - - SWSS_LOG_NOTICE("invalid attribute value on oid"); - status = g_meta->create(&fdb_entry, 3, list1); - META_ASSERT_FAIL(status); - - attr2.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_PORT, switch_id); - - SWSS_LOG_NOTICE("non existing object on oid"); - status = g_meta->create(&fdb_entry, 3, list1); - META_ASSERT_FAIL(status); - - attr2.value.oid = port; - attr3.value.s32 = 0x100; - - SWSS_LOG_NOTICE("invalid attribute value on enum"); - status = g_meta->create(&fdb_entry, 3, list1); - META_ASSERT_FAIL(status); - - attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; - - sai_attribute_t list2[4] = { attr1, attr2, attr3, attr3 }; - - SWSS_LOG_NOTICE("repeated attribute id"); - status = g_meta->create(&fdb_entry, 4, list2); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("correct"); - status = g_meta->create(&fdb_entry, 3, list2); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("already exists"); - status = g_meta->create(&fdb_entry, 3, list2); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -void test_fdb_entry_remove() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_object_id_t switch_id = create_switch(); - - sai_fdb_entry_t fdb_entry; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - memcpy(fdb_entry.mac_address, mac, sizeof(mac)); - fdb_entry.switch_id = switch_id; - sai_object_id_t bridge_id = create_bridge(switch_id); - fdb_entry.bv_id= bridge_id; - - sai_object_id_t port = create_bridge_port(switch_id, bridge_id); - - sai_attribute_t list1[3] = { }; - - sai_attribute_t &attr1 = list1[0]; - sai_attribute_t &attr2 = list1[1]; - sai_attribute_t &attr3 = list1[2]; - - attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; - attr1.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; - - attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; - attr2.value.oid = port; - - attr3.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; - attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; - - SWSS_LOG_NOTICE("creating fdb entry"); - status = g_meta->create(&fdb_entry, 3, list1); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove tests"); - - SWSS_LOG_NOTICE("fdb_entry is null"); - status = g_meta->remove((const sai_fdb_entry_t*)NULL); - META_ASSERT_FAIL(status); - - //SWSS_LOG_NOTICE("invalid vlan"); - //status = g_meta->remove(&fdb_entry); - //META_ASSERT_FAIL(status); - - fdb_entry.mac_address[0] = 1; - - SWSS_LOG_NOTICE("invalid mac"); - status = g_meta->remove(&fdb_entry); - META_ASSERT_FAIL(status); - - fdb_entry.mac_address[0] = 0x11; - - sai_object_meta_key_t key = { .objecttype = SAI_OBJECT_TYPE_FDB_ENTRY, .objectkey = { .key = { .fdb_entry = fdb_entry } } }; - - META_ASSERT_TRUE(g_meta->objectExists(key)); - - SWSS_LOG_NOTICE("success"); - status = g_meta->remove(&fdb_entry); - META_ASSERT_SUCCESS(status); - - META_ASSERT_TRUE(!g_meta->objectExists(key)); - - remove_switch(switch_id); -} - -static sai_fdb_entry_t create_fdb_entry() -{ - SWSS_LOG_ENTER(); - - sai_fdb_entry_t fdb_entry; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - memcpy(fdb_entry.mac_address, mac, sizeof(mac)); - - auto switch_id = create_switch(); - - fdb_entry.switch_id = switch_id; - sai_object_id_t bridge_id = create_bridge(switch_id); - fdb_entry.bv_id = bridge_id; - - sai_object_id_t port = create_bridge_port(switch_id, bridge_id); - - sai_attribute_t list1[4] = { }; - - sai_attribute_t &attr1 = list1[0]; - sai_attribute_t &attr2 = list1[1]; - sai_attribute_t &attr3 = list1[2]; - sai_attribute_t &attr4 = list1[3]; - - attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; - attr1.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; - - attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; - attr2.value.oid = port; - - attr3.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; - attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; - - attr4.id = -1; - - sai_attribute_t list2[4] = { attr1, attr2, attr3, attr3 }; - - auto status = g_meta->create(&fdb_entry, 3, list2); - META_ASSERT_SUCCESS(status); - - return fdb_entry; -} - -void test_fdb_entry_set() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - - sai_fdb_entry_t fdb_entry = create_fdb_entry(); - - //status = g_meta->create(&fdb_entry, 0, 0); - //META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->set(&fdb_entry, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("fdb entry is null"); - status = g_meta->set((const sai_fdb_entry_t*)NULL, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("setting read only object"); - attr.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; - attr.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_BRIDGE_PORT, fdb_entry.switch_id); - - status = g_meta->set(&fdb_entry, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("setting invalid attrib id"); - attr.id = -1; - status = g_meta->set(&fdb_entry, &attr); - META_ASSERT_FAIL(status); - - //SWSS_LOG_NOTICE("invalid vlan"); - //attr.id = SAI_FDB_ENTRY_ATTR_TYPE; - //attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; - //status = g_meta->set(&fdb_entry, &attr); - //META_ASSERT_FAIL(status); - - //SWSS_LOG_NOTICE("vlan outside range"); - //attr.id = SAI_FDB_ENTRY_ATTR_TYPE; - //attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; - //status = g_meta->set(&fdb_entry, &attr); - //META_ASSERT_FAIL(status); - - // correct - attr.id = SAI_FDB_ENTRY_ATTR_TYPE; - attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; - status = g_meta->set(&fdb_entry, &attr); - META_ASSERT_SUCCESS(status); - - // TODO check references ? - - remove_switch(fdb_entry.switch_id); -} - -void test_fdb_entry_get() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - - sai_fdb_entry_t fdb_entry = create_fdb_entry(); - - attr.id = SAI_FDB_ENTRY_ATTR_TYPE; - attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; - status = g_meta->set(&fdb_entry, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get test"); - - // zero attribute count - attr.id = SAI_FDB_ENTRY_ATTR_TYPE; - status = g_meta->get(&fdb_entry, 0, &attr); - META_ASSERT_FAIL(status); - - // attr is null - status = g_meta->get(&fdb_entry, 1, NULL); - META_ASSERT_FAIL(status); - - // fdb entry is null - status = g_meta->get((sai_fdb_entry_t*)NULL, 1, &attr); - META_ASSERT_FAIL(status); - - // attr id out of range - attr.id = -1; - status = g_meta->get(&fdb_entry, 1, &attr); - META_ASSERT_FAIL(status); - - // correct single valid attribute - attr.id = SAI_FDB_ENTRY_ATTR_TYPE; - status = g_meta->get(&fdb_entry, 1, &attr); - META_ASSERT_SUCCESS(status); - - // correct 2 attributes - sai_attribute_t attr1; - attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; - - sai_attribute_t attr2; - attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; - sai_attribute_t list[2] = { attr1, attr2 }; - - status = g_meta->get(&fdb_entry, 2, list); - META_ASSERT_SUCCESS(status); - - remove_switch(fdb_entry.switch_id); -} - -void test_fdb_entry_flow() -{ - SWSS_LOG_ENTER(); - - SWSS_LOG_TIMER("fdb flow"); - - clear_local(); - - sai_object_id_t switch_id = create_switch(); - sai_status_t status; - sai_attribute_t attr; - - sai_fdb_entry_t fdb_entry; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - memcpy(fdb_entry.mac_address, mac, sizeof(mac)); - fdb_entry.switch_id = switch_id; - - sai_object_id_t bridge_id = create_bridge(switch_id); - fdb_entry.bv_id= bridge_id; - - sai_object_id_t lag = create_bridge_port(switch_id, bridge_id); - - sai_attribute_t list[4] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - sai_attribute_t &attr3 = list[2]; - sai_attribute_t &attr4 = list[3]; - - attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; - attr1.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; - - attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; - attr2.value.oid = lag; - - attr3.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; - attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; - - attr4.id = SAI_FDB_ENTRY_ATTR_META_DATA; - attr4.value.u32 = 0x12345678; - - SWSS_LOG_NOTICE("create"); - status = g_meta->create(&fdb_entry, 4, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("create existing"); - status = g_meta->create(&fdb_entry, 4, list); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("set"); - attr.id = SAI_FDB_ENTRY_ATTR_TYPE; - attr.value.s32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; - status = g_meta->set(&fdb_entry, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set"); - attr.id = SAI_FDB_ENTRY_ATTR_META_DATA; - attr.value.u32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; - status = g_meta->set(&fdb_entry, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get"); - status = g_meta->get(&fdb_entry, 4, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove"); - status = g_meta->remove(&fdb_entry); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove non existing"); - status = g_meta->remove(&fdb_entry); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -// NEIGHBOR TESTS - -static sai_object_id_t create_virtual_router( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t vr; - - auto status = g_meta->create(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, &vr, switch_id, 0, NULL); - META_ASSERT_SUCCESS(status); - - return vr; -} - -static sai_object_id_t create_rif( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t rif; - - sai_attribute_t attrs[9] = { }; - - auto port = create_port(switch_id); - - auto vr = create_virtual_router(switch_id); - - attrs[0].id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID; - attrs[0].value.oid = vr; - - attrs[1].id = SAI_ROUTER_INTERFACE_ATTR_TYPE; - attrs[1].value.s32 = SAI_ROUTER_INTERFACE_TYPE_PORT; - - attrs[2].id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID; - attrs[2].value.oid = port; - - auto status = g_meta->create(SAI_OBJECT_TYPE_ROUTER_INTERFACE, &rif, switch_id, 3, attrs); - META_ASSERT_SUCCESS(status); - - return rif; -} - -void test_neighbor_entry_create() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_object_id_t switch_id = create_switch(); - sai_status_t status; - sai_attribute_t attr; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - sai_neighbor_entry_t neighbor_entry; - - sai_object_id_t rif = create_rif(switch_id); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); - neighbor_entry.rif_id = rif; - neighbor_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create tests"); - - SWSS_LOG_NOTICE("zero attribute count (but there are mandatory attributes)"); - status = g_meta->create(&neighbor_entry, 0, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->create(&neighbor_entry, 1, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("neighbor entry is null"); - status = g_meta->create((sai_neighbor_entry_t*)NULL, 1, &attr); - META_ASSERT_FAIL(status); - - sai_attribute_t list[3] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - sai_attribute_t &attr3 = list[2]; - - attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; - memcpy(attr1.value.mac, mac, 6); - - attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - attr3.id = -1; - - SWSS_LOG_NOTICE("invalid attribute id"); - status = g_meta->create(&neighbor_entry, 3, list); - META_ASSERT_FAIL(status); - - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD + 0x100; - SWSS_LOG_NOTICE("invalid attribute value on enum"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_FAIL(status); - - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - sai_attribute_t list2[4] = { attr1, attr2, attr2 }; - - SWSS_LOG_NOTICE("repeated attribute id"); - status = g_meta->create(&neighbor_entry, 3, list2); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("correct ipv4"); - status = g_meta->create(&neighbor_entry, 2, list2); - META_ASSERT_SUCCESS(status); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(neighbor_entry.ip_address.addr.ip6, ip6, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&neighbor_entry, 2, list2); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("already exists"); - status = g_meta->create(&neighbor_entry, 2, list2); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -sai_neighbor_entry_t create_neighbor_entry() -{ - SWSS_LOG_ENTER(); - - sai_object_id_t switch_id = create_switch(); - sai_status_t status; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - sai_neighbor_entry_t neighbor_entry; - - sai_object_id_t rif = create_rif(switch_id); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); - neighbor_entry.rif_id = rif; - neighbor_entry.switch_id = switch_id; - - sai_attribute_t list[3] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - sai_attribute_t &attr3 = list[2]; - - attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; - memcpy(attr1.value.mac, mac, 6); - - attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - attr3.id = -1; - - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - sai_attribute_t list2[4] = { attr1, attr2, attr2 }; - - status = g_meta->create(&neighbor_entry, 2, list2); - META_ASSERT_SUCCESS(status); - - return neighbor_entry; -} - -static sai_object_id_t create_hash( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t hash; - - auto status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 0, NULL); - META_ASSERT_SUCCESS(status); - - return hash; -} - -void test_neighbor_entry_remove() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_object_id_t switch_id = create_switch(); - sai_neighbor_entry_t neighbor_entry; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - sai_attribute_t list[2] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - - attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; - memcpy(attr1.value.mac, mac, 6); - - attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - sai_object_id_t rif = create_rif(switch_id); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); - neighbor_entry.rif_id = rif; - neighbor_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create"); - - SWSS_LOG_NOTICE("correct ipv4"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_SUCCESS(status); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(neighbor_entry.ip_address.addr.ip6, ip6, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove tests"); - - SWSS_LOG_NOTICE("neighbor_entry is null"); - status = g_meta->remove((sai_neighbor_entry_t*)NULL); - META_ASSERT_FAIL(status); - - neighbor_entry.rif_id = SAI_NULL_OBJECT_ID; - - SWSS_LOG_NOTICE("invalid object id null"); - status = g_meta->remove(&neighbor_entry); - META_ASSERT_FAIL(status); - - neighbor_entry.rif_id = create_hash(switch_id); - - SWSS_LOG_NOTICE("invalid object id hash"); - status = g_meta->remove(&neighbor_entry); - META_ASSERT_FAIL(status); - - neighbor_entry.rif_id = create_rif(switch_id); - - SWSS_LOG_NOTICE("invalid object id router"); - status = g_meta->remove(&neighbor_entry); - META_ASSERT_FAIL(status); - - neighbor_entry.rif_id = rif; - - sai_object_meta_key_t key = { .objecttype = SAI_OBJECT_TYPE_NEIGHBOR_ENTRY, .objectkey = { .key = { .neighbor_entry = neighbor_entry } } }; - - META_ASSERT_TRUE(g_meta->objectExists(key)); - - SWSS_LOG_NOTICE("success"); - status = g_meta->remove(&neighbor_entry); - META_ASSERT_SUCCESS(status); - - META_ASSERT_TRUE(!g_meta->objectExists(key)); - - remove_switch(switch_id); -} - -void test_neighbor_entry_set() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_attribute_t attr; - - sai_object_id_t switch_id = create_switch(); - sai_neighbor_entry_t neighbor_entry; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - sai_attribute_t list[2] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - - attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; - memcpy(attr1.value.mac, mac, 6); - - attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - sai_object_id_t rif = create_rif(switch_id); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); - neighbor_entry.rif_id = rif; - neighbor_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create"); - - SWSS_LOG_NOTICE("correct ipv4"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_SUCCESS(status); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(neighbor_entry.ip_address.addr.ip6, ip6, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set tests"); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->set(&neighbor_entry, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("neighbor entry is null"); - status = g_meta->set((sai_neighbor_entry_t*)NULL, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("setting invalid attrib id"); - attr.id = -1; - status = g_meta->set(&neighbor_entry, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("value outside range"); - attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr.value.s32 = 0x100; - status = g_meta->set(&neighbor_entry, &attr); - META_ASSERT_FAIL(status); - - // correct - attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr.value.s32 = SAI_PACKET_ACTION_DROP; - status = g_meta->set(&neighbor_entry, &attr); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_neighbor_entry_get() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_attribute_t attr; - - sai_object_id_t switch_id = create_switch(); - sai_neighbor_entry_t neighbor_entry; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - sai_attribute_t list[2] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - - attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; - memcpy(attr1.value.mac, mac, 6); - - attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - sai_object_id_t rif = create_rif(switch_id); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); - neighbor_entry.rif_id = rif; - neighbor_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create"); - - SWSS_LOG_NOTICE("correct ipv4"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_SUCCESS(status); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(neighbor_entry.ip_address.addr.ip6, ip6, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get test"); - - SWSS_LOG_NOTICE("zero attribute count"); - attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - status = g_meta->get(&neighbor_entry, 0, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->get(&neighbor_entry, 1, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("neighbor entry is null"); - status = g_meta->get((sai_neighbor_entry_t*)NULL, 1, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr id out of range"); - attr.id = -1; - status = g_meta->get(&neighbor_entry, 1, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("correct single valid attribute"); - attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - status = g_meta->get(&neighbor_entry, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct 2 attributes"); - - sai_attribute_t attr3; - sai_attribute_t attr4; - attr3.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr3.value.s32 = 1; - attr4.id = SAI_NEIGHBOR_ENTRY_ATTR_NO_HOST_ROUTE; - - sai_attribute_t list2[2] = { attr3, attr4 }; - status = g_meta->get(&neighbor_entry, 2, list2); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_neighbor_entry_flow() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_object_id_t switch_id = create_switch(); - sai_neighbor_entry_t neighbor_entry; - - sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; - - sai_attribute_t list[4] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - sai_attribute_t &attr3 = list[1]; - sai_attribute_t &attr4 = list[1]; - - attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; - memcpy(attr1.value.mac, mac, 6); - - attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - attr3.id = SAI_NEIGHBOR_ENTRY_ATTR_NO_HOST_ROUTE; - attr3.value.booldata = true; - - attr4.id = SAI_NEIGHBOR_ENTRY_ATTR_META_DATA; - attr4.value.u32 = 1; - - sai_object_id_t rif = create_rif(switch_id); - - neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); - neighbor_entry.rif_id = rif; - neighbor_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create"); - - SWSS_LOG_NOTICE("correct ipv4"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct ipv4 existing"); - status = g_meta->create(&neighbor_entry, 2, list); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("set"); - status = g_meta->set(&neighbor_entry, &attr1); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set"); - status = g_meta->set(&neighbor_entry, &attr2); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set"); - status = g_meta->set(&neighbor_entry, &attr3); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set"); - status = g_meta->set(&neighbor_entry, &attr4); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove"); - status = g_meta->remove(&neighbor_entry); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove existing"); - status = g_meta->remove(&neighbor_entry); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -// VLAN TESTS - -sai_object_id_t create_vlan( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t vlan; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_VLAN_ATTR_VLAN_ID; - attrs[0].value.u16 = 1; - - auto status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan, switch_id, 1, attrs); - META_ASSERT_SUCCESS(status); - - return vlan; -} - -static sai_object_id_t create_stp( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t stp; - - auto status = g_meta->create(SAI_OBJECT_TYPE_STP, &stp, switch_id, 0, NULL); - META_ASSERT_SUCCESS(status); - - return stp; -} - -void test_vlan_create() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_attribute_t vlan1_att; - vlan1_att.id = SAI_VLAN_ATTR_VLAN_ID; - vlan1_att.value.u16 = 1; - - sai_object_id_t vlan1_id; - - sai_object_id_t switch_id = create_switch(); - - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan1_id, switch_id, 1, &vlan1_att); - META_ASSERT_SUCCESS(status); - - sai_attribute_t vlan; - vlan.id = SAI_VLAN_ATTR_VLAN_ID; - vlan.value.u16 = 2; - - sai_object_id_t vlan_id; - - SWSS_LOG_NOTICE("create tests"); - -// SWSS_LOG_NOTICE("existing vlan"); -// status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); -// META_ASSERT_FAIL(status); - - vlan.value.u16 = MAXIMUM_VLAN_NUMBER + 1; - -// SWSS_LOG_NOTICE("vlan outside range"); -// status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); -// META_ASSERT_FAIL(status); - - vlan.value.u16 = 2; - - SWSS_LOG_NOTICE("correct"); - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("existing"); - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -void test_vlan_remove() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_attribute_t vlan1_att; - vlan1_att.id = SAI_VLAN_ATTR_VLAN_ID; - vlan1_att.value.u16 = 1; - - sai_object_id_t vlan1_id; - sai_object_id_t switch_id = create_switch(); - - SWSS_LOG_NOTICE("create"); - - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan1_id, switch_id, 1, &vlan1_att); - META_ASSERT_SUCCESS(status); - - sai_attribute_t vlan; - vlan.id = SAI_VLAN_ATTR_VLAN_ID; - vlan.value.u16 = 2; - - sai_object_id_t vlan_id; - - SWSS_LOG_NOTICE("correct"); - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove tests"); - - SWSS_LOG_NOTICE("invalid vlan"); - status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, SAI_NULL_OBJECT_ID); - META_ASSERT_FAIL(status); - -// SWSS_LOG_NOTICE("default vlan"); -// status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan1_id); -// META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("success"); - status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan_id); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("non existing"); - status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan_id); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -void test_vlan_set() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_attribute_t attr; - - sai_attribute_t vlan1_att; - vlan1_att.id = SAI_VLAN_ATTR_VLAN_ID; - vlan1_att.value.u16 = 1; - - sai_object_id_t vlan1_id; - sai_object_id_t switch_id = create_switch(); - - sai_object_id_t stp = create_stp(switch_id); - - SWSS_LOG_NOTICE("create"); - - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan1_id, switch_id, 1, &vlan1_att); - META_ASSERT_SUCCESS(status); - - sai_attribute_t vlan; - vlan.id = SAI_VLAN_ATTR_VLAN_ID; - vlan.value.u16 = 2; - - sai_object_id_t vlan_id; - - SWSS_LOG_NOTICE("correct"); - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set tests"); - - SWSS_LOG_NOTICE("invalid vlan"); - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, SAI_NULL_OBJECT_ID, &vlan); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("set is null"); - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &vlan); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, NULL); - META_ASSERT_FAIL(status); - - attr.id = -1; - - SWSS_LOG_NOTICE("invalid attribute"); - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_FAIL(status); - - attr.id = SAI_VLAN_ATTR_MEMBER_LIST; - - SWSS_LOG_NOTICE("read only"); - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("max learned addresses"); - attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; - attr.value.u32 = 1; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("null stp instance"); - attr.id = SAI_VLAN_ATTR_STP_INSTANCE; - attr.value.oid = SAI_NULL_OBJECT_ID; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("wrong type on stp instance"); - attr.id = SAI_VLAN_ATTR_STP_INSTANCE; - attr.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("wrong type on stp instance"); - attr.id = SAI_VLAN_ATTR_STP_INSTANCE; - attr.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_STP,switch_id); - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("good stp oid"); - attr.id = SAI_VLAN_ATTR_STP_INSTANCE; - attr.value.oid = stp; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("learn disable"); - attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; - attr.value.booldata = false; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("metadat"); - attr.id = SAI_VLAN_ATTR_META_DATA; - attr.value.u32 = 1; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_vlan_get() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_object_id_t switch_id = create_switch(); - sai_status_t status; - - sai_attribute_t attr; - - sai_attribute_t vlan1_att; - vlan1_att.id = SAI_VLAN_ATTR_VLAN_ID; - vlan1_att.value.u16 = 1; - - sai_object_id_t vlan1_id; - - sai_object_id_t stp = create_stp(switch_id); - - SWSS_LOG_NOTICE("create"); - - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan1_id, switch_id, 1, &vlan1_att); - META_ASSERT_SUCCESS(status); - - sai_attribute_t vlan; - vlan.id = SAI_VLAN_ATTR_VLAN_ID; - vlan.value.u16 = 2; - - sai_object_id_t vlan_id; - - SWSS_LOG_NOTICE("correct"); - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get tests"); - - attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; - - SWSS_LOG_NOTICE("invalid vlan"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, 0, 1, &attr); - META_ASSERT_FAIL(status); - -// SWSS_LOG_NOTICE("invalid vlan"); -// status = g_meta->get(SAI_OBJECT_TYPE_VLAN, 3, 1, &attr); -// META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("zero attributes"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 0, &attr); - META_ASSERT_FAIL(status); - - attr.id = -1; - - SWSS_LOG_NOTICE("invalid attribute"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_FAIL(status); - - attr.id = SAI_VLAN_ATTR_MEMBER_LIST; - attr.value.objlist.count = 1; - attr.value.objlist.list = NULL; - - SWSS_LOG_NOTICE("read only null list"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_FAIL(status); - - sai_object_id_t list[5] = { }; - - list[0] = SAI_NULL_OBJECT_ID; - list[1] = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); - list[2] = create_dummy_object_id(SAI_OBJECT_TYPE_VLAN_MEMBER,switch_id); - list[3] = stp; - - attr.value.objlist.count = 0; - attr.value.objlist.list = list; - - SWSS_LOG_NOTICE("readonly 0 count and not null"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); -// META_ASSERT_SUCCESS(status); - - attr.value.objlist.count = 5; - - SWSS_LOG_NOTICE("readonly count and not null"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - attr.value.objlist.count = 0; - attr.value.objlist.list = NULL; - - SWSS_LOG_NOTICE("readonly count 0 and null"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("max learned addresses"); - attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("stp instance"); - attr.id = SAI_VLAN_ATTR_STP_INSTANCE; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("learn disable"); - attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("metadata"); - attr.id = SAI_VLAN_ATTR_META_DATA; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_vlan_flow() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - - sai_status_t status; - - sai_object_id_t vlan_id; - - sai_attribute_t at; - at.id = SAI_VLAN_ATTR_VLAN_ID; - at.value.u16 = 2; - sai_object_id_t switch_id = create_switch(); - - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &at); - META_ASSERT_SUCCESS(status); - - sai_object_id_t stp = create_stp(switch_id); - - SWSS_LOG_NOTICE("create"); - - attr.id = SAI_VLAN_ATTR_VLAN_ID; - at.value.u16 = 2; - - SWSS_LOG_NOTICE("correct"); - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("existing"); - status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("set"); - - SWSS_LOG_NOTICE("max learned addresses"); - attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; - attr.value.u32 = 1; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("good stp oid"); - attr.id = SAI_VLAN_ATTR_STP_INSTANCE; - attr.value.oid = stp; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("learn disable"); - attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; - attr.value.booldata = false; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("metadata"); - attr.id = SAI_VLAN_ATTR_META_DATA; - attr.value.u32 = 1; - status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get"); - - sai_object_id_t list[5] = { }; - - list[0] = SAI_NULL_OBJECT_ID; - list[1] = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); - list[2] = create_dummy_object_id(SAI_OBJECT_TYPE_VLAN_MEMBER,switch_id); - list[3] = stp; - - attr.value.objlist.count = 0; - attr.value.objlist.list = list; - - SWSS_LOG_NOTICE("readonly 0 count and not null"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - attr.value.objlist.count = 5; - - SWSS_LOG_NOTICE("readonly count and not null"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - attr.value.objlist.count = 0; - attr.value.objlist.list = NULL; - - SWSS_LOG_NOTICE("readonly count 0 and null"); - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("max learned addresses"); - attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("stp instance"); - attr.id = SAI_VLAN_ATTR_STP_INSTANCE; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("learn disable"); - attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("metadata"); - attr.id = SAI_VLAN_ATTR_META_DATA; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove"); - - SWSS_LOG_NOTICE("success"); - status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan_id); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("non existing"); - status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan_id); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("learn disable"); - attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; - status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -// ROUTE TESTS - -static sai_object_id_t create_next_hop( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t nh; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_NEXT_HOP_ATTR_TYPE; - attrs[0].value.s32 = SAI_NEXT_HOP_TYPE_IP; - - attrs[1].id = SAI_NEXT_HOP_ATTR_IP; - - auto rif = create_rif(switch_id); - - attrs[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; - attrs[2].value.oid = rif; - - auto status = g_meta->create(SAI_OBJECT_TYPE_NEXT_HOP, &nh, switch_id, 3, attrs); - META_ASSERT_SUCCESS(status); - - return nh; -} - -void test_route_entry_create() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - - sai_object_id_t switch_id = create_switch(); - sai_route_entry_t route_entry; - - sai_object_id_t vr = create_virtual_router(switch_id); - - sai_object_id_t hop = create_next_hop(switch_id); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - route_entry.destination.addr.ip4 = htonl(0x0a00000f); - route_entry.destination.mask.ip4 = htonl(0xffffff00); - route_entry.vr_id = vr; - route_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create tests"); - - // commented out as there is no mandatory attribute - // SWSS_LOG_NOTICE("zero attribute count (but there are mandatory attributes)"); - // attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - // status = g_meta->create(&route_entry, 0, &attr); - // META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->create(&route_entry, 1, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("route entry is null"); - status = g_meta->create((sai_route_entry_t*)NULL, 1, &attr); - META_ASSERT_FAIL(status); - - sai_attribute_t list[3] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - sai_attribute_t &attr3 = list[2]; - - attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - attr1.value.oid = hop; - - attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - attr3.id = -1; - - SWSS_LOG_NOTICE("invalid attribute id"); - status = g_meta->create(&route_entry, 3, list); - META_ASSERT_FAIL(status); - - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD + 0x100; - SWSS_LOG_NOTICE("invalid attribute value on enum"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - sai_attribute_t list2[4] = { attr1, attr2, attr2 }; - - SWSS_LOG_NOTICE("repeated attribute id"); - status = g_meta->create(&route_entry, 3, list2); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("wrong object type"); - attr1.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("non existing object"); - attr1.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_NEXT_HOP,switch_id); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - int fam = 10; - attr1.value.oid = hop; - route_entry.destination.addr_family = (sai_ip_addr_family_t)fam; - - SWSS_LOG_NOTICE("wrong address family"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("correct ipv4"); - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip62 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0x99}; - memcpy(route_entry.destination.addr.ip6, ip62, 16); - - sai_ip6_t ip6mask2 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xf7,0x00}; - memcpy(route_entry.destination.mask.ip6, ip6mask2, 16); - - SWSS_LOG_NOTICE("invalid mask"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(route_entry.destination.addr.ip6, ip6, 16); - - sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; - memcpy(route_entry.destination.mask.ip6, ip6mask, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("already exists"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -void test_route_entry_remove() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_object_id_t switch_id = create_switch(); - - sai_route_entry_t route_entry; - - sai_object_id_t vr = create_virtual_router(switch_id); - sai_object_id_t hop = create_next_hop(switch_id); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - route_entry.destination.addr.ip4 = htonl(0x0a00000f); - route_entry.destination.mask.ip4 = htonl(0xffffff00); - route_entry.vr_id = vr; - route_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create tests"); - - sai_attribute_t list[3] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - - attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - attr1.value.oid = hop; - - attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - SWSS_LOG_NOTICE("correct ipv4"); - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(route_entry.destination.addr.ip6, ip6, 16); - - sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; - memcpy(route_entry.destination.mask.ip6, ip6mask, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove tests"); - - SWSS_LOG_NOTICE("route_entry is null"); - status = g_meta->remove((sai_route_entry_t*)NULL); - META_ASSERT_FAIL(status); - - route_entry.vr_id = SAI_NULL_OBJECT_ID; - - SWSS_LOG_NOTICE("invalid object id null"); - status = g_meta->remove(&route_entry); - META_ASSERT_FAIL(status); - - route_entry.vr_id = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); - - SWSS_LOG_NOTICE("invalid object id hash"); - status = g_meta->remove(&route_entry); - META_ASSERT_FAIL(status); - - route_entry.vr_id = create_dummy_object_id(SAI_OBJECT_TYPE_VIRTUAL_ROUTER,switch_id); - - SWSS_LOG_NOTICE("invalid object id router"); - status = g_meta->remove(&route_entry); - META_ASSERT_FAIL(status); - - route_entry.vr_id = vr; - - sai_object_meta_key_t key = { .objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY, .objectkey = { .key = { .route_entry = route_entry } } }; - - META_ASSERT_TRUE(g_meta->objectExists(key)); - - SWSS_LOG_NOTICE("success"); - status = g_meta->remove(&route_entry); - META_ASSERT_SUCCESS(status); - - META_ASSERT_TRUE(!g_meta->objectExists(key)); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - route_entry.destination.addr.ip4 = htonl(0x0a00000f); - route_entry.destination.mask.ip4 = htonl(0xffffff00); - - SWSS_LOG_NOTICE("success"); - status = g_meta->remove(&route_entry); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_route_entry_set() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - sai_object_id_t switch_id = create_switch(); - - sai_route_entry_t route_entry; - - sai_object_id_t vr = create_virtual_router(switch_id); - sai_object_id_t hop = create_next_hop(switch_id); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - route_entry.destination.addr.ip4 = htonl(0x0a00000f); - route_entry.destination.mask.ip4 = htonl(0xffffff00); - route_entry.vr_id = vr; - route_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create tests"); - - sai_attribute_t list[3] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - - attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - attr1.value.oid = hop; - - attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - SWSS_LOG_NOTICE("correct ipv4"); - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(route_entry.destination.addr.ip6, ip6, 16); - - sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; - memcpy(route_entry.destination.mask.ip6, ip6mask, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set tests"); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->set(&route_entry, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("route entry is null"); - status = g_meta->set((sai_route_entry_t*)NULL, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("setting invalid attrib id"); - attr.id = -1; - status = g_meta->set(&route_entry, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("value outside range"); - attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - attr.value.s32 = 0x100; - status = g_meta->set(&route_entry, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("correct packet action"); - attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - attr.value.s32 = SAI_PACKET_ACTION_DROP; - status = g_meta->set(&route_entry, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct next hop"); - attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - attr.value.oid = hop; - status = g_meta->set(&route_entry, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct metadata"); - attr.id = SAI_ROUTE_ENTRY_ATTR_META_DATA; - attr.value.u32 = 0x12345678; - status = g_meta->set(&route_entry, &attr); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_route_entry_get() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - sai_object_id_t switch_id = create_switch(); - - sai_route_entry_t route_entry; - - sai_object_id_t vr = create_virtual_router(switch_id); - sai_object_id_t hop = create_next_hop(switch_id); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - route_entry.destination.addr.ip4 = htonl(0x0a00000f); - route_entry.destination.mask.ip4 = htonl(0xffffff00); - route_entry.vr_id = vr; - route_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create tests"); - - sai_attribute_t list[3] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - - attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - attr1.value.oid = hop; - - attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - SWSS_LOG_NOTICE("correct ipv4"); - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(route_entry.destination.addr.ip6, ip6, 16); - - sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; - memcpy(route_entry.destination.mask.ip6, ip6mask, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("zero attribute count"); - attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - status = g_meta->get(&route_entry, 0, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr is null"); - status = g_meta->get(&route_entry, 1, NULL); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("route entry is null"); - status = g_meta->get((sai_route_entry_t*)NULL, 1, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("attr id out of range"); - attr.id = -1; - status = g_meta->get(&route_entry, 1, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("correct packet action"); - attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - status = g_meta->get(&route_entry, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct next hop"); - attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - status = g_meta->get(&route_entry, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct meta"); - attr.id = SAI_ROUTE_ENTRY_ATTR_META_DATA; - status = g_meta->get(&route_entry, 1, &attr); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_route_entry_flow() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - sai_attribute_t attr; - - sai_route_entry_t route_entry; - sai_object_id_t switch_id = create_switch(); - - sai_object_id_t vr = create_virtual_router(switch_id); - sai_object_id_t hop = create_next_hop(switch_id); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - route_entry.destination.addr.ip4 = htonl(0x0a00000f); - route_entry.destination.mask.ip4 = htonl(0xffffff00); - route_entry.vr_id = vr; - route_entry.switch_id = switch_id; - - SWSS_LOG_NOTICE("create tests"); - - sai_attribute_t list[3] = { }; - - sai_attribute_t &attr1 = list[0]; - sai_attribute_t &attr2 = list[1]; - - attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - attr1.value.oid = hop; - - attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; - - SWSS_LOG_NOTICE("correct ipv4"); - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("already exists ipv4"); - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip62 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0x99}; - memcpy(route_entry.destination.addr.ip6, ip62, 16); - - sai_ip6_t ip6mask2 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xf7,0x00}; - memcpy(route_entry.destination.mask.ip6, ip6mask2, 16); - - SWSS_LOG_NOTICE("invalid mask"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; - memcpy(route_entry.destination.addr.ip6, ip6, 16); - - sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; - memcpy(route_entry.destination.mask.ip6, ip6mask, 16); - - SWSS_LOG_NOTICE("correct ipv6"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("already exists"); - status = g_meta->create(&route_entry, 2, list); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("set tests"); - - SWSS_LOG_NOTICE("correct packet action"); - attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - attr.value.s32 = SAI_PACKET_ACTION_DROP; - status = g_meta->set(&route_entry, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct next hop"); - attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - attr.value.oid = hop; - status = g_meta->set(&route_entry, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct metadata"); - attr.id = SAI_ROUTE_ENTRY_ATTR_META_DATA; - attr.value.u32 = 0x12345678; - status = g_meta->set(&route_entry, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get tests"); - - SWSS_LOG_NOTICE("correct packet action"); - attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; - status = g_meta->get(&route_entry, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct next hop"); - attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - status = g_meta->get(&route_entry, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("correct meta"); - attr.id = SAI_ROUTE_ENTRY_ATTR_META_DATA; - status = g_meta->get(&route_entry, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove tests"); - - SWSS_LOG_NOTICE("success"); - status = g_meta->remove(&route_entry); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("non existing"); - status = g_meta->remove(&route_entry); - META_ASSERT_FAIL(status); - - route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - route_entry.destination.addr.ip4 = htonl(0x0a00000f); - route_entry.destination.mask.ip4 = htonl(0xffffff00); - - SWSS_LOG_NOTICE("success"); - status = g_meta->remove(&route_entry); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("non existing"); - status = g_meta->remove(&route_entry); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -// SERIALIZATION TYPES TESTS - -void test_serialization_type_vlan_list() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - SWSS_LOG_NOTICE("create stp"); - sai_object_id_t switch_id = create_switch(); - - sai_object_id_t stp = create_stp(switch_id); - - sai_vlan_id_t list[2] = { 1, 2 }; - - sai_attribute_t attr; - - attr.id = SAI_STP_ATTR_VLAN_LIST; - attr.value.vlanlist.count = 2; - attr.value.vlanlist.list = list; - - SWSS_LOG_NOTICE("set vlan list"); - - status = g_meta->set(SAI_OBJECT_TYPE_STP, stp, &attr); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("get vlan list"); - - status = g_meta->get(SAI_OBJECT_TYPE_STP, stp, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove stp"); - - status = g_meta->remove(SAI_OBJECT_TYPE_STP, stp); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_serialization_type_bool() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_object_id_t vr; - - SWSS_LOG_NOTICE("create stp"); - sai_object_id_t switch_id = create_switch(); - - sai_attribute_t attr; - - attr.id = SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V4_STATE; - attr.value.booldata = true; - - status = g_meta->create(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, &vr, switch_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set bool"); - - status = g_meta->set(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, vr, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get bool"); - - status = g_meta->get(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, vr, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove vr"); - - status = g_meta->remove(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, vr); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_serialization_type_char() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_object_id_t hostif; - - SWSS_LOG_NOTICE("create port"); - sai_object_id_t switch_id = create_switch(); - - sai_object_id_t port = create_port(switch_id); - - sai_attribute_t attr, attr2, attr3; - - attr.id = SAI_HOSTIF_ATTR_TYPE; - attr.value.s32 = SAI_HOSTIF_TYPE_NETDEV; - - attr2.id = SAI_HOSTIF_ATTR_OBJ_ID; - attr2.value.oid = port; - - attr3.id = SAI_HOSTIF_ATTR_NAME; - - memcpy(attr3.value.chardata, "foo", sizeof("foo")); - - sai_attribute_t list[3] = { attr, attr2, attr3 }; - - // TODO we need to support conditions here - - SWSS_LOG_NOTICE("create hostif"); - - status = g_meta->create(SAI_OBJECT_TYPE_HOSTIF, &hostif, switch_id, 3, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set char"); - - status = g_meta->set(SAI_OBJECT_TYPE_HOSTIF, hostif, &attr3); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("get char"); - - status = g_meta->get(SAI_OBJECT_TYPE_HOSTIF, hostif, 1, &attr3); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove hostif"); - - status = g_meta->remove(SAI_OBJECT_TYPE_HOSTIF, hostif); - META_ASSERT_SUCCESS(status); - - attr.id = SAI_HOSTIF_ATTR_TYPE; - attr.value.s32 = SAI_HOSTIF_TYPE_FD; - - sai_attribute_t list2[1] = { attr }; - - SWSS_LOG_NOTICE("create hostif with non mandatory"); - status = g_meta->create(SAI_OBJECT_TYPE_HOSTIF, &hostif, switch_id, 1, list2); - META_ASSERT_SUCCESS(status); - -// TODO this test should pass, we are doing query here for conditional -// attribute, where condition is not met so this attribute will not be used, so -// metadata should figure out that we can't query this attribute, but there is -// a problem with internal existing objects, since we don't have their values -// then we we can't tell whether attribute was passed or not, we need to get -// switch discovered objects and attributes and populate local db then we need -// to update metadata condition in meta_generic_validation_get method where we -// check if attribute is conditional -// -// SWSS_LOG_NOTICE("get char"); -// -// status = g_meta->get(SAI_OBJECT_TYPE_HOSTIF, hostif, 1, &attr2); -// META_ASSERT_FAIL(status); - - attr.id = SAI_HOSTIF_ATTR_TYPE; - attr.value.s32 = SAI_HOSTIF_TYPE_NETDEV; - - sai_attribute_t list3[1] = { attr }; - - SWSS_LOG_NOTICE("create hostif with mandatory missing"); - status = g_meta->create(SAI_OBJECT_TYPE_HOSTIF, &hostif, switch_id, 1, list3); - META_ASSERT_FAIL(status); - - remove_switch(switch_id); -} - -void test_serialization_type_int32_list() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_object_id_t hash; - - sai_attribute_t attr; - - SWSS_LOG_NOTICE("create hash"); - sai_object_id_t switch_id = create_switch(); - - int32_t list[2] = { SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_VLAN_ID }; - - attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; - attr.value.s32list.count = 2; - attr.value.s32list.list = list; - - status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set hash"); - - status = g_meta->set(SAI_OBJECT_TYPE_HASH, hash, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get hash"); - - status = g_meta->get(SAI_OBJECT_TYPE_HASH, hash, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove hash"); - - status = g_meta->remove(SAI_OBJECT_TYPE_HASH, hash); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_serialization_type_uint32_list() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_object_id_t hash; - - sai_attribute_t attr; - - SWSS_LOG_NOTICE("create hash"); - sai_object_id_t switch_id = create_switch(); - - int32_t list[2] = { SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_VLAN_ID }; - - attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; - attr.value.s32list.count = 2; - attr.value.s32list.list = list; - - status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("set hash"); - - status = g_meta->set(SAI_OBJECT_TYPE_HASH, hash, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("get hash"); - - status = g_meta->get(SAI_OBJECT_TYPE_HASH, hash, 1, &attr); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove hash"); - - status = g_meta->remove(SAI_OBJECT_TYPE_HASH, hash); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -// OTHER - -void test_mask() -{ - SWSS_LOG_ENTER(); - - sai_ip6_t ip6mask1 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; - sai_ip6_t ip6mask2 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0xff}; - sai_ip6_t ip6mask3 = {0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00}; - sai_ip6_t ip6mask4 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0xfe}; - sai_ip6_t ip6mask5 = {0x80, 0x00, 0x00, 0x00,0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00}; - - sai_ip6_t ip6mask6 = {0x01, 0x00, 0x00, 0x00,0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00}; - sai_ip6_t ip6mask7 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x8f}; - sai_ip6_t ip6mask8 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x8f}; - sai_ip6_t ip6mask9 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xf1, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0xff}; - - META_ASSERT_TRUE(Meta::is_ipv6_mask_valid(ip6mask1)); - META_ASSERT_TRUE(Meta::is_ipv6_mask_valid(ip6mask2)); - META_ASSERT_TRUE(Meta::is_ipv6_mask_valid(ip6mask3)); - META_ASSERT_TRUE(Meta::is_ipv6_mask_valid(ip6mask4)); - META_ASSERT_TRUE(Meta::is_ipv6_mask_valid(ip6mask5)); - - META_ASSERT_TRUE(!Meta::is_ipv6_mask_valid(ip6mask6)); - META_ASSERT_TRUE(!Meta::is_ipv6_mask_valid(ip6mask7)); - META_ASSERT_TRUE(!Meta::is_ipv6_mask_valid(ip6mask8)); - META_ASSERT_TRUE(!Meta::is_ipv6_mask_valid(ip6mask9)); -} - -static sai_object_id_t create_acl_table( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t at; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_ACL_TABLE_ATTR_ACL_STAGE; - attrs[0].value.s32 = SAI_ACL_STAGE_INGRESS; - - auto status = g_meta->create(SAI_OBJECT_TYPE_ACL_TABLE, &at, switch_id, 1, attrs); - META_ASSERT_SUCCESS(status); - - return at; -} - -static sai_object_id_t create_acl_counter( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t ac; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_ACL_COUNTER_ATTR_TABLE_ID; - attrs[0].value.oid = create_acl_table(switch_id); - - auto status = g_meta->create(SAI_OBJECT_TYPE_ACL_COUNTER, &ac, switch_id, 1, attrs); - META_ASSERT_SUCCESS(status); - - return ac; -} - -static sai_object_id_t create_policer( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t policer; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_POLICER_ATTR_METER_TYPE; - attrs[0].value.s32 = SAI_METER_TYPE_PACKETS; - attrs[1].id = SAI_POLICER_ATTR_MODE; - attrs[1].value.s32 = SAI_POLICER_MODE_SR_TCM; - - auto status = g_meta->create(SAI_OBJECT_TYPE_POLICER, &policer, switch_id, 2, attrs); - META_ASSERT_SUCCESS(status); - - return policer; -} - -static sai_object_id_t create_samplepacket( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t sp; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE; - attrs[0].value.u32 = 1; - - auto status = g_meta->create(SAI_OBJECT_TYPE_SAMPLEPACKET, &sp, switch_id, 1, attrs); - META_ASSERT_SUCCESS(status); - - return sp; -} - -static sai_object_id_t create_hostif_udt( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t udt; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_HOSTIF_USER_DEFINED_TRAP_ATTR_TYPE; - attrs[0].value.s32 = SAI_HOSTIF_USER_DEFINED_TRAP_TYPE_ROUTER; - - auto status = g_meta->create(SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP, &udt, switch_id, 1, attrs); - META_ASSERT_SUCCESS(status); - - return udt; -} - -static sai_object_id_t create_ipg( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t ipg; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_INGRESS_PRIORITY_GROUP_ATTR_PORT; - attrs[0].value.oid = create_port(switch_id); - attrs[1].id = SAI_INGRESS_PRIORITY_GROUP_ATTR_INDEX; - attrs[1].value.u8 = 0; - - auto status = g_meta->create(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, &ipg, switch_id, 2, attrs); - META_ASSERT_SUCCESS(status); - - return ipg; -} - -sai_object_id_t insert_dummy_object( - _In_ sai_object_type_t ot, - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - switch (ot) - { - case SAI_OBJECT_TYPE_PORT: - return create_port(switch_id); - - case SAI_OBJECT_TYPE_ACL_TABLE: - return create_acl_table(switch_id); - - case SAI_OBJECT_TYPE_ACL_COUNTER: - return create_acl_counter(switch_id); - - case SAI_OBJECT_TYPE_POLICER: - return create_policer(switch_id); - - case SAI_OBJECT_TYPE_SAMPLEPACKET: - return create_samplepacket(switch_id); - - case SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP: - return create_hostif_udt(switch_id); - - case SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP: - return create_ipg(switch_id); - - default: - - SWSS_LOG_THROW("not implemented: %s, FIXME", sai_serialize_object_type(ot).c_str()); - } -} - -void test_acl_entry_field_and_action() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_object_id_t switch_id = create_switch(); - sai_status_t status; - - sai_object_id_t aclentry; - - int32_t ids[] = { - SAI_ACL_ENTRY_ATTR_TABLE_ID, - SAI_ACL_ENTRY_ATTR_PRIORITY, - SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6, - SAI_ACL_ENTRY_ATTR_FIELD_DST_IPV6, - SAI_ACL_ENTRY_ATTR_FIELD_SRC_MAC, - SAI_ACL_ENTRY_ATTR_FIELD_DST_MAC, - SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP, - SAI_ACL_ENTRY_ATTR_FIELD_DST_IP, - SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS, - SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS, - SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT, - SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORT, - SAI_ACL_ENTRY_ATTR_FIELD_SRC_PORT, - SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID, - SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_PRI, - SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_CFI, - SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_ID, - SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_PRI, - SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_CFI, - SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT, - SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT, - SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE, - SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL, - SAI_ACL_ENTRY_ATTR_FIELD_DSCP, - SAI_ACL_ENTRY_ATTR_FIELD_ECN, - SAI_ACL_ENTRY_ATTR_FIELD_TTL, - SAI_ACL_ENTRY_ATTR_FIELD_TOS, - SAI_ACL_ENTRY_ATTR_FIELD_IP_FLAGS, - SAI_ACL_ENTRY_ATTR_FIELD_TCP_FLAGS, - SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_FRAG, - SAI_ACL_ENTRY_ATTR_FIELD_IPV6_FLOW_LABEL, - SAI_ACL_ENTRY_ATTR_FIELD_TC, - SAI_ACL_ENTRY_ATTR_FIELD_ICMP_TYPE, - SAI_ACL_ENTRY_ATTR_FIELD_ICMP_CODE, - SAI_ACL_ENTRY_ATTR_FIELD_FDB_DST_USER_META, - SAI_ACL_ENTRY_ATTR_FIELD_ROUTE_DST_USER_META, - SAI_ACL_ENTRY_ATTR_FIELD_NEIGHBOR_DST_USER_META, - SAI_ACL_ENTRY_ATTR_FIELD_PORT_USER_META, - SAI_ACL_ENTRY_ATTR_FIELD_VLAN_USER_META, - SAI_ACL_ENTRY_ATTR_FIELD_ACL_USER_META, - SAI_ACL_ENTRY_ATTR_FIELD_FDB_NPU_META_DST_HIT, - SAI_ACL_ENTRY_ATTR_FIELD_NEIGHBOR_NPU_META_DST_HIT, - SAI_ACL_ENTRY_ATTR_FIELD_ROUTE_NPU_META_DST_HIT, - SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT, - //SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT_LIST, - SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION, - SAI_ACL_ENTRY_ATTR_ACTION_FLOOD, - SAI_ACL_ENTRY_ATTR_ACTION_COUNTER, - SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS, - SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS, - SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER, - SAI_ACL_ENTRY_ATTR_ACTION_DECREMENT_TTL, - SAI_ACL_ENTRY_ATTR_ACTION_SET_TC, - SAI_ACL_ENTRY_ATTR_ACTION_SET_PACKET_COLOR, - SAI_ACL_ENTRY_ATTR_ACTION_SET_INNER_VLAN_ID, - SAI_ACL_ENTRY_ATTR_ACTION_SET_INNER_VLAN_PRI, - SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_ID, - SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_PRI, - SAI_ACL_ENTRY_ATTR_ACTION_SET_SRC_MAC, - SAI_ACL_ENTRY_ATTR_ACTION_SET_DST_MAC, - SAI_ACL_ENTRY_ATTR_ACTION_SET_SRC_IP, - SAI_ACL_ENTRY_ATTR_ACTION_SET_DST_IP, - SAI_ACL_ENTRY_ATTR_ACTION_SET_SRC_IPV6, - SAI_ACL_ENTRY_ATTR_ACTION_SET_DST_IPV6, - SAI_ACL_ENTRY_ATTR_ACTION_SET_DSCP, - SAI_ACL_ENTRY_ATTR_ACTION_SET_ECN, - SAI_ACL_ENTRY_ATTR_ACTION_SET_L4_SRC_PORT, - SAI_ACL_ENTRY_ATTR_ACTION_SET_L4_DST_PORT, - SAI_ACL_ENTRY_ATTR_ACTION_INGRESS_SAMPLEPACKET_ENABLE, - SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_SAMPLEPACKET_ENABLE, - SAI_ACL_ENTRY_ATTR_ACTION_SET_ACL_META_DATA, - SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_BLOCK_PORT_LIST, - SAI_ACL_ENTRY_ATTR_ACTION_SET_USER_TRAP_ID, - }; - - std::vector vattrs; - - // all lists are empty we need info if that is possible - - for (uint32_t i = 0; i < sizeof(ids)/sizeof(int32_t); ++i) - { - sai_attribute_t attr; - - memset(&attr,0,sizeof(attr)); - - attr.value.aclfield.enable = true; - attr.value.aclaction.enable = true; - - attr.id = ids[i]; - - if (attr.id == SAI_ACL_ENTRY_ATTR_TABLE_ID) - attr.value.oid = insert_dummy_object(SAI_OBJECT_TYPE_ACL_TABLE,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT) - attr.value.aclfield.data.oid = insert_dummy_object(SAI_OBJECT_TYPE_PORT,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORT) - attr.value.aclfield.data.oid = insert_dummy_object(SAI_OBJECT_TYPE_PORT,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_FIELD_SRC_PORT) - attr.value.aclfield.data.oid = insert_dummy_object(SAI_OBJECT_TYPE_PORT,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT) - attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_PORT,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_COUNTER) - attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_ACL_COUNTER,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER) - attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_POLICER,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_INGRESS_SAMPLEPACKET_ENABLE) - attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_SAMPLEPACKET,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_SAMPLEPACKET_ENABLE) - attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_SAMPLEPACKET,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_SET_USER_TRAP_ID) - attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP,switch_id); - - if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT_LIST) - { - sai_object_id_t list[1]; - - list[0] = insert_dummy_object(SAI_OBJECT_TYPE_QUEUE,switch_id); - - SWSS_LOG_NOTICE("0x%" PRIx64, list[0]); - - attr.value.aclaction.parameter.objlist.count = 1; - attr.value.aclaction.parameter.objlist.list = list; - } - - vattrs.push_back(attr); - } - - SWSS_LOG_NOTICE("create acl entry"); - - status = g_meta->create(SAI_OBJECT_TYPE_ACL_ENTRY, &aclentry, switch_id, (uint32_t)vattrs.size(), vattrs.data()); - META_ASSERT_SUCCESS(status); - - for (uint32_t i = 0; i < sizeof(ids)/sizeof(int32_t); ++i) - { - if (vattrs[i].id == SAI_ACL_ENTRY_ATTR_TABLE_ID) - continue; - - auto m = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, vattrs[i].id); - - SWSS_LOG_NOTICE("set aclentry %u %s", i, m->attridname); - - status = g_meta->set(SAI_OBJECT_TYPE_ACL_ENTRY, aclentry, &vattrs[i]); - META_ASSERT_SUCCESS(status); - } - - SWSS_LOG_NOTICE("get aclentry"); - - status = g_meta->get(SAI_OBJECT_TYPE_ACL_ENTRY, aclentry, (uint32_t)vattrs.size(), vattrs.data()); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("remove aclentry"); - - status = g_meta->remove(SAI_OBJECT_TYPE_ACL_ENTRY, aclentry); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_construct_key() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - - uint32_t list[4] = {1,2,3,4}; - - attr.id = SAI_PORT_ATTR_HW_LANE_LIST; - attr.value.u32list.count = 4; - attr.value.u32list.list = list; - - sai_object_meta_key_t meta_key; - - meta_key.objecttype = SAI_OBJECT_TYPE_PORT; - - sai_object_id_t switchId = 0x21000000000000; - - std::string key = AttrKeyMap::constructKey(switchId, meta_key, 1, &attr); - - SWSS_LOG_NOTICE("constructed key: %s", key.c_str()); - - META_ASSERT_TRUE(key == "oid:0x21000000000000;SAI_PORT_ATTR_HW_LANE_LIST:1,2,3,4;"); -} - -static sai_object_id_t create_scheduler_group( - _In_ sai_object_id_t switch_id) -{ - SWSS_LOG_ENTER(); - - sai_object_id_t sg; - - sai_attribute_t attrs[9] = { }; - - attrs[0].id = SAI_SCHEDULER_GROUP_ATTR_PORT_ID; - attrs[0].value.oid = create_port(switch_id); - attrs[1].id = SAI_SCHEDULER_GROUP_ATTR_LEVEL; - attrs[1].value.u8 = 0; - attrs[2].id = SAI_SCHEDULER_GROUP_ATTR_MAX_CHILDS; - attrs[2].value.u8 = 1; - attrs[3].id = SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE; - attrs[3].value.oid = attrs[0].value.oid; - - auto status = g_meta->create(SAI_OBJECT_TYPE_SCHEDULER_GROUP, &sg, switch_id, 4, attrs); - META_ASSERT_SUCCESS(status); - - return sg; -} - -void test_queue_create() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_object_id_t switch_id = create_switch(); - - sai_status_t status; - sai_object_id_t queue; - - sai_attribute_t attr1; - sai_attribute_t attr2; - sai_attribute_t attr3; - sai_attribute_t attr4; - - attr1.id = SAI_QUEUE_ATTR_TYPE; - attr1.value.s32 = SAI_QUEUE_TYPE_UNICAST; - - attr2.id = SAI_QUEUE_ATTR_INDEX; - attr2.value.u8 = 7; - - attr3.id = SAI_QUEUE_ATTR_PORT; - attr3.value.oid = create_port(switch_id); - - attr4.id = SAI_QUEUE_ATTR_PARENT_SCHEDULER_NODE; - attr4.value.oid = create_scheduler_group(switch_id); - - sai_attribute_t list[4] = { attr1, attr2, attr3, attr4 }; - - SWSS_LOG_NOTICE("create tests"); - - SWSS_LOG_NOTICE("create queue"); - status = g_meta->create(SAI_OBJECT_TYPE_QUEUE, &queue, switch_id, 4, list); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("create queue but key exists"); - status = g_meta->create(SAI_OBJECT_TYPE_QUEUE, &queue, switch_id, 4, list); - META_ASSERT_FAIL(status); - - SWSS_LOG_NOTICE("remove queue"); - status = g_meta->remove(SAI_OBJECT_TYPE_QUEUE, queue); - META_ASSERT_SUCCESS(status); - - SWSS_LOG_NOTICE("create queue"); - status = g_meta->create(SAI_OBJECT_TYPE_QUEUE, &queue, switch_id, 4, list); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_null_list() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_status_t status; - - sai_object_id_t hash; - - sai_attribute_t attr; - - int32_t list[2] = { SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_VLAN_ID }; - - attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; - attr.value.s32list.count = 0; - attr.value.s32list.list = list; - sai_object_id_t switch_id = create_switch(); - - SWSS_LOG_NOTICE("0 count, not null list"); - status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 1, &attr); - META_ASSERT_FAIL(status); - - attr.value.s32list.list = NULL; - - SWSS_LOG_NOTICE("0 count, null list"); - status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 1, &attr); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -void test_priority_group() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_object_id_t switch_id = create_switch(); - - sai_status_t status; - - sai_attribute_t attr; - - sai_object_id_t pg = insert_dummy_object(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, switch_id); - - SWSS_LOG_NOTICE("set SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE attr"); - - attr.id = SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE; - attr.value.oid = SAI_NULL_OBJECT_ID; - status = g_meta->set(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, pg, &attr); - META_ASSERT_SUCCESS(status); - - remove_switch(switch_id); -} - -#define ASSERT_TRUE(x,y)\ - if ((x) != y) { std::cout << "assert true failed: '" << x << "' != '" << y << "'" << std::endl; throw; } - -#define ASSERT_FAIL(msg) \ - { std::cout << "assert failed: " << msg << std::endl; throw; } - -void test_serialize_bool() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - // test bool - - attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; - attr.value.booldata = true; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "true"); - - attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; - attr.value.booldata = false; - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "false"); - - // deserialize - - attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; - - sai_deserialize_attr_value("true", *meta, attr); - ASSERT_TRUE(true, attr.value.booldata); - - sai_deserialize_attr_value("false", *meta, attr); - ASSERT_TRUE(false, attr.value.booldata); - - try - { - sai_deserialize_attr_value("xx", *meta, attr); - ASSERT_FAIL("invalid bool deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } -} - -void test_serialize_chardata() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - memset(attr.value.chardata, 0, 32); - - attr.id = SAI_HOSTIF_ATTR_NAME; - memcpy(attr.value.chardata, "foo", sizeof("foo")); - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "foo"); - - attr.id = SAI_HOSTIF_ATTR_NAME; - memcpy(attr.value.chardata, "f\\oo\x12", sizeof("f\\oo\x12")); - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "f\\\\oo\\x12"); - - attr.id = SAI_HOSTIF_ATTR_NAME; - memcpy(attr.value.chardata, "\x80\xff", sizeof("\x80\xff")); - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "\\x80\\xFF"); - - // deserialize - - sai_deserialize_attr_value("f\\\\oo\\x12", *meta, attr); - - SWSS_LOG_NOTICE("des: %s", attr.value.chardata); - - ASSERT_TRUE(0, strcmp(attr.value.chardata, "f\\oo\x12")); - - sai_deserialize_attr_value("foo", *meta, attr); - - ASSERT_TRUE(0, strcmp(attr.value.chardata, "foo")); - - try - { - sai_deserialize_attr_value("\\x2g", *meta, attr); - ASSERT_FAIL("invalid chardata deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } - - try - { - sai_deserialize_attr_value("\\x2", *meta, attr); - ASSERT_FAIL("invalid chardata deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } - - try - { - sai_deserialize_attr_value("\\s45", *meta, attr); - ASSERT_FAIL("invalid chardata deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } - - try - { - sai_deserialize_attr_value("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", *meta, attr); - ASSERT_FAIL("invalid chardata deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } -} - -void test_serialize_uint64() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_SWITCH_ATTR_NV_STORAGE_SIZE; - attr.value.u64 = 42; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "42"); - attr.value.u64 = 0x87654321aabbccdd; - - attr.id = SAI_SWITCH_ATTR_NV_STORAGE_SIZE; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - char buf[32]; - sprintf(buf, "%" PRIu64, attr.value.u64); - - ASSERT_TRUE(s, std::string(buf)); - - // deserialize - - sai_deserialize_attr_value("12345", *meta, attr); - - ASSERT_TRUE(12345, attr.value.u64); - - try - { - sai_deserialize_attr_value("22345235345345345435", *meta, attr); - ASSERT_FAIL("invalid u64 deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } - - try - { - sai_deserialize_attr_value("2a", *meta, attr); - ASSERT_FAIL("invalid u64 deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } -} - -void test_serialize_enum() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; - attr.value.s32 = SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD"); - - attr.value.s32 = -1; - - attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "-1"); - - attr.value.s32 = 100; - - attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "100"); - - // deserialize - - sai_deserialize_attr_value("12345", *meta, attr); - - ASSERT_TRUE(12345, attr.value.s32); - - sai_deserialize_attr_value("-1", *meta, attr); - - ASSERT_TRUE(-1, attr.value.s32); - - sai_deserialize_attr_value("SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD", *meta, attr); - - ASSERT_TRUE(SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD, attr.value.s32); - - try - { - sai_deserialize_attr_value("foo", *meta, attr); - ASSERT_FAIL("invalid s32 deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } -} - -void test_serialize_mac() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS; - memcpy(attr.value.mac, "\x01\x22\x33\xaa\xbb\xcc", 6); - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "01:22:33:AA:BB:CC"); - - // deserialize - - sai_deserialize_attr_value("ff:ee:dd:33:44:55", *meta, attr); - - ASSERT_TRUE(0, memcmp("\xff\xee\xdd\x33\x44\x55", attr.value.mac, 6)); - - try - { - sai_deserialize_attr_value("foo", *meta, attr); - ASSERT_FAIL("invalid s32 deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } -} - -void test_serialize_ip_address() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP; - attr.value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - attr.value.ipaddr.addr.ip4 = htonl(0x0a000015); - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "10.0.0.21"); - - attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP; - attr.value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV6; - - uint16_t ip6[] = { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0xaaaa, 0xbbbb }; - - memcpy(attr.value.ipaddr.addr.ip6, ip6, 16); - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "1111:2222:3333:4444:5555:6666:aaaa:bbbb"); - - uint16_t ip6a[] = { 0x0100, 0 ,0 ,0 ,0 ,0 ,0 ,0xff00 }; - - memcpy(attr.value.ipaddr.addr.ip6, ip6a, 16); - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "1::ff"); - - uint16_t ip6b[] = { 0, 0 ,0 ,0 ,0 ,0 ,0 ,0x100 }; - - memcpy(attr.value.ipaddr.addr.ip6, ip6b, 16); - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "::1"); - - try - { - // invalid address family - int k = 100; - attr.value.ipaddr.addr_family = (sai_ip_addr_family_t)k; - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_FAIL("invalid family not throw exception"); - } - catch (const std::runtime_error &e) - { - // ok - } - - // deserialize - - sai_deserialize_attr_value("10.0.0.23", *meta, attr); - - ASSERT_TRUE(attr.value.ipaddr.addr.ip4, htonl(0x0a000017)); - ASSERT_TRUE(attr.value.ipaddr.addr_family, SAI_IP_ADDR_FAMILY_IPV4); - - sai_deserialize_attr_value("1::ff", *meta, attr); - - ASSERT_TRUE(0, memcmp(attr.value.ipaddr.addr.ip6, ip6a, 16)); - ASSERT_TRUE(attr.value.ipaddr.addr_family, SAI_IP_ADDR_FAMILY_IPV6); - - try - { - sai_deserialize_attr_value("foo", *meta, attr); - ASSERT_FAIL("invalid s32 deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } -} - -void test_serialize_uint32_list() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_PORT_ATTR_SUPPORTED_SPEED; //SAI_PORT_ATTR_SUPPORTED_HALF_DUPLEX_SPEED; - - uint32_t list[] = {1,2,3,4,5,6,7}; - - attr.value.u32list.count = 7; - attr.value.u32list.list = NULL; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "7:null"); - - attr.value.u32list.list = list; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "7:1,2,3,4,5,6,7"); - - attr.value.u32list.count = 0; - attr.value.u32list.list = list; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "0:null"); - - attr.value.u32list.count = 0; - attr.value.u32list.list = NULL; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "0:null"); - - memset(&attr, 0, sizeof(attr)); - - sai_deserialize_attr_value("7:1,2,3,4,5,6,7", *meta, attr, false); - - ASSERT_TRUE(attr.value.u32list.count, 7); - ASSERT_TRUE(attr.value.u32list.list[0], 1); - ASSERT_TRUE(attr.value.u32list.list[1], 2); - ASSERT_TRUE(attr.value.u32list.list[2], 3); - ASSERT_TRUE(attr.value.u32list.list[3], 4); -} - -void test_serialize_enum_list() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; - - int32_t list[] = { - SAI_NATIVE_HASH_FIELD_SRC_IP, - SAI_NATIVE_HASH_FIELD_DST_IP, - SAI_NATIVE_HASH_FIELD_VLAN_ID, - 77 - }; - - attr.value.s32list.count = 4; - attr.value.s32list.list = NULL; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "4:null"); - - attr.value.s32list.list = list; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - // or for enum: 4:SAI_NATIVE_HASH_FIELD[SRC_IP,DST_IP,VLAN_ID,77] - - ASSERT_TRUE(s, "4:SAI_NATIVE_HASH_FIELD_SRC_IP,SAI_NATIVE_HASH_FIELD_DST_IP,SAI_NATIVE_HASH_FIELD_VLAN_ID,77"); - - attr.value.s32list.count = 0; - attr.value.s32list.list = list; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "0:null"); - - attr.value.s32list.count = 0; - attr.value.s32list.list = NULL; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "0:null"); -} - -void test_serialize_oid() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID; - - attr.value.oid = 0x1234567890abcdef; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "oid:0x1234567890abcdef"); - - // deserialize - - sai_deserialize_attr_value("oid:0x1234567890abcdef", *meta, attr); - - ASSERT_TRUE(0x1234567890abcdef, attr.value.oid); - - try - { - sai_deserialize_attr_value("foo", *meta, attr); - ASSERT_FAIL("invalid oid deserialize failed to throw exception"); - } - catch (const std::runtime_error& e) - { - // ok - } -} - -void test_serialize_oid_list() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_SWITCH_ATTR_PORT_LIST; - - sai_object_id_t list[] = { - 1,0x42, 0x77 - }; - - attr.value.objlist.count = 3; - attr.value.objlist.list = NULL; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "3:null"); - - attr.value.objlist.list = list; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - // or: 4:[ROUTE:0x1,PORT:0x3,oid:0x77] if we have query function - - ASSERT_TRUE(s, "3:oid:0x1,oid:0x42,oid:0x77"); - - attr.value.objlist.count = 0; - attr.value.objlist.list = list; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "0:null"); - - attr.value.objlist.count = 0; - attr.value.objlist.list = NULL; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "0:null"); - - memset(&attr, 0, sizeof(attr)); - - // deserialize - - sai_deserialize_attr_value("3:oid:0x1,oid:0x42,oid:0x77", *meta, attr, false); - - ASSERT_TRUE(attr.value.objlist.count, 3); - ASSERT_TRUE(attr.value.objlist.list[0], 0x1); - ASSERT_TRUE(attr.value.objlist.list[1], 0x42); - ASSERT_TRUE(attr.value.objlist.list[2], 0x77); -} - -void test_serialize_acl_action() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT; - - attr.value.aclaction.enable = true; - attr.value.aclaction.parameter.oid = (sai_object_id_t)2; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "oid:0x2"); - - attr.value.aclaction.enable = false; - attr.value.aclaction.parameter.oid = (sai_object_id_t)2; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "disabled"); - - attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; - - attr.value.aclaction.enable = true; - attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_TRAP; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "SAI_PACKET_ACTION_TRAP"); - - attr.value.aclaction.enable = true; - attr.value.aclaction.parameter.s32 = 77; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - ASSERT_TRUE(s, "77"); -} - -void test_serialize_qos_map() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - sai_attribute_t attr; - const sai_attr_metadata_t* meta; - std::string s; - - attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST; - - sai_qos_map_t qm = { - .key = { .tc = 1, .dscp = 2, .dot1p = 3, .prio = 4, .pg = 5, .queue_index = 6, .color = SAI_PACKET_COLOR_RED, .mpls_exp = 0 }, - .value = { .tc = 11, .dscp = 22, .dot1p = 33, .prio = 44, .pg = 55, .queue_index = 66, .color = SAI_PACKET_COLOR_GREEN, .mpls_exp = 0 } }; - - attr.value.qosmap.count = 1; - attr.value.qosmap.list = &qm; - - meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_QOS_MAP, attr.id); - - s = sai_serialize_attr_value(*meta, attr); - - std::string ret = "{\"count\":1,\"list\":[{\"key\":{\"color\":\"SAI_PACKET_COLOR_RED\",\"dot1p\":3,\"dscp\":2,\"mpls_exp\":0,\"pg\":5,\"prio\":4,\"qidx\":6,\"tc\":1},\"value\":{\"color\":\"SAI_PACKET_COLOR_GREEN\",\"dot1p\":33,\"dscp\":22,\"mpls_exp\":0,\"pg\":55,\"prio\":44,\"qidx\":66,\"tc\":11}}]}"; - - ASSERT_TRUE(s, ret); - - s = sai_serialize_attr_value(*meta, attr, true); - - std::string ret2 = "{\"count\":1,\"list\":null}"; - ASSERT_TRUE(s, ret2); - - // deserialize - - memset(&attr, 0, sizeof(attr)); - - sai_deserialize_attr_value(ret, *meta, attr); - - ASSERT_TRUE(attr.value.qosmap.count, 1); - - auto &l = attr.value.qosmap.list[0]; - ASSERT_TRUE(l.key.tc, 1); - ASSERT_TRUE(l.key.dscp, 2); - ASSERT_TRUE(l.key.dot1p, 3); - ASSERT_TRUE(l.key.prio, 4); - ASSERT_TRUE(l.key.pg, 5); - ASSERT_TRUE(l.key.queue_index, 6); - ASSERT_TRUE(l.key.color, SAI_PACKET_COLOR_RED); - ASSERT_TRUE(l.key.mpls_exp, 0); - - ASSERT_TRUE(l.value.tc, 11); - ASSERT_TRUE(l.value.dscp, 22); - ASSERT_TRUE(l.value.dot1p, 33); - ASSERT_TRUE(l.value.prio, 44); - ASSERT_TRUE(l.value.pg, 55); - ASSERT_TRUE(l.value.queue_index, 66); - ASSERT_TRUE(l.value.color, SAI_PACKET_COLOR_GREEN); - ASSERT_TRUE(l.value.mpls_exp, 0); -} - -template -void deserialize_number( - _In_ const std::string& s, - _Out_ T& number, - _In_ bool hex = false) -{ - SWSS_LOG_ENTER(); - - errno = 0; - - char *endptr = NULL; - - number = (T)strtoull(s.c_str(), &endptr, hex ? 16 : 10); - - if (errno != 0 || endptr != s.c_str() + s.length()) - { - SWSS_LOG_THROW("invalid number %s", s.c_str()); - } -} - -template -std::string serialize_number( - _In_ const T& number, - _In_ bool hex = false) -{ - SWSS_LOG_ENTER(); - - if (hex) - { - char buf[32]; - - snprintf(buf, sizeof(buf), "0x%" PRIx64, (uint64_t)number); - - return buf; - } - - return std::to_string(number); -} - -void test_numbers() -{ - SWSS_LOG_ENTER(); - - int64_t sp = 0x12345678; - int64_t sn = -0x12345678; - int64_t u = 0x12345678; - - auto ssp = serialize_number(sp); - auto ssn = serialize_number(sn); - auto su = serialize_number(u); - - ASSERT_TRUE(ssp, std::to_string(sp)); - ASSERT_TRUE(ssn, std::to_string(sn)); - ASSERT_TRUE(su, std::to_string(u)); - - auto shsp = serialize_number(sp, true); - auto shsn = serialize_number(sn, true); - auto shu = serialize_number(u, true); - - ASSERT_TRUE(shsp, "0x12345678"); - ASSERT_TRUE(shsn, "0xffffffffedcba988"); - ASSERT_TRUE(shu, "0x12345678"); - - sp = 0; - sn = 0; - u = 0; - - deserialize_number(ssp, sp); - deserialize_number(ssn, sn); - deserialize_number(su, u); - - ASSERT_TRUE(sp, 0x12345678); - ASSERT_TRUE(sn, -0x12345678); - ASSERT_TRUE(u, 0x12345678); - - deserialize_number(shsp, sp, true); - deserialize_number(shsn, sn, true); - deserialize_number(shu, u, true); - - ASSERT_TRUE(sp, 0x12345678); - ASSERT_TRUE(sn, -0x12345678); - ASSERT_TRUE(u, 0x12345678); -} - -void test_bulk_route_entry_create() -{ - SWSS_LOG_ENTER(); - - clear_local(); - - int object_count = 1000; - - std::vector routes; - std::vector attr_counts; - std::vector attr_lists; - std::vector statuses(object_count); - - sai_object_id_t switch_id = create_switch(); - - sai_object_id_t vr = create_virtual_router(switch_id); - sai_object_id_t hop = create_next_hop(switch_id); - - sai_attribute_t attr; - - attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; - attr.value.oid = hop; - - int n = 100; - - for (int i = 0; i < object_count * n; i++) - { - sai_route_entry_t re; - - memset(re.destination.mask.ip6, 0xff, sizeof(re.destination.mask.ip6)); - re.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; - re.destination.addr.ip4 = htonl(0x0a00000f + i); - re.destination.mask.ip4 = htonl(0xffffff00); - re.vr_id = vr; - re.switch_id = switch_id; - - routes.push_back(re); - - attr_counts.push_back(1); - - // since we use the same attribute every where we can get away with this - - attr_lists.push_back(&attr); - } - - auto start = std::chrono::high_resolution_clock::now(); - - for (int i = 0; i < n; i++) - { - auto status = g_meta->bulkCreate( - object_count, - routes.data() + i * object_count, - attr_counts.data(), - attr_lists.data(), - SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, - statuses.data()); - - ASSERT_TRUE(status, SAI_STATUS_SUCCESS); - } - - auto end = std::chrono::high_resolution_clock::now(); - auto time = end - start; - auto us = std::chrono::duration_cast(time); - - std::cout << "ms: " << (double)us.count()/1000 << " / " << n << "/" << object_count << std::endl; -} - -int main() -{ - swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_INFO); - - SWSS_LOG_ENTER(); - - test_bulk_route_entry_create(); - - // serialize tests - - test_serialize_bool(); - test_serialize_chardata(); - test_serialize_uint64(); - test_serialize_enum(); - test_serialize_mac(); - test_serialize_ip_address(); - test_serialize_uint32_list(); - test_serialize_enum_list(); - test_serialize_oid(); - test_serialize_oid_list(); - test_serialize_acl_action(); - test_serialize_qos_map(); - - // attributes tests - - test_switch_set(); - test_switch_get(); - - test_fdb_entry_create(); - test_fdb_entry_remove(); - test_fdb_entry_set(); - test_fdb_entry_get(); - test_fdb_entry_flow(); - - test_neighbor_entry_create(); - test_neighbor_entry_remove(); - test_neighbor_entry_set(); - test_neighbor_entry_get(); - test_neighbor_entry_flow(); - - test_vlan_create(); - test_vlan_remove(); - test_vlan_set(); - test_vlan_get(); - test_vlan_flow(); - - test_route_entry_create(); - test_route_entry_remove(); - test_route_entry_set(); - test_route_entry_get(); - test_route_entry_flow(); - - test_serialization_type_vlan_list(); - test_serialization_type_bool(); - test_serialization_type_char(); - test_serialization_type_int32_list(); - test_serialization_type_uint32_list(); - - test_mask(); - test_acl_entry_field_and_action(); - test_construct_key(); - test_queue_create(); - test_null_list(); - - test_numbers(); - - test_priority_group(); - - std::cout << "SUCCESS" << std::endl; -} diff --git a/pyext/pysairedis.cpp b/pyext/pysairedis.cpp index 98a1894fb..582ed19e3 100644 --- a/pyext/pysairedis.cpp +++ b/pyext/pysairedis.cpp @@ -103,6 +103,7 @@ static PyObject * py_port_state_change_notification = NULL; static PyObject * py_queue_pfc_deadlock_notification = NULL; static PyObject * py_switch_shutdown_request_notification = NULL; static PyObject * py_switch_state_change_notification = NULL; +static PyObject * py_bfd_session_state_change_notification = NULL; void call_python(PyObject* callObject, PyObject* arglist) { @@ -190,6 +191,21 @@ static void sai_switch_state_change_notification( Py_DECREF(arglist); } +static void sai_bfd_session_state_change_notification( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data) +{ + PyObject* obj = py_convert_sai_bfd_session_state_notification_t_to_PyObject(data); + + PyObject* arglist = Py_BuildValue("(iO)", count, obj); + + call_python(py_bfd_session_state_change_notification, arglist); + + Py_DECREF(obj); + + Py_DECREF(arglist); +} + sai_pointer_t sai_get_notification_pointer( sai_attr_id_t id, PyObject*callback) @@ -228,6 +244,11 @@ sai_pointer_t sai_get_notification_pointer( py_queue_pfc_deadlock_notification = callback; return (void*)&sai_queue_pfc_deadlock_notification; + case SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY: + Py_XDECREF(py_bfd_session_state_change_notification); + py_bfd_session_state_change_notification = callback; + return (void*)&sai_bfd_session_state_change_notification; + default: Py_XDECREF(callback); break; diff --git a/saiplayer/SaiPlayer.cpp b/saiplayer/SaiPlayer.cpp index d469b9b71..f9cb6dc0f 100644 --- a/saiplayer/SaiPlayer.cpp +++ b/saiplayer/SaiPlayer.cpp @@ -89,6 +89,7 @@ SaiPlayer::SaiPlayer( m_sn.onQueuePfcDeadlock = std::bind(&SaiPlayer::onQueuePfcDeadlock, this, _1, _2); m_sn.onSwitchShutdownRequest = std::bind(&SaiPlayer::onSwitchShutdownRequest, this, _1); m_sn.onSwitchStateChange = std::bind(&SaiPlayer::onSwitchStateChange, this, _1, _2); + m_sn.onBfdSessionStateChange = std::bind(&SaiPlayer::onBfdSessionStateChange, this, _1, _2); m_switchNotifications= m_sn.getSwitchNotifications(); } @@ -165,6 +166,15 @@ void SaiPlayer::onPortStateChange( // empty } +void SaiPlayer::onBfdSessionStateChange( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data) +{ + SWSS_LOG_ENTER(); + + // empty +} + void SaiPlayer::onQueuePfcDeadlock( _In_ uint32_t count, _In_ const sai_queue_deadlock_notification_data_t *data) @@ -721,6 +731,10 @@ void SaiPlayer::update_notifications_pointers( attr.value.ptr = (void*)m_switchNotifications.on_queue_pfc_deadlock; break; + case SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY: + attr.value.ptr = (void*)m_switchNotifications.on_bfd_session_state_change; + break; + default: SWSS_LOG_ERROR("pointer for %s is not handled, FIXME!", meta->attridname); break; diff --git a/saiplayer/SaiPlayer.h b/saiplayer/SaiPlayer.h index 2c77d6558..efd1f03ba 100644 --- a/saiplayer/SaiPlayer.h +++ b/saiplayer/SaiPlayer.h @@ -194,6 +194,10 @@ namespace saiplayer _In_ sai_object_id_t switch_id, _In_ sai_switch_oper_status_t switch_oper_status); + void onBfdSessionStateChange( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data); + private: std::shared_ptr m_sai; diff --git a/syncd/Makefile.am b/syncd/Makefile.am index 757d7766b..aad2e1e68 100644 --- a/syncd/Makefile.am +++ b/syncd/Makefile.am @@ -60,6 +60,7 @@ syncd_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS) syncd_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) $(CODE_COVERAGE_CXXFLAGS) syncd_LDADD = libSyncd.a $(top_srcdir)/lib/libSaiRedis.a -L$(top_srcdir)/meta/.libs -lsaimetadata -lsaimeta \ -ldl -lhiredis -lswsscommon $(SAILIB) -lpthread -lzmq $(CODE_COVERAGE_LIBS) +syncd_LDFLAGS = -rdynamic if SAITHRIFT libSyncd_a_CXXFLAGS += -DSAITHRIFT=yes diff --git a/syncd/NotificationHandler.cpp b/syncd/NotificationHandler.cpp index 388606607..2e897a1fb 100644 --- a/syncd/NotificationHandler.cpp +++ b/syncd/NotificationHandler.cpp @@ -108,6 +108,10 @@ void NotificationHandler::updateNotificationsPointers( attr.value.ptr = (void*)m_switchNotifications.on_queue_pfc_deadlock; break; + case SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY: + attr.value.ptr = (void*)m_switchNotifications.on_bfd_session_state_change; + break; + default: SWSS_LOG_ERROR("pointer for %s is not handled, FIXME!", meta->attridname); @@ -177,6 +181,17 @@ void NotificationHandler::onSwitchStateChange( enqueueNotification(SAI_SWITCH_NOTIFICATION_NAME_SWITCH_STATE_CHANGE, s); } +void NotificationHandler::onBfdSessionStateChange( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data) +{ + SWSS_LOG_ENTER(); + + std::string s = sai_serialize_bfd_session_state_ntf(count, data); + + enqueueNotification(SAI_SWITCH_NOTIFICATION_NAME_BFD_SESSION_STATE_CHANGE, s); +} + void NotificationHandler::enqueueNotification( _In_ const std::string& op, _In_ const std::string& data, diff --git a/syncd/NotificationHandler.h b/syncd/NotificationHandler.h index f5288a113..4c3e7a934 100644 --- a/syncd/NotificationHandler.h +++ b/syncd/NotificationHandler.h @@ -56,6 +56,10 @@ namespace syncd _In_ sai_object_id_t switch_id, _In_ sai_switch_oper_status_t switch_oper_status); + void onBfdSessionStateChange( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data); + private: void enqueueNotification( diff --git a/syncd/NotificationProcessor.cpp b/syncd/NotificationProcessor.cpp index 1ee3e9e93..3392d3ddc 100644 --- a/syncd/NotificationProcessor.cpp +++ b/syncd/NotificationProcessor.cpp @@ -420,6 +420,35 @@ void NotificationProcessor::process_on_port_state_change( sendNotification(SAI_SWITCH_NOTIFICATION_NAME_PORT_STATE_CHANGE, s); } +void NotificationProcessor::process_on_bfd_session_state_change( + _In_ uint32_t count, + _In_ sai_bfd_session_state_notification_t *data) +{ + SWSS_LOG_ENTER(); + + SWSS_LOG_DEBUG("bfd sessuin state notification count: %u", count); + + for (uint32_t i = 0; i < count; i++) + { + sai_bfd_session_state_notification_t *bfd_session_state = &data[i]; + + /* + * We are using switch_rid as null, since BFD should be already + * defined inside local db after creation. + * + * If this will be faster than return from create BFD then we can use + * query switch id and extract rid of switch id and then convert it to + * switch vid. + */ + + bfd_session_state->bfd_session_id = m_translator->translateRidToVid(bfd_session_state->bfd_session_id, SAI_NULL_OBJECT_ID); + } + + std::string s = sai_serialize_bfd_session_state_ntf(count, data); + + sendNotification(SAI_SWITCH_NOTIFICATION_NAME_BFD_SESSION_STATE_CHANGE, s); +} + void NotificationProcessor::process_on_switch_shutdown_request( _In_ sai_object_id_t switch_rid) { @@ -495,6 +524,21 @@ void NotificationProcessor::handle_port_state_change( sai_deserialize_free_port_oper_status_ntf(count, portoperstatus); } +void NotificationProcessor::handle_bfd_session_state_change( + _In_ const std::string &data) +{ + SWSS_LOG_ENTER(); + + uint32_t count; + sai_bfd_session_state_notification_t *bfdsessionstate = NULL; + + sai_deserialize_bfd_session_state_ntf(data, count, &bfdsessionstate); + + process_on_bfd_session_state_change(count, bfdsessionstate); + + sai_deserialize_free_bfd_session_state_ntf(count, bfdsessionstate); +} + void NotificationProcessor::handle_switch_shutdown_request( _In_ const std::string &data) { @@ -543,6 +587,10 @@ void NotificationProcessor::syncProcessNotification( { handle_queue_deadlock(data); } + else if (notification == SAI_SWITCH_NOTIFICATION_NAME_BFD_SESSION_STATE_CHANGE) + { + handle_bfd_session_state_change(data); + } else { SWSS_LOG_ERROR("unknown notification: %s", notification.c_str()); diff --git a/syncd/NotificationProcessor.h b/syncd/NotificationProcessor.h index 13f2eda01..d378fe612 100644 --- a/syncd/NotificationProcessor.h +++ b/syncd/NotificationProcessor.h @@ -81,6 +81,10 @@ namespace syncd _In_ uint32_t count, _In_ sai_port_oper_status_notification_t *data); + void process_on_bfd_session_state_change( + _In_ uint32_t count, + _In_ sai_bfd_session_state_notification_t *data); + void process_on_switch_shutdown_request( _In_ sai_object_id_t switch_rid); @@ -98,6 +102,9 @@ namespace syncd void handle_port_state_change( _In_ const std::string &data); + void handle_bfd_session_state_change( + _In_ const std::string &data); + void handle_switch_shutdown_request( _In_ const std::string &data); diff --git a/syncd/SaiSwitch.cpp b/syncd/SaiSwitch.cpp index 83d2b2b40..bd5b427d4 100644 --- a/syncd/SaiSwitch.cpp +++ b/syncd/SaiSwitch.cpp @@ -53,6 +53,11 @@ SaiSwitch::SaiSwitch( helperDiscover(); + if (warmBoot) + { + checkWarmBootDiscoveredRids(); + } + helperSaveDiscoveredObjectsToRedis(); helperInternalOids(); @@ -70,11 +75,6 @@ SaiSwitch::SaiSwitch( { saiGetMacAddress(m_default_mac_address); } - - if (warmBoot) - { - checkWarmBootDiscoveredRids(); - } } /* @@ -1184,8 +1184,11 @@ void SaiSwitch::checkWarmBootDiscoveredRids() if (rid2vid.find(rid) != rid2vid.end()) continue; - SWSS_LOG_ERROR("RID %s is missing from current RID2VID map after WARM boot!", - sai_serialize_object_id(rid).c_str()); + auto ot = m_vendorSai->objectTypeQuery(rid); + + SWSS_LOG_ERROR("RID %s (%s) is missing from current RID2VID map after WARM boot!", + sai_serialize_object_id(rid).c_str(), + sai_serialize_object_type(ot).c_str()); success = false; } @@ -1198,4 +1201,3 @@ void SaiSwitch::checkWarmBootDiscoveredRids() SWSS_LOG_NOTICE("all discovered RIDs are present in current RID2VID map for switch VID %s", sai_serialize_object_id(m_switch_vid).c_str()); } - diff --git a/syncd/SwitchNotifications.cpp b/syncd/SwitchNotifications.cpp index 5ba3bea35..423265ab2 100644 --- a/syncd/SwitchNotifications.cpp +++ b/syncd/SwitchNotifications.cpp @@ -57,6 +57,16 @@ void SwitchNotifications::SlotBase::onPortStateChange( return m_slots.at(context)->m_handler->onPortStateChange(count, data); } +void SwitchNotifications::SlotBase::onBfdSessionStateChange( + _In_ int context, + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data) +{ + SWSS_LOG_ENTER(); + + return m_slots.at(context)->m_handler->onBfdSessionStateChange(count, data); +} + void SwitchNotifications::SlotBase::onQueuePfcDeadlock( _In_ int context, _In_ uint32_t count, diff --git a/syncd/SwitchNotifications.h b/syncd/SwitchNotifications.h index 82cf8e4df..898719aad 100644 --- a/syncd/SwitchNotifications.h +++ b/syncd/SwitchNotifications.h @@ -59,6 +59,11 @@ namespace syncd _In_ sai_object_id_t switch_id, _In_ sai_switch_oper_status_t switch_oper_status); + static void onBfdSessionStateChange( + _In_ int context, + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data); + protected: SwitchNotifications* m_handler; @@ -74,7 +79,7 @@ namespace syncd Slot(): SlotBase({ - .on_bfd_session_state_change = nullptr, + .on_bfd_session_state_change = &Slot::onBfdSessionStateChange, .on_fdb_event = &Slot::onFdbEvent, .on_packet_event = nullptr, .on_port_state_change = &Slot::onPortStateChange, @@ -106,6 +111,15 @@ namespace syncd return SlotBase::onPortStateChange(context, count, data); } + static void onBfdSessionStateChange( + _In_ uint32_t count, + _In_ const sai_bfd_session_state_notification_t *data) + { + SWSS_LOG_ENTER(); + + return SlotBase::onBfdSessionStateChange(context, count, data); + } + static void onQueuePfcDeadlock( _In_ uint32_t count, _In_ const sai_queue_deadlock_notification_data_t *data) @@ -152,6 +166,7 @@ namespace syncd std::function onQueuePfcDeadlock; std::function onSwitchShutdownRequest; std::function onSwitchStateChange; + std::function onBfdSessionStateChange; private: diff --git a/syncd/Syncd.cpp b/syncd/Syncd.cpp index 60c0118f5..fe95bdb42 100644 --- a/syncd/Syncd.cpp +++ b/syncd/Syncd.cpp @@ -143,6 +143,7 @@ Syncd::Syncd( m_sn.onQueuePfcDeadlock = std::bind(&NotificationHandler::onQueuePfcDeadlock, m_handler.get(), _1, _2); m_sn.onSwitchShutdownRequest = std::bind(&NotificationHandler::onSwitchShutdownRequest, m_handler.get(), _1); m_sn.onSwitchStateChange = std::bind(&NotificationHandler::onSwitchStateChange, m_handler.get(), _1, _2); + m_sn.onBfdSessionStateChange = std::bind(&NotificationHandler::onBfdSessionStateChange, m_handler.get(), _1, _2); m_handler->setSwitchNotifications(m_sn.getSwitchNotifications()); @@ -708,7 +709,7 @@ sai_status_t Syncd::processGetStatsEvent( if (status != SAI_STATUS_SUCCESS) { - SWSS_LOG_ERROR("Failed to get stats"); + SWSS_LOG_NOTICE("Getting stats error: %s", sai_serialize_status(status).c_str()); } else { @@ -3955,7 +3956,8 @@ void Syncd::performWarmRestartSingleSwitch( SAI_SWITCH_ATTR_SHUTDOWN_REQUEST_NOTIFY, SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY, SAI_SWITCH_ATTR_PORT_STATE_CHANGE_NOTIFY, - SAI_SWITCH_ATTR_QUEUE_PFC_DEADLOCK_NOTIFY + SAI_SWITCH_ATTR_QUEUE_PFC_DEADLOCK_NOTIFY, + SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY }; std::vector attrs; diff --git a/tests/aspell.en.pws b/tests/aspell.en.pws index 7b444acec..e0de14fd1 100644 --- a/tests/aspell.en.pws +++ b/tests/aspell.en.pws @@ -12,6 +12,7 @@ ApplyView AsicView AttrHash BCM +BFD Bool CHARDATA COLDVIDS @@ -96,6 +97,9 @@ WRED Werror ZMQ acl +aclaction +aclfield +addr apache api apis @@ -173,6 +177,7 @@ hardcoded hasEqualAttribute hostif hpp +htonl http https hw diff --git a/unittest/lib/tests b/unittest/lib/tests deleted file mode 100755 index c08a8acc0..000000000 --- a/unittest/lib/tests +++ /dev/null @@ -1,210 +0,0 @@ -#! /bin/bash - -# tests - temporary wrapper script for .libs/tests -# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 -# -# The tests program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command="" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variables: - generated_by_libtool_version='2.4.6' - notinst_deplibs=' /home/kcudnik/sonic-sairedis/meta/.libs/libsaimetadata.la /home/kcudnik/sonic-sairedis/meta/.libs/libsaimeta.la' -else - # When we are sourced in execute mode, $file and $ECHO are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - file="$0" - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - ECHO="printf %s\\n" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on -# windows platforms, and (c) all begin with the string --lt- -# (application programs are unlikely to have options that match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's ../../libtool value, followed by no. -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=$0 - shift - for lt_opt - do - case "$lt_opt" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` - test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. - lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` - cat "$lt_dump_D/$lt_dump_F" - exit 0 - ;; - --lt-*) - $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n "$lt_option_debug"; then - echo "tests:tests:$LINENO: libtool wrapper (GNU libtool) 2.4.6 Debian-2.4.6-14" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - $ECHO "tests:tests:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" - lt_dump_args_N=`expr $lt_dump_args_N + 1` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ - - if test -n "$lt_option_debug"; then - $ECHO "tests:tests:$LINENO: newargv[0]: $progdir/$program" 1>&2 - func_lt_dump_args ${1+"$@"} 1>&2 - fi - exec "$progdir/$program" ${1+"$@"} - - $ECHO "$0: cannot exec $program $*" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from $@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case " $* " in - *\ --lt-*) - for lt_wr_arg - do - case $lt_wr_arg in - --lt-*) ;; - *) set x "$@" "$lt_wr_arg"; shift;; - esac - shift - done ;; - esac - func_exec_program_core ${1+"$@"} -} - - # Parse options - func_parse_lt_options "$0" ${1+"$@"} - - # Find the directory that this script lives in. - thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no - if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then - # special case for '.' - if test "$thisdir" = "."; then - thisdir=`pwd` - fi - # remove .libs from thisdir - case "$thisdir" in - *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; - .libs ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program='tests' - progdir="$thisdir/.libs" - - - if test -f "$progdir/$program"; then - # Add our own library path to LD_LIBRARY_PATH - LD_LIBRARY_PATH="/home/kcudnik/lib:/home/kcudnik/sonic-sairedis/meta/.libs:$LD_LIBRARY_PATH" - - # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH - # The second colon is a workaround for a bug in BeOS R4 sed - LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` - - export LD_LIBRARY_PATH - - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - func_exec_program ${1+"$@"} - fi - else - # The program doesn't exist. - $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 - $ECHO "This script is just a wrapper for $program." 1>&2 - $ECHO "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/unittest/meta/Makefile.am b/unittest/meta/Makefile.am index cb186ba88..842b5e661 100644 --- a/unittest/meta/Makefile.am +++ b/unittest/meta/Makefile.am @@ -6,7 +6,39 @@ LDADD_GTEST = -L/usr/src/gtest -lgtest -lgtest_main tests_SOURCES = \ main.cpp \ - TestAttrKeyMap.cpp + ../../meta/DummySaiInterface.cpp \ + ../../meta/MetaTestSaiInterface.cpp \ + ../../lib/VirtualObjectIdManager.cpp \ + ../../lib/SwitchConfig.cpp \ + ../../lib/SwitchConfigContainer.cpp \ + ../../lib/ZeroMQChannel.cpp \ + ../../lib/Channel.cpp \ + TestAttrKeyMap.cpp \ + TestGlobals.cpp \ + TestMetaKeyHasher.cpp \ + TestNotificationFactory.cpp \ + TestNotificationFdbEvent.cpp \ + TestNotificationPortStateChange.cpp \ + TestNotificationQueuePfcDeadlock.cpp \ + TestNotificationSwitchShutdownRequest.cpp \ + TestNotificationSwitchStateChange.cpp \ + TestOidRefCounter.cpp \ + TestPerformanceIntervalTimer.cpp \ + TestPortRelatedSet.cpp \ + TestSaiAttrWrapper.cpp \ + TestSaiAttributeList.cpp \ + TestSaiObject.cpp \ + TestSaiObjectCollection.cpp \ + TestSaiInterface.cpp \ + TestSaiSerialize.cpp \ + TestLegacy.cpp \ + TestLegacyFdbEntry.cpp \ + TestLegacyNeighborEntry.cpp \ + TestLegacyVlan.cpp \ + TestLegacyRouteEntry.cpp \ + TestLegacyOther.cpp \ + TestZeroMQSelectableChannel.cpp \ + TestMeta.cpp tests_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) tests_LDADD = $(LDADD_GTEST) -lhiredis -lswsscommon -lpthread -L$(top_srcdir)/meta/.libs -lsaimetadata -lsaimeta -lzmq $(CODE_COVERAGE_LIBS) diff --git a/unittest/meta/TestAttrKeyMap.cpp b/unittest/meta/TestAttrKeyMap.cpp index 3682ca6bd..75660b9b6 100644 --- a/unittest/meta/TestAttrKeyMap.cpp +++ b/unittest/meta/TestAttrKeyMap.cpp @@ -12,6 +12,8 @@ TEST(AttrKeyMap, constructKey) sai_object_meta_key_t mk; + memset(&mk, 0, sizeof(mk)); + EXPECT_THROW( akm->constructKey(SAI_NULL_OBJECT_ID, mk, 0, nullptr), std::runtime_error); diff --git a/unittest/meta/TestGlobals.cpp b/unittest/meta/TestGlobals.cpp new file mode 100644 index 000000000..8fbab604d --- /dev/null +++ b/unittest/meta/TestGlobals.cpp @@ -0,0 +1,47 @@ +#include "Globals.h" + +#include + +#include + +using namespace saimeta; + +static_assert(SAI_MAX_HARDWARE_ID_LEN <= 256, "max is 256"); + +TEST(Globals, getHardwareInfo) +{ + EXPECT_EQ("", Globals::getHardwareInfo(0, nullptr)); + + EXPECT_EQ("", Globals::getHardwareInfo(1, nullptr)); + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO; + attr.value.s8list.count = 0; + attr.value.s8list.list = nullptr; + + EXPECT_EQ("", Globals::getHardwareInfo(1, &attr)); + + attr.value.s8list.count = 1; + attr.value.s8list.list = nullptr; + + EXPECT_EQ("", Globals::getHardwareInfo(1, &attr)); + + char hwinfo[SAI_MAX_HARDWARE_ID_LEN + 2]; + + memset(hwinfo, '0', SAI_MAX_HARDWARE_ID_LEN + 2); + + hwinfo[SAI_MAX_HARDWARE_ID_LEN + 1] = 0; + + attr.value.s8list.count = SAI_MAX_HARDWARE_ID_LEN + 1; + attr.value.s8list.list = (int8_t*)hwinfo; + + EXPECT_EQ(std::string(SAI_MAX_HARDWARE_ID_LEN, '0'), Globals::getHardwareInfo(1, &attr)); + + attr.value.s8list.count = 10; + attr.value.s8list.list = (int8_t*)hwinfo; + + hwinfo[3] = 0; + + EXPECT_EQ("000", Globals::getHardwareInfo(1, &attr)); +} diff --git a/unittest/meta/TestLegacy.cpp b/unittest/meta/TestLegacy.cpp new file mode 100644 index 000000000..e3c442224 --- /dev/null +++ b/unittest/meta/TestLegacy.cpp @@ -0,0 +1,230 @@ +#include "TestLegacy.h" + +#include "sai_serialize.h" + +#include + +//using namespace TestLegacy; + +using namespace saimeta; + +namespace TestLegacy +{ + std::shared_ptr g_sai = std::make_shared(); + std::shared_ptr g_meta = std::make_shared(g_sai); + + // STATIC HELPER METHODS + + void clear_local() + { + SWSS_LOG_ENTER(); + + g_sai = std::make_shared(); + g_meta = std::make_shared(g_sai); + } + + sai_object_id_t create_switch() + { + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + + sai_object_id_t switch_id; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + auto status = g_meta->create(SAI_OBJECT_TYPE_SWITCH, &switch_id, SAI_NULL_OBJECT_ID, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return switch_id; + } + + void remove_switch( + _In_ sai_object_id_t switchId) + { + SWSS_LOG_ENTER(); + + EXPECT_TRUE(g_meta->isEmpty() == false); + + SWSS_LOG_NOTICE("removing: %lX", switchId); + + auto status = g_meta->remove(SAI_OBJECT_TYPE_SWITCH, switchId); + + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + if (g_meta->isEmpty() == false) + { + g_meta->dump(); + } + + EXPECT_TRUE(g_meta->isEmpty()); + } + + sai_object_id_t create_bridge( + _In_ sai_object_id_t switch_id) + { + SWSS_LOG_ENTER(); + + sai_object_id_t bridge_id; + + sai_attribute_t attrs[9] = {}; + + attrs[0].id = SAI_BRIDGE_ATTR_TYPE; + attrs[0].value.s32 = SAI_BRIDGE_TYPE_1Q; + + sai_status_t status = g_meta->create(SAI_OBJECT_TYPE_BRIDGE, &bridge_id, switch_id, 1, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return bridge_id; + } + + sai_object_id_t create_port( + _In_ sai_object_id_t switch_id) + { + SWSS_LOG_ENTER(); + + sai_object_id_t port; + + static uint32_t id = 1; + id++; + sai_attribute_t attrs[9] = { }; + + uint32_t list[1] = { id }; + + attrs[0].id = SAI_PORT_ATTR_HW_LANE_LIST; + attrs[0].value.u32list.count = 1; + attrs[0].value.u32list.list = list; + + attrs[1].id = SAI_PORT_ATTR_SPEED; + attrs[1].value.u32 = 10000; + + auto status = g_meta->create(SAI_OBJECT_TYPE_PORT, &port, switch_id, 2, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return port; + } + + sai_object_id_t create_bridge_port( + _In_ sai_object_id_t switch_id, + _In_ sai_object_id_t bridge_id) + { + SWSS_LOG_ENTER(); + + sai_object_id_t bridge_port; + + sai_attribute_t attrs[9] = { }; + + auto port = create_port(switch_id); + + attrs[0].id = SAI_BRIDGE_PORT_ATTR_TYPE; + attrs[0].value.s32 = SAI_BRIDGE_PORT_TYPE_PORT; + + attrs[1].id = SAI_BRIDGE_PORT_ATTR_PORT_ID; + attrs[1].value.oid = port; + + auto status = g_meta->create(SAI_OBJECT_TYPE_BRIDGE_PORT, &bridge_port, switch_id, 2, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return bridge_port; + } + + sai_object_id_t create_dummy_object_id( + _In_ sai_object_type_t object_type, + _In_ sai_object_id_t switch_id) + { + SWSS_LOG_ENTER(); + + sai_object_id_t oid; + + auto status = g_sai->create(object_type, &oid, switch_id, 0, NULL); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_THROW("failed to create oid"); + } + + SWSS_LOG_DEBUG("created oid %s", sai_serialize_object_id(oid).c_str()); + + return oid; + } + + sai_object_id_t create_virtual_router( + _In_ sai_object_id_t switch_id) + { + SWSS_LOG_ENTER(); + + sai_object_id_t vr; + + auto status = g_meta->create(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, &vr, switch_id, 0, NULL); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return vr; + } + + sai_object_id_t create_rif( + _In_ sai_object_id_t switch_id) + { + SWSS_LOG_ENTER(); + + sai_object_id_t rif; + + sai_attribute_t attrs[9] = { }; + + auto port = create_port(switch_id); + + auto vr = create_virtual_router(switch_id); + + attrs[0].id = SAI_ROUTER_INTERFACE_ATTR_VIRTUAL_ROUTER_ID; + attrs[0].value.oid = vr; + + attrs[1].id = SAI_ROUTER_INTERFACE_ATTR_TYPE; + attrs[1].value.s32 = SAI_ROUTER_INTERFACE_TYPE_PORT; + + attrs[2].id = SAI_ROUTER_INTERFACE_ATTR_PORT_ID; + attrs[2].value.oid = port; + + auto status = g_meta->create(SAI_OBJECT_TYPE_ROUTER_INTERFACE, &rif, switch_id, 3, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return rif; + } + + sai_object_id_t create_stp( + _In_ sai_object_id_t switch_id) + { + SWSS_LOG_ENTER(); + + sai_object_id_t stp; + + auto status = g_meta->create(SAI_OBJECT_TYPE_STP, &stp, switch_id, 0, NULL); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return stp; + } + + sai_object_id_t create_next_hop( + _In_ sai_object_id_t switch_id) + { + SWSS_LOG_ENTER(); + + sai_object_id_t nh; + + sai_attribute_t attrs[9] = { }; + + attrs[0].id = SAI_NEXT_HOP_ATTR_TYPE; + attrs[0].value.s32 = SAI_NEXT_HOP_TYPE_IP; + + attrs[1].id = SAI_NEXT_HOP_ATTR_IP; + + auto rif = create_rif(switch_id); + + attrs[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; + attrs[2].value.oid = rif; + + auto status = g_meta->create(SAI_OBJECT_TYPE_NEXT_HOP, &nh, switch_id, 3, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return nh; + } +} diff --git a/unittest/meta/TestLegacy.h b/unittest/meta/TestLegacy.h new file mode 100644 index 000000000..728ce210f --- /dev/null +++ b/unittest/meta/TestLegacy.h @@ -0,0 +1,43 @@ +#include "Meta.h" +#include "MetaTestSaiInterface.h" + +namespace TestLegacy +{ + extern std::shared_ptr g_sai; + extern std::shared_ptr g_meta; + + // STATIC HELPER METHODS + + void clear_local(); + + sai_object_id_t create_switch(); + + void remove_switch( + _In_ sai_object_id_t switchId); + + sai_object_id_t create_bridge( + _In_ sai_object_id_t switch_id); + + sai_object_id_t create_port( + _In_ sai_object_id_t switch_id); + + sai_object_id_t create_bridge_port( + _In_ sai_object_id_t switch_id, + _In_ sai_object_id_t bridge_id); + + sai_object_id_t create_dummy_object_id( + _In_ sai_object_type_t object_type, + _In_ sai_object_id_t switch_id); + + sai_object_id_t create_virtual_router( + _In_ sai_object_id_t switch_id); + + sai_object_id_t create_rif( + _In_ sai_object_id_t switch_id); + + sai_object_id_t create_stp( + _In_ sai_object_id_t switch_id); + + sai_object_id_t create_next_hop( + _In_ sai_object_id_t switch_id); +} diff --git a/unittest/meta/TestLegacyFdbEntry.cpp b/unittest/meta/TestLegacyFdbEntry.cpp new file mode 100644 index 000000000..d9734972b --- /dev/null +++ b/unittest/meta/TestLegacyFdbEntry.cpp @@ -0,0 +1,415 @@ +#include "TestLegacy.h" + +#include + +#include + +using namespace TestLegacy; + +// STATIC HELPERS + +static sai_fdb_entry_t create_fdb_entry() +{ + SWSS_LOG_ENTER(); + + sai_fdb_entry_t fdb_entry; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + memcpy(fdb_entry.mac_address, mac, sizeof(mac)); + + auto switch_id = create_switch(); + + fdb_entry.switch_id = switch_id; + sai_object_id_t bridge_id = create_bridge(switch_id); + fdb_entry.bv_id = bridge_id; + + sai_object_id_t port = create_bridge_port(switch_id, bridge_id); + + sai_attribute_t list1[4] = { }; + + sai_attribute_t &attr1 = list1[0]; + sai_attribute_t &attr2 = list1[1]; + sai_attribute_t &attr3 = list1[2]; + sai_attribute_t &attr4 = list1[3]; + + attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; + attr1.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + + attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; + attr2.value.oid = port; + + attr3.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; + + attr4.id = -1; + + sai_attribute_t list2[4] = { attr1, attr2, attr3, attr3 }; + + auto status = g_meta->create(&fdb_entry, 3, list2); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return fdb_entry; +} + +// TESTS + +TEST(LegacyFdbEntry, fdb_entry_create) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + + sai_object_id_t switch_id = create_switch(); + + sai_fdb_entry_t fdb_entry; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + memcpy(fdb_entry.mac_address, mac, sizeof(mac)); + + fdb_entry.switch_id = switch_id; + sai_object_id_t bridge_id = create_bridge(switch_id); + fdb_entry.bv_id = bridge_id; + + sai_object_id_t port = create_bridge_port(switch_id, bridge_id); + + SWSS_LOG_NOTICE("create tests"); + + SWSS_LOG_NOTICE("zero attribute count (but there are mandatory attributes)"); + attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + status = g_meta->create(&fdb_entry, 0, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->create(&fdb_entry, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("fdb entry is null"); + status = g_meta->create((const sai_fdb_entry_t*)NULL, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + sai_attribute_t list1[4] = { }; + + sai_attribute_t &attr1 = list1[0]; + sai_attribute_t &attr2 = list1[1]; + sai_attribute_t &attr3 = list1[2]; + sai_attribute_t &attr4 = list1[3]; + + attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; + attr1.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + + attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; + attr2.value.oid = port; + + attr3.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; + + attr4.id = -1; + + SWSS_LOG_NOTICE("invalid attribute id"); + status = g_meta->create(&fdb_entry, 4, list1); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + +// // packet action is now optional +// SWSS_LOG_NOTICE("passing optional attribute"); +// status = g_meta->create(&fdb_entry, 1, list1); +// EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + attr2.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_HASH, switch_id); + + SWSS_LOG_NOTICE("invalid attribute value on oid"); + status = g_meta->create(&fdb_entry, 3, list1); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr2.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_PORT, switch_id); + + SWSS_LOG_NOTICE("non existing object on oid"); + status = g_meta->create(&fdb_entry, 3, list1); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr2.value.oid = port; + attr3.value.s32 = 0x100; + + SWSS_LOG_NOTICE("invalid attribute value on enum"); + status = g_meta->create(&fdb_entry, 3, list1); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_attribute_t list2[4] = { attr1, attr2, attr3, attr3 }; + + SWSS_LOG_NOTICE("repeated attribute id"); + status = g_meta->create(&fdb_entry, 4, list2); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct"); + status = g_meta->create(&fdb_entry, 3, list2); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("already exists"); + status = g_meta->create(&fdb_entry, 3, list2); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyFdbEntry, fdb_entry_remove) +{ + clear_local(); + + sai_status_t status; + + sai_object_id_t switch_id = create_switch(); + + sai_fdb_entry_t fdb_entry; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + memcpy(fdb_entry.mac_address, mac, sizeof(mac)); + fdb_entry.switch_id = switch_id; + sai_object_id_t bridge_id = create_bridge(switch_id); + fdb_entry.bv_id= bridge_id; + + sai_object_id_t port = create_bridge_port(switch_id, bridge_id); + + sai_attribute_t list1[3] = { }; + + sai_attribute_t &attr1 = list1[0]; + sai_attribute_t &attr2 = list1[1]; + sai_attribute_t &attr3 = list1[2]; + + attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; + attr1.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + + attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; + attr2.value.oid = port; + + attr3.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; + + SWSS_LOG_NOTICE("creating fdb entry"); + status = g_meta->create(&fdb_entry, 3, list1); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove tests"); + + SWSS_LOG_NOTICE("fdb_entry is null"); + status = g_meta->remove((const sai_fdb_entry_t*)NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + //SWSS_LOG_NOTICE("invalid vlan"); + //status = g_meta->remove(&fdb_entry); + //EXPECT_NE(SAI_STATUS_SUCCESS, status); + + fdb_entry.mac_address[0] = 1; + + SWSS_LOG_NOTICE("invalid mac"); + status = g_meta->remove(&fdb_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + fdb_entry.mac_address[0] = 0x11; + + sai_object_meta_key_t key = { .objecttype = SAI_OBJECT_TYPE_FDB_ENTRY, .objectkey = { .key = { .fdb_entry = fdb_entry } } }; + + EXPECT_TRUE(g_meta->objectExists(key)); + + SWSS_LOG_NOTICE("success"); + status = g_meta->remove(&fdb_entry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + EXPECT_TRUE(!g_meta->objectExists(key)); + + remove_switch(switch_id); +} + +TEST(LegacyFdbEntry, fdb_entry_set) +{ + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + sai_fdb_entry_t fdb_entry = create_fdb_entry(); + + //status = g_meta->create(&fdb_entry, 0, 0); + //EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->set(&fdb_entry, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("fdb entry is null"); + status = g_meta->set((const sai_fdb_entry_t*)NULL, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("setting read only object"); + attr.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; + attr.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_BRIDGE_PORT, fdb_entry.switch_id); + + status = g_meta->set(&fdb_entry, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("setting invalid attrib id"); + attr.id = -1; + status = g_meta->set(&fdb_entry, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + //SWSS_LOG_NOTICE("invalid vlan"); + //attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + //attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + //status = g_meta->set(&fdb_entry, &attr); + //EXPECT_NE(SAI_STATUS_SUCCESS, status); + + //SWSS_LOG_NOTICE("vlan outside range"); + //attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + //attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + //status = g_meta->set(&fdb_entry, &attr); + //EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // correct + attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + status = g_meta->set(&fdb_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // TODO check references ? + + remove_switch(fdb_entry.switch_id); +} + +TEST(LegacyFdbEntry, fdb_entry_get) +{ + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + sai_fdb_entry_t fdb_entry = create_fdb_entry(); + + attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + attr.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + status = g_meta->set(&fdb_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get test"); + + // zero attribute count + attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + status = g_meta->get(&fdb_entry, 0, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // attr is null + status = g_meta->get(&fdb_entry, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // fdb entry is null + status = g_meta->get((sai_fdb_entry_t*)NULL, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // attr id out of range + attr.id = -1; + status = g_meta->get(&fdb_entry, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // correct single valid attribute + attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + status = g_meta->get(&fdb_entry, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // correct 2 attributes + sai_attribute_t attr1; + attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; + + sai_attribute_t attr2; + attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; + sai_attribute_t list[2] = { attr1, attr2 }; + + status = g_meta->get(&fdb_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(fdb_entry.switch_id); +} + +TEST(LegacyFdbEntry, fdb_entry_flow) +{ + SWSS_LOG_TIMER("fdb flow"); + + clear_local(); + + sai_object_id_t switch_id = create_switch(); + sai_status_t status; + sai_attribute_t attr; + + sai_fdb_entry_t fdb_entry; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + memcpy(fdb_entry.mac_address, mac, sizeof(mac)); + fdb_entry.switch_id = switch_id; + + sai_object_id_t bridge_id = create_bridge(switch_id); + fdb_entry.bv_id= bridge_id; + + sai_object_id_t lag = create_bridge_port(switch_id, bridge_id); + + sai_attribute_t list[4] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + sai_attribute_t &attr3 = list[2]; + sai_attribute_t &attr4 = list[3]; + + attr1.id = SAI_FDB_ENTRY_ATTR_TYPE; + attr1.value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; + + attr2.id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; + attr2.value.oid = lag; + + attr3.id = SAI_FDB_ENTRY_ATTR_PACKET_ACTION; + attr3.value.s32 = SAI_PACKET_ACTION_FORWARD; + + attr4.id = SAI_FDB_ENTRY_ATTR_META_DATA; + attr4.value.u32 = 0x12345678; + + SWSS_LOG_NOTICE("create"); + status = g_meta->create(&fdb_entry, 4, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("create existing"); + status = g_meta->create(&fdb_entry, 4, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set"); + attr.id = SAI_FDB_ENTRY_ATTR_TYPE; + attr.value.s32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; + status = g_meta->set(&fdb_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set"); + attr.id = SAI_FDB_ENTRY_ATTR_META_DATA; + attr.value.u32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; + status = g_meta->set(&fdb_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get"); + status = g_meta->get(&fdb_entry, 4, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove"); + status = g_meta->remove(&fdb_entry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove non existing"); + status = g_meta->remove(&fdb_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} diff --git a/unittest/meta/TestLegacyNeighborEntry.cpp b/unittest/meta/TestLegacyNeighborEntry.cpp new file mode 100644 index 000000000..b23eda496 --- /dev/null +++ b/unittest/meta/TestLegacyNeighborEntry.cpp @@ -0,0 +1,475 @@ +#include "TestLegacy.h" + +#include + +#include + +#include + +using namespace TestLegacy; + +// STATIC HELPERS + +//static sai_neighbor_entry_t create_neighbor_entry() +//{ +// SWSS_LOG_ENTER(); +// +// sai_object_id_t switch_id = create_switch(); +// sai_status_t status; +// +// sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; +// +// sai_neighbor_entry_t neighbor_entry; +// +// sai_object_id_t rif = create_rif(switch_id); +// +// neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; +// neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); +// neighbor_entry.rif_id = rif; +// neighbor_entry.switch_id = switch_id; +// +// sai_attribute_t list[3] = { }; +// +// sai_attribute_t &attr1 = list[0]; +// sai_attribute_t &attr2 = list[1]; +// sai_attribute_t &attr3 = list[2]; +// +// attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; +// memcpy(attr1.value.mac, mac, 6); +// +// attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; +// attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; +// +// attr3.id = -1; +// +// attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; +// +// sai_attribute_t list2[4] = { attr1, attr2, attr2 }; +// +// status = g_meta->create(&neighbor_entry, 2, list2); +// EXPECT_EQ(SAI_STATUS_SUCCESS, status); +// +// return neighbor_entry; +//} + +static sai_object_id_t create_hash( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t hash; + + auto status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 0, NULL); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return hash; +} + +// ACTUAL TESTS + +TEST(LegacyNeighborEntry, neighbor_entry_create) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_object_id_t switch_id = create_switch(); + sai_status_t status; + sai_attribute_t attr; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + sai_neighbor_entry_t neighbor_entry; + + sai_object_id_t rif = create_rif(switch_id); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); + neighbor_entry.rif_id = rif; + neighbor_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create tests"); + + SWSS_LOG_NOTICE("zero attribute count (but there are mandatory attributes)"); + status = g_meta->create(&neighbor_entry, 0, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->create(&neighbor_entry, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("neighbor entry is null"); + status = g_meta->create((sai_neighbor_entry_t*)NULL, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + sai_attribute_t list[3] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + sai_attribute_t &attr3 = list[2]; + + attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; + memcpy(attr1.value.mac, mac, 6); + + attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + attr3.id = -1; + + SWSS_LOG_NOTICE("invalid attribute id"); + status = g_meta->create(&neighbor_entry, 3, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD + 0x100; + SWSS_LOG_NOTICE("invalid attribute value on enum"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_attribute_t list2[4] = { attr1, attr2, attr2 }; + + SWSS_LOG_NOTICE("repeated attribute id"); + status = g_meta->create(&neighbor_entry, 3, list2); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct ipv4"); + status = g_meta->create(&neighbor_entry, 2, list2); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(neighbor_entry.ip_address.addr.ip6, ip6, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&neighbor_entry, 2, list2); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("already exists"); + status = g_meta->create(&neighbor_entry, 2, list2); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyNeighborEntry, neighbor_entry_remove) +{ + clear_local(); + + sai_status_t status; + + sai_object_id_t switch_id = create_switch(); + sai_neighbor_entry_t neighbor_entry; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + sai_attribute_t list[2] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + + attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; + memcpy(attr1.value.mac, mac, 6); + + attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_object_id_t rif = create_rif(switch_id); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); + neighbor_entry.rif_id = rif; + neighbor_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create"); + + SWSS_LOG_NOTICE("correct ipv4"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(neighbor_entry.ip_address.addr.ip6, ip6, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove tests"); + + SWSS_LOG_NOTICE("neighbor_entry is null"); + status = g_meta->remove((sai_neighbor_entry_t*)NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + neighbor_entry.rif_id = SAI_NULL_OBJECT_ID; + + SWSS_LOG_NOTICE("invalid object id null"); + status = g_meta->remove(&neighbor_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + neighbor_entry.rif_id = create_hash(switch_id); + + SWSS_LOG_NOTICE("invalid object id hash"); + status = g_meta->remove(&neighbor_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + neighbor_entry.rif_id = create_rif(switch_id); + + SWSS_LOG_NOTICE("invalid object id router"); + status = g_meta->remove(&neighbor_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + neighbor_entry.rif_id = rif; + + sai_object_meta_key_t key = { .objecttype = SAI_OBJECT_TYPE_NEIGHBOR_ENTRY, .objectkey = { .key = { .neighbor_entry = neighbor_entry } } }; + + EXPECT_TRUE(g_meta->objectExists(key)); + + SWSS_LOG_NOTICE("success"); + status = g_meta->remove(&neighbor_entry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + EXPECT_TRUE(!g_meta->objectExists(key)); + + remove_switch(switch_id); +} + +TEST(LegacyNeighborEntry, neighbor_entry_set) +{ + clear_local(); + + sai_status_t status; + + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + sai_object_id_t switch_id = create_switch(); + sai_neighbor_entry_t neighbor_entry; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + sai_attribute_t list[2] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + + attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; + memcpy(attr1.value.mac, mac, 6); + + attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_object_id_t rif = create_rif(switch_id); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); + neighbor_entry.rif_id = rif; + neighbor_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create"); + + SWSS_LOG_NOTICE("correct ipv4"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(neighbor_entry.ip_address.addr.ip6, ip6, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set tests"); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->set(&neighbor_entry, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("neighbor entry is null"); + status = g_meta->set((sai_neighbor_entry_t*)NULL, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("setting invalid attrib id"); + attr.id = -1; + status = g_meta->set(&neighbor_entry, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("value outside range"); + attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = 0x100; + status = g_meta->set(&neighbor_entry, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // correct + attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_DROP; + status = g_meta->set(&neighbor_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyNeighborEntry, neighbor_entry_get) +{ + clear_local(); + + sai_status_t status; + + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + sai_object_id_t switch_id = create_switch(); + sai_neighbor_entry_t neighbor_entry; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + sai_attribute_t list[2] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + + attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; + memcpy(attr1.value.mac, mac, 6); + + attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_object_id_t rif = create_rif(switch_id); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); + neighbor_entry.rif_id = rif; + neighbor_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create"); + + SWSS_LOG_NOTICE("correct ipv4"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(neighbor_entry.ip_address.addr.ip6, ip6, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get test"); + + SWSS_LOG_NOTICE("zero attribute count"); + attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + status = g_meta->get(&neighbor_entry, 0, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->get(&neighbor_entry, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("neighbor entry is null"); + status = g_meta->get((sai_neighbor_entry_t*)NULL, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr id out of range"); + attr.id = -1; + status = g_meta->get(&neighbor_entry, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct single valid attribute"); + attr.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + status = g_meta->get(&neighbor_entry, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct 2 attributes"); + + sai_attribute_t attr3; + sai_attribute_t attr4; + attr3.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + attr3.value.s32 = 1; + attr4.id = SAI_NEIGHBOR_ENTRY_ATTR_NO_HOST_ROUTE; + + sai_attribute_t list2[2] = { attr3, attr4 }; + status = g_meta->get(&neighbor_entry, 2, list2); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyNeighborEntry, neighbor_entry_flow) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_object_id_t switch_id = create_switch(); + sai_neighbor_entry_t neighbor_entry; + + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + sai_attribute_t list[4] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + sai_attribute_t &attr3 = list[1]; + sai_attribute_t &attr4 = list[1]; + + attr1.id = SAI_NEIGHBOR_ENTRY_ATTR_DST_MAC_ADDRESS; + memcpy(attr1.value.mac, mac, 6); + + attr2.id = SAI_NEIGHBOR_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + attr3.id = SAI_NEIGHBOR_ENTRY_ATTR_NO_HOST_ROUTE; + attr3.value.booldata = true; + + attr4.id = SAI_NEIGHBOR_ENTRY_ATTR_META_DATA; + attr4.value.u32 = 1; + + sai_object_id_t rif = create_rif(switch_id); + + neighbor_entry.ip_address.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + neighbor_entry.ip_address.addr.ip4 = htonl(0x0a00000f); + neighbor_entry.rif_id = rif; + neighbor_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create"); + + SWSS_LOG_NOTICE("correct ipv4"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct ipv4 existing"); + status = g_meta->create(&neighbor_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set"); + status = g_meta->set(&neighbor_entry, &attr1); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set"); + status = g_meta->set(&neighbor_entry, &attr2); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set"); + status = g_meta->set(&neighbor_entry, &attr3); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set"); + status = g_meta->set(&neighbor_entry, &attr4); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove"); + status = g_meta->remove(&neighbor_entry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove existing"); + status = g_meta->remove(&neighbor_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} diff --git a/unittest/meta/TestLegacyOther.cpp b/unittest/meta/TestLegacyOther.cpp new file mode 100644 index 000000000..21f8846ef --- /dev/null +++ b/unittest/meta/TestLegacyOther.cpp @@ -0,0 +1,1038 @@ +#include "TestLegacy.h" +#include "AttrKeyMap.h" + +#include "sai_serialize.h" + +#include +#include + +#include + +#include + +using namespace TestLegacy; +using namespace saimeta; + +// STATIC HELPERS + +static sai_object_id_t create_acl_table( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t at; + + sai_attribute_t attrs[9] = { }; + + attrs[0].id = SAI_ACL_TABLE_ATTR_ACL_STAGE; + attrs[0].value.s32 = SAI_ACL_STAGE_INGRESS; + + auto status = g_meta->create(SAI_OBJECT_TYPE_ACL_TABLE, &at, switch_id, 1, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return at; +} + +static sai_object_id_t create_acl_counter( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t ac; + + sai_attribute_t attrs[9] = { }; + + attrs[0].id = SAI_ACL_COUNTER_ATTR_TABLE_ID; + attrs[0].value.oid = create_acl_table(switch_id); + + auto status = g_meta->create(SAI_OBJECT_TYPE_ACL_COUNTER, &ac, switch_id, 1, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return ac; +} + +static sai_object_id_t create_policer( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t policer; + + sai_attribute_t attrs[9] = { }; + + attrs[0].id = SAI_POLICER_ATTR_METER_TYPE; + attrs[0].value.s32 = SAI_METER_TYPE_PACKETS; + attrs[1].id = SAI_POLICER_ATTR_MODE; + attrs[1].value.s32 = SAI_POLICER_MODE_SR_TCM; + + auto status = g_meta->create(SAI_OBJECT_TYPE_POLICER, &policer, switch_id, 2, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return policer; +} + +static sai_object_id_t create_samplepacket( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t sp; + + sai_attribute_t attrs[9] = { }; + + attrs[0].id = SAI_SAMPLEPACKET_ATTR_SAMPLE_RATE; + attrs[0].value.u32 = 1; + + auto status = g_meta->create(SAI_OBJECT_TYPE_SAMPLEPACKET, &sp, switch_id, 1, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return sp; +} + +static sai_object_id_t create_hostif_udt( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t udt; + + sai_attribute_t attrs[9] = { }; + + attrs[0].id = SAI_HOSTIF_USER_DEFINED_TRAP_ATTR_TYPE; + attrs[0].value.s32 = SAI_HOSTIF_USER_DEFINED_TRAP_TYPE_ROUTER; + + auto status = g_meta->create(SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP, &udt, switch_id, 1, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return udt; +} + +static sai_object_id_t create_ipg( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t ipg; + + sai_attribute_t attrs[9] = { }; + + attrs[0].id = SAI_INGRESS_PRIORITY_GROUP_ATTR_PORT; + attrs[0].value.oid = create_port(switch_id); + attrs[1].id = SAI_INGRESS_PRIORITY_GROUP_ATTR_INDEX; + attrs[1].value.u8 = 0; + + auto status = g_meta->create(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, &ipg, switch_id, 2, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return ipg; +} + +static sai_object_id_t insert_dummy_object( + _In_ sai_object_type_t ot, + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + switch (ot) + { + case SAI_OBJECT_TYPE_PORT: + return create_port(switch_id); + + case SAI_OBJECT_TYPE_ACL_TABLE: + return create_acl_table(switch_id); + + case SAI_OBJECT_TYPE_ACL_COUNTER: + return create_acl_counter(switch_id); + + case SAI_OBJECT_TYPE_POLICER: + return create_policer(switch_id); + + case SAI_OBJECT_TYPE_SAMPLEPACKET: + return create_samplepacket(switch_id); + + case SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP: + return create_hostif_udt(switch_id); + + case SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP: + return create_ipg(switch_id); + + default: + + SWSS_LOG_THROW("not implemented: %s, FIXME", sai_serialize_object_type(ot).c_str()); + } +} + +static sai_object_id_t create_scheduler_group( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); + + sai_object_id_t sg; + + sai_attribute_t attrs[9] = { }; + + attrs[0].id = SAI_SCHEDULER_GROUP_ATTR_PORT_ID; + attrs[0].value.oid = create_port(switch_id); + attrs[1].id = SAI_SCHEDULER_GROUP_ATTR_LEVEL; + attrs[1].value.u8 = 0; + attrs[2].id = SAI_SCHEDULER_GROUP_ATTR_MAX_CHILDS; + attrs[2].value.u8 = 1; + attrs[3].id = SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE; + attrs[3].value.oid = attrs[0].value.oid; + + auto status = g_meta->create(SAI_OBJECT_TYPE_SCHEDULER_GROUP, &sg, switch_id, 4, attrs); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + return sg; +} + +// ACTUAL TESTS + +TEST(Legacy, switch_set) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + sai_object_id_t switch_id = create_switch(); + + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // id outside range + attr.id = -1; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + g_sai->setStatus(SAI_STATUS_FAILURE); + attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + g_sai->setStatus(SAI_STATUS_SUCCESS); + + attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; + attr.value.s32 = 0x1000; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // enum + attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; + attr.value.s32 = SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // bool + attr.id = SAI_SWITCH_ATTR_BCAST_CPU_FLOOD_ENABLE; + attr.value.booldata = SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // mac + sai_mac_t mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS; + memcpy(attr.value.mac, mac, sizeof(mac)); + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // uint8 + attr.id = SAI_SWITCH_ATTR_QOS_DEFAULT_TC; + attr.value.u8 = 0x11; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // object id with not allowed null + + // currently hash is read only + // + // // null oid + + // attr.id = SAI_SWITCH_ATTR_LAG_HASH_IPV6; + // attr.value.oid = SAI_NULL_OBJECT_ID; + // status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + // EXPECT_NE(SAI_STATUS_SUCCESS, status); + // + // // wrong object type + // attr.id = SAI_SWITCH_ATTR_LAG_HASH_IPV6; + // attr.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_LAG); + // status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + // EXPECT_NE(SAI_STATUS_SUCCESS, status); + // + // // valid object (object must exist) + // attr.id = SAI_SWITCH_ATTR_LAG_HASH_IPV6; + // attr.value.oid = create_hash(switch_id); + // + // status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + // EXPECT_EQ(SAI_STATUS_SUCCESS, status); + // + // EXPECT_TRUE(g_meta->getObjectReferenceCount(attr.value.oid) == 1); + + // object id with allowed null + + // null oid + attr.id = SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP; + attr.value.oid = SAI_NULL_OBJECT_ID; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // wrong object + attr.id = SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP; + status = g_meta->create(SAI_OBJECT_TYPE_LAG, &attr.value.oid, switch_id, 0, NULL); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + // good object + attr.id = SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP; + + sai_attribute_t a[2] = { }; + a[0].id = SAI_QOS_MAP_ATTR_TYPE; + a[0].value.s32 = 1; + a[1].id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST; + status = g_meta->create(SAI_OBJECT_TYPE_QOS_MAP, &attr.value.oid, switch_id, 2, a); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + sai_object_id_t oid = attr.value.oid; + + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + EXPECT_TRUE(g_meta->getObjectReferenceCount(attr.value.oid) == 1); + + attr.id = SAI_SWITCH_ATTR_QOS_DOT1P_TO_TC_MAP; + attr.value.oid = SAI_NULL_OBJECT_ID; + status = g_meta->set(SAI_OBJECT_TYPE_SWITCH, switch_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // check if it was decreased + EXPECT_TRUE(g_meta->getObjectReferenceCount(oid) == 0); + + remove_switch(switch_id); +} + +TEST(Legacy, switch_get) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + sai_object_id_t switch_id = create_switch(); + + attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; + status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 0, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1000, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + attr.id = -1; + status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr.id = SAI_SWITCH_ATTR_PORT_NUMBER; + attr.value.u32 = 0; + status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + sai_attribute_t attr1; + attr1.id = SAI_SWITCH_ATTR_PORT_NUMBER; + + sai_attribute_t attr2; + attr2.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID; + sai_attribute_t list[2] = { attr1, attr2 }; + + status = g_meta->get(SAI_OBJECT_TYPE_SWITCH, switch_id, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, serialization_type_vlan_list) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + SWSS_LOG_NOTICE("create stp"); + sai_object_id_t switch_id = create_switch(); + + sai_object_id_t stp = create_stp(switch_id); + + sai_vlan_id_t list[2] = { 1, 2 }; + + sai_attribute_t attr; + + attr.id = SAI_STP_ATTR_VLAN_LIST; + attr.value.vlanlist.count = 2; + attr.value.vlanlist.list = list; + + SWSS_LOG_NOTICE("set vlan list"); + + status = g_meta->set(SAI_OBJECT_TYPE_STP, stp, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get vlan list"); + + status = g_meta->get(SAI_OBJECT_TYPE_STP, stp, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove stp"); + + status = g_meta->remove(SAI_OBJECT_TYPE_STP, stp); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, serialization_type_bool) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_object_id_t vr; + + SWSS_LOG_NOTICE("create stp"); + sai_object_id_t switch_id = create_switch(); + + sai_attribute_t attr; + + attr.id = SAI_VIRTUAL_ROUTER_ATTR_ADMIN_V4_STATE; + attr.value.booldata = true; + + status = g_meta->create(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, &vr, switch_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set bool"); + + status = g_meta->set(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, vr, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get bool"); + + status = g_meta->get(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, vr, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove vr"); + + status = g_meta->remove(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, vr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, serialization_type_char) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_object_id_t hostif; + + SWSS_LOG_NOTICE("create port"); + sai_object_id_t switch_id = create_switch(); + + sai_object_id_t port = create_port(switch_id); + + sai_attribute_t attr, attr2, attr3; + + attr.id = SAI_HOSTIF_ATTR_TYPE; + attr.value.s32 = SAI_HOSTIF_TYPE_NETDEV; + + attr2.id = SAI_HOSTIF_ATTR_OBJ_ID; + attr2.value.oid = port; + + attr3.id = SAI_HOSTIF_ATTR_NAME; + + memcpy(attr3.value.chardata, "foo", sizeof("foo")); + + sai_attribute_t list[3] = { attr, attr2, attr3 }; + + // TODO we need to support conditions here + + SWSS_LOG_NOTICE("create hostif"); + + status = g_meta->create(SAI_OBJECT_TYPE_HOSTIF, &hostif, switch_id, 3, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set char"); + + status = g_meta->set(SAI_OBJECT_TYPE_HOSTIF, hostif, &attr3); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get char"); + + status = g_meta->get(SAI_OBJECT_TYPE_HOSTIF, hostif, 1, &attr3); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove hostif"); + + status = g_meta->remove(SAI_OBJECT_TYPE_HOSTIF, hostif); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + attr.id = SAI_HOSTIF_ATTR_TYPE; + attr.value.s32 = SAI_HOSTIF_TYPE_FD; + + sai_attribute_t list2[1] = { attr }; + + SWSS_LOG_NOTICE("create hostif with non mandatory"); + status = g_meta->create(SAI_OBJECT_TYPE_HOSTIF, &hostif, switch_id, 1, list2); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + // TODO this test should pass, we are doing query here for conditional + // attribute, where condition is not met so this attribute will not be used, so + // metadata should figure out that we can't query this attribute, but there is + // a problem with internal existing objects, since we don't have their values + // then we we can't tell whether attribute was passed or not, we need to get + // switch discovered objects and attributes and populate local db then we need + // to update metadata condition in meta_generic_validation_get method where we + // check if attribute is conditional + // + // SWSS_LOG_NOTICE("get char"); + // + // status = g_meta->get(SAI_OBJECT_TYPE_HOSTIF, hostif, 1, &attr2); + // EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr.id = SAI_HOSTIF_ATTR_TYPE; + attr.value.s32 = SAI_HOSTIF_TYPE_NETDEV; + + sai_attribute_t list3[1] = { attr }; + + SWSS_LOG_NOTICE("create hostif with mandatory missing"); + status = g_meta->create(SAI_OBJECT_TYPE_HOSTIF, &hostif, switch_id, 1, list3); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, serialization_type_int32_list) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_object_id_t hash; + + sai_attribute_t attr; + + SWSS_LOG_NOTICE("create hash"); + sai_object_id_t switch_id = create_switch(); + + int32_t list[2] = { SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_VLAN_ID }; + + attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; + attr.value.s32list.count = 2; + attr.value.s32list.list = list; + + status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set hash"); + + status = g_meta->set(SAI_OBJECT_TYPE_HASH, hash, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get hash"); + + status = g_meta->get(SAI_OBJECT_TYPE_HASH, hash, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove hash"); + + status = g_meta->remove(SAI_OBJECT_TYPE_HASH, hash); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, test_serialization_type_uint32_list) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_object_id_t hash; + + sai_attribute_t attr; + + SWSS_LOG_NOTICE("create hash"); + sai_object_id_t switch_id = create_switch(); + + int32_t list[2] = { SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_VLAN_ID }; + + attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; + attr.value.s32list.count = 2; + attr.value.s32list.list = list; + + status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set hash"); + + status = g_meta->set(SAI_OBJECT_TYPE_HASH, hash, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get hash"); + + status = g_meta->get(SAI_OBJECT_TYPE_HASH, hash, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove hash"); + + status = g_meta->remove(SAI_OBJECT_TYPE_HASH, hash); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, mask) +{ + SWSS_LOG_ENTER(); + + sai_ip6_t ip6mask1 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; + sai_ip6_t ip6mask2 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0xff}; + sai_ip6_t ip6mask3 = {0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00}; + sai_ip6_t ip6mask4 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0xfe}; + sai_ip6_t ip6mask5 = {0x80, 0x00, 0x00, 0x00,0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00}; + + sai_ip6_t ip6mask6 = {0x01, 0x00, 0x00, 0x00,0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00,0x00,0x00,0x00,0x00}; + sai_ip6_t ip6mask7 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x8f}; + sai_ip6_t ip6mask8 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x8f}; + sai_ip6_t ip6mask9 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xf1, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0xff}; + + EXPECT_TRUE(Meta::is_ipv6_mask_valid(ip6mask1)); + EXPECT_TRUE(Meta::is_ipv6_mask_valid(ip6mask2)); + EXPECT_TRUE(Meta::is_ipv6_mask_valid(ip6mask3)); + EXPECT_TRUE(Meta::is_ipv6_mask_valid(ip6mask4)); + EXPECT_TRUE(Meta::is_ipv6_mask_valid(ip6mask5)); + + EXPECT_TRUE(!Meta::is_ipv6_mask_valid(ip6mask6)); + EXPECT_TRUE(!Meta::is_ipv6_mask_valid(ip6mask7)); + EXPECT_TRUE(!Meta::is_ipv6_mask_valid(ip6mask8)); + EXPECT_TRUE(!Meta::is_ipv6_mask_valid(ip6mask9)); +} + +TEST(Legacy, acl_entry_field_and_action) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_object_id_t switch_id = create_switch(); + sai_status_t status; + + sai_object_id_t aclentry; + + int32_t ids[] = { + SAI_ACL_ENTRY_ATTR_TABLE_ID, + SAI_ACL_ENTRY_ATTR_PRIORITY, + SAI_ACL_ENTRY_ATTR_FIELD_SRC_IPV6, + SAI_ACL_ENTRY_ATTR_FIELD_DST_IPV6, + SAI_ACL_ENTRY_ATTR_FIELD_SRC_MAC, + SAI_ACL_ENTRY_ATTR_FIELD_DST_MAC, + SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP, + SAI_ACL_ENTRY_ATTR_FIELD_DST_IP, + SAI_ACL_ENTRY_ATTR_FIELD_IN_PORTS, + SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORTS, + SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT, + SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORT, + SAI_ACL_ENTRY_ATTR_FIELD_SRC_PORT, + SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_ID, + SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_PRI, + SAI_ACL_ENTRY_ATTR_FIELD_OUTER_VLAN_CFI, + SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_ID, + SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_PRI, + SAI_ACL_ENTRY_ATTR_FIELD_INNER_VLAN_CFI, + SAI_ACL_ENTRY_ATTR_FIELD_L4_SRC_PORT, + SAI_ACL_ENTRY_ATTR_FIELD_L4_DST_PORT, + SAI_ACL_ENTRY_ATTR_FIELD_ETHER_TYPE, + SAI_ACL_ENTRY_ATTR_FIELD_IP_PROTOCOL, + SAI_ACL_ENTRY_ATTR_FIELD_DSCP, + SAI_ACL_ENTRY_ATTR_FIELD_ECN, + SAI_ACL_ENTRY_ATTR_FIELD_TTL, + SAI_ACL_ENTRY_ATTR_FIELD_TOS, + SAI_ACL_ENTRY_ATTR_FIELD_IP_FLAGS, + SAI_ACL_ENTRY_ATTR_FIELD_TCP_FLAGS, + SAI_ACL_ENTRY_ATTR_FIELD_ACL_IP_FRAG, + SAI_ACL_ENTRY_ATTR_FIELD_IPV6_FLOW_LABEL, + SAI_ACL_ENTRY_ATTR_FIELD_TC, + SAI_ACL_ENTRY_ATTR_FIELD_ICMP_TYPE, + SAI_ACL_ENTRY_ATTR_FIELD_ICMP_CODE, + SAI_ACL_ENTRY_ATTR_FIELD_FDB_DST_USER_META, + SAI_ACL_ENTRY_ATTR_FIELD_ROUTE_DST_USER_META, + SAI_ACL_ENTRY_ATTR_FIELD_NEIGHBOR_DST_USER_META, + SAI_ACL_ENTRY_ATTR_FIELD_PORT_USER_META, + SAI_ACL_ENTRY_ATTR_FIELD_VLAN_USER_META, + SAI_ACL_ENTRY_ATTR_FIELD_ACL_USER_META, + SAI_ACL_ENTRY_ATTR_FIELD_FDB_NPU_META_DST_HIT, + SAI_ACL_ENTRY_ATTR_FIELD_NEIGHBOR_NPU_META_DST_HIT, + SAI_ACL_ENTRY_ATTR_FIELD_ROUTE_NPU_META_DST_HIT, + SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT, + //SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT_LIST, + SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION, + SAI_ACL_ENTRY_ATTR_ACTION_FLOOD, + SAI_ACL_ENTRY_ATTR_ACTION_COUNTER, + SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_INGRESS, + SAI_ACL_ENTRY_ATTR_ACTION_MIRROR_EGRESS, + SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER, + SAI_ACL_ENTRY_ATTR_ACTION_DECREMENT_TTL, + SAI_ACL_ENTRY_ATTR_ACTION_SET_TC, + SAI_ACL_ENTRY_ATTR_ACTION_SET_PACKET_COLOR, + SAI_ACL_ENTRY_ATTR_ACTION_SET_INNER_VLAN_ID, + SAI_ACL_ENTRY_ATTR_ACTION_SET_INNER_VLAN_PRI, + SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_ID, + SAI_ACL_ENTRY_ATTR_ACTION_SET_OUTER_VLAN_PRI, + SAI_ACL_ENTRY_ATTR_ACTION_SET_SRC_MAC, + SAI_ACL_ENTRY_ATTR_ACTION_SET_DST_MAC, + SAI_ACL_ENTRY_ATTR_ACTION_SET_SRC_IP, + SAI_ACL_ENTRY_ATTR_ACTION_SET_DST_IP, + SAI_ACL_ENTRY_ATTR_ACTION_SET_SRC_IPV6, + SAI_ACL_ENTRY_ATTR_ACTION_SET_DST_IPV6, + SAI_ACL_ENTRY_ATTR_ACTION_SET_DSCP, + SAI_ACL_ENTRY_ATTR_ACTION_SET_ECN, + SAI_ACL_ENTRY_ATTR_ACTION_SET_L4_SRC_PORT, + SAI_ACL_ENTRY_ATTR_ACTION_SET_L4_DST_PORT, + SAI_ACL_ENTRY_ATTR_ACTION_INGRESS_SAMPLEPACKET_ENABLE, + SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_SAMPLEPACKET_ENABLE, + SAI_ACL_ENTRY_ATTR_ACTION_SET_ACL_META_DATA, + SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_BLOCK_PORT_LIST, + SAI_ACL_ENTRY_ATTR_ACTION_SET_USER_TRAP_ID, + }; + + std::vector vattrs; + + // all lists are empty we need info if that is possible + + for (uint32_t i = 0; i < sizeof(ids)/sizeof(int32_t); ++i) + { + sai_attribute_t attr; + + memset(&attr,0,sizeof(attr)); + + attr.value.aclfield.enable = true; + attr.value.aclaction.enable = true; + + attr.id = ids[i]; + + if (attr.id == SAI_ACL_ENTRY_ATTR_TABLE_ID) + attr.value.oid = insert_dummy_object(SAI_OBJECT_TYPE_ACL_TABLE,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_FIELD_IN_PORT) + attr.value.aclfield.data.oid = insert_dummy_object(SAI_OBJECT_TYPE_PORT,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_FIELD_OUT_PORT) + attr.value.aclfield.data.oid = insert_dummy_object(SAI_OBJECT_TYPE_PORT,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_FIELD_SRC_PORT) + attr.value.aclfield.data.oid = insert_dummy_object(SAI_OBJECT_TYPE_PORT,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT) + attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_PORT,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_COUNTER) + attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_ACL_COUNTER,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_SET_POLICER) + attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_POLICER,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_INGRESS_SAMPLEPACKET_ENABLE) + attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_SAMPLEPACKET,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_EGRESS_SAMPLEPACKET_ENABLE) + attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_SAMPLEPACKET,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_SET_USER_TRAP_ID) + attr.value.aclaction.parameter.oid = insert_dummy_object(SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP,switch_id); + + if (attr.id == SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT_LIST) + { + sai_object_id_t list[1]; + + list[0] = insert_dummy_object(SAI_OBJECT_TYPE_QUEUE,switch_id); + + SWSS_LOG_NOTICE("0x%" PRIx64, list[0]); + + attr.value.aclaction.parameter.objlist.count = 1; + attr.value.aclaction.parameter.objlist.list = list; + } + + vattrs.push_back(attr); + } + + SWSS_LOG_NOTICE("create acl entry"); + + status = g_meta->create(SAI_OBJECT_TYPE_ACL_ENTRY, &aclentry, switch_id, (uint32_t)vattrs.size(), vattrs.data()); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + for (uint32_t i = 0; i < sizeof(ids)/sizeof(int32_t); ++i) + { + if (vattrs[i].id == SAI_ACL_ENTRY_ATTR_TABLE_ID) + continue; + + auto m = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, vattrs[i].id); + + SWSS_LOG_NOTICE("set aclentry %u %s", i, m->attridname); + + status = g_meta->set(SAI_OBJECT_TYPE_ACL_ENTRY, aclentry, &vattrs[i]); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + } + + SWSS_LOG_NOTICE("get aclentry"); + + status = g_meta->get(SAI_OBJECT_TYPE_ACL_ENTRY, aclentry, (uint32_t)vattrs.size(), vattrs.data()); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove aclentry"); + + status = g_meta->remove(SAI_OBJECT_TYPE_ACL_ENTRY, aclentry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, construct_key) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_attribute_t attr; + + uint32_t list[4] = {1,2,3,4}; + + attr.id = SAI_PORT_ATTR_HW_LANE_LIST; + attr.value.u32list.count = 4; + attr.value.u32list.list = list; + + sai_object_meta_key_t meta_key; + + meta_key.objecttype = SAI_OBJECT_TYPE_PORT; + + sai_object_id_t switchId = 0x21000000000000; + + std::string key = AttrKeyMap::constructKey(switchId, meta_key, 1, &attr); + + SWSS_LOG_NOTICE("constructed key: %s", key.c_str()); + + EXPECT_TRUE(key == "oid:0x21000000000000;SAI_PORT_ATTR_HW_LANE_LIST:1,2,3,4;"); +} + +TEST(Legacy, queue_create) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_object_id_t switch_id = create_switch(); + + sai_status_t status; + sai_object_id_t queue; + + sai_attribute_t attr1; + sai_attribute_t attr2; + sai_attribute_t attr3; + sai_attribute_t attr4; + + attr1.id = SAI_QUEUE_ATTR_TYPE; + attr1.value.s32 = SAI_QUEUE_TYPE_UNICAST; + + attr2.id = SAI_QUEUE_ATTR_INDEX; + attr2.value.u8 = 7; + + attr3.id = SAI_QUEUE_ATTR_PORT; + attr3.value.oid = create_port(switch_id); + + attr4.id = SAI_QUEUE_ATTR_PARENT_SCHEDULER_NODE; + attr4.value.oid = create_scheduler_group(switch_id); + + sai_attribute_t list[4] = { attr1, attr2, attr3, attr4 }; + + SWSS_LOG_NOTICE("create tests"); + + SWSS_LOG_NOTICE("create queue"); + status = g_meta->create(SAI_OBJECT_TYPE_QUEUE, &queue, switch_id, 4, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("create queue but key exists"); + status = g_meta->create(SAI_OBJECT_TYPE_QUEUE, &queue, switch_id, 4, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove queue"); + status = g_meta->remove(SAI_OBJECT_TYPE_QUEUE, queue); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("create queue"); + status = g_meta->create(SAI_OBJECT_TYPE_QUEUE, &queue, switch_id, 4, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, null_list) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_object_id_t hash; + + sai_attribute_t attr; + + int32_t list[2] = { SAI_NATIVE_HASH_FIELD_SRC_IP, SAI_NATIVE_HASH_FIELD_VLAN_ID }; + + attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; + attr.value.s32list.count = 0; + attr.value.s32list.list = list; + sai_object_id_t switch_id = create_switch(); + + SWSS_LOG_NOTICE("0 count, not null list"); + status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr.value.s32list.list = NULL; + + SWSS_LOG_NOTICE("0 count, null list"); + status = g_meta->create(SAI_OBJECT_TYPE_HASH, &hash, switch_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, priority_group) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_object_id_t switch_id = create_switch(); + + sai_status_t status; + + sai_attribute_t attr; + + sai_object_id_t pg = insert_dummy_object(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, switch_id); + + SWSS_LOG_NOTICE("set SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE attr"); + + attr.id = SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE; + attr.value.oid = SAI_NULL_OBJECT_ID; + status = g_meta->set(SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP, pg, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(Legacy, bulk_route_entry_create) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + int object_count = 1000; + + std::vector routes; + std::vector attr_counts; + std::vector attr_lists; + std::vector statuses(object_count); + + sai_object_id_t switch_id = create_switch(); + + sai_object_id_t vr = create_virtual_router(switch_id); + sai_object_id_t hop = create_next_hop(switch_id); + + sai_attribute_t attr; + + attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr.value.oid = hop; + + int n = 100; + + for (int i = 0; i < object_count * n; i++) + { + sai_route_entry_t re; + + memset(re.destination.mask.ip6, 0xff, sizeof(re.destination.mask.ip6)); + re.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + re.destination.addr.ip4 = htonl(0x0a00000f + i); + re.destination.mask.ip4 = htonl(0xffffff00); + re.vr_id = vr; + re.switch_id = switch_id; + + routes.push_back(re); + + attr_counts.push_back(1); + + // since we use the same attribute every where we can get away with this + + attr_lists.push_back(&attr); + } + + auto start = std::chrono::high_resolution_clock::now(); + + if (getenv("TEST_NO_PERF")) + { + object_count = 10; + + std::cout << "disabling performance tests" << std::endl; + } + + + for (int i = 0; i < n; i++) + { + auto status = g_meta->bulkCreate( + object_count, + routes.data() + i * object_count, + attr_counts.data(), + attr_lists.data(), + SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, + statuses.data()); + + EXPECT_EQ(status, SAI_STATUS_SUCCESS); + } + + auto end = std::chrono::high_resolution_clock::now(); + auto time = end - start; + auto us = std::chrono::duration_cast(time); + + std::cout << "ms: " << (double)us.count()/1000 << " / " << n << "/" << object_count << std::endl; +} + diff --git a/unittest/meta/TestLegacyRouteEntry.cpp b/unittest/meta/TestLegacyRouteEntry.cpp new file mode 100644 index 000000000..9c5e91cca --- /dev/null +++ b/unittest/meta/TestLegacyRouteEntry.cpp @@ -0,0 +1,544 @@ +#include "TestLegacy.h" + +#include + +#include + +#include + +using namespace TestLegacy; + +// STATIC HELPERS + +// ACTUAL TESTS + +TEST(LegacyRouteEntry, route_entry_create) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + + sai_object_id_t switch_id = create_switch(); + sai_route_entry_t route_entry; + + sai_object_id_t vr = create_virtual_router(switch_id); + + sai_object_id_t hop = create_next_hop(switch_id); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + route_entry.destination.addr.ip4 = htonl(0x0a00000f); + route_entry.destination.mask.ip4 = htonl(0xffffff00); + route_entry.vr_id = vr; + route_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create tests"); + + // commented out as there is no mandatory attribute + // SWSS_LOG_NOTICE("zero attribute count (but there are mandatory attributes)"); + // attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + // status = g_meta->create(&route_entry, 0, &attr); + // EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->create(&route_entry, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("route entry is null"); + status = g_meta->create((sai_route_entry_t*)NULL, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + sai_attribute_t list[3] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + sai_attribute_t &attr3 = list[2]; + + attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr1.value.oid = hop; + + attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + attr3.id = -1; + + SWSS_LOG_NOTICE("invalid attribute id"); + status = g_meta->create(&route_entry, 3, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD + 0x100; + SWSS_LOG_NOTICE("invalid attribute value on enum"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_attribute_t list2[4] = { attr1, attr2, attr2 }; + + SWSS_LOG_NOTICE("repeated attribute id"); + status = g_meta->create(&route_entry, 3, list2); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("wrong object type"); + attr1.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("non existing object"); + attr1.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_NEXT_HOP,switch_id); + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + int fam = 10; + attr1.value.oid = hop; + route_entry.destination.addr_family = (sai_ip_addr_family_t)fam; + + SWSS_LOG_NOTICE("wrong address family"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct ipv4"); + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip62 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0x99}; + memcpy(route_entry.destination.addr.ip6, ip62, 16); + + sai_ip6_t ip6mask2 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xf7,0x00}; + memcpy(route_entry.destination.mask.ip6, ip6mask2, 16); + + SWSS_LOG_NOTICE("invalid mask"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(route_entry.destination.addr.ip6, ip6, 16); + + sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; + memcpy(route_entry.destination.mask.ip6, ip6mask, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("already exists"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyRouteEntry, route_entry_remove) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + sai_object_id_t switch_id = create_switch(); + + sai_route_entry_t route_entry; + + sai_object_id_t vr = create_virtual_router(switch_id); + sai_object_id_t hop = create_next_hop(switch_id); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + route_entry.destination.addr.ip4 = htonl(0x0a00000f); + route_entry.destination.mask.ip4 = htonl(0xffffff00); + route_entry.vr_id = vr; + route_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create tests"); + + sai_attribute_t list[3] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + + attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr1.value.oid = hop; + + attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + SWSS_LOG_NOTICE("correct ipv4"); + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(route_entry.destination.addr.ip6, ip6, 16); + + sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; + memcpy(route_entry.destination.mask.ip6, ip6mask, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove tests"); + + SWSS_LOG_NOTICE("route_entry is null"); + status = g_meta->remove((sai_route_entry_t*)NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + route_entry.vr_id = SAI_NULL_OBJECT_ID; + + SWSS_LOG_NOTICE("invalid object id null"); + status = g_meta->remove(&route_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + route_entry.vr_id = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); + + SWSS_LOG_NOTICE("invalid object id hash"); + status = g_meta->remove(&route_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + route_entry.vr_id = create_dummy_object_id(SAI_OBJECT_TYPE_VIRTUAL_ROUTER,switch_id); + + SWSS_LOG_NOTICE("invalid object id router"); + status = g_meta->remove(&route_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + route_entry.vr_id = vr; + + sai_object_meta_key_t key = { .objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY, .objectkey = { .key = { .route_entry = route_entry } } }; + + EXPECT_TRUE(g_meta->objectExists(key)); + + SWSS_LOG_NOTICE("success"); + status = g_meta->remove(&route_entry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + EXPECT_TRUE(!g_meta->objectExists(key)); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + route_entry.destination.addr.ip4 = htonl(0x0a00000f); + route_entry.destination.mask.ip4 = htonl(0xffffff00); + + SWSS_LOG_NOTICE("success"); + status = g_meta->remove(&route_entry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyRouteEntry, route_entry_set) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + sai_object_id_t switch_id = create_switch(); + + memset(&attr, 0, sizeof(attr)); + + sai_route_entry_t route_entry; + + sai_object_id_t vr = create_virtual_router(switch_id); + sai_object_id_t hop = create_next_hop(switch_id); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + route_entry.destination.addr.ip4 = htonl(0x0a00000f); + route_entry.destination.mask.ip4 = htonl(0xffffff00); + route_entry.vr_id = vr; + route_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create tests"); + + sai_attribute_t list[3] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + + attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr1.value.oid = hop; + + attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + SWSS_LOG_NOTICE("correct ipv4"); + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(route_entry.destination.addr.ip6, ip6, 16); + + sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; + memcpy(route_entry.destination.mask.ip6, ip6mask, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set tests"); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->set(&route_entry, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("route entry is null"); + status = g_meta->set((sai_route_entry_t*)NULL, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("setting invalid attrib id"); + attr.id = -1; + status = g_meta->set(&route_entry, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("value outside range"); + attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = 0x100; + status = g_meta->set(&route_entry, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct packet action"); + attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_DROP; + status = g_meta->set(&route_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct next hop"); + attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr.value.oid = hop; + status = g_meta->set(&route_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct metadata"); + attr.id = SAI_ROUTE_ENTRY_ATTR_META_DATA; + attr.value.u32 = 0x12345678; + status = g_meta->set(&route_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyRouteEntry, route_entry_get) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + sai_object_id_t switch_id = create_switch(); + + memset(&attr, 0, sizeof(attr)); + + sai_route_entry_t route_entry; + + sai_object_id_t vr = create_virtual_router(switch_id); + sai_object_id_t hop = create_next_hop(switch_id); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + route_entry.destination.addr.ip4 = htonl(0x0a00000f); + route_entry.destination.mask.ip4 = htonl(0xffffff00); + route_entry.vr_id = vr; + route_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create tests"); + + sai_attribute_t list[3] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + + attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr1.value.oid = hop; + + attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + SWSS_LOG_NOTICE("correct ipv4"); + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(route_entry.destination.addr.ip6, ip6, 16); + + sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; + memcpy(route_entry.destination.mask.ip6, ip6mask, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("zero attribute count"); + attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + status = g_meta->get(&route_entry, 0, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->get(&route_entry, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("route entry is null"); + status = g_meta->get((sai_route_entry_t*)NULL, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr id out of range"); + attr.id = -1; + status = g_meta->get(&route_entry, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct packet action"); + attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + status = g_meta->get(&route_entry, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct next hop"); + attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + status = g_meta->get(&route_entry, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct meta"); + attr.id = SAI_ROUTE_ENTRY_ATTR_META_DATA; + status = g_meta->get(&route_entry, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyRouteEntry, route_entry_flow) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + sai_attribute_t attr; + + sai_route_entry_t route_entry; + sai_object_id_t switch_id = create_switch(); + + sai_object_id_t vr = create_virtual_router(switch_id); + sai_object_id_t hop = create_next_hop(switch_id); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + route_entry.destination.addr.ip4 = htonl(0x0a00000f); + route_entry.destination.mask.ip4 = htonl(0xffffff00); + route_entry.vr_id = vr; + route_entry.switch_id = switch_id; + + SWSS_LOG_NOTICE("create tests"); + + sai_attribute_t list[3] = { }; + + sai_attribute_t &attr1 = list[0]; + sai_attribute_t &attr2 = list[1]; + + attr1.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr1.value.oid = hop; + + attr2.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr2.value.s32 = SAI_PACKET_ACTION_FORWARD; + + SWSS_LOG_NOTICE("correct ipv4"); + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("already exists ipv4"); + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip62 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0x99}; + memcpy(route_entry.destination.addr.ip6, ip62, 16); + + sai_ip6_t ip6mask2 = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xf7,0x00}; + memcpy(route_entry.destination.mask.ip6, ip6mask2, 16); + + SWSS_LOG_NOTICE("invalid mask"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + sai_ip6_t ip6 = {0x00, 0x11, 0x22, 0x33,0x44, 0x55, 0x66,0x77, 0x88, 0x99, 0xaa, 0xbb,0xcc,0xdd,0xee,0xff}; + memcpy(route_entry.destination.addr.ip6, ip6, 16); + + sai_ip6_t ip6mask = {0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff, 0xff,0xff,0xff,0xff,0x00}; + memcpy(route_entry.destination.mask.ip6, ip6mask, 16); + + SWSS_LOG_NOTICE("correct ipv6"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("already exists"); + status = g_meta->create(&route_entry, 2, list); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set tests"); + + SWSS_LOG_NOTICE("correct packet action"); + attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_DROP; + status = g_meta->set(&route_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct next hop"); + attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + attr.value.oid = hop; + status = g_meta->set(&route_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct metadata"); + attr.id = SAI_ROUTE_ENTRY_ATTR_META_DATA; + attr.value.u32 = 0x12345678; + status = g_meta->set(&route_entry, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get tests"); + + SWSS_LOG_NOTICE("correct packet action"); + attr.id = SAI_ROUTE_ENTRY_ATTR_PACKET_ACTION; + status = g_meta->get(&route_entry, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct next hop"); + attr.id = SAI_ROUTE_ENTRY_ATTR_NEXT_HOP_ID; + status = g_meta->get(&route_entry, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("correct meta"); + attr.id = SAI_ROUTE_ENTRY_ATTR_META_DATA; + status = g_meta->get(&route_entry, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove tests"); + + SWSS_LOG_NOTICE("success"); + status = g_meta->remove(&route_entry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("non existing"); + status = g_meta->remove(&route_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + route_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + route_entry.destination.addr.ip4 = htonl(0x0a00000f); + route_entry.destination.mask.ip4 = htonl(0xffffff00); + + SWSS_LOG_NOTICE("success"); + status = g_meta->remove(&route_entry); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("non existing"); + status = g_meta->remove(&route_entry); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} diff --git a/unittest/meta/TestLegacyVlan.cpp b/unittest/meta/TestLegacyVlan.cpp new file mode 100644 index 000000000..61005b3d6 --- /dev/null +++ b/unittest/meta/TestLegacyVlan.cpp @@ -0,0 +1,483 @@ +#include "TestLegacy.h" + +#include + +#include + +#include + +using namespace TestLegacy; + +// STATIC HELPERS + +//static sai_object_id_t create_vlan( +// _In_ sai_object_id_t switch_id) +//{ +// SWSS_LOG_ENTER(); +// +// sai_object_id_t vlan; +// +// sai_attribute_t attrs[9] = { }; +// +// attrs[0].id = SAI_VLAN_ATTR_VLAN_ID; +// attrs[0].value.u16 = 1; +// +// auto status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan, switch_id, 1, attrs); +// EXPECT_EQ(SAI_STATUS_SUCCESS, status); +// +// return vlan; +//} + +// ACTUAL TESTS + +TEST(LegacyVlan, vlan_create) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_attribute_t vlan1_att; + vlan1_att.id = SAI_VLAN_ATTR_VLAN_ID; + vlan1_att.value.u16 = 1; + + sai_object_id_t vlan1_id; + + sai_object_id_t switch_id = create_switch(); + + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan1_id, switch_id, 1, &vlan1_att); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + sai_attribute_t vlan; + vlan.id = SAI_VLAN_ATTR_VLAN_ID; + vlan.value.u16 = 2; + + sai_object_id_t vlan_id; + + SWSS_LOG_NOTICE("create tests"); + +// SWSS_LOG_NOTICE("existing vlan"); +// status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); +// EXPECT_NE(SAI_STATUS_SUCCESS, status); + + vlan.value.u16 = MAXIMUM_VLAN_NUMBER + 1; + +// SWSS_LOG_NOTICE("vlan outside range"); +// status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); +// EXPECT_NE(SAI_STATUS_SUCCESS, status); + + vlan.value.u16 = 2; + + SWSS_LOG_NOTICE("correct"); + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("existing"); + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyVlan, vlan_remove) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_attribute_t vlan1_att; + vlan1_att.id = SAI_VLAN_ATTR_VLAN_ID; + vlan1_att.value.u16 = 1; + + sai_object_id_t vlan1_id; + sai_object_id_t switch_id = create_switch(); + + SWSS_LOG_NOTICE("create"); + + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan1_id, switch_id, 1, &vlan1_att); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + sai_attribute_t vlan; + vlan.id = SAI_VLAN_ATTR_VLAN_ID; + vlan.value.u16 = 2; + + sai_object_id_t vlan_id; + + SWSS_LOG_NOTICE("correct"); + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove tests"); + + SWSS_LOG_NOTICE("invalid vlan"); + status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, SAI_NULL_OBJECT_ID); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + +// SWSS_LOG_NOTICE("default vlan"); +// status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan1_id); +// EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("success"); + status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan_id); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("non existing"); + status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan_id); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyVlan, vlan_set) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_status_t status; + + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + sai_attribute_t vlan1_att; + vlan1_att.id = SAI_VLAN_ATTR_VLAN_ID; + vlan1_att.value.u16 = 1; + + sai_object_id_t vlan1_id; + sai_object_id_t switch_id = create_switch(); + + sai_object_id_t stp = create_stp(switch_id); + + SWSS_LOG_NOTICE("create"); + + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan1_id, switch_id, 1, &vlan1_att); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + sai_attribute_t vlan; + vlan.id = SAI_VLAN_ATTR_VLAN_ID; + vlan.value.u16 = 2; + + sai_object_id_t vlan_id; + + SWSS_LOG_NOTICE("correct"); + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set tests"); + + SWSS_LOG_NOTICE("invalid vlan"); + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, SAI_NULL_OBJECT_ID, &vlan); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set is null"); + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &vlan); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr.id = -1; + + SWSS_LOG_NOTICE("invalid attribute"); + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr.id = SAI_VLAN_ATTR_MEMBER_LIST; + + SWSS_LOG_NOTICE("read only"); + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("max learned addresses"); + attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; + attr.value.u32 = 1; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("null stp instance"); + attr.id = SAI_VLAN_ATTR_STP_INSTANCE; + attr.value.oid = SAI_NULL_OBJECT_ID; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("wrong type on stp instance"); + attr.id = SAI_VLAN_ATTR_STP_INSTANCE; + attr.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("wrong type on stp instance"); + attr.id = SAI_VLAN_ATTR_STP_INSTANCE; + attr.value.oid = create_dummy_object_id(SAI_OBJECT_TYPE_STP,switch_id); + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("good stp oid"); + attr.id = SAI_VLAN_ATTR_STP_INSTANCE; + attr.value.oid = stp; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("learn disable"); + attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; + attr.value.booldata = false; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("metadat"); + attr.id = SAI_VLAN_ATTR_META_DATA; + attr.value.u32 = 1; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyVlan, vlan_get) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_object_id_t switch_id = create_switch(); + sai_status_t status; + + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + sai_attribute_t vlan1_att; + vlan1_att.id = SAI_VLAN_ATTR_VLAN_ID; + vlan1_att.value.u16 = 1; + + sai_object_id_t vlan1_id; + + sai_object_id_t stp = create_stp(switch_id); + + SWSS_LOG_NOTICE("create"); + + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan1_id, switch_id, 1, &vlan1_att); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + sai_attribute_t vlan; + vlan.id = SAI_VLAN_ATTR_VLAN_ID; + vlan.value.u16 = 2; + + sai_object_id_t vlan_id; + + SWSS_LOG_NOTICE("correct"); + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &vlan); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get tests"); + + attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; + + SWSS_LOG_NOTICE("invalid vlan"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, 0, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + +// SWSS_LOG_NOTICE("invalid vlan"); +// status = g_meta->get(SAI_OBJECT_TYPE_VLAN, 3, 1, &attr); +// EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("attr is null"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, NULL); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("zero attributes"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 0, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr.id = -1; + + SWSS_LOG_NOTICE("invalid attribute"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + attr.id = SAI_VLAN_ATTR_MEMBER_LIST; + attr.value.objlist.count = 1; + attr.value.objlist.list = NULL; + + SWSS_LOG_NOTICE("read only null list"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + sai_object_id_t list[5] = { }; + + list[0] = SAI_NULL_OBJECT_ID; + list[1] = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); + list[2] = create_dummy_object_id(SAI_OBJECT_TYPE_VLAN_MEMBER,switch_id); + list[3] = stp; + + attr.value.objlist.count = 0; + attr.value.objlist.list = list; + + SWSS_LOG_NOTICE("readonly 0 count and not null"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); +// EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + attr.value.objlist.count = 5; + + SWSS_LOG_NOTICE("readonly count and not null"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + attr.value.objlist.count = 0; + attr.value.objlist.list = NULL; + + SWSS_LOG_NOTICE("readonly count 0 and null"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("max learned addresses"); + attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("stp instance"); + attr.id = SAI_VLAN_ATTR_STP_INSTANCE; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("learn disable"); + attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("metadata"); + attr.id = SAI_VLAN_ATTR_META_DATA; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} + +TEST(LegacyVlan, vlan_flow) +{ + SWSS_LOG_ENTER(); + + clear_local(); + + sai_attribute_t attr; + + sai_status_t status; + + sai_object_id_t vlan_id; + + attr.id = SAI_VLAN_ATTR_VLAN_ID; + attr.value.u16 = 2; + sai_object_id_t switch_id = create_switch(); + + sai_object_id_t stp = create_stp(switch_id); + + SWSS_LOG_NOTICE("create"); + + attr.id = SAI_VLAN_ATTR_VLAN_ID; + attr.value.u16 = 2; + + SWSS_LOG_NOTICE("correct"); + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("existing"); + status = g_meta->create(SAI_OBJECT_TYPE_VLAN, &vlan_id, switch_id, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("set"); + + SWSS_LOG_NOTICE("max learned addresses"); + attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; + attr.value.u32 = 1; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("good stp oid"); + attr.id = SAI_VLAN_ATTR_STP_INSTANCE; + attr.value.oid = stp; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("learn disable"); + attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; + attr.value.booldata = false; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("metadata"); + attr.id = SAI_VLAN_ATTR_META_DATA; + attr.value.u32 = 1; + status = g_meta->set(SAI_OBJECT_TYPE_VLAN, vlan_id, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("get"); + + sai_object_id_t list[5] = { }; + + list[0] = SAI_NULL_OBJECT_ID; + list[1] = create_dummy_object_id(SAI_OBJECT_TYPE_HASH,switch_id); + list[2] = create_dummy_object_id(SAI_OBJECT_TYPE_VLAN_MEMBER,switch_id); + list[3] = stp; + + attr.value.objlist.count = 0; + attr.value.objlist.list = list; + + SWSS_LOG_NOTICE("readonly 0 count and not null"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + attr.value.objlist.count = 5; + + SWSS_LOG_NOTICE("readonly count and not null"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + attr.value.objlist.count = 0; + attr.value.objlist.list = NULL; + + SWSS_LOG_NOTICE("readonly count 0 and null"); + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("max learned addresses"); + attr.id = SAI_VLAN_ATTR_MAX_LEARNED_ADDRESSES; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("stp instance"); + attr.id = SAI_VLAN_ATTR_STP_INSTANCE; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("learn disable"); + attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("metadata"); + attr.id = SAI_VLAN_ATTR_META_DATA; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("remove"); + + SWSS_LOG_NOTICE("success"); + status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan_id); + EXPECT_EQ(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("non existing"); + status = g_meta->remove(SAI_OBJECT_TYPE_VLAN, vlan_id); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + SWSS_LOG_NOTICE("learn disable"); + attr.id = SAI_VLAN_ATTR_LEARN_DISABLE; + status = g_meta->get(SAI_OBJECT_TYPE_VLAN, vlan_id, 1, &attr); + EXPECT_NE(SAI_STATUS_SUCCESS, status); + + remove_switch(switch_id); +} diff --git a/unittest/meta/TestMeta.cpp b/unittest/meta/TestMeta.cpp new file mode 100644 index 000000000..1b2a9eae0 --- /dev/null +++ b/unittest/meta/TestMeta.cpp @@ -0,0 +1,297 @@ +#include "Meta.h" +#include "MetaTestSaiInterface.h" + +#include + +#include + +using namespace saimeta; + +TEST(Meta, initialize) +{ + Meta m(std::make_shared()); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.initialize(0,0)); +} + +TEST(Meta, uninitialize) +{ + Meta m(std::make_shared()); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.uninitialize()); +} + +TEST(Meta, quad_mcast_fdb_entry) +{ + Meta m(std::make_shared()); + + sai_object_id_t switchId = 0; + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_SWITCH, &switchId, SAI_NULL_OBJECT_ID, 1, &attr)); + + sai_object_id_t vlanId = 0; + + attr.id = SAI_VLAN_ATTR_VLAN_ID; + attr.value.u16 = 2; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_VLAN, &vlanId, switchId, 1, &attr)); + + sai_object_id_t l2mcGroupId = 0; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_L2MC_GROUP, &l2mcGroupId, switchId, 0, 0)); + + sai_attribute_t attrs[2]; + + attrs[0].id = SAI_MCAST_FDB_ENTRY_ATTR_GROUP_ID; + attrs[0].value.oid = l2mcGroupId; + + attrs[1].id = SAI_MCAST_FDB_ENTRY_ATTR_PACKET_ACTION; + attrs[1].value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_mcast_fdb_entry_t e; + + memset(&e, 0, sizeof(e)); + + e.bv_id = vlanId; + e.switch_id = switchId; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(&e, 2, attrs)); + + attr.id = SAI_MCAST_FDB_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_DROP; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.set(&e, &attr)); + + attr.id = SAI_MCAST_FDB_ENTRY_ATTR_GROUP_ID; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.get(&e, 1, &attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.remove(&e)); +} + +TEST(Meta, quad_l2mc_entry) +{ + Meta m(std::make_shared()); + + sai_object_id_t switchId = 0; + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_SWITCH, &switchId, SAI_NULL_OBJECT_ID, 1, &attr)); + + sai_object_id_t vlanId = 0; + + attr.id = SAI_VLAN_ATTR_VLAN_ID; + attr.value.u16 = 2; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_VLAN, &vlanId, switchId, 1, &attr)); + + sai_object_id_t l2mcGroupId = 0; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_L2MC_GROUP, &l2mcGroupId, switchId, 0, 0)); + + + attr.id = SAI_L2MC_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_l2mc_entry_t e; + + memset(&e, 0, sizeof(e)); + + e.bv_id = vlanId; + e.switch_id = switchId; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(&e, 1, &attr)); + + attr.id = SAI_L2MC_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_DROP; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.set(&e, &attr)); + + attr.id = SAI_L2MC_ENTRY_ATTR_PACKET_ACTION; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.get(&e, 1, &attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.remove(&e)); +} + +TEST(Meta, quad_inseg_entry) +{ + Meta m(std::make_shared()); + + sai_object_id_t switchId = 0; + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_SWITCH, &switchId, SAI_NULL_OBJECT_ID, 1, &attr)); + + sai_object_id_t vlanId = 0; + + attr.id = SAI_VLAN_ATTR_VLAN_ID; + attr.value.u16 = 2; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_VLAN, &vlanId, switchId, 1, &attr)); + + attr.id = SAI_L2MC_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_FORWARD; + + sai_inseg_entry_t e; + + memset(&e, 0, sizeof(e)); + + e.switch_id = switchId; + e.label = 1; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(&e, 1, &attr)); + + attr.id = SAI_INSEG_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_DROP; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.set(&e, &attr)); + + attr.id = SAI_INSEG_ENTRY_ATTR_PACKET_ACTION; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.get(&e, 1, &attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.remove(&e)); +} + +TEST(Meta, quad_nat_entry) +{ + Meta m(std::make_shared()); + + sai_object_id_t switchId = 0; + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_SWITCH, &switchId, SAI_NULL_OBJECT_ID, 1, &attr)); + + sai_object_id_t vrId = 0; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, &vrId, switchId, 0, &attr)); + + attr.id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; + attr.value.s32 = SAI_NAT_TYPE_NONE; + + sai_nat_entry_t e; + + memset(&e, 0, sizeof(e)); + + e.switch_id = switchId; + e.vr_id = vrId; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(&e, 1, &attr)); + + attr.id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; + attr.value.s32 = SAI_NAT_TYPE_NONE; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.set(&e, &attr)); + + attr.id = SAI_NAT_ENTRY_ATTR_NAT_TYPE; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.get(&e, 1, &attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.remove(&e)); +} + +TEST(Meta, quad_impc_entry) +{ + Meta m(std::make_shared()); + + sai_object_id_t switchId = 0; + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_SWITCH, &switchId, SAI_NULL_OBJECT_ID, 1, &attr)); + + sai_object_id_t rpfGroupId = 0; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_RPF_GROUP, &rpfGroupId, switchId, 0, &attr)); + + sai_object_id_t vrId = 0; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_VIRTUAL_ROUTER, &vrId, switchId, 0, &attr)); + + sai_attribute_t attrs[2]; + + attrs[0].id = SAI_IPMC_ENTRY_ATTR_PACKET_ACTION; + attrs[0].value.s32 = SAI_PACKET_ACTION_FORWARD; + + attrs[1].id = SAI_IPMC_ENTRY_ATTR_RPF_GROUP_ID; + attrs[1].value.oid = rpfGroupId; + + sai_ipmc_entry_t e; + + memset(&e, 0, sizeof(e)); + + e.switch_id = switchId; + e.vr_id = vrId; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(&e, 2, attrs)); + + attr.id = SAI_IPMC_ENTRY_ATTR_PACKET_ACTION; + attr.value.s32 = SAI_PACKET_ACTION_DROP; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.set(&e, &attr)); + + attr.id = SAI_IPMC_ENTRY_ATTR_RPF_GROUP_ID; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.get(&e, 1, &attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.remove(&e)); +} + +TEST(Meta, flushFdbEntries) +{ + Meta m(std::make_shared()); + + sai_object_id_t switchId = 0; + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.create(SAI_OBJECT_TYPE_SWITCH, &switchId, SAI_NULL_OBJECT_ID, 1, &attr)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.flushFdbEntries(switchId, 0, 0)); + + EXPECT_NE(SAI_STATUS_SUCCESS, m.flushFdbEntries(switchId, 10000, 0)); + + EXPECT_NE(SAI_STATUS_SUCCESS, m.flushFdbEntries(switchId, 1, 0)); + + EXPECT_NE(SAI_STATUS_SUCCESS, m.flushFdbEntries(0, 0, 0)); + + attr.id = 10000; + + EXPECT_NE(SAI_STATUS_SUCCESS, m.flushFdbEntries(switchId, 1, &attr)); + + sai_attribute_t attrs[2]; + + attrs[0].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + attrs[0].value.s32 = SAI_FDB_FLUSH_ENTRY_TYPE_ALL; + + attrs[1].id = SAI_FDB_FLUSH_ATTR_ENTRY_TYPE; + attrs[1].value.s32 = SAI_FDB_FLUSH_ENTRY_TYPE_ALL; + + EXPECT_NE(SAI_STATUS_SUCCESS, m.flushFdbEntries(switchId, 2, attrs)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, m.flushFdbEntries(switchId, 1, attrs)); +} diff --git a/unittest/meta/TestMetaKeyHasher.cpp b/unittest/meta/TestMetaKeyHasher.cpp new file mode 100644 index 000000000..7412900e7 --- /dev/null +++ b/unittest/meta/TestMetaKeyHasher.cpp @@ -0,0 +1,152 @@ +#include "MetaKeyHasher.h" + +#include + +#include + +using namespace saimeta; + +TEST(MetaKeyHasher, operator_eq_route_entry) +{ + sai_route_entry_t ra; + sai_route_entry_t rb; + + memset(&ra, 0, sizeof(ra)); + memset(&rb, 0, sizeof(ra)); + + sai_object_meta_key_t ma = { .objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY, .objectkey = { .key = { .route_entry = ra } } }; + sai_object_meta_key_t mb = { .objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY, .objectkey = { .key = { .route_entry = rb } } }; + + MetaKeyHasher mh; + + EXPECT_TRUE(mh.operator()(ma, mb)); +} + +TEST(MetaKeyHasher, operator_eq_nat_entry) +{ + sai_nat_entry_t ra; + sai_nat_entry_t rb; + + memset(&ra, 0, sizeof(ra)); + memset(&rb, 0, sizeof(ra)); + + sai_object_meta_key_t ma = { .objecttype = SAI_OBJECT_TYPE_NAT_ENTRY, .objectkey = { .key = { .nat_entry = ra } } }; + sai_object_meta_key_t mb = { .objecttype = SAI_OBJECT_TYPE_NAT_ENTRY, .objectkey = { .key = { .nat_entry = rb } } }; + + MetaKeyHasher mh; + + EXPECT_TRUE(mh.operator()(ma, mb)); +} + +TEST(MetaKeyHasher, operator_eq_inseg_entry) +{ + sai_inseg_entry_t ra; + sai_inseg_entry_t rb; + + memset(&ra, 0, sizeof(ra)); + memset(&rb, 0, sizeof(ra)); + + sai_object_meta_key_t ma = { .objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY, .objectkey = { .key = { .inseg_entry = ra } } }; + sai_object_meta_key_t mb = { .objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY, .objectkey = { .key = { .inseg_entry = rb } } }; + + MetaKeyHasher mh; + + EXPECT_TRUE(mh.operator()(ma, mb)); +} + +TEST(MetaKeyHasher, operator_eq) +{ + sai_object_meta_key_t ma; + sai_object_meta_key_t mb; + + memset(&ma, 0, sizeof(ma)); + memset(&mb, 0, sizeof(mb)); + + ma.objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY; + mb.objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY; + + MetaKeyHasher mh; + + EXPECT_FALSE(mh.operator()(ma, mb)); +} + +TEST(MetaKeyHasher, operator_hash) +{ + sai_object_meta_key_t ma; + + memset(&ma, 0, sizeof(ma)); + + MetaKeyHasher mh; + + ma.objecttype = SAI_OBJECT_TYPE_NAT_ENTRY; + + EXPECT_EQ(mh.operator()(ma), 0); + + ma.objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY; + + EXPECT_EQ(mh.operator()(ma), 0); + + ma.objecttype = SAI_OBJECT_TYPE_IPMC_ENTRY; + + EXPECT_EQ(mh.operator()(ma), 0); + + ma.objecttype = SAI_OBJECT_TYPE_L2MC_ENTRY; + + EXPECT_EQ(mh.operator()(ma), 0); + + ma.objecttype = SAI_OBJECT_TYPE_IPMC_ENTRY; + ma.objectkey.key.ipmc_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + ma.objectkey.key.ipmc_entry.source.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + + EXPECT_EQ(mh.operator()(ma), 0); + + ma.objecttype = SAI_OBJECT_TYPE_L2MC_ENTRY; + ma.objectkey.key.l2mc_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + ma.objectkey.key.l2mc_entry.source.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + + EXPECT_EQ(mh.operator()(ma), 0); +} + +TEST(MetaKeyHasher, operator_eq_l2mc) +{ + sai_object_meta_key_t ma; + sai_object_meta_key_t mb; + + memset(&ma, 0, sizeof(ma)); + memset(&mb, 0, sizeof(mb)); + + ma.objecttype = SAI_OBJECT_TYPE_L2MC_ENTRY; + mb.objecttype = SAI_OBJECT_TYPE_L2MC_ENTRY; + + ma.objectkey.key.l2mc_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + ma.objectkey.key.l2mc_entry.source.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + + mb.objectkey.key.l2mc_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + mb.objectkey.key.l2mc_entry.source.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + + MetaKeyHasher mh; + + EXPECT_TRUE(mh.operator()(ma, mb)); +} + +TEST(MetaKeyHasher, operator_eq_ipck) +{ + sai_object_meta_key_t ma; + sai_object_meta_key_t mb; + + memset(&ma, 0, sizeof(ma)); + memset(&mb, 0, sizeof(mb)); + + ma.objecttype = SAI_OBJECT_TYPE_IPMC_ENTRY; + mb.objecttype = SAI_OBJECT_TYPE_IPMC_ENTRY; + + ma.objectkey.key.ipmc_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + ma.objectkey.key.ipmc_entry.source.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + + mb.objectkey.key.ipmc_entry.destination.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + mb.objectkey.key.ipmc_entry.source.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + + MetaKeyHasher mh; + + EXPECT_TRUE(mh.operator()(ma, mb)); +} diff --git a/unittest/meta/TestNotificationFactory.cpp b/unittest/meta/TestNotificationFactory.cpp new file mode 100644 index 000000000..c6bb35522 --- /dev/null +++ b/unittest/meta/TestNotificationFactory.cpp @@ -0,0 +1,78 @@ +#include "NotificationFactory.h" + +#include "sairediscommon.h" +#include "sai_serialize.h" + +#include + +#include + +using namespace sairedis; + +TEST(NotificationFactory, deserialize) +{ + EXPECT_THROW(NotificationFactory::deserialize("foo", "bar"), std::runtime_error); + + EXPECT_THROW(NotificationFactory::deserialize(SAI_SWITCH_NOTIFICATION_NAME_FDB_EVENT, "bar"), std::invalid_argument); +} + +TEST(NotificationFactory, deserialize_fdb_event) +{ + auto ntf = NotificationFactory::deserialize( + SAI_SWITCH_NOTIFICATION_NAME_FDB_EVENT, + "[{\"fdb_entry\":\"{\\\"bvid\\\":\\\"oid:0x260000000005be\\\",\\\"mac\\\":\\\"52:54:00:86:DD:7A\\\",\\\"switch_id\\\":\\\"oid:0x21000000000000\\\"}\"," + "\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\"," + "\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_TYPE\",\"value\":\"SAI_FDB_ENTRY_TYPE_DYNAMIC\"},{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\"oid:0x3a000000000660\"}]}]"); + + EXPECT_EQ(ntf->getNotificationType(), SAI_SWITCH_NOTIFICATION_TYPE_FDB_EVENT); +} + +TEST(NotificationFactory, deserialize_port_state_change) +{ + auto ntf = NotificationFactory::deserialize( + SAI_SWITCH_NOTIFICATION_NAME_PORT_STATE_CHANGE, + "[{\"port_id\":\"oid:0x100000000001a\",\"port_state\":\"SAI_PORT_OPER_STATUS_UP\"}]"); + + EXPECT_EQ(ntf->getNotificationType(), SAI_SWITCH_NOTIFICATION_TYPE_PORT_STATE_CHANGE); +} + +TEST(NotificationFactory, deserialize_queue_pfc_deadlock) +{ + auto str = "[{\"event\":\"SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_DETECTED\",\"queue_id\":\"oid:0x1500000000020a\"}]"; + + auto ntf = NotificationFactory::deserialize( + SAI_SWITCH_NOTIFICATION_NAME_QUEUE_PFC_DEADLOCK, + str); + + EXPECT_EQ(ntf->getNotificationType(), SAI_SWITCH_NOTIFICATION_TYPE_QUEUE_PFC_DEADLOCK); + + EXPECT_EQ(str, ntf->getSerializedNotification()); +} + +TEST(NotificationFactory, deserialize_shutdown_request) +{ + auto ntf = NotificationFactory::deserialize( + SAI_SWITCH_NOTIFICATION_NAME_SWITCH_SHUTDOWN_REQUEST, + "{\"switch_id\":\"oid:0x2100000000\"}"); + + EXPECT_EQ(ntf->getNotificationType(), SAI_SWITCH_NOTIFICATION_TYPE_SWITCH_SHUTDOWN_REQUEST); + + EXPECT_EQ("{\"switch_id\":\"oid:0x2100000000\"}", ntf->getSerializedNotification()); +} + +TEST(NotificationFactory, deserialize_switch_state_change) +{ + sai_switch_oper_status_t status = SAI_SWITCH_OPER_STATUS_UP; + + auto str = sai_serialize_switch_oper_status(0x2100000000, status); + + // {"status":"SAI_SWITCH_OPER_STATUS_UP","switch_id":"oid:0x2100000000"} + + auto ntf = NotificationFactory::deserialize( + SAI_SWITCH_NOTIFICATION_NAME_SWITCH_STATE_CHANGE, + str); + + EXPECT_EQ(ntf->getNotificationType(), SAI_SWITCH_NOTIFICATION_TYPE_SWITCH_STATE_CHANGE); + + EXPECT_EQ(str, ntf->getSerializedNotification()); +} diff --git a/unittest/meta/TestNotificationFdbEvent.cpp b/unittest/meta/TestNotificationFdbEvent.cpp new file mode 100644 index 000000000..63f57544b --- /dev/null +++ b/unittest/meta/TestNotificationFdbEvent.cpp @@ -0,0 +1,68 @@ +#include "NotificationFdbEvent.h" +#include "Meta.h" +#include "MetaTestSaiInterface.h" + +#include "sairediscommon.h" +#include "sai_serialize.h" + +#include + +#include + +using namespace sairedis; +using namespace saimeta; + +static std::string s = +"[{\"fdb_entry\":\"{\\\"bvid\\\":\\\"oid:0x260000000005be\\\",\\\"mac\\\":\\\"52:54:00:86:DD:7A\\\",\\\"switch_id\\\":\\\"oid:0x21000000000000\\\"}\"," +"\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\"," +"\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_TYPE\",\"value\":\"SAI_FDB_ENTRY_TYPE_DYNAMIC\"},{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\"oid:0x3a000000000660\"}]}]"; + +static std::string null = +"[{\"fdb_entry\":\"{\\\"bvid\\\":\\\"oid:0x260000000005be\\\",\\\"mac\\\":\\\"52:54:00:86:DD:7A\\\",\\\"switch_id\\\":\\\"oid:0x0\\\"}\"," +"\"fdb_event\":\"SAI_FDB_EVENT_LEARNED\"," +"\"list\":[{\"id\":\"SAI_FDB_ENTRY_ATTR_TYPE\",\"value\":\"SAI_FDB_ENTRY_TYPE_DYNAMIC\"},{\"id\":\"SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID\",\"value\":\"oid:0x3a000000000660\"}]}]"; + +static std::string fullnull = "[]"; + +TEST(NotificationFdbEvent, ctr) +{ + NotificationFdbEvent n(s); +} + +TEST(NotificationFdbEvent, getSwitchId) +{ + NotificationFdbEvent n(s); + + EXPECT_EQ(n.getSwitchId(), 0x21000000000000); + + NotificationFdbEvent n2(null); + + EXPECT_EQ(n2.getSwitchId(), 0); +} + +TEST(NotificationFdbEvent, getAnyObjectId) +{ + NotificationFdbEvent n(s); + + EXPECT_EQ(n.getAnyObjectId(), 0x21000000000000); + + NotificationFdbEvent n2(null); + + EXPECT_EQ(n2.getAnyObjectId(), 0x260000000005be); + + NotificationFdbEvent n3(fullnull); + + EXPECT_EQ(n3.getSwitchId(), 0x0); + + EXPECT_EQ(n3.getAnyObjectId(), 0x0); +} + +TEST(NotificationFdbEvent, processMetadata) +{ + NotificationFdbEvent n(s); + + auto sai = std::make_shared(); + auto meta = std::make_shared(sai); + + n.processMetadata(meta); +} diff --git a/unittest/meta/TestNotificationPortStateChange.cpp b/unittest/meta/TestNotificationPortStateChange.cpp new file mode 100644 index 000000000..7f0102784 --- /dev/null +++ b/unittest/meta/TestNotificationPortStateChange.cpp @@ -0,0 +1,78 @@ +#include "NotificationPortStateChange.h" +#include "Meta.h" +#include "MetaTestSaiInterface.h" + +#include "sairediscommon.h" +#include "sai_serialize.h" + +#include + +#include + +using namespace sairedis; +using namespace saimeta; + +static std::string s = "[{\"port_id\":\"oid:0x100000000001a\",\"port_state\":\"SAI_PORT_OPER_STATUS_UP\"}]"; +static std::string null = "[{\"port_id\":\"oid:0x0\",\"port_state\":\"SAI_PORT_OPER_STATUS_UP\"}]"; +static std::string fullnull = "[]"; + +TEST(NotificationPortStateChange, ctr) +{ + NotificationPortStateChange n(s); +} + +TEST(NotificationPortStateChange, getSwitchId) +{ + NotificationPortStateChange n(s); + + EXPECT_EQ(n.getSwitchId(), 0); + + NotificationPortStateChange n2(null); + + EXPECT_EQ(n2.getSwitchId(), 0); +} + +TEST(NotificationPortStateChange, getAnyObjectId) +{ + NotificationPortStateChange n(s); + + EXPECT_EQ(n.getAnyObjectId(), 0x100000000001a); + + NotificationPortStateChange n2(null); + + EXPECT_EQ(n2.getAnyObjectId(), 0); + + NotificationPortStateChange n3(fullnull); + + EXPECT_EQ(n3.getSwitchId(), 0); + + EXPECT_EQ(n3.getAnyObjectId(), 0); +} + +TEST(NotificationPortStateChange, processMetadata) +{ + NotificationPortStateChange n(s); + + auto sai = std::make_shared(); + auto meta = std::make_shared(sai); + + n.processMetadata(meta); +} + +static void on_port_state_change_notification( + _In_ uint32_t count, + _In_ const sai_port_oper_status_notification_t *data) +{ + SWSS_LOG_ENTER(); +} + +TEST(NotificationPortStateChange, executeCallback) +{ + NotificationPortStateChange n(s); + + sai_switch_notifications_t ntfs; + + ntfs.on_port_state_change = &on_port_state_change_notification; + + n.executeCallback(ntfs); +} diff --git a/unittest/meta/TestNotificationQueuePfcDeadlock.cpp b/unittest/meta/TestNotificationQueuePfcDeadlock.cpp new file mode 100644 index 000000000..398d8ab39 --- /dev/null +++ b/unittest/meta/TestNotificationQueuePfcDeadlock.cpp @@ -0,0 +1,79 @@ +#include "NotificationQueuePfcDeadlock.h" +#include "Meta.h" +#include "MetaTestSaiInterface.h" + +#include "sairediscommon.h" +#include "sai_serialize.h" + +#include + +#include + +using namespace sairedis; +using namespace saimeta; + +static std::string s = "[{\"event\":\"SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_DETECTED\",\"queue_id\":\"oid:0x1500000000020a\"}]"; +static std::string null = "[{\"event\":\"SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_DETECTED\",\"queue_id\":\"oid:0x0\"}]"; +static std::string fullnull = "[]"; + +TEST(NotificationQueuePfcDeadlock, ctr) +{ + NotificationQueuePfcDeadlock n(s); +} + +TEST(NotificationQueuePfcDeadlock, getSwitchId) +{ + NotificationQueuePfcDeadlock n(s); + + EXPECT_EQ(n.getSwitchId(), 0); + + NotificationQueuePfcDeadlock n2(null); + + EXPECT_EQ(n2.getSwitchId(), 0); +} + +TEST(NotificationQueuePfcDeadlock, getAnyObjectId) +{ + NotificationQueuePfcDeadlock n(s); + + EXPECT_EQ(n.getAnyObjectId(), 0x1500000000020a); + + NotificationQueuePfcDeadlock n2(null); + + EXPECT_EQ(n2.getAnyObjectId(), 0); + + NotificationQueuePfcDeadlock n3(fullnull); + + EXPECT_EQ(n3.getSwitchId(), 0); + + EXPECT_EQ(n3.getAnyObjectId(), 0); +} + +TEST(NotificationQueuePfcDeadlock, processMetadata) +{ + NotificationQueuePfcDeadlock n(s); + + auto sai = std::make_shared(); + auto meta = std::make_shared(sai); + + n.processMetadata(meta); +} + +static void on_queue_pfc_deadlock_notification( + _In_ uint32_t count, + _In_ const sai_queue_deadlock_notification_data_t *data) +{ + SWSS_LOG_ENTER(); +} + +TEST(NotificationQueuePfcDeadlock, executeCallback) +{ + NotificationQueuePfcDeadlock n(s); + + sai_switch_notifications_t ntfs; + + ntfs.on_queue_pfc_deadlock = &on_queue_pfc_deadlock_notification; + + n.executeCallback(ntfs); +} + diff --git a/unittest/meta/TestNotificationSwitchShutdownRequest.cpp b/unittest/meta/TestNotificationSwitchShutdownRequest.cpp new file mode 100644 index 000000000..d50d48060 --- /dev/null +++ b/unittest/meta/TestNotificationSwitchShutdownRequest.cpp @@ -0,0 +1,70 @@ +#include "NotificationSwitchShutdownRequest.h" +#include "Meta.h" +#include "MetaTestSaiInterface.h" + +#include "sairediscommon.h" +#include "sai_serialize.h" + +#include + +#include + +using namespace sairedis; +using namespace saimeta; + +static std::string s = "{\"switch_id\":\"oid:0x2100000000\"}"; +static std::string null = "{\"switch_id\":\"oid:0x0\"}"; + +TEST(NotificationSwitchShutdownRequest, ctr) +{ + NotificationSwitchShutdownRequest n(s); +} + +TEST(NotificationSwitchShutdownRequest, getSwitchId) +{ + NotificationSwitchShutdownRequest n(s); + + EXPECT_EQ(n.getSwitchId(), 0x2100000000); + + NotificationSwitchShutdownRequest n2(null); + + EXPECT_EQ(n2.getSwitchId(), 0); +} + +TEST(NotificationSwitchShutdownRequest, getAnyObjectId) +{ + NotificationSwitchShutdownRequest n(s); + + EXPECT_EQ(n.getAnyObjectId(), 0x2100000000); + + NotificationSwitchShutdownRequest n2(null); + + EXPECT_EQ(n2.getAnyObjectId(), 0); +} + +TEST(NotificationSwitchShutdownRequest, processMetadata) +{ + NotificationSwitchShutdownRequest n(s); + + auto sai = std::make_shared(); + auto meta = std::make_shared(sai); + + n.processMetadata(meta); +} + +static void on_switch_shutdown_request_notification( + _In_ sai_object_id_t switch_id) +{ + SWSS_LOG_ENTER(); +} + +TEST(NotificationSwitchShutdownRequest, executeCallback) +{ + NotificationSwitchShutdownRequest n(s); + + sai_switch_notifications_t ntfs; + + ntfs.on_switch_shutdown_request = &on_switch_shutdown_request_notification; + + n.executeCallback(ntfs); +} diff --git a/unittest/meta/TestNotificationSwitchStateChange.cpp b/unittest/meta/TestNotificationSwitchStateChange.cpp new file mode 100644 index 000000000..3a7df6e59 --- /dev/null +++ b/unittest/meta/TestNotificationSwitchStateChange.cpp @@ -0,0 +1,71 @@ +#include "NotificationSwitchStateChange.h" +#include "Meta.h" +#include "MetaTestSaiInterface.h" + +#include "sairediscommon.h" +#include "sai_serialize.h" + +#include + +#include + +using namespace sairedis; +using namespace saimeta; + +static std::string s = "{\"status\":\"SAI_SWITCH_OPER_STATUS_UP\",\"switch_id\":\"oid:0x2100000000\"}"; +static std::string null = "{\"status\":\"SAI_SWITCH_OPER_STATUS_UP\",\"switch_id\":\"oid:0x0\"}"; + +TEST(NotificationSwitchStateChange, ctr) +{ + NotificationSwitchStateChange n(s); +} + +TEST(NotificationSwitchStateChange, getSwitchId) +{ + NotificationSwitchStateChange n(s); + + EXPECT_EQ(n.getSwitchId(), 0x2100000000); + + NotificationSwitchStateChange n2(null); + + EXPECT_EQ(n2.getSwitchId(), 0); +} + +TEST(NotificationSwitchStateChange, getAnyObjectId) +{ + NotificationSwitchStateChange n(s); + + EXPECT_EQ(n.getAnyObjectId(), 0x2100000000); + + NotificationSwitchStateChange n2(null); + + EXPECT_EQ(n2.getAnyObjectId(), 0); +} + +TEST(NotificationSwitchStateChange, processMetadata) +{ + NotificationSwitchStateChange n(s); + + auto sai = std::make_shared(); + auto meta = std::make_shared(sai); + + n.processMetadata(meta); +} + +static void on_switch_state_change_notification( + _In_ sai_object_id_t switch_id, + _In_ sai_switch_oper_status_t switch_oper_status) +{ + SWSS_LOG_ENTER(); +} + +TEST(NotificationSwitchStateChange, executeCallback) +{ + NotificationSwitchStateChange n(s); + + sai_switch_notifications_t ntfs; + + ntfs.on_switch_state_change = &on_switch_state_change_notification; + + n.executeCallback(ntfs); +} diff --git a/unittest/meta/TestOidRefCounter.cpp b/unittest/meta/TestOidRefCounter.cpp new file mode 100644 index 000000000..aa9ca81ea --- /dev/null +++ b/unittest/meta/TestOidRefCounter.cpp @@ -0,0 +1,90 @@ +#include "OidRefCounter.h" + +#include + +#include + +using namespace saimeta; + +TEST(OidRefCounter, objectReferenceIncrement) +{ + OidRefCounter c; + + EXPECT_THROW(c.objectReferenceIncrement(1), std::runtime_error); +} + +TEST(OidRefCounter, objectReferenceDecrement) +{ + OidRefCounter c; + + EXPECT_THROW(c.objectReferenceDecrement(1), std::runtime_error); + + c.objectReferenceInsert(2); + + EXPECT_THROW(c.objectReferenceDecrement(2), std::runtime_error); +} + +TEST(OidRefCounter, objectReferenceDecrement_list) +{ + OidRefCounter c; + + sai_object_list_t list; + + sai_object_id_t l[2] = {1, 2}; + + list.count = 2; + list.list = l; + + EXPECT_THROW(c.objectReferenceDecrement(list), std::runtime_error); +} + +TEST(OidRefCounter, objectReferenceInsert) +{ + OidRefCounter c; + + c.objectReferenceInsert(2); + + EXPECT_THROW(c.objectReferenceInsert(2), std::runtime_error); +} + +TEST(OidRefCounter, objectReferenceRemove) +{ + OidRefCounter c; + + c.objectReferenceInsert(2); + + c.objectReferenceIncrement(2); + + EXPECT_THROW(c.objectReferenceRemove(2), std::runtime_error); + + EXPECT_THROW(c.objectReferenceRemove(3), std::runtime_error); +} + +TEST(OidRefCounter, getObjectReferenceCount) +{ + OidRefCounter c; + + EXPECT_THROW(c.getObjectReferenceCount(3), std::runtime_error); +} + + +TEST(OidRefCounter, isObjectInUse) +{ + OidRefCounter c; + + EXPECT_THROW(c.isObjectInUse(3), std::runtime_error); +} + +TEST(OidRefCounter, getAllReferences) +{ + OidRefCounter c; + + EXPECT_EQ(c.getAllReferences().size(), 0); +} + +TEST(OidRefCounter, objectReferenceClear) +{ + OidRefCounter c; + + EXPECT_THROW(c.objectReferenceClear(2), std::runtime_error); +} diff --git a/unittest/meta/TestPerformanceIntervalTimer.cpp b/unittest/meta/TestPerformanceIntervalTimer.cpp new file mode 100644 index 000000000..ed142a783 --- /dev/null +++ b/unittest/meta/TestPerformanceIntervalTimer.cpp @@ -0,0 +1,15 @@ +#include "PerformanceIntervalTimer.h" + +#include + +#include + +using namespace sairediscommon; + +TEST(PerformanceIntervalTimer, inc) +{ + PerformanceIntervalTimer p("foo", 2); + + p.inc(); + p.inc(10); +} diff --git a/unittest/meta/TestPortRelatedSet.cpp b/unittest/meta/TestPortRelatedSet.cpp new file mode 100644 index 000000000..9fbcc69e2 --- /dev/null +++ b/unittest/meta/TestPortRelatedSet.cpp @@ -0,0 +1,18 @@ +#include "PortRelatedSet.h" + +#include + +#include + +using namespace saimeta; + +TEST(PortRelatedSet, inc) +{ + PortRelatedSet set; + + set.insert(0, 0); + + EXPECT_EQ(set.getAllPorts().size(), 0); + + EXPECT_THROW(set.insert(0, 1), std::runtime_error); +} diff --git a/unittest/meta/TestSaiAttrWrapper.cpp b/unittest/meta/TestSaiAttrWrapper.cpp new file mode 100644 index 000000000..f7a9b39a3 --- /dev/null +++ b/unittest/meta/TestSaiAttrWrapper.cpp @@ -0,0 +1,34 @@ +#include "SaiAttrWrapper.h" + +#include + +#include + +using namespace saimeta; + +TEST(SaiAttrWrapper, ctr) +{ + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + EXPECT_THROW(std::make_shared(nullptr, attr), std::runtime_error); +} + +TEST(SaiAttrWrapper, getAttrId) +{ + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + auto meta = sai_metadata_get_attr_metadata( + SAI_OBJECT_TYPE_SWITCH, + SAI_SWITCH_ATTR_INIT_SWITCH); + + SaiAttrWrapper w(meta, attr); + + EXPECT_EQ(w.getAttrId(), SAI_SWITCH_ATTR_INIT_SWITCH); +} + diff --git a/unittest/meta/TestSaiAttributeList.cpp b/unittest/meta/TestSaiAttributeList.cpp new file mode 100644 index 000000000..2e2b0ac4c --- /dev/null +++ b/unittest/meta/TestSaiAttributeList.cpp @@ -0,0 +1,46 @@ +#include "SaiAttributeList.h" + +#include + +#include + +using namespace saimeta; + +TEST(SaiAttributeList, ctr_vector) +{ + std::vector vals; + + vals.emplace_back("foo", "bar"); + + EXPECT_THROW(std::make_shared(SAI_OBJECT_TYPE_SWITCH, vals, false), std::runtime_error); + + vals.clear(); + + vals.emplace_back("SAI_SWITCH_ATTR_INIT_SWITCH", "true"); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" + EXPECT_THROW(std::make_shared((sai_object_type_t)-1, vals, false), std::runtime_error); +#pragma GCC diagnostic pop +} + +TEST(SaiAttributeList, ctr_hash) +{ + std::unordered_map hash; + + hash["foo"] = "bar"; + + EXPECT_THROW(std::make_shared(SAI_OBJECT_TYPE_SWITCH, hash, false), std::runtime_error); + + hash.clear(); + + hash["NULL"] = "NULL"; + hash["SAI_SWITCH_ATTR_INIT_SWITCH"] = "true"; + + SaiAttributeList w(SAI_OBJECT_TYPE_SWITCH, hash, false); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" + EXPECT_THROW(std::make_shared((sai_object_type_t)-1, hash, false), std::runtime_error); +#pragma GCC diagnostic pop +} diff --git a/unittest/meta/TestSaiInterface.cpp b/unittest/meta/TestSaiInterface.cpp new file mode 100644 index 000000000..b657aa77e --- /dev/null +++ b/unittest/meta/TestSaiInterface.cpp @@ -0,0 +1,125 @@ +#include "SaiInterface.h" +#include "DummySaiInterface.h" + +#include + +#include + +using namespace saimeta; +using namespace sairedis; + +TEST(SaiInterface, create) +{ + DummySaiInterface ds; + + SaiInterface *sai = &ds; + + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_NULL, .objectkey = { .key = { .object_id = 0 } } }; + + EXPECT_EQ(SAI_STATUS_FAILURE, sai->create(mk, 0, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_SWITCH; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->create(mk, 0, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_FDB_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->create(mk, 0, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_NAT_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->create(mk, 0, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->create(mk, 0, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_L2MC_ENTRY; + EXPECT_EQ(SAI_STATUS_FAILURE, sai->create(mk, 0, 0, nullptr)); +} + +TEST(SaiInterface, remove) +{ + DummySaiInterface ds; + + SaiInterface *sai = &ds; + + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_NULL, .objectkey = { .key = { .object_id = 0 } } }; + + EXPECT_EQ(SAI_STATUS_FAILURE, sai->remove(mk)); + + mk.objecttype = SAI_OBJECT_TYPE_SWITCH; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->remove(mk)); + + mk.objecttype = SAI_OBJECT_TYPE_FDB_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->remove(mk)); + + mk.objecttype = SAI_OBJECT_TYPE_NAT_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->remove(mk)); + + mk.objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->remove(mk)); + + mk.objecttype = SAI_OBJECT_TYPE_L2MC_ENTRY; + EXPECT_EQ(SAI_STATUS_FAILURE, sai->remove(mk)); +} + +TEST(SaiInterface, set) +{ + DummySaiInterface ds; + + SaiInterface *sai = &ds; + + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_NULL, .objectkey = { .key = { .object_id = 0 } } }; + + EXPECT_EQ(SAI_STATUS_FAILURE, sai->set(mk, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_SWITCH; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->set(mk, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_FDB_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->set(mk, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_NAT_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->set(mk, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->set(mk, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->set(mk, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_NEIGHBOR_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->set(mk, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_L2MC_ENTRY; + EXPECT_EQ(SAI_STATUS_FAILURE, sai->set(mk, nullptr)); +} + +TEST(SaiInterface, get) +{ + DummySaiInterface ds; + + SaiInterface *sai = &ds; + + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_NULL, .objectkey = { .key = { .object_id = 0 } } }; + + EXPECT_EQ(SAI_STATUS_FAILURE, sai->get(mk, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_SWITCH; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->get(mk, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_FDB_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->get(mk, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_NAT_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->get(mk, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_INSEG_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->get(mk, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_ROUTE_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->get(mk, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_NEIGHBOR_ENTRY; + EXPECT_EQ(SAI_STATUS_SUCCESS, sai->get(mk, 0, nullptr)); + + mk.objecttype = SAI_OBJECT_TYPE_L2MC_ENTRY; + EXPECT_EQ(SAI_STATUS_FAILURE, sai->get(mk, 0, nullptr)); +} diff --git a/unittest/meta/TestSaiObject.cpp b/unittest/meta/TestSaiObject.cpp new file mode 100644 index 000000000..fb4cf2d16 --- /dev/null +++ b/unittest/meta/TestSaiObject.cpp @@ -0,0 +1,43 @@ +#include "SaiObject.h" + +#include + +#include + +using namespace saimeta; + +TEST(SaiObject, ctr) +{ + sai_object_meta_key_t meta_key = { .objecttype = SAI_OBJECT_TYPE_NULL, .objectkey = { .key = { .object_id = 0 } } }; + + EXPECT_THROW(std::make_shared(meta_key), std::runtime_error); +} + +TEST(SaiObject, hasAttr) +{ + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_SWITCH, .objectkey = { .key = { .object_id = 0 } } }; + + SaiObject so(mk); + + EXPECT_FALSE(so.hasAttr(1)); +} + +TEST(SaiObject, setAttr) +{ + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_SWITCH, .objectkey = { .key = { .object_id = 0 } } }; + + SaiObject so(mk); + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_INIT_SWITCH; + attr.value.booldata = true; + + auto meta = sai_metadata_get_attr_metadata( + SAI_OBJECT_TYPE_SWITCH, + SAI_SWITCH_ATTR_INIT_SWITCH); + + auto a = std::make_shared(meta, attr); + + so.setAttr(a); +} diff --git a/unittest/meta/TestSaiObjectCollection.cpp b/unittest/meta/TestSaiObjectCollection.cpp new file mode 100644 index 000000000..46931df99 --- /dev/null +++ b/unittest/meta/TestSaiObjectCollection.cpp @@ -0,0 +1,58 @@ +#include "SaiObjectCollection.h" + +#include + +#include + +using namespace saimeta; + +TEST(SaiObjectCollection, createObject) +{ + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_SWITCH, .objectkey = { .key = { .object_id = 1 } } }; + + SaiObjectCollection oc; + + oc.createObject(mk); + + EXPECT_THROW(oc.createObject(mk), std::runtime_error); +} + +TEST(SaiObjectCollection, removeObject) +{ + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_SWITCH, .objectkey = { .key = { .object_id = 1 } } }; + + SaiObjectCollection oc; + + EXPECT_THROW(oc.removeObject(mk), std::runtime_error); +} + +TEST(SaiObjectCollection, setObjectAttr) +{ + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_SWITCH, .objectkey = { .key = { .object_id = 1 } } }; + + SaiObjectCollection oc; + + auto meta = sai_metadata_get_attr_metadata( + SAI_OBJECT_TYPE_SWITCH, + SAI_SWITCH_ATTR_INIT_SWITCH); + + EXPECT_THROW(oc.setObjectAttr(mk, *meta, nullptr), std::runtime_error); +} + +TEST(SaiObjectCollection, getObjectAttr) +{ + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_SWITCH, .objectkey = { .key = { .object_id = 1 } } }; + + SaiObjectCollection oc; + + EXPECT_EQ(oc.getObjectAttr(mk, 0), nullptr); +} + +TEST(SaiObjectCollection, getObject) +{ + sai_object_meta_key_t mk = { .objecttype = SAI_OBJECT_TYPE_SWITCH, .objectkey = { .key = { .object_id = 1 } } }; + + SaiObjectCollection oc; + + EXPECT_THROW(oc.getObject(mk), std::runtime_error); +} diff --git a/unittest/meta/TestSaiSerialize.cpp b/unittest/meta/TestSaiSerialize.cpp new file mode 100644 index 000000000..512e0d988 --- /dev/null +++ b/unittest/meta/TestSaiSerialize.cpp @@ -0,0 +1,1159 @@ +#include "sai_serialize.h" +#include "MetaTestSaiInterface.h" +#include "Meta.h" + +#include "sairedis.h" +#include "sairediscommon.h" + +#include +#include + +#include + +#include + +using namespace saimeta; + +TEST(SaiSerialize, transfer_attributes) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t src; + sai_attribute_t dst; + + memset(&src, 0, sizeof(src)); + memset(&dst, 0, sizeof(dst)); + + EXPECT_EQ(SAI_STATUS_SUCCESS, transfer_attributes(SAI_OBJECT_TYPE_SWITCH, 1, &src, &dst, true)); + + EXPECT_THROW(transfer_attributes(SAI_OBJECT_TYPE_NULL, 1, &src, &dst, true), std::runtime_error); + + src.id = 0; + dst.id = 1; + + EXPECT_THROW(transfer_attributes(SAI_OBJECT_TYPE_SWITCH, 1, &src, &dst, true), std::runtime_error); + + for (size_t idx = 0 ; idx < sai_metadata_attr_sorted_by_id_name_count; ++idx) + { + auto meta = sai_metadata_attr_sorted_by_id_name[idx]; + + src.id = meta->attrid; + dst.id = meta->attrid; + + EXPECT_EQ(SAI_STATUS_SUCCESS, transfer_attributes(meta->objecttype, 1, &src, &dst, true)); + } +} + +TEST(SaiSerialize, sai_serialize_object_meta_key) +{ + sai_object_meta_key_t mk; + + mk.objecttype = SAI_OBJECT_TYPE_NULL; + + EXPECT_THROW(sai_serialize_object_meta_key(mk), std::runtime_error); + + memset(&mk, 0, sizeof(mk)); + + for (int32_t i = SAI_OBJECT_TYPE_NULL+1; i < SAI_OBJECT_TYPE_EXTENSIONS_MAX; i++) + { + mk.objecttype = (sai_object_type_t)i; + + auto s = sai_serialize_object_meta_key(mk); + + sai_deserialize_object_meta_key(s, mk); + } +} + +TEST(SaiSerialize, sai_serialize_attr_value) +{ + sai_attribute_t attr; + + memset(&attr, 0, sizeof(attr)); + + for (size_t idx = 0 ; idx < sai_metadata_attr_sorted_by_id_name_count; ++idx) + { + auto meta = sai_metadata_attr_sorted_by_id_name[idx]; + + switch (meta->attrvaluetype) + { + // values that currently don't have serialization methods + case SAI_ATTR_VALUE_TYPE_TIMESPEC: + case SAI_ATTR_VALUE_TYPE_PORT_ERR_STATUS_LIST: + case SAI_ATTR_VALUE_TYPE_PORT_EYE_VALUES_LIST: + case SAI_ATTR_VALUE_TYPE_FABRIC_PORT_REACHABILITY: + case SAI_ATTR_VALUE_TYPE_PRBS_RX_STATE: + case SAI_ATTR_VALUE_TYPE_SEGMENT_LIST: + case SAI_ATTR_VALUE_TYPE_TLV_LIST: + case SAI_ATTR_VALUE_TYPE_MAP_LIST: + continue; + + default: + break; + } + + attr.id = meta->attrid; + + if (meta->isaclaction) + { + attr.value.aclaction.enable = true; + } + + if (meta->isaclfield) + { + attr.value.aclfield.enable = true; + } + + auto s = sai_serialize_attr_value(*meta, attr, false); + + sai_deserialize_attr_value(s, *meta, attr, false); + + sai_deserialize_free_attribute_value(meta->attrvaluetype, attr); + } +} + +TEST(SaiSerialize, sai_deserialize_redis_communication_mode) +{ + sai_redis_communication_mode_t value; + + sai_deserialize_redis_communication_mode(REDIS_COMMUNICATION_MODE_REDIS_ASYNC_STRING, value); + + EXPECT_EQ(value, SAI_REDIS_COMMUNICATION_MODE_REDIS_ASYNC); + + sai_deserialize_redis_communication_mode(REDIS_COMMUNICATION_MODE_REDIS_SYNC_STRING, value); + + EXPECT_EQ(value, SAI_REDIS_COMMUNICATION_MODE_REDIS_SYNC); + + sai_deserialize_redis_communication_mode(REDIS_COMMUNICATION_MODE_ZMQ_SYNC_STRING, value); + + EXPECT_EQ(value, SAI_REDIS_COMMUNICATION_MODE_ZMQ_SYNC); +} + +TEST(SaiSerialize, sai_deserialize_ingress_priority_group_attr) +{ + auto s = sai_serialize_ingress_priority_group_attr(SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE); + + EXPECT_EQ(s, "SAI_INGRESS_PRIORITY_GROUP_ATTR_BUFFER_PROFILE"); + + sai_ingress_priority_group_attr_t attr; + + sai_deserialize_ingress_priority_group_attr(s, attr); +} + +//TEST(SaiSerialize, char_to_int) +//{ +// EXPECT_THROW(char_to_int('g'), std::runtime_error); +// +// EXPECT_EQ(char_to_int('a'), 10); +//} + +TEST(SaiSerialize, transfer_list) +{ + sai_attribute_t src; + sai_attribute_t dst; + + memset(&src, 0, sizeof(src)); + memset(&dst, 0, sizeof(dst)); + + src.id = SAI_PORT_ATTR_HW_LANE_LIST; + dst.id = SAI_PORT_ATTR_HW_LANE_LIST; + + uint32_t list[2] = { 2, 1 }; + + src.value.u32list.count = 2; + src.value.u32list.list = list; + + dst.value.u32list.count = 2; + dst.value.u32list.list = nullptr; + + EXPECT_EQ(SAI_STATUS_FAILURE, transfer_attributes(SAI_OBJECT_TYPE_PORT, 1, &src, &dst, false)); + + src.value.u32list.count = 1; + src.value.u32list.list = nullptr; + + dst.value.u32list.count = 1; + dst.value.u32list.list = list; + + EXPECT_THROW(transfer_attributes(SAI_OBJECT_TYPE_PORT, 1, &src, &dst, false), std::runtime_error); + + src.value.u32list.count = 2; + src.value.u32list.list = list; + + dst.value.u32list.count = 1; + dst.value.u32list.list = list; + + EXPECT_EQ(SAI_STATUS_BUFFER_OVERFLOW, transfer_attributes(SAI_OBJECT_TYPE_PORT, 1, &src, &dst, false)); +} + +TEST(SaiSerialize, sai_deserialize_ip_prefix) +{ + sai_ip_prefix_t p; + + memset(&p, 0, sizeof(p)); + + p.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + + p.addr.ip6[0] = 0x11; + + p.mask.ip6[0] = 0xFF; + p.mask.ip6[1] = 0xF0; + + auto s = sai_serialize_ip_prefix(p); + + EXPECT_EQ(s, "1100::/12"); + + sai_deserialize_ip_prefix(s, p); + + EXPECT_THROW(sai_deserialize_ip_prefix("a/0/c", p), std::runtime_error); + + EXPECT_THROW(sai_deserialize_ip_prefix("12x/0", p), std::runtime_error); + + p.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + + sai_deserialize_ip_prefix("127.0.0.1/8", p); +} + +TEST(SaiSerialize, sai_serialize_ip_prefix) +{ + sai_ip_prefix_t p; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" + p.addr_family = (sai_ip_addr_family_t)7; +#pragma GCC diagnostic pop + + EXPECT_THROW(sai_serialize_ip_prefix(p), std::runtime_error); +} + +TEST(SaiSerialize, sai_deserialize_ip_address) +{ + sai_ip_address_t a; + + EXPECT_THROW(sai_deserialize_ip_address("123", a), std::runtime_error); +} + +TEST(SaiSerialize, sai_deserialize_ipv4) +{ + sai_ip4_t a; + + EXPECT_THROW(sai_deserialize_ipv4("123", a), std::runtime_error); +} + +TEST(SaiSerialize, sai_deserialize_ipv6) +{ + sai_ip6_t a; + + EXPECT_THROW(sai_deserialize_ipv6("123", a), std::runtime_error); +} + +TEST(SaiSerialize, sai_deserialize_chardata) +{ + sai_attribute_t a; + + EXPECT_THROW(sai_deserialize_chardata(std::string("123456789012345678901234567890123"), a.value.chardata), std::runtime_error); + + EXPECT_THROW(sai_deserialize_chardata(std::string("abc\\"), a.value.chardata), std::runtime_error); + + EXPECT_THROW(sai_deserialize_chardata(std::string("abc\\x"), a.value.chardata), std::runtime_error); + + EXPECT_THROW(sai_deserialize_chardata(std::string("a\\\\bc\\x1"), a.value.chardata), std::runtime_error); + + EXPECT_THROW(sai_deserialize_chardata(std::string("a\\\\bc\\xzg"), a.value.chardata), std::runtime_error); + + sai_deserialize_chardata(std::string("a\\\\\\x22"), a.value.chardata); +} + +TEST(SaiSerialize, sai_serialize_chardata) +{ + sai_attribute_t a; + + a.value.chardata[0] = 'a'; + a.value.chardata[1] = '\\'; + a.value.chardata[2] = 'b'; + a.value.chardata[3] = 7; + a.value.chardata[4] = 0; + + auto s = sai_serialize_chardata(a.value.chardata); + + EXPECT_EQ(s, "a\\\\b\\x07"); +} + +TEST(SaiSerialize, sai_serialize_api) +{ + EXPECT_EQ(sai_serialize_api(SAI_API_VLAN), "SAI_API_VLAN"); +} + +TEST(SaiSerialize, sai_serialize_vlan_id) +{ + EXPECT_EQ(sai_serialize_vlan_id(123), "123"); +} + +TEST(SaiSerialize, sai_deserialize_vlan_id) +{ + sai_vlan_id_t vlan; + + sai_deserialize_vlan_id("123", vlan); +} + +TEST(SaiSerialize, sai_serialize_port_stat) +{ + EXPECT_EQ(sai_serialize_port_stat(SAI_PORT_STAT_IF_IN_OCTETS),"SAI_PORT_STAT_IF_IN_OCTETS"); +} + +TEST(SaiSerialize, sai_serialize_switch_stat) +{ + EXPECT_EQ(sai_serialize_switch_stat(SAI_SWITCH_STAT_IN_CONFIGURED_DROP_REASONS_0_DROPPED_PKTS), + "SAI_SWITCH_STAT_IN_CONFIGURED_DROP_REASONS_0_DROPPED_PKTS"); +} + +TEST(SaiSerialize, sai_serialize_port_pool_stat) +{ + EXPECT_EQ(sai_serialize_port_pool_stat(SAI_PORT_POOL_STAT_IF_OCTETS), "SAI_PORT_POOL_STAT_IF_OCTETS"); +} + +TEST(SaiSerialize, sai_serialize_queue_stat) +{ + EXPECT_EQ(sai_serialize_queue_stat(SAI_QUEUE_STAT_PACKETS), "SAI_QUEUE_STAT_PACKETS"); +} + +TEST(SaiSerialize, sai_serialize_router_interface_stat) +{ + EXPECT_EQ(sai_serialize_router_interface_stat(SAI_ROUTER_INTERFACE_STAT_IN_OCTETS), + "SAI_ROUTER_INTERFACE_STAT_IN_OCTETS"); +} + +TEST(SaiSerialize, sai_serialize_ingress_priority_group_stat) +{ + EXPECT_EQ(sai_serialize_ingress_priority_group_stat(SAI_INGRESS_PRIORITY_GROUP_STAT_PACKETS), + "SAI_INGRESS_PRIORITY_GROUP_STAT_PACKETS"); +} + +TEST(SaiSerialize, sai_serialize_buffer_pool_stat) +{ + EXPECT_EQ(sai_serialize_buffer_pool_stat(SAI_BUFFER_POOL_STAT_CURR_OCCUPANCY_BYTES), + "SAI_BUFFER_POOL_STAT_CURR_OCCUPANCY_BYTES"); +} + +TEST(SaiSerialize, sai_serialize_tunnel_stat) +{ + EXPECT_EQ(sai_serialize_tunnel_stat(SAI_TUNNEL_STAT_IN_OCTETS), "SAI_TUNNEL_STAT_IN_OCTETS"); +} + +TEST(SaiSerialize, sai_serialize_queue_attr) +{ + EXPECT_EQ(sai_serialize_queue_attr(SAI_QUEUE_ATTR_TYPE), "SAI_QUEUE_ATTR_TYPE"); +} + +TEST(SaiSerialize, sai_serialize_macsec_sa_attr) +{ + EXPECT_EQ(sai_serialize_macsec_sa_attr(SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION), + "SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION"); +} + +TEST(SaiSerialize, sai_serialize_ingress_drop_reason) +{ + EXPECT_EQ(sai_serialize_ingress_drop_reason(SAI_IN_DROP_REASON_L2_ANY), "SAI_IN_DROP_REASON_L2_ANY"); +} + +TEST(SaiSerialize, sai_serialize_egress_drop_reason) +{ + EXPECT_EQ(sai_serialize_egress_drop_reason(SAI_OUT_DROP_REASON_L2_ANY), "SAI_OUT_DROP_REASON_L2_ANY"); +} + +TEST(SaiSerialize, sai_serialize_switch_shutdown_request) +{ + EXPECT_EQ(sai_serialize_switch_shutdown_request(0x1), "{\"switch_id\":\"oid:0x1\"}"); +} + +TEST(SaiSerialize, sai_serialize_oid_list) +{ + sai_object_list_t list; + + list.count = 2; + list.list = nullptr; + + EXPECT_EQ(sai_serialize_oid_list(list, true), "2"); + + + EXPECT_EQ(sai_serialize_oid_list(list, false), "2:null"); +} + +TEST(SaiSerialize, sai_serialize_hex_binary) +{ + EXPECT_EQ(sai_serialize_hex_binary(nullptr, 0), ""); + + uint8_t buf[1]; + + EXPECT_EQ(sai_serialize_hex_binary(buf, 0), ""); +} + +TEST(SaiSerialize, sai_serialize_system_port_config_list) +{ + sai_system_port_config_t pc; + + memset(&pc, 0, sizeof(pc)); + + sai_system_port_config_list_t list; + + list.count = 1; + list.list = &pc; + + sai_attr_metadata_t *meta = nullptr; + + sai_serialize_system_port_config_list(*meta, list, false); +} + +TEST(SaiSerialize, sai_deserialize_system_port_config_list) +{ + sai_system_port_config_t pc; + + memset(&pc, 0, sizeof(pc)); + + sai_system_port_config_list_t list; + + list.count = 1; + list.list = &pc; + + sai_attr_metadata_t *meta = nullptr; + + auto s = sai_serialize_system_port_config_list(*meta, list, false); + + sai_deserialize_system_port_config_list(s, list, false); +} + +TEST(SaiSerialize, sai_serialize_port_oper_status) +{ + EXPECT_EQ(sai_serialize_port_oper_status(SAI_PORT_OPER_STATUS_UP), "SAI_PORT_OPER_STATUS_UP"); +} + +TEST(SaiSerialize, sai_serialize_queue_deadlock_event) +{ + EXPECT_EQ(sai_serialize_queue_deadlock_event(SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_DETECTED), + "SAI_QUEUE_PFC_DEADLOCK_EVENT_TYPE_DETECTED"); +} + +TEST(SaiSerialize, sai_serialize_fdb_event_ntf) +{ + EXPECT_THROW(sai_serialize_fdb_event_ntf(1, nullptr), std::runtime_error); +} + +TEST(SaiSerialize, sai_serialize_port_oper_status_ntf) +{ + sai_port_oper_status_notification_t ntf; + + memset(&ntf, 0, sizeof(ntf)); + + sai_serialize_port_oper_status_ntf(1, &ntf); + + EXPECT_THROW(sai_serialize_port_oper_status_ntf(1, nullptr), std::runtime_error); +} + +TEST(SaiSerialize, sai_serialize_queue_deadlock_ntf) +{ + sai_queue_deadlock_notification_data_t ntf; + + memset(&ntf, 0, sizeof(ntf)); + + sai_serialize_queue_deadlock_ntf(1, &ntf); + + EXPECT_THROW(sai_serialize_queue_deadlock_ntf(1, nullptr), std::runtime_error); +} + +TEST(SaiSerialize, sai_serialize) +{ + sai_redis_notify_syncd_t value = SAI_REDIS_NOTIFY_SYNCD_INSPECT_ASIC; + + EXPECT_EQ(sai_serialize(value), SYNCD_INSPECT_ASIC); +} + +TEST(SaiSerialize, sai_serialize_redis_communication_mode) +{ + EXPECT_EQ(sai_serialize_redis_communication_mode(SAI_REDIS_COMMUNICATION_MODE_REDIS_SYNC), + REDIS_COMMUNICATION_MODE_REDIS_SYNC_STRING); +} + +TEST(SaiSerialize, sai_deserialize_queue_attr) +{ + sai_queue_attr_t attr = SAI_QUEUE_ATTR_PORT; + sai_deserialize_queue_attr("SAI_QUEUE_ATTR_TYPE", attr); + + EXPECT_EQ(attr, SAI_QUEUE_ATTR_TYPE); +} + +TEST(SaiSerialize, sai_deserialize_macsec_sa_attr) +{ + sai_macsec_sa_attr_t attr = SAI_MACSEC_SA_ATTR_SC_ID; + sai_deserialize_macsec_sa_attr("SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION", attr); + + EXPECT_EQ(attr, SAI_MACSEC_SA_ATTR_MACSEC_DIRECTION); +} + +TEST(SaiSerialize, sai_deserialize) +{ + sai_redis_notify_syncd_t value = SAI_REDIS_NOTIFY_SYNCD_APPLY_VIEW; + + sai_deserialize("SYNCD_INSPECT_ASIC", value); + + EXPECT_EQ(value, SAI_REDIS_NOTIFY_SYNCD_INSPECT_ASIC); +} + +// LEGACY TESTS + +TEST(SaiSerialize, serialize_bool) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + // test bool + + attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; + attr.value.booldata = true; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + EXPECT_EQ(sai_serialize_attr_value(*meta, attr), "true"); + + attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; + attr.value.booldata = false; + + EXPECT_EQ(sai_serialize_attr_value(*meta, attr), "false"); + + // deserialize + + attr.id = SAI_SWITCH_ATTR_ON_LINK_ROUTE_SUPPORTED; + + sai_deserialize_attr_value("true", *meta, attr); + + EXPECT_EQ(true, attr.value.booldata); + + sai_deserialize_attr_value("false", *meta, attr); + + EXPECT_EQ(false, attr.value.booldata); + + EXPECT_THROW(sai_deserialize_attr_value("xx", *meta, attr), std::runtime_error); +} + +TEST(SaiSerialize, serialize_chardata) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + memset(attr.value.chardata, 0, 32); + + attr.id = SAI_HOSTIF_ATTR_NAME; + memcpy(attr.value.chardata, "foo", sizeof("foo")); + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "foo"); + + attr.id = SAI_HOSTIF_ATTR_NAME; + memcpy(attr.value.chardata, "f\\oo\x12", sizeof("f\\oo\x12")); + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "f\\\\oo\\x12"); + + attr.id = SAI_HOSTIF_ATTR_NAME; + memcpy(attr.value.chardata, "\x80\xff", sizeof("\x80\xff")); + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HOSTIF, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "\\x80\\xFF"); + + // deserialize + + sai_deserialize_attr_value("f\\\\oo\\x12", *meta, attr); + + SWSS_LOG_NOTICE("des: %s", attr.value.chardata); + + EXPECT_EQ(0, strcmp(attr.value.chardata, "f\\oo\x12")); + + sai_deserialize_attr_value("foo", *meta, attr); + + EXPECT_EQ(0, strcmp(attr.value.chardata, "foo")); + + EXPECT_THROW(sai_deserialize_attr_value("\\x2g", *meta, attr), std::runtime_error); + + EXPECT_THROW(sai_deserialize_attr_value("\\x2", *meta, attr), std::runtime_error); + + EXPECT_THROW(sai_deserialize_attr_value("\\s45", *meta, attr), std::runtime_error); + + EXPECT_THROW(sai_deserialize_attr_value("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", *meta, attr), std::runtime_error); +} + +TEST(SaiSerialize, serialize_uint64) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_SWITCH_ATTR_NV_STORAGE_SIZE; + attr.value.u64 = 42; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "42"); + + attr.value.u64 = 0x87654321aabbccdd; + + attr.id = SAI_SWITCH_ATTR_NV_STORAGE_SIZE; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + char buf[32]; + sprintf(buf, "%" PRIu64, attr.value.u64); + + EXPECT_EQ(s, std::string(buf)); + + // deserialize + + sai_deserialize_attr_value("12345", *meta, attr); + + EXPECT_EQ(12345, attr.value.u64); + + EXPECT_THROW(sai_deserialize_attr_value("22345235345345345435", *meta, attr), std::runtime_error); + + EXPECT_THROW(sai_deserialize_attr_value("2a", *meta, attr), std::runtime_error); +} + +TEST(SaiSerialize, serialize_enum) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; + attr.value.s32 = SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD"); + + attr.value.s32 = -1; + + attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "-1"); + + attr.value.s32 = 100; + + attr.id = SAI_SWITCH_ATTR_SWITCHING_MODE; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "100"); + + // deserialize + + sai_deserialize_attr_value("12345", *meta, attr); + + EXPECT_EQ(12345, attr.value.s32); + + sai_deserialize_attr_value("-1", *meta, attr); + + EXPECT_EQ(-1, attr.value.s32); + + sai_deserialize_attr_value("SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD", *meta, attr); + + EXPECT_EQ(SAI_SWITCH_SWITCHING_MODE_STORE_AND_FORWARD, attr.value.s32); + + EXPECT_THROW(sai_deserialize_attr_value("foo", *meta, attr), std::runtime_error); +} + +TEST(SaiSerialize, serialize_mac) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_SWITCH_ATTR_SRC_MAC_ADDRESS; + memcpy(attr.value.mac, "\x01\x22\x33\xaa\xbb\xcc", 6); + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "01:22:33:AA:BB:CC"); + + // deserialize + + sai_deserialize_attr_value("ff:ee:dd:33:44:55", *meta, attr); + + EXPECT_EQ(0, memcmp("\xff\xee\xdd\x33\x44\x55", attr.value.mac, 6)); + + EXPECT_THROW(sai_deserialize_attr_value("foo", *meta, attr), std::runtime_error); +} + +TEST(SaiSerialize, serialize_ip_address) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP; + attr.value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4; + attr.value.ipaddr.addr.ip4 = htonl(0x0a000015); + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "10.0.0.21"); + + attr.id = SAI_TUNNEL_ATTR_ENCAP_SRC_IP; + attr.value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV6; + + uint16_t ip6[] = { 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0xaaaa, 0xbbbb }; + + memcpy(attr.value.ipaddr.addr.ip6, ip6, 16); + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "1111:2222:3333:4444:5555:6666:aaaa:bbbb"); + + uint16_t ip6a[] = { 0x0100, 0 ,0 ,0 ,0 ,0 ,0 ,0xff00 }; + + memcpy(attr.value.ipaddr.addr.ip6, ip6a, 16); + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "1::ff"); + + uint16_t ip6b[] = { 0, 0 ,0 ,0 ,0 ,0 ,0 ,0x100 }; + + memcpy(attr.value.ipaddr.addr.ip6, ip6b, 16); + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_TUNNEL, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "::1"); + + int k = 100; + attr.value.ipaddr.addr_family = (sai_ip_addr_family_t)k; + + EXPECT_THROW(sai_serialize_attr_value(*meta, attr), std::runtime_error); + + // deserialize + + sai_deserialize_attr_value("10.0.0.23", *meta, attr); + + EXPECT_EQ(attr.value.ipaddr.addr.ip4, htonl(0x0a000017)); + EXPECT_EQ(attr.value.ipaddr.addr_family, SAI_IP_ADDR_FAMILY_IPV4); + + sai_deserialize_attr_value("1::ff", *meta, attr); + + EXPECT_EQ(0, memcmp(attr.value.ipaddr.addr.ip6, ip6a, 16)); + EXPECT_EQ(attr.value.ipaddr.addr_family, SAI_IP_ADDR_FAMILY_IPV6); + + EXPECT_THROW(sai_deserialize_attr_value("foo", *meta, attr), std::runtime_error); +} + +TEST(SaiSerialize, serialize_uint32_list) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_PORT_ATTR_SUPPORTED_SPEED; //SAI_PORT_ATTR_SUPPORTED_HALF_DUPLEX_SPEED; + + uint32_t list[] = {1,2,3,4,5,6,7}; + + attr.value.u32list.count = 7; + attr.value.u32list.list = NULL; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "7:null"); + + attr.value.u32list.list = list; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "7:1,2,3,4,5,6,7"); + + attr.value.u32list.count = 0; + attr.value.u32list.list = list; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "0:null"); + + attr.value.u32list.count = 0; + attr.value.u32list.list = NULL; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_PORT, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "0:null"); + + memset(&attr, 0, sizeof(attr)); + + sai_deserialize_attr_value("7:1,2,3,4,5,6,7", *meta, attr, false); + + EXPECT_EQ(attr.value.u32list.count, 7); + EXPECT_EQ(attr.value.u32list.list[0], 1); + EXPECT_EQ(attr.value.u32list.list[1], 2); + EXPECT_EQ(attr.value.u32list.list[2], 3); + EXPECT_EQ(attr.value.u32list.list[3], 4); +} + +TEST(SaiSerialize, serialize_enum_list) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_HASH_ATTR_NATIVE_HASH_FIELD_LIST; + + int32_t list[] = { + SAI_NATIVE_HASH_FIELD_SRC_IP, + SAI_NATIVE_HASH_FIELD_DST_IP, + SAI_NATIVE_HASH_FIELD_VLAN_ID, + 77 + }; + + attr.value.s32list.count = 4; + attr.value.s32list.list = NULL; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "4:null"); + + attr.value.s32list.list = list; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + // or for enum: 4:SAI_NATIVE_HASH_FIELD[SRC_IP,DST_IP,VLAN_ID,77] + + EXPECT_EQ(s, "4:SAI_NATIVE_HASH_FIELD_SRC_IP,SAI_NATIVE_HASH_FIELD_DST_IP,SAI_NATIVE_HASH_FIELD_VLAN_ID,77"); + + attr.value.s32list.count = 0; + attr.value.s32list.list = list; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "0:null"); + + attr.value.s32list.count = 0; + attr.value.s32list.list = NULL; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_HASH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "0:null"); +} + +TEST(SaiSerialize, serialize_oid) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_SWITCH_ATTR_DEFAULT_VIRTUAL_ROUTER_ID; + + attr.value.oid = 0x1234567890abcdef; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "oid:0x1234567890abcdef"); + + // deserialize + + sai_deserialize_attr_value("oid:0x1234567890abcdef", *meta, attr); + + EXPECT_EQ(0x1234567890abcdef, attr.value.oid); + + EXPECT_THROW(sai_deserialize_attr_value("foo", *meta, attr), std::runtime_error); +} + +TEST(SaiSerialize, serialize_oid_list) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_SWITCH_ATTR_PORT_LIST; + + sai_object_id_t list[] = { + 1,0x42, 0x77 + }; + + attr.value.objlist.count = 3; + attr.value.objlist.list = NULL; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "3:null"); + + attr.value.objlist.list = list; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + // or: 4:[ROUTE:0x1,PORT:0x3,oid:0x77] if we have query function + + EXPECT_EQ(s, "3:oid:0x1,oid:0x42,oid:0x77"); + + attr.value.objlist.count = 0; + attr.value.objlist.list = list; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "0:null"); + + attr.value.objlist.count = 0; + attr.value.objlist.list = NULL; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_SWITCH, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "0:null"); + + memset(&attr, 0, sizeof(attr)); + + // deserialize + + sai_deserialize_attr_value("3:oid:0x1,oid:0x42,oid:0x77", *meta, attr, false); + + EXPECT_EQ(attr.value.objlist.count, 3); + EXPECT_EQ(attr.value.objlist.list[0], 0x1); + EXPECT_EQ(attr.value.objlist.list[1], 0x42); + EXPECT_EQ(attr.value.objlist.list[2], 0x77); +} + +TEST(SaiSerialize, serialize_acl_action) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_ACL_ENTRY_ATTR_ACTION_REDIRECT; + + attr.value.aclaction.enable = true; + attr.value.aclaction.parameter.oid = (sai_object_id_t)2; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "oid:0x2"); + + attr.value.aclaction.enable = false; + attr.value.aclaction.parameter.oid = (sai_object_id_t)2; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "disabled"); + + attr.id = SAI_ACL_ENTRY_ATTR_ACTION_PACKET_ACTION; + + attr.value.aclaction.enable = true; + attr.value.aclaction.parameter.s32 = SAI_PACKET_ACTION_TRAP; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "SAI_PACKET_ACTION_TRAP"); + + attr.value.aclaction.enable = true; + attr.value.aclaction.parameter.s32 = 77; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_ACL_ENTRY, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + EXPECT_EQ(s, "77"); +} + +TEST(SaiSerialize, serialize_qos_map) +{ + sai_attribute_t attr; + const sai_attr_metadata_t* meta; + std::string s; + + attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST; + + sai_qos_map_t qm = { + .key = { .tc = 1, .dscp = 2, .dot1p = 3, .prio = 4, .pg = 5, .queue_index = 6, .color = SAI_PACKET_COLOR_RED, .mpls_exp = 0 }, + .value = { .tc = 11, .dscp = 22, .dot1p = 33, .prio = 44, .pg = 55, .queue_index = 66, .color = SAI_PACKET_COLOR_GREEN, .mpls_exp = 0 } }; + + attr.value.qosmap.count = 1; + attr.value.qosmap.list = &qm; + + meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_QOS_MAP, attr.id); + + s = sai_serialize_attr_value(*meta, attr); + + std::string ret = "{\"count\":1,\"list\":[{\"key\":{\"color\":\"SAI_PACKET_COLOR_RED\",\"dot1p\":3,\"dscp\":2,\"mpls_exp\":0,\"pg\":5,\"prio\":4,\"qidx\":6,\"tc\":1},\"value\":{\"color\":\"SAI_PACKET_COLOR_GREEN\",\"dot1p\":33,\"dscp\":22,\"mpls_exp\":0,\"pg\":55,\"prio\":44,\"qidx\":66,\"tc\":11}}]}"; + + EXPECT_EQ(s, ret); + + s = sai_serialize_attr_value(*meta, attr, true); + + std::string ret2 = "{\"count\":1,\"list\":null}"; + EXPECT_EQ(s, ret2); + + // deserialize + + memset(&attr, 0, sizeof(attr)); + + sai_deserialize_attr_value(ret, *meta, attr); + + EXPECT_EQ(attr.value.qosmap.count, 1); + + auto &l = attr.value.qosmap.list[0]; + + EXPECT_EQ(l.key.tc, 1); + EXPECT_EQ(l.key.dscp, 2); + EXPECT_EQ(l.key.dot1p, 3); + EXPECT_EQ(l.key.prio, 4); + EXPECT_EQ(l.key.pg, 5); + EXPECT_EQ(l.key.queue_index, 6); + EXPECT_EQ(l.key.color, SAI_PACKET_COLOR_RED); + EXPECT_EQ(l.key.mpls_exp, 0); + + EXPECT_EQ(l.value.tc, 11); + EXPECT_EQ(l.value.dscp, 22); + EXPECT_EQ(l.value.dot1p, 33); + EXPECT_EQ(l.value.prio, 44); + EXPECT_EQ(l.value.pg, 55); + EXPECT_EQ(l.value.queue_index, 66); + EXPECT_EQ(l.value.color, SAI_PACKET_COLOR_GREEN); + EXPECT_EQ(l.value.mpls_exp, 0); +} + +template +static void deserialize_number( + _In_ const std::string& s, + _Out_ T& number, + _In_ bool hex = false) +{ + SWSS_LOG_ENTER(); + + errno = 0; + + char *endptr = NULL; + + number = (T)strtoull(s.c_str(), &endptr, hex ? 16 : 10); + + if (errno != 0 || endptr != s.c_str() + s.length()) + { + SWSS_LOG_THROW("invalid number %s", s.c_str()); + } +} + +template +static std::string serialize_number( + _In_ const T& number, + _In_ bool hex = false) +{ + SWSS_LOG_ENTER(); + + if (hex) + { + char buf[32]; + + snprintf(buf, sizeof(buf), "0x%" PRIx64, (uint64_t)number); + + return buf; + } + + return std::to_string(number); +} + +TEST(SaiSerialize, serialize_number) +{ + SWSS_LOG_ENTER(); + + int64_t sp = 0x12345678; + int64_t sn = -0x12345678; + int64_t u = 0x12345678; + + auto ssp = serialize_number(sp); + auto ssn = serialize_number(sn); + auto su = serialize_number(u); + + EXPECT_EQ(ssp, std::to_string(sp)); + EXPECT_EQ(ssn, std::to_string(sn)); + EXPECT_EQ(su, std::to_string(u)); + + auto shsp = serialize_number(sp, true); + auto shsn = serialize_number(sn, true); + auto shu = serialize_number(u, true); + + EXPECT_EQ(shsp, "0x12345678"); + EXPECT_EQ(shsn, "0xffffffffedcba988"); + EXPECT_EQ(shu, "0x12345678"); + + sp = 0; + sn = 0; + u = 0; + + deserialize_number(ssp, sp); + deserialize_number(ssn, sn); + deserialize_number(su, u); + + EXPECT_EQ(sp, 0x12345678); + EXPECT_EQ(sn, -0x12345678); + EXPECT_EQ(u, 0x12345678); + + deserialize_number(shsp, sp, true); + deserialize_number(shsn, sn, true); + deserialize_number(shu, u, true); + + EXPECT_EQ(sp, 0x12345678); + EXPECT_EQ(sn, -0x12345678); + EXPECT_EQ(u, 0x12345678); +} diff --git a/unittest/meta/TestZeroMQSelectableChannel.cpp b/unittest/meta/TestZeroMQSelectableChannel.cpp new file mode 100644 index 000000000..443b6dc4b --- /dev/null +++ b/unittest/meta/TestZeroMQSelectableChannel.cpp @@ -0,0 +1,89 @@ +#include "ZeroMQSelectableChannel.h" +#include "ZeroMQChannel.h" + +#include "swss/select.h" + +#include + +using namespace sairedis; + +TEST(ZeroMQSelectableChannel, ctr) +{ + EXPECT_THROW(std::make_shared("/dev_not/foo"), std::runtime_error); +} + +TEST(ZeroMQSelectableChannel, empty) +{ + ZeroMQSelectableChannel c("ipc:///tmp/zmq_test"); + + EXPECT_EQ(c.empty(), true); +} + +TEST(ZeroMQSelectableChannel, pop) +{ + ZeroMQSelectableChannel c("ipc:///tmp/zmq_test"); + + swss::KeyOpFieldsValuesTuple kco; + + EXPECT_THROW(c.pop(kco, false), std::runtime_error); +} + +TEST(ZeroMQSelectableChannel, hasData) +{ + ZeroMQSelectableChannel c("ipc:///tmp/zmq_test"); + + EXPECT_EQ(c.hasData(), false); +} + +TEST(ZeroMQSelectableChannel, hasCachedData) +{ + ZeroMQSelectableChannel c("ipc:///tmp/zmq_test"); + + EXPECT_EQ(c.hasCachedData(), false); +} + +TEST(ZeroMQSelectableChannel, set) +{ + ZeroMQSelectableChannel c("ipc:///tmp/zmq_test"); + + std::vector values; + + // wrong state + EXPECT_THROW(c.set("key", values, "op"), std::runtime_error); +} + +static void cb( + _In_ const std::string&, + _In_ const std::string&, + _In_ const std::vector&) +{ + SWSS_LOG_ENTER(); + + // notification callback +} + +TEST(ZeroMQSelectableChannel, readData) +{ + ZeroMQChannel main("ipc:///tmp/zmq_test", "ipc:///tmp/zmq_test_ntf", cb); + + ZeroMQSelectableChannel c("ipc:///tmp/zmq_test"); + + swss::Select ss; + + ss.addSelectable(&c); + + swss::Selectable *sel = NULL; + + std::vector values; + + main.set("key", values, "command"); + + int result = ss.select(&sel); + + EXPECT_EQ(result, swss::Select::OBJECT); + + swss::KeyOpFieldsValuesTuple kco; + + c.pop(kco, false); +} + diff --git a/unittest/meta/tests b/unittest/meta/tests deleted file mode 100755 index c08a8acc0..000000000 --- a/unittest/meta/tests +++ /dev/null @@ -1,210 +0,0 @@ -#! /bin/bash - -# tests - temporary wrapper script for .libs/tests -# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 -# -# The tests program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command="" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variables: - generated_by_libtool_version='2.4.6' - notinst_deplibs=' /home/kcudnik/sonic-sairedis/meta/.libs/libsaimetadata.la /home/kcudnik/sonic-sairedis/meta/.libs/libsaimeta.la' -else - # When we are sourced in execute mode, $file and $ECHO are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - file="$0" - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - ECHO="printf %s\\n" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on -# windows platforms, and (c) all begin with the string --lt- -# (application programs are unlikely to have options that match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's ../../libtool value, followed by no. -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=$0 - shift - for lt_opt - do - case "$lt_opt" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` - test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. - lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` - cat "$lt_dump_D/$lt_dump_F" - exit 0 - ;; - --lt-*) - $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n "$lt_option_debug"; then - echo "tests:tests:$LINENO: libtool wrapper (GNU libtool) 2.4.6 Debian-2.4.6-14" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - $ECHO "tests:tests:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" - lt_dump_args_N=`expr $lt_dump_args_N + 1` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ - - if test -n "$lt_option_debug"; then - $ECHO "tests:tests:$LINENO: newargv[0]: $progdir/$program" 1>&2 - func_lt_dump_args ${1+"$@"} 1>&2 - fi - exec "$progdir/$program" ${1+"$@"} - - $ECHO "$0: cannot exec $program $*" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from $@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case " $* " in - *\ --lt-*) - for lt_wr_arg - do - case $lt_wr_arg in - --lt-*) ;; - *) set x "$@" "$lt_wr_arg"; shift;; - esac - shift - done ;; - esac - func_exec_program_core ${1+"$@"} -} - - # Parse options - func_parse_lt_options "$0" ${1+"$@"} - - # Find the directory that this script lives in. - thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no - if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then - # special case for '.' - if test "$thisdir" = "."; then - thisdir=`pwd` - fi - # remove .libs from thisdir - case "$thisdir" in - *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; - .libs ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program='tests' - progdir="$thisdir/.libs" - - - if test -f "$progdir/$program"; then - # Add our own library path to LD_LIBRARY_PATH - LD_LIBRARY_PATH="/home/kcudnik/lib:/home/kcudnik/sonic-sairedis/meta/.libs:$LD_LIBRARY_PATH" - - # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH - # The second colon is a workaround for a bug in BeOS R4 sed - LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` - - export LD_LIBRARY_PATH - - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - func_exec_program ${1+"$@"} - fi - else - # The program doesn't exist. - $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 - $ECHO "This script is just a wrapper for $program." 1>&2 - $ECHO "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/unittest/syncd/tests b/unittest/syncd/tests deleted file mode 100755 index 18e6b955c..000000000 --- a/unittest/syncd/tests +++ /dev/null @@ -1,210 +0,0 @@ -#! /bin/bash - -# tests - temporary wrapper script for .libs/tests -# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 -# -# The tests program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command="" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variables: - generated_by_libtool_version='2.4.6' - notinst_deplibs=' /home/kcudnik/sonic-sairedis/lib/.libs/libsairedis.la /home/kcudnik/sonic-sairedis/meta/.libs/libsaimetadata.la /home/kcudnik/sonic-sairedis/meta/.libs/libsaimeta.la' -else - # When we are sourced in execute mode, $file and $ECHO are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - file="$0" - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - ECHO="printf %s\\n" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on -# windows platforms, and (c) all begin with the string --lt- -# (application programs are unlikely to have options that match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's ../../libtool value, followed by no. -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=$0 - shift - for lt_opt - do - case "$lt_opt" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` - test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. - lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` - cat "$lt_dump_D/$lt_dump_F" - exit 0 - ;; - --lt-*) - $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n "$lt_option_debug"; then - echo "tests:tests:$LINENO: libtool wrapper (GNU libtool) 2.4.6 Debian-2.4.6-14" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - $ECHO "tests:tests:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" - lt_dump_args_N=`expr $lt_dump_args_N + 1` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ - - if test -n "$lt_option_debug"; then - $ECHO "tests:tests:$LINENO: newargv[0]: $progdir/$program" 1>&2 - func_lt_dump_args ${1+"$@"} 1>&2 - fi - exec "$progdir/$program" ${1+"$@"} - - $ECHO "$0: cannot exec $program $*" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from $@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case " $* " in - *\ --lt-*) - for lt_wr_arg - do - case $lt_wr_arg in - --lt-*) ;; - *) set x "$@" "$lt_wr_arg"; shift;; - esac - shift - done ;; - esac - func_exec_program_core ${1+"$@"} -} - - # Parse options - func_parse_lt_options "$0" ${1+"$@"} - - # Find the directory that this script lives in. - thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no - if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then - # special case for '.' - if test "$thisdir" = "."; then - thisdir=`pwd` - fi - # remove .libs from thisdir - case "$thisdir" in - *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; - .libs ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program='tests' - progdir="$thisdir/.libs" - - - if test -f "$progdir/$program"; then - # Add our own library path to LD_LIBRARY_PATH - LD_LIBRARY_PATH="/home/kcudnik/lib:/home/kcudnik/sonic-sairedis/lib/.libs:/home/kcudnik/sonic-sairedis/meta/.libs:$LD_LIBRARY_PATH" - - # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH - # The second colon is a workaround for a bug in BeOS R4 sed - LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` - - export LD_LIBRARY_PATH - - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - func_exec_program ${1+"$@"} - fi - else - # The program doesn't exist. - $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 - $ECHO "This script is just a wrapper for $program." 1>&2 - $ECHO "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/unittest/vslib/Makefile.am b/unittest/vslib/Makefile.am index 9ac3b1fc2..7139edab6 100644 --- a/unittest/vslib/Makefile.am +++ b/unittest/vslib/Makefile.am @@ -22,6 +22,7 @@ tests_SOURCES = main.cpp \ TestMACsecEgressFilter.cpp \ TestMACsecForwarder.cpp \ TestMACsecIngressFilter.cpp \ + TestMACsecFilterStateGuard.cpp \ TestNetMsgRegistrar.cpp \ TestRealObjectIdManager.cpp \ TestResourceLimiter.cpp \ diff --git a/unittest/vslib/TestMACsecEgressFilter.cpp b/unittest/vslib/TestMACsecEgressFilter.cpp index 377b02538..e93656d7f 100644 --- a/unittest/vslib/TestMACsecEgressFilter.cpp +++ b/unittest/vslib/TestMACsecEgressFilter.cpp @@ -47,5 +47,5 @@ TEST(MACsecEgressFilter, forward) filter.set_macsec_fd(70); // bad fd - EXPECT_EQ(filter.execute(packet, len), TrafficFilter::ERROR); + EXPECT_EQ(filter.execute(packet, len), TrafficFilter::TERMINATE); } diff --git a/unittest/vslib/TestMACsecFilterStateGuard.cpp b/unittest/vslib/TestMACsecFilterStateGuard.cpp new file mode 100644 index 000000000..4bb9bfcd3 --- /dev/null +++ b/unittest/vslib/TestMACsecFilterStateGuard.cpp @@ -0,0 +1,18 @@ +#include "MACsecFilterStateGuard.h" + +#include + +using namespace saivs; + +TEST(MACsecFilterStateGuard, ctr) +{ + MACsecFilter::MACsecFilterState state = MACsecFilter::MACsecFilterState::MACSEC_FILTER_STATE_IDLE; + + { + MACsecFilterStateGuard guard(state, MACsecFilter::MACsecFilterState::MACSEC_FILTER_STATE_BUSY); + + EXPECT_EQ(state, MACsecFilter::MACsecFilterState::MACSEC_FILTER_STATE_BUSY); + } + + EXPECT_EQ(state, MACsecFilter::MACsecFilterState::MACSEC_FILTER_STATE_IDLE); +} diff --git a/unittest/vslib/tests b/unittest/vslib/tests deleted file mode 100755 index c08a8acc0..000000000 --- a/unittest/vslib/tests +++ /dev/null @@ -1,210 +0,0 @@ -#! /bin/bash - -# tests - temporary wrapper script for .libs/tests -# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 -# -# The tests program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command="" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variables: - generated_by_libtool_version='2.4.6' - notinst_deplibs=' /home/kcudnik/sonic-sairedis/meta/.libs/libsaimetadata.la /home/kcudnik/sonic-sairedis/meta/.libs/libsaimeta.la' -else - # When we are sourced in execute mode, $file and $ECHO are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - file="$0" - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - ECHO="printf %s\\n" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on -# windows platforms, and (c) all begin with the string --lt- -# (application programs are unlikely to have options that match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's ../../libtool value, followed by no. -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=$0 - shift - for lt_opt - do - case "$lt_opt" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` - test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. - lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` - cat "$lt_dump_D/$lt_dump_F" - exit 0 - ;; - --lt-*) - $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n "$lt_option_debug"; then - echo "tests:tests:$LINENO: libtool wrapper (GNU libtool) 2.4.6 Debian-2.4.6-14" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - $ECHO "tests:tests:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" - lt_dump_args_N=`expr $lt_dump_args_N + 1` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ - - if test -n "$lt_option_debug"; then - $ECHO "tests:tests:$LINENO: newargv[0]: $progdir/$program" 1>&2 - func_lt_dump_args ${1+"$@"} 1>&2 - fi - exec "$progdir/$program" ${1+"$@"} - - $ECHO "$0: cannot exec $program $*" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from $@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case " $* " in - *\ --lt-*) - for lt_wr_arg - do - case $lt_wr_arg in - --lt-*) ;; - *) set x "$@" "$lt_wr_arg"; shift;; - esac - shift - done ;; - esac - func_exec_program_core ${1+"$@"} -} - - # Parse options - func_parse_lt_options "$0" ${1+"$@"} - - # Find the directory that this script lives in. - thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no - if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then - # special case for '.' - if test "$thisdir" = "."; then - thisdir=`pwd` - fi - # remove .libs from thisdir - case "$thisdir" in - *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; - .libs ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program='tests' - progdir="$thisdir/.libs" - - - if test -f "$progdir/$program"; then - # Add our own library path to LD_LIBRARY_PATH - LD_LIBRARY_PATH="/home/kcudnik/lib:/home/kcudnik/sonic-sairedis/meta/.libs:$LD_LIBRARY_PATH" - - # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH - # The second colon is a workaround for a bug in BeOS R4 sed - LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` - - export LD_LIBRARY_PATH - - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - func_exec_program ${1+"$@"} - fi - else - # The program doesn't exist. - $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 - $ECHO "This script is just a wrapper for $program." 1>&2 - $ECHO "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/unittest/vslib/testslibsaivs b/unittest/vslib/testslibsaivs deleted file mode 100755 index 80094c4b5..000000000 --- a/unittest/vslib/testslibsaivs +++ /dev/null @@ -1,210 +0,0 @@ -#! /bin/bash - -# testslibsaivs - temporary wrapper script for .libs/testslibsaivs -# Generated by libtool (GNU libtool) 2.4.6 Debian-2.4.6-14 -# -# The testslibsaivs program cannot be directly executed until all the libtool -# libraries that it depends on are installed. -# -# This wrapper script should never be moved out of the build directory. -# If it is, it will not operate correctly. - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi -BIN_SH=xpg4; export BIN_SH # for Tru64 -DUALCASE=1; export DUALCASE # for MKS sh - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -relink_command="" - -# This environment variable determines our operation mode. -if test "$libtool_install_magic" = "%%%MAGIC variable%%%"; then - # install mode needs the following variables: - generated_by_libtool_version='2.4.6' - notinst_deplibs=' /home/kcudnik/sonic-sairedis/vslib/.libs/libsaivs.la /home/kcudnik/sonic-sairedis/meta/.libs/libsaimetadata.la /home/kcudnik/sonic-sairedis/meta/.libs/libsaimeta.la' -else - # When we are sourced in execute mode, $file and $ECHO are already set. - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - file="$0" - -# A function that is used when there is no print builtin or printf. -func_fallback_echo () -{ - eval 'cat <<_LTECHO_EOF -$1 -_LTECHO_EOF' -} - ECHO="printf %s\\n" - fi - -# Very basic option parsing. These options are (a) specific to -# the libtool wrapper, (b) are identical between the wrapper -# /script/ and the wrapper /executable/ that is used only on -# windows platforms, and (c) all begin with the string --lt- -# (application programs are unlikely to have options that match -# this pattern). -# -# There are only two supported options: --lt-debug and -# --lt-dump-script. There is, deliberately, no --lt-help. -# -# The first argument to this parsing function should be the -# script's ../../libtool value, followed by no. -lt_option_debug= -func_parse_lt_options () -{ - lt_script_arg0=$0 - shift - for lt_opt - do - case "$lt_opt" in - --lt-debug) lt_option_debug=1 ;; - --lt-dump-script) - lt_dump_D=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%/[^/]*$%%'` - test "X$lt_dump_D" = "X$lt_script_arg0" && lt_dump_D=. - lt_dump_F=`$ECHO "X$lt_script_arg0" | /usr/bin/sed -e 's/^X//' -e 's%^.*/%%'` - cat "$lt_dump_D/$lt_dump_F" - exit 0 - ;; - --lt-*) - $ECHO "Unrecognized --lt- option: '$lt_opt'" 1>&2 - exit 1 - ;; - esac - done - - # Print the debug banner immediately: - if test -n "$lt_option_debug"; then - echo "testslibsaivs:testslibsaivs:$LINENO: libtool wrapper (GNU libtool) 2.4.6 Debian-2.4.6-14" 1>&2 - fi -} - -# Used when --lt-debug. Prints its arguments to stdout -# (redirection is the responsibility of the caller) -func_lt_dump_args () -{ - lt_dump_args_N=1; - for lt_arg - do - $ECHO "testslibsaivs:testslibsaivs:$LINENO: newargv[$lt_dump_args_N]: $lt_arg" - lt_dump_args_N=`expr $lt_dump_args_N + 1` - done -} - -# Core function for launching the target application -func_exec_program_core () -{ - - if test -n "$lt_option_debug"; then - $ECHO "testslibsaivs:testslibsaivs:$LINENO: newargv[0]: $progdir/$program" 1>&2 - func_lt_dump_args ${1+"$@"} 1>&2 - fi - exec "$progdir/$program" ${1+"$@"} - - $ECHO "$0: cannot exec $program $*" 1>&2 - exit 1 -} - -# A function to encapsulate launching the target application -# Strips options in the --lt-* namespace from $@ and -# launches target application with the remaining arguments. -func_exec_program () -{ - case " $* " in - *\ --lt-*) - for lt_wr_arg - do - case $lt_wr_arg in - --lt-*) ;; - *) set x "$@" "$lt_wr_arg"; shift;; - esac - shift - done ;; - esac - func_exec_program_core ${1+"$@"} -} - - # Parse options - func_parse_lt_options "$0" ${1+"$@"} - - # Find the directory that this script lives in. - thisdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - test "x$thisdir" = "x$file" && thisdir=. - - # Follow symbolic links until we get to the real thisdir. - file=`ls -ld "$file" | /usr/bin/sed -n 's/.*-> //p'` - while test -n "$file"; do - destdir=`$ECHO "$file" | /usr/bin/sed 's%/[^/]*$%%'` - - # If there was a directory component, then change thisdir. - if test "x$destdir" != "x$file"; then - case "$destdir" in - [\\/]* | [A-Za-z]:[\\/]*) thisdir="$destdir" ;; - *) thisdir="$thisdir/$destdir" ;; - esac - fi - - file=`$ECHO "$file" | /usr/bin/sed 's%^.*/%%'` - file=`ls -ld "$thisdir/$file" | /usr/bin/sed -n 's/.*-> //p'` - done - - # Usually 'no', except on cygwin/mingw when embedded into - # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=no - if test "$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR" = "yes"; then - # special case for '.' - if test "$thisdir" = "."; then - thisdir=`pwd` - fi - # remove .libs from thisdir - case "$thisdir" in - *[\\/].libs ) thisdir=`$ECHO "$thisdir" | /usr/bin/sed 's%[\\/][^\\/]*$%%'` ;; - .libs ) thisdir=. ;; - esac - fi - - # Try to get the absolute directory name. - absdir=`cd "$thisdir" && pwd` - test -n "$absdir" && thisdir="$absdir" - - program='testslibsaivs' - progdir="$thisdir/.libs" - - - if test -f "$progdir/$program"; then - # Add our own library path to LD_LIBRARY_PATH - LD_LIBRARY_PATH="/home/kcudnik/sonic-sairedis/vslib/.libs:/home/kcudnik/lib:/home/kcudnik/sonic-sairedis/meta/.libs:$LD_LIBRARY_PATH" - - # Some systems cannot cope with colon-terminated LD_LIBRARY_PATH - # The second colon is a workaround for a bug in BeOS R4 sed - LD_LIBRARY_PATH=`$ECHO "$LD_LIBRARY_PATH" | /usr/bin/sed 's/::*$//'` - - export LD_LIBRARY_PATH - - if test "$libtool_execute_magic" != "%%%MAGIC variable%%%"; then - # Run the actual program with our arguments. - func_exec_program ${1+"$@"} - fi - else - # The program doesn't exist. - $ECHO "$0: error: '$progdir/$program' does not exist" 1>&2 - $ECHO "This script is just a wrapper for $program." 1>&2 - $ECHO "See the libtool documentation for more information." 1>&2 - exit 1 - fi -fi diff --git a/vslib/MACsecEgressFilter.cpp b/vslib/MACsecEgressFilter.cpp index fefa1c4ad..4e4284d3c 100644 --- a/vslib/MACsecEgressFilter.cpp +++ b/vslib/MACsecEgressFilter.cpp @@ -26,7 +26,7 @@ TrafficFilter::FilterStatus MACsecEgressFilter::forward( { if (errno != ENETDOWN && errno != EIO) { - SWSS_LOG_ERROR( + SWSS_LOG_WARN( "failed to write to macsec device %s fd %d, errno(%d): %s", m_macsecInterfaceName.c_str(), m_macsecfd, @@ -36,12 +36,13 @@ TrafficFilter::FilterStatus MACsecEgressFilter::forward( if (errno == EBADF) { - SWSS_LOG_ERROR( + // If the MACsec device was deleted by outside, + // this action should not terminate the Main tap thread. + // So just report a warning. + SWSS_LOG_WARN( "ending thread for macsec device %s fd %d", m_macsecInterfaceName.c_str(), m_macsecfd); - - return TrafficFilter::ERROR; } } diff --git a/vslib/MACsecFilter.cpp b/vslib/MACsecFilter.cpp index 77ed84df5..6c7e6e316 100644 --- a/vslib/MACsecFilter.cpp +++ b/vslib/MACsecFilter.cpp @@ -1,4 +1,5 @@ #include "MACsecFilter.h" +#include "MACsecFilterStateGuard.h" #include "swss/logger.h" #include "swss/select.h" @@ -17,7 +18,8 @@ MACsecFilter::MACsecFilter( _In_ const std::string &macsecInterfaceName): m_macsecDeviceEnable(false), m_macsecfd(0), - m_macsecInterfaceName(macsecInterfaceName) + m_macsecInterfaceName(macsecInterfaceName), + m_state(MACsecFilter::MACsecFilterState::MACSEC_FILTER_STATE_IDLE) { SWSS_LOG_ENTER(); @@ -30,6 +32,17 @@ void MACsecFilter::enable_macsec_device( SWSS_LOG_ENTER(); m_macsecDeviceEnable = enable; + + // The function, execute(), may be running in another thread, + // the macsec device enable state cannot be changed in the busy state. + // Because if the macsec device was deleted in the busy state, + // the error value of function, forward, will be returned + // to the caller of execute() + // and the caller thread will exit due to the error return value. + while(get_state() == MACsecFilter::MACsecFilterState::MACSEC_FILTER_STATE_BUSY) + { + // Waiting the MACsec filter exit from the BUSY state + } } void MACsecFilter::set_macsec_fd( @@ -40,12 +53,20 @@ void MACsecFilter::set_macsec_fd( m_macsecfd = macsecfd; } +MACsecFilter::MACsecFilterState MACsecFilter::get_state() const +{ + SWSS_LOG_ENTER(); + + return m_state; +} + TrafficFilter::FilterStatus MACsecFilter::execute( _Inout_ void *buffer, _Inout_ size_t &length) { SWSS_LOG_ENTER(); + MACsecFilterStateGuard state_guard(m_state, MACsecFilter::MACsecFilterState::MACSEC_FILTER_STATE_BUSY); auto mac_hdr = static_cast(buffer); if (ntohs(mac_hdr->h_proto) == EAPOL_ETHER_TYPE) diff --git a/vslib/MACsecFilter.h b/vslib/MACsecFilter.h index 165028e00..cd75684c8 100644 --- a/vslib/MACsecFilter.h +++ b/vslib/MACsecFilter.h @@ -11,6 +11,14 @@ namespace saivs { public: + typedef enum _MACsecFilterState + { + MACSEC_FILTER_STATE_IDLE, + + MACSEC_FILTER_STATE_BUSY, + + } MACsecFilterState; + MACsecFilter( _In_ const std::string &macsecInterfaceName); @@ -26,16 +34,20 @@ namespace saivs void set_macsec_fd( _In_ int macsecfd); + MACsecFilterState get_state() const; + protected: virtual FilterStatus forward( _In_ const void *buffer, _In_ size_t length) = 0; - bool m_macsecDeviceEnable; + volatile bool m_macsecDeviceEnable; int m_macsecfd; const std::string m_macsecInterfaceName; + + MACsecFilterState m_state; }; } diff --git a/vslib/MACsecFilterStateGuard.cpp b/vslib/MACsecFilterStateGuard.cpp new file mode 100644 index 000000000..f7d4b0942 --- /dev/null +++ b/vslib/MACsecFilterStateGuard.cpp @@ -0,0 +1,23 @@ +#include "MACsecFilterStateGuard.h" + +#include + +using namespace saivs; + +MACsecFilterStateGuard::MACsecFilterStateGuard( + _Inout_ MACsecFilter::MACsecFilterState &guarded_state, + _In_ MACsecFilter::MACsecFilterState target_state): + m_guarded_state(guarded_state) +{ + SWSS_LOG_ENTER(); + + m_old_state = m_guarded_state; + m_guarded_state = target_state; +} + +MACsecFilterStateGuard::~MACsecFilterStateGuard() +{ + SWSS_LOG_ENTER(); + + m_guarded_state = m_old_state; +} diff --git a/vslib/MACsecFilterStateGuard.h b/vslib/MACsecFilterStateGuard.h new file mode 100644 index 000000000..c6e1007f0 --- /dev/null +++ b/vslib/MACsecFilterStateGuard.h @@ -0,0 +1,22 @@ +#pragma once + +#include "MACsecFilter.h" + +namespace saivs +{ + class MACsecFilterStateGuard + { + public: + + MACsecFilterStateGuard( + _Inout_ MACsecFilter::MACsecFilterState &guarded_state, + _In_ MACsecFilter::MACsecFilterState target_state); + + ~MACsecFilterStateGuard(); + + private: + + MACsecFilter::MACsecFilterState m_old_state; + MACsecFilter::MACsecFilterState &m_guarded_state; + }; +} diff --git a/vslib/MACsecManager.cpp b/vslib/MACsecManager.cpp index fc8621abf..8b8930d9c 100644 --- a/vslib/MACsecManager.cpp +++ b/vslib/MACsecManager.cpp @@ -253,11 +253,6 @@ bool MACsecManager::delete_macsec_sa( } } - // The SA is the last one in this MACsec SC, delete the MACsec SC - if (get_macsec_sa_count(attr.m_macsecName, attr.m_direction, attr.m_sci) == 0) - { - return delete_macsec_sc(attr); - } return true; } diff --git a/vslib/Makefile.am b/vslib/Makefile.am index b42363360..3e8df86bf 100644 --- a/vslib/Makefile.am +++ b/vslib/Makefile.am @@ -23,6 +23,7 @@ libSaiVS_a_SOURCES = \ LaneMap.cpp \ LaneMapFileParser.cpp \ MACsecAttr.cpp \ + MACsecFilterStateGuard.cpp \ MACsecEgressFilter.cpp \ MACsecFilter.cpp \ MACsecForwarder.cpp \ diff --git a/vslib/Switch.cpp b/vslib/Switch.cpp index ea166f8bb..1729083f4 100644 --- a/vslib/Switch.cpp +++ b/vslib/Switch.cpp @@ -105,6 +105,11 @@ void Switch::updateNotifications( (sai_queue_pfc_deadlock_notification_fn)attr.value.ptr; break; + case SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY: + m_switchNotifications.on_bfd_session_state_change = + (sai_bfd_session_state_change_notification_fn)attr.value.ptr; + break; + default: SWSS_LOG_THROW("pointer for %s is not handled, FIXME!", meta->attridname); } diff --git a/vslib/SwitchStateBase.cpp b/vslib/SwitchStateBase.cpp index 1493bdaf9..7ca4bff25 100644 --- a/vslib/SwitchStateBase.cpp +++ b/vslib/SwitchStateBase.cpp @@ -941,6 +941,10 @@ sai_status_t SwitchStateBase::set_switch_default_attributes() CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + attr.id = SAI_SWITCH_ATTR_BFD_SESSION_STATE_CHANGE_NOTIFY; + + CHECK_STATUS(set(SAI_OBJECT_TYPE_SWITCH, m_switch_id, &attr)); + attr.id = SAI_SWITCH_ATTR_FDB_AGING_TIME; attr.value.u32 = 0; diff --git a/vslib/SwitchStateBase.h b/vslib/SwitchStateBase.h index ce531d6f2..d870deaab 100644 --- a/vslib/SwitchStateBase.h +++ b/vslib/SwitchStateBase.h @@ -584,6 +584,8 @@ namespace saivs MACsecManager m_macsecManager; + std::unordered_map m_macsecFlowPortMap; + protected: constexpr static const int maxDebugCounters = 32; diff --git a/vslib/SwitchStateBaseMACsec.cpp b/vslib/SwitchStateBaseMACsec.cpp index a73b51160..af8d64436 100644 --- a/vslib/SwitchStateBaseMACsec.cpp +++ b/vslib/SwitchStateBaseMACsec.cpp @@ -65,15 +65,34 @@ sai_status_t SwitchStateBase::setAclEntryMACsecFlowActive( if (loadMACsecAttrsFromACLEntry(entryId, attr, SAI_OBJECT_TYPE_MACSEC_SA, macsecAttrs) == SAI_STATUS_SUCCESS) { + // In Linux MACsec model, Egress SA need to be created before ingress SA for (auto &macsecAttr : macsecAttrs) { - if (m_macsecManager.create_macsec_sa(macsecAttr)) + if (macsecAttr.m_direction == SAI_MACSEC_DIRECTION_EGRESS) { - SWSS_LOG_NOTICE( + if (m_macsecManager.create_macsec_sa(macsecAttr)) + { + SWSS_LOG_NOTICE( "Enable MACsec SA %s:%u at the device %s", macsecAttr.m_sci.c_str(), static_cast(macsecAttr.m_an), macsecAttr.m_macsecName.c_str()); + } + } + } + + for (auto &macsecAttr : macsecAttrs) + { + if (macsecAttr.m_direction == SAI_MACSEC_DIRECTION_INGRESS) + { + if (m_macsecManager.create_macsec_sa(macsecAttr)) + { + SWSS_LOG_NOTICE( + "Enable MACsec SA %s:%u at the device %s", + macsecAttr.m_sci.c_str(), + static_cast(macsecAttr.m_an), + macsecAttr.m_macsecName.c_str()); + } } } } @@ -91,20 +110,15 @@ sai_status_t SwitchStateBase::setAclEntryMACsecFlowActive( if (loadMACsecAttrsFromACLEntry(entryId, attr, SAI_OBJECT_TYPE_MACSEC_SC, macsecAttrs) == SAI_STATUS_SUCCESS) { - if (!macsecAttrs.empty()) + for (auto &macsecAttr : macsecAttrs) { - if (macsecAttrs.size() > 1) - { - SWSS_LOG_ERROR("Duplicated MACsec sc for the ACL entry %s", sai_serialize_object_id(entryId).c_str()); - - CHECK_STATUS(set_internal(SAI_OBJECT_TYPE_ACL_ENTRY, sai_serialize_object_id(entryId), attr)); - - return SAI_STATUS_FAILURE; - } - - if (m_macsecManager.delete_macsec_sc(macsecAttrs.back())) + if (m_macsecManager.delete_macsec_sa(macsecAttr)) { - SWSS_LOG_NOTICE("The MACsec port %s is created.", macsecAttrs.back().m_macsecName.c_str()); + SWSS_LOG_NOTICE( + "Delete MACsec SA %s:%u at the device %s", + macsecAttr.m_sci.c_str(), + static_cast(macsecAttr.m_an), + macsecAttr.m_macsecName.c_str()); } } } @@ -207,6 +221,20 @@ sai_status_t SwitchStateBase::removeMACsecPort( } } + auto itr = m_macsecFlowPortMap.begin(); + + while (itr != m_macsecFlowPortMap.end()) + { + if (itr->second == macsecPortId) + { + itr = m_macsecFlowPortMap.erase(itr); + } + else + { + itr ++; + } + } + auto sid = sai_serialize_object_id(macsecPortId); return remove_internal(SAI_OBJECT_TYPE_MACSEC_PORT, sid); } @@ -279,6 +307,15 @@ sai_status_t SwitchStateBase::findPortByMACsecFlow( { SWSS_LOG_ENTER(); + auto itr = m_macsecFlowPortMap.find(macsecFlowId); + + if (itr != m_macsecFlowPortMap.end()) + { + portId = itr->second; + + return SAI_STATUS_SUCCESS; + } + sai_attribute_t attr; // MACsec flow => ACL entry => ACL table @@ -359,6 +396,8 @@ sai_status_t SwitchStateBase::findPortByMACsecFlow( portId = port_ids.front(); + m_macsecFlowPortMap[macsecFlowId] = portId; + return SAI_STATUS_SUCCESS; } diff --git a/vslib/TrafficForwarder.cpp b/vslib/TrafficForwarder.cpp index 3f077c6eb..0c867a8a9 100644 --- a/vslib/TrafficForwarder.cpp +++ b/vslib/TrafficForwarder.cpp @@ -37,7 +37,7 @@ bool TrafficForwarder::addVlanTag( if (cmsg->cmsg_level != SOL_PACKET || cmsg->cmsg_type != PACKET_AUXDATA) continue; - struct tpacket_auxdata* aux = (struct tpacket_auxdata*)CMSG_DATA(cmsg); + struct tpacket_auxdata* aux = (struct tpacket_auxdata*)(void *)CMSG_DATA(cmsg); if ((aux->tp_status & TP_STATUS_VLAN_VALID) && (aux->tp_status & TP_STATUS_VLAN_TPID_VALID))