From 24c64946e46b7f72d83c9e1ceed6466340356706 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Wed, 17 Jul 2019 12:01:40 -0700 Subject: [PATCH 01/20] fixed issue of permenent block on redisBufferRead() due to unprotected access from different threads syncd main thread was doing g_redisClient->hget without acquiring g_mutex, thereby causing either syncd main thread or notification thread to block indefinitely on redisBufferRead(). --- .DS_Store | Bin 0 -> 6148 bytes syncd/syncd.cpp | 12 +++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..fec43ae7bdec61da3f29aa64a635f2b06c42c193 GIT binary patch literal 6148 zcmeH~J&pn~427S8m5^vCDbsL(y+MSA6YK@hG9`inQEZo^@3Z5EVe8chJxk7uop^q} zVloC`hsXE{Yyqt4uGsr9F=PCJJAQD*8RK|AU%qd*i>I;3y&lkcjpy}TmWY4|h=2%) zfC$WpKpf&c|2H#wCOwJ>h`>Au`1hgEU2AIV8lMgh(E?CcOowqEy#%#*f?88sS7vCI z-GgPRMH}MzD5sX(S5sTpUJlFV!}8ANT@1~7Ijk_CSq;%30wORWu&gsGKLUY4 Jg9!X9fnOBN6N>-< literal 0 HcmV?d00001 diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index a24f79bf5..096cdb493 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -3057,13 +3057,15 @@ bool processFlexCounterEvent( sai_object_id_t vid = SAI_NULL_OBJECT_ID; sai_deserialize_object_id(vidStr, vid); sai_object_id_t rid; - - if (!try_translate_vid_to_rid(vid, rid)) { - SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", - sai_serialize_object_id(vid).c_str()); + std::lock_guard lock(g_mutex); + if (!try_translate_vid_to_rid(vid, rid)) + { + SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", + sai_serialize_object_id(vid).c_str()); - return false; + return false; + } } sai_object_type_t objectType = redis_sai_object_type_query(vid); // VID and RID will have the same object type From 676c0b58c4452478161d14a04140ed663127e91d Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Thu, 18 Jul 2019 15:33:34 -0700 Subject: [PATCH 02/20] Delete .DS_Store . --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index fec43ae7bdec61da3f29aa64a635f2b06c42c193..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~J&pn~427S8m5^vCDbsL(y+MSA6YK@hG9`inQEZo^@3Z5EVe8chJxk7uop^q} zVloC`hsXE{Yyqt4uGsr9F=PCJJAQD*8RK|AU%qd*i>I;3y&lkcjpy}TmWY4|h=2%) zfC$WpKpf&c|2H#wCOwJ>h`>Au`1hgEU2AIV8lMgh(E?CcOowqEy#%#*f?88sS7vCI z-GgPRMH}MzD5sX(S5sTpUJlFV!}8ANT@1~7Ijk_CSq;%30wORWu&gsGKLUY4 Jg9!X9fnOBN6N>-< From f0094914cb93249482ee79fc5d4db402aecf79d6 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 19 Jul 2019 16:47:53 -0700 Subject: [PATCH 03/20] resolved merge conflict --- syncd/syncd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 991b96486..eb9a2b258 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -3106,7 +3106,7 @@ bool processFlexCounterEvent( if (!try_translate_vid_to_rid(vid, rid)) { SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", - sai_serialize_object_id(vid).c_str()); + sai_serialize_object_id(vid).c_str()); return false; } } From e840a6b0f4d2df1679d654796f4e303f73d98abe Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 19 Jul 2019 18:03:05 -0700 Subject: [PATCH 04/20] Revert "resolved merge conflict" This reverts commit f0094914cb93249482ee79fc5d4db402aecf79d6. --- syncd/syncd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index eb9a2b258..991b96486 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -3106,7 +3106,7 @@ bool processFlexCounterEvent( if (!try_translate_vid_to_rid(vid, rid)) { SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", - sai_serialize_object_id(vid).c_str()); + sai_serialize_object_id(vid).c_str()); return false; } } From 03fc996e8c530505a3ad22b23e75ef2c77ebc668 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 19 Jul 2019 18:06:40 -0700 Subject: [PATCH 05/20] Revert "Merge remote-tracking branch 'upstream/master'" This reverts commit 550aca906c4f0ccca0d03a95c96152e9a37abae1, reversing changes made to 676c0b58c4452478161d14a04140ed663127e91d. --- lib/inc/sai_redis.h | 4 - lib/inc/sairedis.h | 13 - lib/src/sai_redis_generic_create.cpp | 6 +- lib/src/sai_redis_generic_get.cpp | 2 +- lib/src/sai_redis_generic_remove.cpp | 8 +- lib/src/sai_redis_generic_set.cpp | 81 +- lib/src/sai_redis_interfacequery.cpp | 2 - lib/src/sai_redis_switch.cpp | 20 - saiplayer/saiplayer.cpp | 54 +- syncd/scripts/syncd_init_common.sh | 4 +- syncd/syncd.cpp | 1376 +++++++++++++------------- tests/aspell.en.pws | 2 - 12 files changed, 676 insertions(+), 896 deletions(-) diff --git a/lib/inc/sai_redis.h b/lib/inc/sai_redis.h index e0fd780f6..bf29a8dea 100644 --- a/lib/inc/sai_redis.h +++ b/lib/inc/sai_redis.h @@ -54,16 +54,12 @@ extern void recordLine(std::string s); extern std::string joinFieldValues( _In_ const std::vector &values); -extern sai_status_t internal_api_wait_for_response( - _In_ sai_common_api_t api); - // other global declarations extern volatile bool g_record; extern volatile bool g_useTempView; extern volatile bool g_asicInitViewMode; extern volatile bool g_logrotate; -extern volatile bool g_syncMode; extern sai_service_method_table_t g_services; extern std::shared_ptr g_asicState; diff --git a/lib/inc/sairedis.h b/lib/inc/sairedis.h index 610e3952e..e70a03ad7 100644 --- a/lib/inc/sairedis.h +++ b/lib/inc/sairedis.h @@ -104,19 +104,6 @@ typedef enum _sai_redis_switch_attr_t */ SAI_REDIS_SWITCH_ATTR_PERFORM_LOG_ROTATE, - /** - * @brief Synchronous mode. - * - * Enable or disable synchronous mode. When enabled syncd also needs to be - * running in synchronous mode. Command pipeline will be disabled when this - * flag will be set to true. - * - * @type bool - * @flags CREATE_AND_SET - * @default false - */ - SAI_REDIS_SWITCH_ATTR_SYNC_MODE, - } sai_redis_switch_attr_t; /* diff --git a/lib/src/sai_redis_generic_create.cpp b/lib/src/sai_redis_generic_create.cpp index e9dbfd3d1..49361c5a6 100644 --- a/lib/src/sai_redis_generic_create.cpp +++ b/lib/src/sai_redis_generic_create.cpp @@ -234,7 +234,9 @@ sai_status_t internal_redis_generic_create( g_asicState->set(key, entry, "create"); - return internal_api_wait_for_response(SAI_COMMON_API_CREATE); + // we assume create will always succeed which may not be true + // we should make this synchronous call + return SAI_STATUS_SUCCESS; } sai_status_t redis_generic_create( @@ -387,7 +389,7 @@ sai_status_t internal_redis_bulk_generic_create( g_asicState->set(key, entries, "bulkcreate"); } - return internal_api_wait_for_response(SAI_COMMON_API_CREATE); + return SAI_STATUS_SUCCESS; } #define REDIS_ENTRY_CREATE(OT,ot) \ diff --git a/lib/src/sai_redis_generic_get.cpp b/lib/src/sai_redis_generic_get.cpp index 8eb352219..0c79293dc 100644 --- a/lib/src/sai_redis_generic_get.cpp +++ b/lib/src/sai_redis_generic_get.cpp @@ -205,7 +205,7 @@ sai_status_t internal_redis_generic_get( const std::string &op = kfvOp(kco); const std::string &opkey = kfvKey(kco); - SWSS_LOG_INFO("response: op = %s, key = %s", opkey.c_str(), op.c_str()); + SWSS_LOG_DEBUG("response: op = %s, key = %s", opkey.c_str(), op.c_str()); if (op != "getresponse") // ignore non response messages { diff --git a/lib/src/sai_redis_generic_remove.cpp b/lib/src/sai_redis_generic_remove.cpp index d6afc1c69..372aa2f47 100644 --- a/lib/src/sai_redis_generic_remove.cpp +++ b/lib/src/sai_redis_generic_remove.cpp @@ -21,7 +21,7 @@ sai_status_t internal_redis_generic_remove( g_asicState->del(key, "remove"); - return internal_api_wait_for_response(SAI_COMMON_API_REMOVE); + return SAI_STATUS_SUCCESS; } sai_status_t redis_generic_remove( @@ -118,10 +118,10 @@ sai_status_t internal_redis_bulk_generic_remove( } /* - * Capital 'R' stands for bulk CREATE operation. + * Capital 'C' stands for bulk CREATE operation. */ - recordLine("R|" + str_object_type + joined); + recordLine("C|" + str_object_type + joined); } // key: object_type:count @@ -134,7 +134,7 @@ sai_status_t internal_redis_bulk_generic_remove( g_asicState->set(key, entries, "bulkremove"); } - return internal_api_wait_for_response(SAI_COMMON_API_CREATE); + return SAI_STATUS_SUCCESS; } diff --git a/lib/src/sai_redis_generic_set.cpp b/lib/src/sai_redis_generic_set.cpp index e084d9440..1bd7ad80e 100644 --- a/lib/src/sai_redis_generic_set.cpp +++ b/lib/src/sai_redis_generic_set.cpp @@ -2,83 +2,6 @@ #include "meta/sai_serialize.h" #include "meta/saiattributelist.h" -sai_status_t internal_api_wait_for_response( - _In_ sai_common_api_t api) -{ - SWSS_LOG_ENTER(); - - if (!g_syncMode) - { - /* - * By default sync mode is disabled and all create/set/remove are - * considered success operations. - */ - - return SAI_STATUS_SUCCESS; - } - - SWSS_LOG_INFO("waiting for response %d", api); - - swss::Select s; - - s.addSelectable(g_redisGetConsumer.get()); - - while (true) - { - SWSS_LOG_INFO("wait for %d api response", api); - - swss::Selectable *sel; - - // get timeout and selector is used for all quad api's - int result = s.select(&sel, GET_RESPONSE_TIMEOUT); - - if (result == swss::Select::OBJECT) - { - swss::KeyOpFieldsValuesTuple kco; - - g_redisGetConsumer->pop(kco); - - const std::string &op = kfvOp(kco); - const std::string &opkey = kfvKey(kco); - - SWSS_LOG_INFO("response: op = %s, key = %s", opkey.c_str(), op.c_str()); - - if (op != "getresponse") // ignore non response messages - { - continue; - } - - sai_status_t status; - sai_deserialize_status(opkey, status); - - if (g_record) - { - const std::string &str_status = kfvKey(kco); - const std::vector &values = kfvFieldsValues(kco); - - // first serialized is status - recordLine("G|" + str_status + "|" + joinFieldValues(values)); - } - - SWSS_LOG_DEBUG("generic %d api status: %d", api, status); - - return status; - } - - SWSS_LOG_ERROR("generic %d api failed due to SELECT operation result: %s", api, getSelectResultAsString(result).c_str()); - break; - } - - if (g_record) - { - recordLine("G|SAI_STATUS_FAILURE"); - } - - SWSS_LOG_ERROR("generic %d api failed to get response", api); - - return SAI_STATUS_FAILURE; -} - sai_status_t internal_redis_generic_set( _In_ sai_object_type_t object_type, _In_ const std::string &serialized_object_id, @@ -105,7 +28,7 @@ sai_status_t internal_redis_generic_set( g_asicState->set(key, entry, "set"); - return internal_api_wait_for_response(SAI_COMMON_API_SET); + return SAI_STATUS_SUCCESS; } sai_status_t internal_redis_bulk_generic_set( @@ -187,7 +110,7 @@ sai_status_t internal_redis_bulk_generic_set( g_asicState->set(key, entries, "bulkset"); } - return internal_api_wait_for_response(SAI_COMMON_API_CREATE); + return SAI_STATUS_SUCCESS; } diff --git a/lib/src/sai_redis_interfacequery.cpp b/lib/src/sai_redis_interfacequery.cpp index 8a9761f06..16fb96acc 100644 --- a/lib/src/sai_redis_interfacequery.cpp +++ b/lib/src/sai_redis_interfacequery.cpp @@ -124,8 +124,6 @@ sai_status_t sai_api_initialize( g_redisNotifications = std::make_shared(g_dbNtf.get(), "NOTIFICATIONS"); g_redisClient = std::make_shared(g_db.get()); - g_asicState->setBuffered(false); // in sync mode, always false - clear_local_state(); g_asicInitViewMode = false; diff --git a/lib/src/sai_redis_switch.cpp b/lib/src/sai_redis_switch.cpp index 36248ccc7..f664232d2 100644 --- a/lib/src/sai_redis_switch.cpp +++ b/lib/src/sai_redis_switch.cpp @@ -7,7 +7,6 @@ volatile bool g_asicInitViewMode = false; // default mode is apply mode volatile bool g_useTempView = false; -volatile bool g_syncMode = false; sai_status_t sai_redis_internal_notify_syncd( _In_ const std::string& key) @@ -267,26 +266,7 @@ sai_status_t redis_set_switch_attribute( g_useTempView = attr->value.booldata; return SAI_STATUS_SUCCESS; - case SAI_REDIS_SWITCH_ATTR_SYNC_MODE: - - g_syncMode = attr->value.booldata; - - if (g_syncMode) - { - SWSS_LOG_NOTICE("disabling buffered pipeline in sync mode"); - g_asicState->setBuffered(false); - } - - return SAI_STATUS_SUCCESS; - case SAI_REDIS_SWITCH_ATTR_USE_PIPELINE: - - if (g_syncMode) - { - SWSS_LOG_WARN("use pipeline is not supported in sync mode"); - return SAI_STATUS_NOT_SUPPORTED; - } - g_asicState->setBuffered(attr->value.booldata); return SAI_STATUS_SUCCESS; diff --git a/saiplayer/saiplayer.cpp b/saiplayer/saiplayer.cpp index 0eb1f6235..a15bab185 100644 --- a/saiplayer/saiplayer.cpp +++ b/saiplayer/saiplayer.cpp @@ -964,54 +964,6 @@ sai_status_t handle_bulk_route( return status; } - else if (api == (sai_common_api_t)SAI_COMMON_API_BULK_CREATE) - { - std::vector attr_count; - - std::vector attr_list; - - // route can have multiple attributes, so we need to handle them all - for (const auto &alist: attributes) - { - attr_list.push_back(alist->get_attr_list()); - attr_count.push_back(alist->get_attr_count()); - } - - SWSS_LOG_NOTICE("executing BULK route create with %zu routes", attr_count.size()); - - sai_status_t status = sai_bulk_create_route_entry( - (uint32_t)routes.size(), - routes.data(), - attr_count.data(), - attr_list.data(), - SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, // TODO we need to get that from recording - statuses.data()); - - if (status != SAI_STATUS_SUCCESS) - { - // Entire API fails, so no need to compare statuses. - return status; - } - - for (size_t i = 0; i < statuses.size(); ++i) - { - if (statuses[i] != recorded_statuses[i]) - { - /* - * If recorded statuses are different than received, throw - * exception since data don't match. - */ - - SWSS_LOG_THROW("recorded status is %s but returned is %s on %s", - sai_serialize_status(recorded_statuses[i]).c_str(), - sai_serialize_status(statuses[i]).c_str(), - object_ids[i].c_str()); - } - } - - return status; - - } else { SWSS_LOG_THROW("api %d is not supported in bulk route", api); @@ -1029,8 +981,7 @@ void processBulk( return; } - if (api != (sai_common_api_t)SAI_COMMON_API_BULK_SET && - api != (sai_common_api_t)SAI_COMMON_API_BULK_CREATE) + if (api != (sai_common_api_t)SAI_COMMON_API_BULK_SET) { SWSS_LOG_THROW("bulk common api %d is not supported yet, FIXME", api); } @@ -1203,9 +1154,6 @@ int replay(int argc, char **argv) case 'S': processBulk((sai_common_api_t)SAI_COMMON_API_BULK_SET, line); continue; - case 'C': - processBulk((sai_common_api_t)SAI_COMMON_API_BULK_CREATE, line); - continue; case 'g': api = SAI_COMMON_API_GET; break; diff --git a/syncd/scripts/syncd_init_common.sh b/syncd/scripts/syncd_init_common.sh index ad568bb5c..7c808446f 100755 --- a/syncd/scripts/syncd_init_common.sh +++ b/syncd/scripts/syncd_init_common.sh @@ -59,9 +59,9 @@ function set_start_type() { if [ x"$WARM_BOOT" == x"true" ]; then CMD_ARGS+=" -t warm" - elif [ x"$FAST_REBOOT" == x"yes" ]; then + elif [ $FAST_REBOOT == "yes" ]; then CMD_ARGS+=" -t fast" - elif [ x"$FASTFAST_REBOOT" == x"yes" ]; then + elif [ $FASTFAST_REBOOT == "yes" ]; then CMD_ARGS+=" -t fastfast" fi } diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 991b96486..096cdb493 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -103,7 +103,6 @@ struct cmdOptions bool run_rpc_server; std::string portMapFile; #endif // SAITHRIFT - bool syncMode; ~cmdOptions() {} }; @@ -134,11 +133,11 @@ void notify_OA_about_syncd_exception() if (notifications != NULL) { std::vector entry; - + SWSS_LOG_NOTICE("sending switch_shutdown_request notification to OA"); - + notifications->send("switch_shutdown_request", "", entry); - + SWSS_LOG_NOTICE("notification send successfull"); } } @@ -158,27 +157,27 @@ void sai_diag_shell( SWSS_LOG_ENTER(); sai_status_t status; - + /* * This is currently blocking API on broadcom, it will block until we exit * shell. */ - + while (true) { sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_SWITCH_SHELL_ENABLE; attr.value.booldata = true; - + status = sai_metadata_sai_switch_api->set_switch_attribute(switch_id, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to enable switch shell: %s", sai_serialize_status(status).c_str()); return; } - + sleep(1); } } @@ -215,14 +214,14 @@ sai_object_type_t redis_sai_object_type_query( { return SAI_OBJECT_TYPE_NULL; } - + sai_object_type_t ot = (sai_object_type_t)((object_id >> OT_POSITION) & 0xFF); - + if (!sai_metadata_is_object_type_valid(ot)) { SWSS_LOG_THROW("invalid object id 0x%lx", object_id); } - + return ot; } @@ -232,12 +231,12 @@ int redis_get_switch_id_index( SWSS_LOG_ENTER(); sai_object_type_t switch_object_type = redis_sai_object_type_query(switch_id); - + if (switch_object_type == SAI_OBJECT_TYPE_SWITCH) { return (int)((switch_id >> SWID_POSITION) & 0xFF); } - + SWSS_LOG_THROW("object type of switch %s is %s, should be SWITCH", sai_serialize_object_id(switch_id).c_str(), sai_serialize_object_type(switch_object_type).c_str()); @@ -252,30 +251,30 @@ sai_object_id_t redis_sai_switch_id_query( { return oid; } - + sai_object_type_t object_type = redis_sai_object_type_query(oid); - + if (object_type == SAI_OBJECT_TYPE_NULL) { SWSS_LOG_THROW("invalid object type of oid 0x%lx", oid); } - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { return oid; } - + /* * Each VID contains switch index at constant position. * * We extract this index from VID and we create switch ID (VID) for * specific object. We can do this for each object. */ - + int sw_index = (int)((oid >> SWID_POSITION) & 0xFF); - + sai_object_id_t switch_id = redis_construct_object_id(SAI_OBJECT_TYPE_SWITCH, sw_index, sw_index); - + return switch_id; } @@ -288,38 +287,38 @@ sai_object_id_t redis_create_virtual_object_id( /* * NOTE: switch ID is VID switch ID from sairedis. */ - + /* * Check if object type is in valid range. */ - + if (!sai_metadata_is_object_type_valid(object_type)) { SWSS_LOG_THROW("invalid object type: %s", sai_serialize_object_type(object_type).c_str()); } - + /* * Switch id is deterministic and it comes from sairedis so make check here * that we will not use this for creating switch VIDs. */ - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { SWSS_LOG_THROW("this function should not be used to create VID for switch id"); } - + uint64_t virtual_id = g_redisClient->incr(VIDCOUNTER); - + int switch_index = redis_get_switch_id_index(switch_id); - + sai_object_id_t vid = redis_construct_object_id(object_type, switch_index, virtual_id); - + auto info = sai_metadata_get_object_type_info(object_type); - + SWSS_LOG_DEBUG("created virtual object id 0x%lx for object type %s", vid, info->objecttypename); - + return vid; } @@ -390,11 +389,11 @@ sai_object_id_t translate_rid_to_vid( */ std::string str_vid = *pvid; - + sai_deserialize_object_id(str_vid, vid); - + SWSS_LOG_DEBUG("translated RID 0x%lx to VID 0x%lx", rid, vid); - + return vid; } @@ -503,60 +502,60 @@ void translate_rid_to_vid_list( sai_attribute_t &attr = attr_list[i]; auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %x, attribute %d", object_type, attr.id); } - + /* * TODO: Many times we do switch for list of attributes to perform some * operation on each oid from that attribute, we should provide clever * way via sai metadata utils to get that. */ - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: attr.value.oid = translate_rid_to_vid(attr.value.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: translate_list_rid_to_vid(attr.value.objlist, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) attr.value.aclfield.data.oid = translate_rid_to_vid(attr.value.aclfield.data.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) translate_list_rid_to_vid(attr.value.aclfield.data.objlist, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) attr.value.aclaction.parameter.oid = translate_rid_to_vid(attr.value.aclaction.parameter.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) translate_list_rid_to_vid(attr.value.aclaction.parameter.objlist, switch_id); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } } @@ -576,23 +575,23 @@ sai_object_id_t translate_vid_to_rid( if (vid == SAI_NULL_OBJECT_ID) { SWSS_LOG_DEBUG("translated VID null to RID null"); - + return SAI_NULL_OBJECT_ID; } - + auto it = local_vid_to_rid.find(vid); - + if (it != local_vid_to_rid.end()) { return it->second; } - + std::string str_vid = sai_serialize_object_id(vid); - + std::string str_rid; - + auto prid = g_redisClient->hget(VIDTORID, str_vid); - + if (prid == NULL) { if (isInitViewMode()) @@ -609,28 +608,28 @@ sai_object_id_t translate_vid_to_rid( * like buffer limitations etc, mostly probably this will happen on * SWITCH object. */ - + SWSS_LOG_THROW("can't get RID in init view mode - don't query created objects"); } - + SWSS_LOG_THROW("unable to get RID for VID: 0x%lx", vid); } - + str_rid = *prid; - + sai_object_id_t rid; - + sai_deserialize_object_id(str_rid, rid); - + /* * We got this RID from redis db, so put it also to local db so it will be * faster to retrieve it late on. */ - + local_vid_to_rid[vid] = rid; - + SWSS_LOG_DEBUG("translated VID 0x%lx to RID 0x%lx", vid, rid); - + return rid; } @@ -674,60 +673,60 @@ void translate_vid_to_rid_list( * All id's received from sairedis should be virtual, so lets translate * them to real id's before we execute actual api. */ - + for (uint32_t i = 0; i < attr_count; i++) { sai_attribute_t &attr = attr_list[i]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %x, attribute %d", object_type, attr.id); } - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: attr.value.oid = translate_vid_to_rid(attr.value.oid); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: translate_list_vid_to_rid(attr.value.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) attr.value.aclfield.data.oid = translate_vid_to_rid(attr.value.aclfield.data.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) translate_list_vid_to_rid(attr.value.aclfield.data.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) attr.value.aclaction.parameter.oid = translate_vid_to_rid(attr.value.aclaction.parameter.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) translate_list_vid_to_rid(attr.value.aclaction.parameter.objlist); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } } @@ -745,18 +744,18 @@ void snoop_get_attr( * Note: str_object_type + ":" + str_object_id is meta_key we can us that * here later on. */ - + std::string str_object_type = sai_serialize_object_type(object_type); - + std::string prefix = ""; - + if (isInitViewMode()) { prefix = TEMP_PREFIX; } - + std::string key = prefix + (ASIC_STATE_TABLE + (":" + str_object_type + ":" + str_object_id)); - + SWSS_LOG_DEBUG("%s", key.c_str()); @@ -773,20 +772,20 @@ void snoop_get_oid( /* * If snooped oid is NULL then we don't need take any action. */ - + return; } - + /* * We need use redis version of object type query here since we are * operating on VID value, and syncd is compiled against real SAI * implementation which has different function sai_object_type_query. */ - + sai_object_type_t object_type = redis_sai_object_type_query(vid); - + std::string str_vid = sai_serialize_object_id(vid); - + snoop_get_attr(object_type, str_vid, "NULL", "NULL"); } @@ -809,9 +808,9 @@ void snoop_get_attr_value( SWSS_LOG_ENTER(); std::string value = sai_serialize_attr_value(*meta, attr); - + SWSS_LOG_DEBUG("%s:%s", meta->attridname, value.c_str()); - + snoop_get_attr(meta->objecttype, str_object_id, meta->attridname, value); } @@ -827,94 +826,94 @@ void snoop_get_response( * NOTE: this method is operating on VIDs, all RIDs were translated outside * this method. */ - + /* * Vlan (including vlan 1) will need to be put into TEMP view this should * also be valid for all objects that were queried. */ - + for (uint32_t idx = 0; idx < attr_count; ++idx) { const sai_attribute_t &attr = attr_list[idx]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %d, attribute %d", object_type, attr.id); } - + /* * We should snoop oid values even if they are readonly we just note in * temp view that those objects exist on switch. */ - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: snoop_get_oid(attr.value.oid); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: snoop_get_oid_list(attr.value.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) snoop_get_oid(attr.value.aclfield.data.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) snoop_get_oid_list(attr.value.aclfield.data.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) snoop_get_oid(attr.value.aclaction.parameter.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) snoop_get_oid_list(attr.value.aclaction.parameter.objlist); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } - + if (SAI_HAS_FLAG_READ_ONLY(meta->flags)) { /* * If value is read only, we skip it, since after syncd restart we * won't be able to set/create it anyway. */ - + continue; } - + if (meta->objecttype == SAI_OBJECT_TYPE_PORT && meta->attrid == SAI_PORT_ATTR_HW_LANE_LIST) { /* * Skip port lanes for now since we don't create ports. */ - + SWSS_LOG_INFO("skipping %s for %s", meta->attridname, str_object_id.c_str()); continue; } - + /* * Put non readonly, and non oid attribute value to temp view. * @@ -924,7 +923,7 @@ void snoop_get_response( * Similar action can happen when we will do this on asicSet during * apply view. */ - + snoop_get_attr_value(str_object_id, meta, attr); } } @@ -940,25 +939,25 @@ void internal_syncd_get_send( SWSS_LOG_ENTER(); std::vector entry; - + if (status == SAI_STATUS_SUCCESS) { translate_rid_to_vid_list(object_type, switch_id, attr_count, attr_list); - + /* * Normal serialization + translate RID to VID. */ - + entry = SaiAttributeList::serialize_attr_list( object_type, attr_count, attr_list, false); - + /* * All oid values here are VIDs. */ - + snoop_get_response(object_type, str_object_id, attr_count, attr_list); } else if (status == SAI_STATUS_BUFFER_OVERFLOW) @@ -972,7 +971,7 @@ void internal_syncd_get_send( * different attributes can have different lists, many of them may * serialize only count, and will need to support that on the receiver. */ - + entry = SaiAttributeList::serialize_attr_list( object_type, attr_count, @@ -985,52 +984,25 @@ void internal_syncd_get_send( * Some other error, don't send attributes at all. */ } - + for (const auto &e: entry) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(e).c_str(), fvValue(e).c_str()); } - + std::string str_status = sai_serialize_status(status); - + SWSS_LOG_INFO("sending response for GET api with status: %s", str_status.c_str()); - + /* * Since we have only one get at a time, we don't have to serialize object * type and object id, only get status is required to be returned. Get * response will not put any data to table, only queue is used. */ - - getResponse->set(str_status, entry, "getresponse"); - - SWSS_LOG_INFO("response for GET api was send"); -} -void internal_syncd_api_send_response( - _In_ sai_common_api_t api, - _In_ sai_status_t status) -{ - SWSS_LOG_ENTER(); - - /* - * By default synchronous mode is disabled and can be enabled by command - * line on syncd start. This will also require to enable synchronous mode - * in OA/sairedis because same GET RESPONSE channel is used to generate - * response for sairedis quad API. - */ - - if (!options.syncMode) - return; - - std::vector entry; - - std::string str_status = sai_serialize_status(status); - - SWSS_LOG_INFO("sending response for %d api with status: %s", api, str_status.c_str()); - getResponse->set(str_status, entry, "getresponse"); - - SWSS_LOG_INFO("response for %d api was send", api); + + SWSS_LOG_INFO("response for GET api was send"); } const char* profile_get_value( @@ -1044,17 +1016,17 @@ const char* profile_get_value( SWSS_LOG_WARN("variable is null"); return NULL; } - + auto it = gProfileMap.find(variable); - + if (it == gProfileMap.end()) { SWSS_LOG_NOTICE("%s: NULL", variable); return NULL; } - + SWSS_LOG_NOTICE("%s: %s", variable, it->second.c_str()); - + return it->second.c_str(); } @@ -1070,30 +1042,30 @@ int profile_get_next_value( if (value == NULL) { SWSS_LOG_INFO("resetting profile map iterator"); - + gProfileIter = gProfileMap.begin(); return 0; } - + if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return -1; } - + if (gProfileIter == gProfileMap.end()) { SWSS_LOG_INFO("iterator reached end"); return -1; } - + *variable = gProfileIter->first.c_str(); *value = gProfileIter->second.c_str(); - + SWSS_LOG_INFO("key: %s:%s", *variable, *value); - + gProfileIter++; - + return 0; } @@ -1109,13 +1081,13 @@ void startDiagShell() if (options.diagShell) { SWSS_LOG_NOTICE("starting diag shell thread"); - + /* * TODO actual switch id must be supplied */ - + std::thread diag_shell_thread = std::thread(sai_diag_shell, SAI_NULL_OBJECT_ID); - + diag_shell_thread.detach(); } } @@ -1126,19 +1098,19 @@ void on_switch_create( SWSS_LOG_ENTER(); sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid); - + if (switches.size() > 0) { SWSS_LOG_THROW("creating multiple switches is not supported yet, FIXME"); } - + /* * All needed data to populate switch should be obtained inside SaiSwitch * constructor, like getting all queues, ports, etc. */ - + switches[switch_vid] = std::make_shared(switch_vid, switch_rid); - + startDiagShell(); } @@ -1161,7 +1133,7 @@ void on_switch_remove( * * To support multiple switches this function needs to be refactored. */ - + SWSS_LOG_THROW("remove switch is not implemented, FIXME"); } @@ -1215,52 +1187,52 @@ sai_status_t handle_generic( * TODO: Could deserialize to meta key and then we could combine with non * object id. */ - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + SWSS_LOG_DEBUG("calling %s for %s", sai_serialize_common_api(api).c_str(), sai_serialize_object_type(object_type).c_str()); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = object_id; - + /* * We need to do translate vid/rid except for create, since create will * create new RID value, and we will have to map them to VID we received in * create query. */ - + /* * TODO: use metadata utils. */ - + auto info = sai_metadata_get_object_type_info(object_type); - + if (info->isnonobjectid) { SWSS_LOG_THROW("passing non object id %s as generic object", info->objecttypename); } - + switch (api) { case SAI_COMMON_API_CREATE: - + { /* * Object id is VID, we can use it to extract switch id. */ - + sai_object_id_t switch_id = redis_sai_switch_id_query(object_id); - + if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_THROW("invalid switch_id translated from VID 0x%lx", object_id); } - + if (object_type != SAI_OBJECT_TYPE_SWITCH) { /* @@ -1269,7 +1241,7 @@ sai_status_t handle_generic( * since rid doesn't exist yet, so skip translate for switch, * but use translate for all other objects. */ - + switch_id = translate_vid_to_rid(switch_id); } else @@ -1280,41 +1252,41 @@ sai_status_t handle_generic( * NOTE: to support multiple switches we need support * here for create. */ - + SWSS_LOG_THROW("creating multiple switches is not supported yet, FIXME"); } } - + sai_status_t status = info->create(&meta_key, switch_id, attr_count, attr_list); - + if (status == SAI_STATUS_SUCCESS) { sai_object_id_t real_object_id = meta_key.objectkey.key.object_id; - + /* * Object was created so new object id was generated we * need to save virtual id's to redis db. */ - + std::string str_vid = sai_serialize_object_id(object_id); std::string str_rid = sai_serialize_object_id(real_object_id); - + /* * TODO: This must be ATOMIC. * * To support multiple switches vid/rid map must be per switch. */ - + { - + g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); - + save_rid_and_vid_to_local(real_object_id, object_id); } - + SWSS_LOG_INFO("saved VID %s to RID %s", str_vid.c_str(), str_rid.c_str()); - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_create(switch_id); @@ -1322,36 +1294,36 @@ sai_status_t handle_generic( SWSS_LOG_NOTICE("Initialize gSwitchId with ID = 0x%lx", gSwitchId); } } - + return status; } - + case SAI_COMMON_API_REMOVE: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + sai_status_t status = info->remove(&meta_key); - + if (status == SAI_STATUS_SUCCESS) { std::string str_vid = sai_serialize_object_id(object_id); std::string str_rid = sai_serialize_object_id(rid); - + /* * TODO: This must be ATOMIC. */ - + { - + g_redisClient->hdel(VIDTORID, str_vid); g_redisClient->hdel(RIDTOVID, str_rid); - + remove_rid_and_vid_from_local(rid, object_id); } - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_remove(object_id); @@ -1379,48 +1351,48 @@ sai_status_t handle_generic( * also needs to be of internal/vendor default but we * can already deduce that. */ - + sai_object_id_t switch_vid = redis_sai_switch_id_query(object_id); - + if (switches.at(switch_vid)->isDiscoveredRid(rid)) { switches.at(switch_vid)->removeExistingObjectReference(rid); } } } - + return status; } - + case SAI_COMMON_API_SET: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + sai_status_t status = info->set(&meta_key, attr_list); - + if (is_set_attribute_workaround(meta_key.objecttype, attr_list->id, status)) { return SAI_STATUS_SUCCESS; } - + return status; } - + case SAI_COMMON_API_GET: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + return info->get(&meta_key, attr_count, attr_list); } - + default: - + SWSS_LOG_THROW("common api (%s) is not implemented", sai_serialize_common_api(api).c_str()); } } @@ -1431,25 +1403,25 @@ void translate_vid_to_rid_non_object_id( SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(meta_key.objecttype); - + if (info->isobjectid) { meta_key.objectkey.key.object_id = translate_vid_to_rid(meta_key.objectkey.key.object_id); - + return; } - + for (size_t j = 0; j < info->structmemberscount; ++j) { const sai_struct_member_info_t *m = info->structmembers[j]; - + if (m->membervaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID) { sai_object_id_t vid = m->getoid(&meta_key); - + sai_object_id_t rid = translate_vid_to_rid(vid); - + m->setoid(&meta_key, rid); } } @@ -1464,23 +1436,23 @@ sai_status_t handle_non_object_id( SWSS_LOG_ENTER(); translate_vid_to_rid_non_object_id(meta_key); - + auto info = sai_metadata_get_object_type_info(meta_key.objecttype); - + switch (api) { case SAI_COMMON_API_CREATE: return info->create(&meta_key, SAI_NULL_OBJECT_ID, attr_count, attr_list); - + case SAI_COMMON_API_REMOVE: return info->remove(&meta_key); - + case SAI_COMMON_API_SET: return info->set(&meta_key, attr_list); - + case SAI_COMMON_API_GET: return info->get(&meta_key, attr_count, attr_list); - + default: SWSS_LOG_THROW("other apis not implemented"); } @@ -1492,11 +1464,11 @@ void sendNotifyResponse( SWSS_LOG_ENTER(); std::string str_status = sai_serialize_status(status); - + std::vector entry; - - SWSS_LOG_INFO("sending response: %s", str_status.c_str()); - + + SWSS_LOG_NOTICE("sending response: %s", str_status.c_str()); + getResponse->set(str_status, entry, "notify"); } @@ -1505,11 +1477,11 @@ void clearTempView() SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("clearing current TEMP VIEW"); - + SWSS_LOG_TIMER("clear temp view"); - + std::string pattern = TEMP_PREFIX + (ASIC_STATE_TABLE + std::string(":*")); - + /* * TODO this must be ATOMIC, and could use lua script. * @@ -1521,11 +1493,11 @@ void clearTempView() { g_redisClient->del(key); } - + /* * Also clear list of objects removed in init view mode. */ - + initViewRemovedVidSet.clear(); } @@ -1553,10 +1525,10 @@ void InspectAsic() } auto str_object_type = key.substr(start + 1, mid - start - 1); auto str_object_id = key.substr(mid + 1); - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + // Find all the attrid from ASIC DB, and use them to query ASIC auto hash = g_redisClient->hgetall(key); std::vector values; @@ -1564,28 +1536,28 @@ void InspectAsic() { const std::string &skey = kv.first; const std::string &svalue = kv.second; - + swss::FieldValueTuple fvt(skey, svalue); - + values.push_back(fvt); } - + SaiAttributeList list(object_type, values, false); - + sai_attribute_t *attr_list = list.get_attr_list(); - + uint32_t attr_count = list.get_attr_count(); - + SWSS_LOG_DEBUG("attr count: %u", list.get_attr_count()); - + if (attr_count == 0) { // TODO: how to check ASIC on ASIC DB key with NULL:NULL hash continue; // Just ignore } - + auto info = sai_metadata_get_object_type_info(object_type); - + // Call SAI Get API on this key sai_status_t status; switch (object_type) @@ -1594,38 +1566,38 @@ void InspectAsic() { sai_fdb_entry_t fdb_entry; sai_deserialize_fdb_entry(str_object_id, fdb_entry); - + fdb_entry.switch_id = translate_vid_to_rid(fdb_entry.switch_id); fdb_entry.bv_id = translate_vid_to_rid(fdb_entry.bv_id); - + status = sai_metadata_sai_fdb_api->get_fdb_entry_attribute(&fdb_entry, attr_count, attr_list); break; } - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: { sai_neighbor_entry_t neighbor_entry; sai_deserialize_neighbor_entry(str_object_id, neighbor_entry); - + neighbor_entry.switch_id = translate_vid_to_rid(neighbor_entry.switch_id); neighbor_entry.rif_id = translate_vid_to_rid(neighbor_entry.rif_id); - + status = sai_metadata_sai_neighbor_api->get_neighbor_entry_attribute(&neighbor_entry, attr_count, attr_list); break; } - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: { sai_route_entry_t route_entry; sai_deserialize_route_entry(str_object_id, route_entry); - + route_entry.switch_id = translate_vid_to_rid(route_entry.switch_id); route_entry.vr_id = translate_vid_to_rid(route_entry.vr_id); - + status = sai_metadata_sai_route_api->get_route_entry_attribute(&route_entry, attr_count, attr_list); break; } - + default: { if (info->isnonobjectid) @@ -1634,20 +1606,20 @@ void InspectAsic() sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); } - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = translate_vid_to_rid(object_id); - + status = info->get(&meta_key, attr_count, attr_list); break; } } - + if (status == SAI_STATUS_NOT_IMPLEMENTED) { SWSS_LOG_ERROR("not implemented get api: %s", str_object_type.c_str()); @@ -1656,25 +1628,25 @@ void InspectAsic() { SWSS_LOG_ERROR("failed to execute get api: %s", sai_serialize_status(status).c_str()); } - + // Compare fields and values from ASIC_DB and SAI response // Log the difference for (uint32_t index = 0; index < attr_count; ++index) { const sai_attribute_t *attr = &attr_list[index]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr->id); - + if (meta == NULL) { SWSS_LOG_ERROR("FATAL: failed to find metadata for object type %d and attr id %d", object_type, attr->id); break; } - + std::string str_attr_id = sai_serialize_attr_id(*meta); - + std::string str_attr_value = sai_serialize_attr_value(*meta, *attr, false); - + std::string hash_attr_value = hash[str_attr_id]; if (hash_attr_value == str_attr_value) { @@ -1694,19 +1666,19 @@ sai_status_t onApplyViewInFastFastBoot() sai_switch_api_t* sai_switch_api = nullptr; sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_FAST_API_ENABLE; attr.value.booldata = false; - + sai_status_t status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_FAST_API_ENABLE=false: %s", sai_serialize_status(status).c_str()); } - + return status; } @@ -1718,14 +1690,14 @@ sai_status_t notifySyncd( if (!options.useTempView) { SWSS_LOG_NOTICE("received %s, ignored since TEMP VIEW is not used, returning success", op.c_str()); - + sendNotifyResponse(SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; } - + static bool firstInitWasPerformed = false; - + if (g_veryFirstRun && firstInitWasPerformed && op == SYNCD_INIT_VIEW) { /* @@ -1734,95 +1706,95 @@ sai_status_t notifySyncd( * already exists and will fail with creating multiple switches * error. */ - + g_veryFirstRun = false; } else if (g_veryFirstRun) { SWSS_LOG_NOTICE("very first run is TRUE, op = %s", op.c_str()); - + sai_status_t status = SAI_STATUS_SUCCESS; - + /* * On the very first start of syncd, "compile" view is directly applied * on device, since it will make it easier to switch to new asic state * later on when we restart orch agent. */ - + if (op == SYNCD_INIT_VIEW) { /* * On first start we just do "apply" directly on asic so we set * init to false instead of true. */ - + g_asicInitViewMode = false; - + firstInitWasPerformed = true; - + /* * We need to clear current temp view to make space for new one. */ - + clearTempView(); } else if (op == SYNCD_APPLY_VIEW) { g_veryFirstRun = false; - + g_asicInitViewMode = false; - + if (options.startType == SAI_FASTFAST_BOOT) { /* fastfast boot configuration end */ status = onApplyViewInFastFastBoot(); } - + SWSS_LOG_NOTICE("setting very first run to FALSE, op = %s", op.c_str()); } else { SWSS_LOG_THROW("unknown operation: %s", op.c_str()); } - + sendNotifyResponse(status); - + return status; } - + if (op == SYNCD_INIT_VIEW) { if (g_asicInitViewMode) { SWSS_LOG_WARN("syncd is already in asic INIT VIEW mode, but received init again, orchagent restarted before apply?"); } - + g_asicInitViewMode = true; - + clearTempView(); - + /* * TODO: Currently as WARN to be easier to spot, later should be NOTICE. */ - + SWSS_LOG_WARN("syncd switched to INIT VIEW mode, all op will be saved to TEMP view"); - + sendNotifyResponse(SAI_STATUS_SUCCESS); } else if (op == SYNCD_APPLY_VIEW) { g_asicInitViewMode = false; - + /* * TODO: Currently as WARN to be easier to spot, later should be NOTICE. */ - + SWSS_LOG_WARN("syncd received APPLY VIEW, will translate"); - + sai_status_t status = syncdApplyView(); - + sendNotifyResponse(status); - + if (status == SAI_STATUS_SUCCESS) { /* @@ -1830,7 +1802,7 @@ sai_status_t notifySyncd( * need to clear local db, and all new VIDs will be queried using * redis. */ - + local_rid_to_vid.clear(); local_vid_to_rid.clear(); } @@ -1841,27 +1813,27 @@ sai_status_t notifySyncd( * executed, on asic, or asic is inconsistent state then we should * die or hang */ - + return status; } } else if (op == SYNCD_INSPECT_ASIC) { SWSS_LOG_NOTICE("syncd switched to INSPECT ASIC mode"); - + InspectAsic(); - + sendNotifyResponse(SAI_STATUS_SUCCESS); } else { SWSS_LOG_ERROR("unknown operation: %s", op.c_str()); - + sendNotifyResponse(SAI_STATUS_NOT_IMPLEMENTED); - + SWSS_LOG_THROW("notify syncd %s operation failed", op.c_str()); } - + return SAI_STATUS_SUCCESS; } @@ -1879,10 +1851,10 @@ std::vector extractCounterIdsGeneric( std::string field = fvField(v); T counterId; deserializeIdFn(field.c_str(), &counterId); - + counterIdList.push_back(counterId); } - + return counterIdList; } @@ -1900,7 +1872,7 @@ sai_status_t getStatsGeneric( kco, deserializeIdFn); counters.resize(counter_ids.size()); - + return getStatsFn( object_id, (uint32_t)counter_ids.size(), @@ -1920,7 +1892,7 @@ sai_status_t clearStatsGeneric( const std::vector counter_ids = extractCounterIdsGeneric( kco, deserializeIdFn); - + return clearStatsFn( object_id, static_cast(counter_ids.size()), @@ -1935,17 +1907,17 @@ sai_status_t processGetStatsEvent( const std::string &key = kfvKey(kco); const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_id_t rid = translate_vid_to_rid(object_id); sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + std::vector result; - + sai_status_t status = SAI_STATUS_SUCCESS; - + switch (object_type) { case SAI_OBJECT_TYPE_PORT: @@ -1976,9 +1948,9 @@ sai_status_t processGetStatsEvent( SWSS_LOG_ERROR("SAI object type %s not supported", str_object_type.c_str()); status = SAI_STATUS_NOT_SUPPORTED; } - + std::vector entry; - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to get stats"); @@ -1991,9 +1963,9 @@ sai_status_t processGetStatsEvent( entry.emplace_back(fvField(values[i]), std::to_string(result[i])); } } - + getResponse->set(sai_serialize_status(status), entry, "getresponse"); - + return status; } @@ -2005,7 +1977,7 @@ sai_status_t processClearStatsEvent( const std::string &key = kfvKey(kco); const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_id_t rid; @@ -2018,7 +1990,7 @@ sai_status_t processClearStatsEvent( getResponse->set(sai_serialize_status(status), fvTuples, "getresponse"); return status; } - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); switch (object_type) @@ -2034,7 +2006,7 @@ sai_status_t processClearStatsEvent( SWSS_LOG_ERROR("SAI object type %s not supported", str_object_type.c_str()); status = SAI_STATUS_NOT_SUPPORTED; } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to clear stats"); @@ -2046,7 +2018,7 @@ sai_status_t processClearStatsEvent( fvTuples.emplace_back(fvField(fv), ""); } } - + getResponse->set(sai_serialize_status(status), fvTuples, "getresponse"); return status; } @@ -2061,7 +2033,7 @@ void on_switch_create_in_init_view( /* * This needs to be refactored if we need multiple switch support. */ - + /* * We can have multiple switches here, but each switch is identified by * SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO. This attribute is treated as key, @@ -2086,7 +2058,7 @@ void on_switch_create_in_init_view( * Since we are creating switch here, we are sure that this switch don't * have any oid attributes set, so we can pass all attributes */ - + /* * Multiple switches scenario with changed order: * @@ -2100,7 +2072,7 @@ void on_switch_create_in_init_view( * * Currently we don't have good solution for that so we will throw in that case. */ - + if (switches.size() == 0) { /* @@ -2112,16 +2084,16 @@ void on_switch_create_in_init_view( * This scenario can happen when you start syncd on empty database and * then you quit and restart it again. */ - + sai_object_id_t switch_rid; - + sai_status_t status; - + { SWSS_LOG_TIMER("cold boot: create switch"); status = sai_metadata_sai_switch_api->create_switch(&switch_rid, attr_count, attr_list); } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to create switch in init view mode: %s", @@ -2137,27 +2109,27 @@ void on_switch_create_in_init_view( * Object was created so new object id was generated we * need to save virtual id's to redis db. */ - + std::string str_vid = sai_serialize_object_id(switch_vid); std::string str_rid = sai_serialize_object_id(switch_rid); - + SWSS_LOG_NOTICE("created real switch VID %s to RID %s in init view mode", str_vid.c_str(), str_rid.c_str()); - + /* * TODO: This must be ATOMIC. * * To support multiple switches vid/rid map must be per switch. */ - + g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); - + save_rid_and_vid_to_local(switch_rid, switch_vid); - + /* * Make switch initialization and get all default data. */ - + switches[switch_vid] = std::make_shared(switch_vid, switch_rid); } else if (switches.size() == 1) @@ -2167,29 +2139,29 @@ void on_switch_create_in_init_view( * info and we need to know that current switch VID also should match * since it's deterministic created. */ - + auto sw = switches.begin()->second; - + /* * Switches VID must match, since it's deterministic. */ - + if (switch_vid != sw->getVid()) { SWSS_LOG_THROW("created switch VID don't match: previous %s, current: %s", sai_serialize_object_id(switch_vid).c_str(), sai_serialize_object_id(sw->getVid()).c_str()); } - + /* * Also hardware info also must match. */ - + std::string currentHw = sw->getHardwareInfo(); std::string newHw; - + auto attr = sai_metadata_get_attr_by_id(SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO, attr_count, attr_list); - + if (attr == NULL) { /* @@ -2199,15 +2171,15 @@ void on_switch_create_in_init_view( else { SWSS_LOG_DEBUG("new switch contains hardware info of length %u", attr->value.s8list.count); - + newHw = std::string((char*)attr->value.s8list.list, attr->value.s8list.count); } - + if (currentHw != newHw) { SWSS_LOG_THROW("hardware info missmatch: current '%s' vs new '%s'", currentHw.c_str(), newHw.c_str()); } - + SWSS_LOG_NOTICE("current switch hardware info: '%s'", currentHw.c_str()); } else @@ -2231,17 +2203,17 @@ sai_status_t processEventInInitViewMode( * but if that happen, this id will be treated as "new" object instead of * existing one. */ - + /* * TODO: use metadata utils. */ - + auto info = sai_metadata_get_object_type_info(object_type); - + switch (api) { case SAI_COMMON_API_CREATE: - + if (info->isnonobjectid) { /* @@ -2252,28 +2224,26 @@ sai_status_t processEventInInitViewMode( { sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + /* * Object ID here is actual VID returned from redis during * creation this is floating VID in init view mode. */ - + SWSS_LOG_DEBUG("generic create (init view) for %s, floating VID: %s", sai_serialize_object_type(object_type).c_str(), sai_serialize_object_id(object_id).c_str()); - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_create_in_init_view(object_id, attr_count, attr_list); } } - - internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_REMOVE: - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { /* @@ -2284,10 +2254,10 @@ sai_status_t processEventInInitViewMode( * * To support multiple switches this case must be refactored. */ - + SWSS_LOG_THROW("remove switch (%s) is not supported in init view mode yet! FIXME", str_object_id.c_str()); } - + if (!info->isnonobjectid) { /* @@ -2300,32 +2270,28 @@ sai_status_t processEventInInitViewMode( * need to have a list of removed objects, and then only * populate objects which not exist on removed list. */ - + sai_object_id_t object_vid; sai_deserialize_object_id(str_object_id, object_vid); - + initViewRemovedVidSet.insert(object_vid); } - - internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_SET: - + /* * We support SET api on all objects in init view mode. */ - - internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_GET: - + { sai_status_t status; - + if (info->isnonobjectid) { /* @@ -2334,20 +2300,20 @@ sai_status_t processEventInInitViewMode( * since user explicitly know what attributes were set, similar * for other non object id types. */ - + SWSS_LOG_ERROR("get is not supported on %s in init view mode", sai_serialize_object_type(object_type).c_str()); - + status = SAI_STATUS_NOT_SUPPORTED; } else { sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + SWSS_LOG_DEBUG("generic get (init view) for object type %s:%s", sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); - + /* * Object must exists, we can't call GET on created object * in init view mode, get here can be called on existing @@ -2362,19 +2328,19 @@ sai_status_t processEventInInitViewMode( * Translate vid to rid will make sure that object exist * and it have RID defined, so we can query it. */ - + sai_object_id_t rid = translate_vid_to_rid(object_id); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = rid; - + status = info->get(&meta_key, attr_count, attr_list); } - + sai_object_id_t switch_id; - + if (switches.size() == 1) { /* @@ -2386,7 +2352,7 @@ sai_status_t processEventInInitViewMode( * can extract switch id, we could also have this method * inside metadata to get meta key. */ - + switch_id = switches.begin()->second->getVid(); } else @@ -2395,17 +2361,17 @@ sai_status_t processEventInInitViewMode( * This needs to be updated to support multiple switches * scenario. */ - + SWSS_LOG_THROW("multiple switches are not supported yet: %zu", switches.size()); } - + internal_syncd_get_send(object_type, str_object_id, switch_id, status, attr_count, attr_list); - + return status; } - + default: - + SWSS_LOG_THROW("common api (%s) is not implemented in init view mode", sai_serialize_common_api(api).c_str()); } @@ -2418,39 +2384,39 @@ sai_object_id_t extractSwitchVid( SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(object_type); - + /* * Could be replaced by meta_key. */ - + sai_fdb_entry_t fdb_entry; sai_neighbor_entry_t neighbor_entry; sai_route_entry_t route_entry; sai_object_id_t oid; - + switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: sai_deserialize_fdb_entry(str_object_id, fdb_entry); return fdb_entry.switch_id; - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: sai_deserialize_neighbor_entry(str_object_id, neighbor_entry); return neighbor_entry.switch_id; - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: sai_deserialize_route_entry(str_object_id, route_entry); return route_entry.switch_id; - + default: - + if (info->isnonobjectid) { SWSS_LOG_THROW("passing non object id %s as generic object", info->objecttypename); } - + sai_deserialize_object_id(str_object_id, oid); - + return redis_sai_switch_id_query(oid); } } @@ -2467,16 +2433,16 @@ sai_status_t handle_bulk_generic( * Since we don't have asic support yet for bulk api, just execute one by * one. */ - + for (size_t idx = 0; idx < object_ids.size(); ++idx) { sai_status_t status = SAI_STATUS_FAILURE; - + auto &list = attributes[idx]; - + sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); - + sai_object_meta_key_t meta_key; meta_key.objecttype = object_type; switch (object_type) @@ -2493,7 +2459,7 @@ sai_status_t handle_bulk_generic( default: SWSS_LOG_THROW("invalid object_type: %s", sai_serialize_object_type(object_type).c_str()); } - + if (api == (sai_common_api_t)SAI_COMMON_API_BULK_SET) { status = handle_non_object_id(meta_key, SAI_COMMON_API_SET, attr_count, attr_list); @@ -2510,14 +2476,13 @@ sai_status_t handle_bulk_generic( { SWSS_LOG_THROW("api %d is not supported in bulk route", api); } - + if (status != SAI_STATUS_SUCCESS) { - internal_syncd_api_send_response(api, status); return status; } } - + return SAI_STATUS_SUCCESS; } @@ -2529,80 +2494,80 @@ sai_status_t processBulkEvent( SWSS_LOG_ENTER(); const std::string &key = kfvKey(kco); - + std::string str_object_type = key.substr(0, key.find(":")); - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + const std::vector &values = kfvFieldsValues(kco); - + // key = str_object_id // val = attrid=attrvalue|... - + std::vector object_ids; - + std::vector> attributes; - + for (const auto &fvt: values) { std::string str_object_id = fvField(fvt); std::string joined = fvValue(fvt); - + // decode values - + auto v = swss::tokenize(joined, '|'); - + object_ids.push_back(str_object_id); - + std::vector entries; // attributes per object id - + for (size_t i = 0; i < v.size(); ++i) { const std::string item = v.at(i); - + auto start = item.find_first_of("="); - + auto field = item.substr(0, start); auto value = item.substr(start + 1); - + swss::FieldValueTuple entry(field, value); - + entries.push_back(entry); } - + // since now we converted this to proper list, we can extract attributes - + std::shared_ptr list = std::make_shared(object_type, entries, false); - + attributes.push_back(list); } - + SWSS_LOG_NOTICE("bulk %s execute with %zu items", str_object_type.c_str(), object_ids.size()); - + if (isInitViewMode()) { SWSS_LOG_THROW("bulk api (%d) is not supported in init view mode", api); } - + if (api != SAI_COMMON_API_BULK_GET) { // translate attributes for all objects - + for (auto &list: attributes) { sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); - + translate_vid_to_rid_list(object_type, attr_count, attr_list); } } - + sai_status_t status; - + switch (object_type) { case SAI_OBJECT_TYPE_ROUTE_ENTRY: @@ -2610,20 +2575,18 @@ sai_status_t processBulkEvent( case SAI_OBJECT_TYPE_FDB_ENTRY: status = handle_bulk_generic(object_type, object_ids, api, attributes); break; - + default: SWSS_LOG_THROW("bulk api for %s is not supported yet, FIXME", sai_serialize_object_type(object_type).c_str()); } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to execute bulk api: %s", sai_serialize_status(status).c_str()); } - - internal_syncd_api_send_response(api, status); - + return status; } @@ -2634,38 +2597,38 @@ sai_status_t processFdbFlush( const std::string &key = kfvKey(kco); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t switch_vid; - + sai_deserialize_object_id(str_object_id, switch_vid); - + sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid); - + const std::vector &values = kfvFieldsValues(kco); - + for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SaiAttributeList list(SAI_OBJECT_TYPE_FDB_FLUSH, values, false); - + /* * Attribute list can't be const since we will use it to translate VID to * RID in place. */ - + sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); - + translate_vid_to_rid_list(SAI_OBJECT_TYPE_FDB_FLUSH, attr_count, attr_list); - + sai_status_t status = sai_metadata_sai_fdb_api->flush_fdb_entries(switch_rid, attr_count, attr_list); - + std::vector en; - + getResponse->set(sai_serialize_status(status), en, "flushresponse"); - + return status; } @@ -2675,13 +2638,13 @@ sai_status_t processEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + swss::KeyOpFieldsValuesTuple kco; - + sai_status_t status = SAI_STATUS_SUCCESS; - + do { - + if (isInitViewMode()) { /* @@ -2689,34 +2652,34 @@ sai_status_t processEvent( * specify temporary view prefix in consumer since consumer puts data * to redis db. */ - + consumer.pop(kco, TEMP_PREFIX); } else { consumer.pop(kco); } - + const std::string &key = kfvKey(kco); const std::string &op = kfvOp(kco); - + if (key.length() == 0) { SWSS_LOG_DEBUG("no elements in m_buffer"); return status; } - + /* * TODO: Key is serialized meta_key, we could use deserialize * to extract it here. */ - + const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + SWSS_LOG_INFO("key: %s op: %s", key.c_str(), op.c_str()); - + sai_common_api_t api = SAI_COMMON_API_MAX; - + if (op == "create") { api = SAI_COMMON_API_CREATE; @@ -2761,42 +2724,42 @@ sai_status_t processEvent( { SWSS_LOG_THROW("api '%s' is not implemented", op.c_str()); } - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + /* * TODO: use metadata utils is object type valid. */ - + if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX) { SWSS_LOG_THROW("undefined object type %s", sai_serialize_object_type(object_type).c_str()); } - + const std::vector &values = kfvFieldsValues(kco); - + for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SaiAttributeList list(object_type, values, false); - + /* * Attribute list can't be const since we will use it to translate VID to * RID in place. */ - + sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); - + /* * NOTE: This check pointers must be executed before init view mode, since * this methods replaces pointers from orchagent memory space to syncd * memory space. */ - + if (object_type == SAI_OBJECT_TYPE_SWITCH && (api == SAI_COMMON_API_CREATE || api == SAI_COMMON_API_SET)) { /* @@ -2805,15 +2768,15 @@ sai_status_t processEvent( * will internally check whether pointer is null or not, so we here * will receive all notifications, but redis only those that were set. */ - + check_notifications_pointers(attr_count, attr_list); } - + if (isInitViewMode()) { return processEventInInitViewMode(object_type, str_object_id, api, attr_count, attr_list); } - + if (api != SAI_COMMON_API_GET) { /* @@ -2821,51 +2784,51 @@ sai_status_t processEvent( * buffer so then all OIDs will be NULL, and translation will also * convert them to NULL. */ - + SWSS_LOG_DEBUG("translating VID to RIDs on all attributes"); - + translate_vid_to_rid_list(object_type, attr_count, attr_list); } - + // TODO use metadata utils auto info = sai_metadata_get_object_type_info(object_type); - + /* * TODO use sai meta key deserialize */ - + if (info->isnonobjectid) { sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; - + switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: sai_deserialize_fdb_entry(str_object_id, meta_key.objectkey.key.fdb_entry); break; - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: sai_deserialize_neighbor_entry(str_object_id, meta_key.objectkey.key.neighbor_entry); break; - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: sai_deserialize_route_entry(str_object_id, meta_key.objectkey.key.route_entry); break; - + default: - + SWSS_LOG_THROW("non object id %s is not supported yet, FIXME", info->objecttypename); } - + status = handle_non_object_id(meta_key, api, attr_count, attr_list); } else { status = handle_generic(object_type, str_object_id, api, attr_count, attr_list); } - + if (api == SAI_COMMON_API_GET) { if (status != SAI_STATUS_SUCCESS) @@ -2875,49 +2838,42 @@ sai_status_t processEvent( op.c_str(), sai_serialize_status(status).c_str()); } - + /* * Extracting switch is double work here, we can avoid this when we * will use meta_key. */ - + sai_object_id_t switch_vid = extractSwitchVid(object_type, str_object_id); - + internal_syncd_get_send(object_type, str_object_id, switch_vid, status, attr_count, attr_list); } else if (status != SAI_STATUS_SUCCESS) { - internal_syncd_api_send_response(api, status); - if (!info->isnonobjectid && api == SAI_COMMON_API_SET) { sai_object_id_t vid; sai_deserialize_object_id(str_object_id, vid); - + sai_object_id_t rid = translate_vid_to_rid(vid); - + SWSS_LOG_ERROR("VID: %s RID: %s", sai_serialize_object_id(vid).c_str(), sai_serialize_object_id(rid).c_str()); } - + for (const auto &v: values) { SWSS_LOG_ERROR("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SWSS_LOG_THROW("failed to execute api: %s, key: %s, status: %s", op.c_str(), key.c_str(), sai_serialize_status(status).c_str()); } - else // non GET api, status is SUCCESS - { - internal_syncd_api_send_response(api, status); - } - } while (!consumer.empty()); - + return status; } @@ -2931,22 +2887,22 @@ void processFlexCounterGroupEvent( std::lock_guard lock(g_mutex); consumer.pop(kco); } - + const auto &groupName = kfvKey(kco); const auto &op = kfvOp(kco); const auto values = kfvFieldsValues(kco); - + if (op == DEL_COMMAND) { FlexCounter::removeCounterPlugin(groupName); return; } - + for (const auto& valuePair : values) { const auto field = fvField(valuePair); const auto value = fvValue(valuePair); - + if (op == SET_COMMAND) { if (field == POLL_INTERVAL_FIELD) @@ -3009,16 +2965,16 @@ bool tryPopFlexCounterEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + if (g_flexCounterEventQueue.empty()) { return false; } - + kco = g_flexCounterEventQueue.front(); - + g_flexCounterEventQueue.pop(); - + return true; } @@ -3028,7 +2984,7 @@ void pushFlexCounterEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + g_flexCounterEventQueue.push(kco); } @@ -3042,17 +2998,17 @@ void processFlexCounterEventThread() while (g_processFlexCounterEventThreadRun) { swss::KeyOpFieldsValuesTuple kco; - + if (tryPopFlexCounterEvent(kco)) { if (!processFlexCounterEvent(kco)) { // event was not successfully processed, put it again to the queue - + pushFlexCounterEvent(kco); } } - + sleep(1); } } @@ -3063,19 +3019,19 @@ void processFlexCounterEvent( SWSS_LOG_ENTER(); swss::KeyOpFieldsValuesTuple kco; - + { std::lock_guard lock(g_mutex); consumer.pop(kco); } - + // because flex counter event can arrive independently (on RIF interface) // it may happen that it will be picked up from the select api before // actual interface will be created, and subscription for counters will // fail, so let's process each request in the thread and use queue for // arriving events, and failed events will be put back to the queue until // they will be processed - + pushFlexCounterEvent(kco); } @@ -3086,34 +3042,35 @@ bool processFlexCounterEvent( const auto &key = kfvKey(kco); const std::string &op = kfvOp(kco); - + std::size_t delimiter = key.find_first_of(":"); if (delimiter == std::string::npos) { SWSS_LOG_ERROR("Failed to parse the key %s", key.c_str()); - + return true; // if key is invalid there is no need to process this event again } - + const auto groupName = key.substr(0, delimiter); const auto vidStr = key.substr(delimiter+1); - + sai_object_id_t vid = SAI_NULL_OBJECT_ID; sai_deserialize_object_id(vidStr, vid); sai_object_id_t rid; { std::lock_guard lock(g_mutex); if (!try_translate_vid_to_rid(vid, rid)) - { - SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", - sai_serialize_object_id(vid).c_str()); + { + SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", + sai_serialize_object_id(vid).c_str()); + return false; } } - + sai_object_type_t objectType = redis_sai_object_type_query(vid); // VID and RID will have the same object type std::string objectTypeStr = sai_serialize_object_type(objectType); - + if (op == DEL_COMMAND) { if (objectType == SAI_OBJECT_TYPE_PORT) @@ -3141,7 +3098,7 @@ bool processFlexCounterEvent( SWSS_LOG_ERROR("Object type for removal not supported, %s", objectTypeStr.c_str()); } } - + const auto values = kfvFieldsValues(kco); std::vector counterIds; std::string statsMode; @@ -3149,11 +3106,11 @@ bool processFlexCounterEvent( { const auto field = fvField(valuePair); const auto value = fvValue(valuePair); - + if (op == SET_COMMAND) { auto idStrings = swss::tokenize(value, ','); - + if (objectType == SAI_OBJECT_TYPE_PORT && field == PORT_COUNTER_ID_LIST) { std::vector portCounterIds; @@ -3163,7 +3120,7 @@ bool processFlexCounterEvent( sai_deserialize_port_stat(str.c_str(), &stat); portCounterIds.push_back(stat); } - + FlexCounter::setPortCounterList(vid, rid, groupName, portCounterIds); } else if (objectType == SAI_OBJECT_TYPE_QUEUE && field == QUEUE_COUNTER_ID_LIST) @@ -3175,7 +3132,7 @@ bool processFlexCounterEvent( sai_deserialize_queue_stat(str.c_str(), &stat); queueCounterIds.push_back(stat); } - + FlexCounter::setQueueCounterList(vid, rid, groupName, queueCounterIds); } else if (objectType == SAI_OBJECT_TYPE_QUEUE && field == QUEUE_ATTR_ID_LIST) @@ -3187,7 +3144,7 @@ bool processFlexCounterEvent( sai_deserialize_queue_attr(str, attr); queueAttrIds.push_back(attr); } - + FlexCounter::setQueueAttrList(vid, rid, groupName, queueAttrIds); } else if (objectType == SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP && field == PG_COUNTER_ID_LIST) @@ -3199,7 +3156,7 @@ bool processFlexCounterEvent( sai_deserialize_ingress_priority_group_stat(str.c_str(), &stat); pgCounterIds.push_back(stat); } - + FlexCounter::setPriorityGroupCounterList(vid, rid, groupName, pgCounterIds); } else if (objectType == SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP && field == PG_ATTR_ID_LIST) @@ -3211,7 +3168,7 @@ bool processFlexCounterEvent( sai_deserialize_ingress_priority_group_attr(str, attr); pgAttrIds.push_back(attr); } - + FlexCounter::setPriorityGroupAttrList(vid, rid, groupName, pgAttrIds); } else if (objectType == SAI_OBJECT_TYPE_ROUTER_INTERFACE && field == RIF_COUNTER_ID_LIST) @@ -3223,7 +3180,7 @@ bool processFlexCounterEvent( sai_deserialize_router_interface_stat(str.c_str(), &stat); rifCounterIds.push_back(stat); } - + FlexCounter::setRifCounterList(vid, rid, groupName, rifCounterIds); } else if (objectType == SAI_OBJECT_TYPE_BUFFER_POOL && field == BUFFER_POOL_COUNTER_ID_LIST) @@ -3240,7 +3197,7 @@ bool processFlexCounterEvent( } } } - + if (objectType == SAI_OBJECT_TYPE_BUFFER_POOL && counterIds.size()) { std::vector bufferPoolCounterIds; @@ -3250,10 +3207,10 @@ bool processFlexCounterEvent( sai_deserialize_buffer_pool_stat(str.c_str(), &stat); bufferPoolCounterIds.push_back(stat); } - + FlexCounter::setBufferPoolCounterList(vid, rid, groupName, bufferPoolCounterIds, statsMode); } - + return true; } @@ -3261,7 +3218,7 @@ void printUsage() { SWSS_LOG_ENTER(); - std::cout << "Usage: syncd [-N] [-U] [-d] [-p profile] [-i interval] [-t [cold|warm|fast|fastfast]] [-h] [-u] [-S] [-s]" << std::endl; + std::cout << "Usage: syncd [-N] [-U] [-d] [-p profile] [-i interval] [-t [cold|warm|fast|fastfast]] [-h] [-u] [-S]" << std::endl; std::cout << " -N --nocounters" << std::endl; std::cout << " Disable counter thread" << std::endl; std::cout << " -d --diag" << std::endl; @@ -3286,8 +3243,6 @@ void printUsage() std::cout << " -m --portmap" << std::endl; std::cout << " Specify port map file" << std::endl; #endif // SAITHRIFT - std::cout << " -s --syncMode" << std::endl; - std::cout << " Enable synchronous mode" << std::endl; std::cout << " -h --help" << std::endl; std::cout << " Print out this message" << std::endl; } @@ -3298,7 +3253,6 @@ void handleCmdLine(int argc, char **argv) options.disableExitSleep = false; options.enableUnittests = false; - options.syncMode = false; #ifdef SAITHRIFT options.run_rpc_server = false; @@ -3323,51 +3277,50 @@ void handleCmdLine(int argc, char **argv) { "rpcserver", no_argument, 0, 'r' }, { "portmap", required_argument, 0, 'm' }, #endif // SAITHRIFT - { "syncMode", no_argument, 0, 's' }, { 0, 0, 0, 0 } }; - + int option_index = 0; - + int c = getopt_long(argc, argv, optstring, long_options, &option_index); - + if (c == -1) { break; } - + switch (c) { case 'U': SWSS_LOG_NOTICE("enable unittests"); options.enableUnittests = true; break; - + case 'C': SWSS_LOG_NOTICE("enable consistency check"); g_enableConsistencyCheck = true; break; - + case 'u': SWSS_LOG_NOTICE("enable use temp view"); options.useTempView = true; break; - + case 'S': SWSS_LOG_NOTICE("disable crash sleep"); options.disableExitSleep = true; break; - + case 'd': SWSS_LOG_NOTICE("enable diag shell"); options.diagShell = true; break; - + case 'p': SWSS_LOG_NOTICE("profile map file: %s", optarg); options.profileMapFile = std::string(optarg); break; - + case 't': SWSS_LOG_NOTICE("start type: %s", optarg); if (std::string(optarg) == "cold") @@ -3404,20 +3357,15 @@ void handleCmdLine(int argc, char **argv) break; #endif // SAITHRIFT - case 's': - SWSS_LOG_NOTICE("enable synchronous mode"); - options.syncMode = true; - break; - case 'h': printUsage(); exit(EXIT_SUCCESS); - + case '?': SWSS_LOG_WARN("unknown option %c", optopt); printUsage(); exit(EXIT_FAILURE); - + default: SWSS_LOG_ERROR("getopt_long failure"); exit(EXIT_FAILURE); @@ -3433,44 +3381,44 @@ void handleProfileMap(const std::string& profileMapFile) { return; } - + std::ifstream profile(profileMapFile); - + if (!profile.is_open()) { SWSS_LOG_ERROR("failed to open profile map file: %s : %s", profileMapFile.c_str(), strerror(errno)); exit(EXIT_FAILURE); } - + // Provide default value at boot up time and let sai profile value // Override following values if existing. // SAI reads these values at start up time. It would be too late to // set these values later when WARM BOOT is detected. gProfileMap[SAI_KEY_WARM_BOOT_WRITE_FILE] = DEF_SAI_WARM_BOOT_DATA_FILE; gProfileMap[SAI_KEY_WARM_BOOT_READ_FILE] = DEF_SAI_WARM_BOOT_DATA_FILE; - + std::string line; - + while(getline(profile, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) { continue; } - + size_t pos = line.find("="); - + if (pos == std::string::npos) { SWSS_LOG_WARN("not found '=' in line %s", line.c_str()); continue; } - + std::string key = line.substr(0, pos); std::string value = line.substr(pos + 1); - + gProfileMap[key] = value; - + SWSS_LOG_INFO("insert: %s:%s", key.c_str(), value.c_str()); } } @@ -3487,39 +3435,39 @@ void handlePortMap(const std::string& portMapFile) { return; } - + std::ifstream portmap(portMapFile); - + if (!portmap.is_open()) { std::cerr << "failed to open port map file:" << portMapFile.c_str() << " : "<< strerror(errno) << std::endl; exit(EXIT_FAILURE); } - + std::string line; - + while(getline(portmap, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) { continue; } - + std::istringstream iss(line); std::string name, lanes, alias; iss >> name >> lanes >> alias; - + iss.clear(); iss.str(lanes); std::string lane_str; std::set lane_set; - + while (getline(iss, lane_str, ',')) { int lane = stoi(lane_str); lane_set.insert(lane); } - + gPortMap.insert(std::pair,std::string>(lane_set, name)); } } @@ -3530,9 +3478,9 @@ typedef enum _syncd_restart_type_t SYNCD_RESTART_TYPE_COLD, SYNCD_RESTART_TYPE_WARM, - + SYNCD_RESTART_TYPE_FAST, - + SYNCD_RESTART_TYPE_PRE_SHUTDOWN, } syncd_restart_type_t; @@ -3544,35 +3492,35 @@ syncd_restart_type_t handleRestartQuery(swss::NotificationConsumer &restartQuery std::string op; std::string data; std::vector values; - + restartQuery.pop(op, data, values); - + SWSS_LOG_DEBUG("op = %s", op.c_str()); - + if (op == "COLD") { SWSS_LOG_NOTICE("received COLD switch shutdown event"); return SYNCD_RESTART_TYPE_COLD; } - + if (op == "WARM") { SWSS_LOG_NOTICE("received WARM switch shutdown event"); return SYNCD_RESTART_TYPE_WARM; } - + if (op == "FAST") { SWSS_LOG_NOTICE("received FAST switch shutdown event"); return SYNCD_RESTART_TYPE_FAST; } - + if (op == "PRE-SHUTDOWN") { SWSS_LOG_NOTICE("received PRE_SHUTDOWN switch event"); return SYNCD_RESTART_TYPE_PRE_SHUTDOWN; } - + SWSS_LOG_WARN("received '%s' unknown switch shutdown event, assuming COLD", op.c_str()); return SYNCD_RESTART_TYPE_COLD; } @@ -3594,13 +3542,13 @@ bool isVeryFirstRun() * TODO we need to fix this, since when there will be queue, it will still think * this is first run, let's query HIDDEN ? */ - + auto keys = g_redisClient->keys(HIDDEN); - + bool firstRun = keys.size() == 0; - + SWSS_LOG_NOTICE("First Run: %s", firstRun ? "True" : "False"); - + return firstRun; } @@ -3617,7 +3565,7 @@ int get_enum_value_from_name( return metadata->values[idx]; } } - + SWSS_LOG_ERROR("not found %s", name); return 0; } @@ -3627,7 +3575,7 @@ void saiLoglevelNotify(std::string apiStr, std::string prioStr) SWSS_LOG_ENTER(); using namespace swss; - + static const std::map saiLoglevelMap = { { "SAI_LOG_LEVEL_CRITICAL", SAI_LOG_LEVEL_CRITICAL }, { "SAI_LOG_LEVEL_ERROR", SAI_LOG_LEVEL_ERROR }, @@ -3636,24 +3584,24 @@ void saiLoglevelNotify(std::string apiStr, std::string prioStr) { "SAI_LOG_LEVEL_INFO", SAI_LOG_LEVEL_INFO }, { "SAI_LOG_LEVEL_DEBUG", SAI_LOG_LEVEL_DEBUG }, }; - + if (saiLoglevelMap.find(prioStr) == saiLoglevelMap.end()) { SWSS_LOG_ERROR("Invalid SAI loglevel %s %s", apiStr.c_str(), prioStr.c_str()); return; } - + sai_api_t api = (sai_api_t)get_enum_value_from_name(apiStr.c_str(), &sai_metadata_enum_sai_api_t); - + sai_status_t status = sai_log_set(api, saiLoglevelMap.at(prioStr)); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_INFO("Failed to set %s on %s: %s", prioStr.c_str(), apiStr.c_str(), sai_serialize_status(status).c_str()); return; } - + SWSS_LOG_NOTICE("Setting SAI loglevel %s to %s", apiStr.c_str(), prioStr.c_str()); } @@ -3664,7 +3612,7 @@ void set_sai_api_loglevel() /* * We start from 1 since 0 is SAI_API_UNSPECIFIED. */ - + for (uint32_t idx = 1; idx < sai_metadata_enum_sai_api_t.valuescount; ++idx) { swss::Logger::linkToDb(sai_metadata_enum_sai_api_t.valuesnames[idx], saiLoglevelNotify, "SAI_LOG_LEVEL_NOTICE"); @@ -3678,7 +3626,7 @@ void set_sai_api_log_min_prio(const std::string &prioStr) /* * We start from 1 since 0 is SAI_API_UNSPECIFIED. */ - + for (uint32_t idx = 1; idx < sai_metadata_enum_sai_api_t.valuescount; ++idx) { const auto& api_name = sai_metadata_enum_sai_api_t.valuesnames[idx]; @@ -3698,9 +3646,9 @@ void onSyncdStart(bool warmStart) * will generate new id's for ports, this may cause race condition so we * need to use a lock here to prevent that. */ - + SWSS_LOG_TIMER("on syncd start"); - + if (warmStart) { /* @@ -3714,20 +3662,20 @@ void onSyncdStart(bool warmStart) * * If we want to support multiple switches, this needs to be adjusted. */ - + performWarmRestart(); - + SWSS_LOG_NOTICE("skipping hard reinit since WARM start was performed"); return; } - + SWSS_LOG_NOTICE("performing hard reinit since COLD start was performed"); - + /* * Switch was restarted in hard way, we need to perform hard reinit and * recreate switches map. */ - + hardReinit(); } @@ -3751,14 +3699,14 @@ void sai_meta_log_syncd( // SWSS_LOG_ENTER() is omitted since this is logging for metadata char buffer[0x1000]; - + va_list ap; va_start(ap, format); vsnprintf(buffer, 0x1000, format, ap); va_end(ap); - + swss::Logger::Priority p = swss::Logger::SWSS_NOTICE; - + switch (log_level) { case SAI_LOG_LEVEL_DEBUG: @@ -3778,12 +3726,12 @@ void sai_meta_log_syncd( case SAI_LOG_LEVEL_CRITICAL: p = swss::Logger::SWSS_CRIT; break; - + default: p = swss::Logger::SWSS_NOTICE; break; } - + swss::Logger::getInstance().write(p, ":- %s: %s", func, buffer); } @@ -3800,13 +3748,13 @@ int syncd_main(int argc, char **argv) swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG); SWSS_LOG_ENTER(); - + swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE); - + set_sai_api_loglevel(); - + swss::Logger::linkToDbNative("syncd"); - + swss::WarmStart::initialize("syncd", "syncd"); swss::WarmStart::checkWarmStart("syncd", "syncd"); @@ -3816,9 +3764,9 @@ int syncd_main(int argc, char **argv) #pragma GCC diagnostic pop meta_init_db(); - + handleCmdLine(argc, argv); - + handleProfileMap(options.profileMapFile); #ifdef SAITHRIFT @@ -3833,59 +3781,59 @@ int syncd_main(int argc, char **argv) std::shared_ptr dbFlexCounter = std::make_shared(FLEX_COUNTER_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::shared_ptr dbState = std::make_shared(STATE_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::unique_ptr warmRestartTable = std::unique_ptr(new swss::Table(dbState.get(), STATE_WARM_RESTART_TABLE_NAME)); - + g_redisClient = std::make_shared(dbAsic.get()); - + std::shared_ptr asicState = std::make_shared(dbAsic.get(), ASIC_STATE_TABLE); std::shared_ptr restartQuery = std::make_shared(dbAsic.get(), "RESTARTQUERY"); std::shared_ptr flexCounter = std::make_shared(dbFlexCounter.get(), FLEX_COUNTER_TABLE); std::shared_ptr flexCounterGroup = std::make_shared(dbFlexCounter.get(), FLEX_COUNTER_GROUP_TABLE); - + /* * At the end we cant use producer consumer concept since if one process * will restart there may be something in the queue also "remove" from * response queue will also trigger another "response". */ - + getResponse = std::make_shared(dbAsic.get(), "GETRESPONSE"); notifications = std::make_shared(dbNtf.get(), "NOTIFICATIONS"); - + g_veryFirstRun = isVeryFirstRun(); - + /* ignore warm logic here if syncd starts in Mellanox fastfast boot mode */ if (swss::WarmStart::isWarmStart() && (options.startType != SAI_FASTFAST_BOOT)) { options.startType = SAI_WARM_BOOT; } - + if (options.startType == SAI_WARM_BOOT) { const char *warmBootReadFile = profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE); - + SWSS_LOG_NOTICE("using warmBootReadFile: '%s'", warmBootReadFile); - + if (warmBootReadFile == NULL || access(warmBootReadFile, F_OK) == -1) { SWSS_LOG_WARN("user requested warmStart but warmBootReadFile is not specified or not accesible, forcing cold start"); - + options.startType = SAI_COLD_BOOT; } } - + if (options.startType == SAI_WARM_BOOT && g_veryFirstRun) { SWSS_LOG_WARN("warm start requested, but this is very first syncd start, forcing cold start"); - + /* * We force cold start since if it's first run then redis db is not * complete so redis asic view will not reflect warm boot asic state, * if this happen then orch agent needs to be restarted as well to * repopulate asic view. */ - + options.startType = SAI_COLD_BOOT; } - + if (options.startType == SAI_FASTFAST_BOOT) { /* @@ -3896,23 +3844,23 @@ int syncd_main(int argc, char **argv) } else { gProfileMap[SAI_KEY_BOOT_TYPE] = std::to_string(options.startType); } - + sai_status_t status = sai_api_initialize(0, (sai_service_method_table_t*)&test_services); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("fail to sai_api_initialize: %d", status); return EXIT_FAILURE; } - + sai_apis_t apis; int failed = sai_metadata_apis_query(sai_api_query, &apis); - + if (failed > 0) { SWSS_LOG_NOTICE("sai_api_query failed for %d apis", failed); } - + /* * TODO: user should create switch from OA, so shell should be started only * after we create switch. @@ -3927,59 +3875,59 @@ int syncd_main(int argc, char **argv) #endif // SAITHRIFT SWSS_LOG_NOTICE("syncd started"); - + syncd_restart_type_t shutdownType = SYNCD_RESTART_TYPE_COLD; - + sai_switch_api_t *sai_switch_api = NULL; sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api); - + volatile bool runMainLoop = true; - + std::shared_ptr s = std::make_shared(); - + try { SWSS_LOG_NOTICE("before onSyncdStart"); onSyncdStart(options.startType == SAI_WARM_BOOT); SWSS_LOG_NOTICE("after onSyncdStart"); - + // create notifications processing thread after we create_switch to // make sure, we have switch_id translated to VID before we start // processing possible quick fdb notifications, and pointer for // notification queue is created before we create switch startNotificationsProcessingThread(); - + SWSS_LOG_NOTICE("syncd listening for events"); - + s->addSelectable(asicState.get()); s->addSelectable(restartQuery.get()); s->addSelectable(flexCounter.get()); s->addSelectable(flexCounterGroup.get()); - + SWSS_LOG_NOTICE("starting main loop"); } catch(const std::exception &e) { SWSS_LOG_ERROR("Runtime error during syncd init: %s", e.what()); - + notify_OA_about_syncd_exception(); - + s = std::make_shared(); - + s->addSelectable(restartQuery.get()); - + SWSS_LOG_NOTICE("starting main loop, ONLY restart query"); - + if (options.disableExitSleep) runMainLoop = false; } - + TimerWatchdog twd(30 * 1000000); // watch for executions over 30 seconds - + twd.setCallback(timerWatchdogCallback); - + g_processFlexCounterEventThreadRun = true; - + g_processFlexCounterEventThread = std::make_shared(processFlexCounterEventThread); @@ -3988,11 +3936,11 @@ int syncd_main(int argc, char **argv) try { swss::Selectable *sel = NULL; - + int result = s->select(&sel); - + twd.setStartTime(); - + if (sel == restartQuery.get()) { /* @@ -4002,16 +3950,16 @@ int syncd_main(int argc, char **argv) * this may lead to forget populate object table which will * lead to unable to find some objects. */ - + SWSS_LOG_NOTICE("is asic queue empty: %d",asicState->empty()); - + while (!asicState->empty()) { processEvent(*asicState.get()); } - + SWSS_LOG_NOTICE("drained queue"); - + shutdownType = handleRestartQuery(*restartQuery); if (shutdownType != SYNCD_RESTART_TYPE_PRE_SHUTDOWN) { @@ -4019,54 +3967,54 @@ int syncd_main(int argc, char **argv) runMainLoop = false; break; } - + // Handle switch pre-shutdown and wait for the final shutdown // event - + SWSS_LOG_TIMER("warm pre-shutdown"); - + FlexCounter::removeAllCounters(); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_RESTART_WARM=true: %s for pre-shutdown", sai_serialize_status(status).c_str()); - + shutdownType = SYNCD_RESTART_TYPE_COLD; - + warmRestartTable->hset("warm-shutdown", "state", "set-flag-failed"); continue; } - + attr.id = SAI_SWITCH_ATTR_PRE_SHUTDOWN; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status == SAI_STATUS_SUCCESS) { warmRestartTable->hset("warm-shutdown", "state", "pre-shutdown-succeeded"); - + s = std::make_shared(); // make sure previous select is destroyed - + s->addSelectable(restartQuery.get()); - + SWSS_LOG_NOTICE("switched to PRE_SHUTDOWN, from now on accepting only shurdown requests"); } else { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_PRE_SHUTDOWN=true: %s", sai_serialize_status(status).c_str()); - + warmRestartTable->hset("warm-shutdown", "state", "pre-shutdown-failed"); - + // Restore cold shutdown. attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = false; @@ -4085,53 +4033,53 @@ int syncd_main(int argc, char **argv) { processEvent(*(swss::ConsumerTable*)sel); } - + twd.setEndTime(); } catch(const std::exception &e) { SWSS_LOG_ERROR("Runtime error: %s", e.what()); - + notify_OA_about_syncd_exception(); - + s = std::make_shared(); - + s->addSelectable(restartQuery.get()); - + if (options.disableExitSleep) runMainLoop = false; - + // make sure that if second exception will arise, then we break the loop options.disableExitSleep = true; - + twd.setEndTime(); } } - + if (shutdownType == SYNCD_RESTART_TYPE_WARM) { const char *warmBootWriteFile = profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE); - + SWSS_LOG_NOTICE("using warmBootWriteFile: '%s'", warmBootWriteFile); - + if (warmBootWriteFile == NULL) { SWSS_LOG_WARN("user requested warm shutdown but warmBootWriteFile is not specified, forcing cold shutdown"); - + shutdownType = SYNCD_RESTART_TYPE_COLD; warmRestartTable->hset("warm-shutdown", "state", "warm-shutdown-failed"); } else { SWSS_LOG_NOTICE("Warm Reboot requested, keeping data plane running"); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_RESTART_WARM=true: %s, fall back to cold restart", @@ -4141,7 +4089,7 @@ int syncd_main(int argc, char **argv) } } } - + SWSS_LOG_NOTICE("Removing the switch gSwitchId=0x%lx", gSwitchId); #ifdef SAI_SUPPORT_UNINIT_DATA_PLANE_ON_REMOVAL @@ -4149,14 +4097,14 @@ int syncd_main(int argc, char **argv) if (shutdownType == SYNCD_RESTART_TYPE_FAST || shutdownType == SYNCD_RESTART_TYPE_WARM) { SWSS_LOG_NOTICE("Fast/warm reboot requested, keeping data plane running"); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL; attr.value.booldata = false; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL=false: %s", @@ -4167,25 +4115,25 @@ int syncd_main(int argc, char **argv) #endif g_processFlexCounterEventThreadRun = false; - + g_processFlexCounterEventThread->join(); - + FlexCounter::removeAllCounters(); - + { SWSS_LOG_TIMER("remove switch"); status = sai_switch_api->remove_switch(gSwitchId); } - + // Stop notification thread after removing switch stopNotificationsProcessingThread(); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_NOTICE("Can't delete a switch. gSwitchId=0x%lx status=%s", gSwitchId, sai_serialize_status(status).c_str()); } - + if (shutdownType == SYNCD_RESTART_TYPE_WARM) { warmRestartTable->hset("warm-shutdown", "state", @@ -4193,17 +4141,17 @@ int syncd_main(int argc, char **argv) "warm-shutdown-succeeded": "warm-shutdown-failed"); } - + SWSS_LOG_NOTICE("calling api uninitialize"); - + status = sai_api_uninitialize(); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to uninitialize api: %s", sai_serialize_status(status).c_str()); } - + SWSS_LOG_NOTICE("uninitialize finished"); - + return EXIT_SUCCESS; } diff --git a/tests/aspell.en.pws b/tests/aspell.en.pws index 21b18b89e..3430c32b3 100644 --- a/tests/aspell.en.pws +++ b/tests/aspell.en.pws @@ -244,5 +244,3 @@ VXLAN workaroung xoff xon -booldata -setBuffered From 0347277bb98c31abee63f87b008dd70d457dcbab Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 19 Jul 2019 18:13:42 -0700 Subject: [PATCH 06/20] Revert "Revert "Merge remote-tracking branch 'upstream/master'"" This reverts commit 03fc996e8c530505a3ad22b23e75ef2c77ebc668. --- lib/inc/sai_redis.h | 4 + lib/inc/sairedis.h | 13 + lib/src/sai_redis_generic_create.cpp | 6 +- lib/src/sai_redis_generic_get.cpp | 2 +- lib/src/sai_redis_generic_remove.cpp | 8 +- lib/src/sai_redis_generic_set.cpp | 81 +- lib/src/sai_redis_interfacequery.cpp | 2 + lib/src/sai_redis_switch.cpp | 20 + saiplayer/saiplayer.cpp | 54 +- syncd/scripts/syncd_init_common.sh | 4 +- syncd/syncd.cpp | 1376 +++++++++++++------------- tests/aspell.en.pws | 2 + 12 files changed, 896 insertions(+), 676 deletions(-) diff --git a/lib/inc/sai_redis.h b/lib/inc/sai_redis.h index bf29a8dea..e0fd780f6 100644 --- a/lib/inc/sai_redis.h +++ b/lib/inc/sai_redis.h @@ -54,12 +54,16 @@ extern void recordLine(std::string s); extern std::string joinFieldValues( _In_ const std::vector &values); +extern sai_status_t internal_api_wait_for_response( + _In_ sai_common_api_t api); + // other global declarations extern volatile bool g_record; extern volatile bool g_useTempView; extern volatile bool g_asicInitViewMode; extern volatile bool g_logrotate; +extern volatile bool g_syncMode; extern sai_service_method_table_t g_services; extern std::shared_ptr g_asicState; diff --git a/lib/inc/sairedis.h b/lib/inc/sairedis.h index e70a03ad7..610e3952e 100644 --- a/lib/inc/sairedis.h +++ b/lib/inc/sairedis.h @@ -104,6 +104,19 @@ typedef enum _sai_redis_switch_attr_t */ SAI_REDIS_SWITCH_ATTR_PERFORM_LOG_ROTATE, + /** + * @brief Synchronous mode. + * + * Enable or disable synchronous mode. When enabled syncd also needs to be + * running in synchronous mode. Command pipeline will be disabled when this + * flag will be set to true. + * + * @type bool + * @flags CREATE_AND_SET + * @default false + */ + SAI_REDIS_SWITCH_ATTR_SYNC_MODE, + } sai_redis_switch_attr_t; /* diff --git a/lib/src/sai_redis_generic_create.cpp b/lib/src/sai_redis_generic_create.cpp index 49361c5a6..e9dbfd3d1 100644 --- a/lib/src/sai_redis_generic_create.cpp +++ b/lib/src/sai_redis_generic_create.cpp @@ -234,9 +234,7 @@ sai_status_t internal_redis_generic_create( g_asicState->set(key, entry, "create"); - // we assume create will always succeed which may not be true - // we should make this synchronous call - return SAI_STATUS_SUCCESS; + return internal_api_wait_for_response(SAI_COMMON_API_CREATE); } sai_status_t redis_generic_create( @@ -389,7 +387,7 @@ sai_status_t internal_redis_bulk_generic_create( g_asicState->set(key, entries, "bulkcreate"); } - return SAI_STATUS_SUCCESS; + return internal_api_wait_for_response(SAI_COMMON_API_CREATE); } #define REDIS_ENTRY_CREATE(OT,ot) \ diff --git a/lib/src/sai_redis_generic_get.cpp b/lib/src/sai_redis_generic_get.cpp index 0c79293dc..8eb352219 100644 --- a/lib/src/sai_redis_generic_get.cpp +++ b/lib/src/sai_redis_generic_get.cpp @@ -205,7 +205,7 @@ sai_status_t internal_redis_generic_get( const std::string &op = kfvOp(kco); const std::string &opkey = kfvKey(kco); - SWSS_LOG_DEBUG("response: op = %s, key = %s", opkey.c_str(), op.c_str()); + SWSS_LOG_INFO("response: op = %s, key = %s", opkey.c_str(), op.c_str()); if (op != "getresponse") // ignore non response messages { diff --git a/lib/src/sai_redis_generic_remove.cpp b/lib/src/sai_redis_generic_remove.cpp index 372aa2f47..d6afc1c69 100644 --- a/lib/src/sai_redis_generic_remove.cpp +++ b/lib/src/sai_redis_generic_remove.cpp @@ -21,7 +21,7 @@ sai_status_t internal_redis_generic_remove( g_asicState->del(key, "remove"); - return SAI_STATUS_SUCCESS; + return internal_api_wait_for_response(SAI_COMMON_API_REMOVE); } sai_status_t redis_generic_remove( @@ -118,10 +118,10 @@ sai_status_t internal_redis_bulk_generic_remove( } /* - * Capital 'C' stands for bulk CREATE operation. + * Capital 'R' stands for bulk CREATE operation. */ - recordLine("C|" + str_object_type + joined); + recordLine("R|" + str_object_type + joined); } // key: object_type:count @@ -134,7 +134,7 @@ sai_status_t internal_redis_bulk_generic_remove( g_asicState->set(key, entries, "bulkremove"); } - return SAI_STATUS_SUCCESS; + return internal_api_wait_for_response(SAI_COMMON_API_CREATE); } diff --git a/lib/src/sai_redis_generic_set.cpp b/lib/src/sai_redis_generic_set.cpp index 1bd7ad80e..e084d9440 100644 --- a/lib/src/sai_redis_generic_set.cpp +++ b/lib/src/sai_redis_generic_set.cpp @@ -2,6 +2,83 @@ #include "meta/sai_serialize.h" #include "meta/saiattributelist.h" +sai_status_t internal_api_wait_for_response( + _In_ sai_common_api_t api) +{ + SWSS_LOG_ENTER(); + + if (!g_syncMode) + { + /* + * By default sync mode is disabled and all create/set/remove are + * considered success operations. + */ + + return SAI_STATUS_SUCCESS; + } + + SWSS_LOG_INFO("waiting for response %d", api); + + swss::Select s; + + s.addSelectable(g_redisGetConsumer.get()); + + while (true) + { + SWSS_LOG_INFO("wait for %d api response", api); + + swss::Selectable *sel; + + // get timeout and selector is used for all quad api's + int result = s.select(&sel, GET_RESPONSE_TIMEOUT); + + if (result == swss::Select::OBJECT) + { + swss::KeyOpFieldsValuesTuple kco; + + g_redisGetConsumer->pop(kco); + + const std::string &op = kfvOp(kco); + const std::string &opkey = kfvKey(kco); + + SWSS_LOG_INFO("response: op = %s, key = %s", opkey.c_str(), op.c_str()); + + if (op != "getresponse") // ignore non response messages + { + continue; + } + + sai_status_t status; + sai_deserialize_status(opkey, status); + + if (g_record) + { + const std::string &str_status = kfvKey(kco); + const std::vector &values = kfvFieldsValues(kco); + + // first serialized is status + recordLine("G|" + str_status + "|" + joinFieldValues(values)); + } + + SWSS_LOG_DEBUG("generic %d api status: %d", api, status); + + return status; + } + + SWSS_LOG_ERROR("generic %d api failed due to SELECT operation result: %s", api, getSelectResultAsString(result).c_str()); + break; + } + + if (g_record) + { + recordLine("G|SAI_STATUS_FAILURE"); + } + + SWSS_LOG_ERROR("generic %d api failed to get response", api); + + return SAI_STATUS_FAILURE; +} + sai_status_t internal_redis_generic_set( _In_ sai_object_type_t object_type, _In_ const std::string &serialized_object_id, @@ -28,7 +105,7 @@ sai_status_t internal_redis_generic_set( g_asicState->set(key, entry, "set"); - return SAI_STATUS_SUCCESS; + return internal_api_wait_for_response(SAI_COMMON_API_SET); } sai_status_t internal_redis_bulk_generic_set( @@ -110,7 +187,7 @@ sai_status_t internal_redis_bulk_generic_set( g_asicState->set(key, entries, "bulkset"); } - return SAI_STATUS_SUCCESS; + return internal_api_wait_for_response(SAI_COMMON_API_CREATE); } diff --git a/lib/src/sai_redis_interfacequery.cpp b/lib/src/sai_redis_interfacequery.cpp index 16fb96acc..8a9761f06 100644 --- a/lib/src/sai_redis_interfacequery.cpp +++ b/lib/src/sai_redis_interfacequery.cpp @@ -124,6 +124,8 @@ sai_status_t sai_api_initialize( g_redisNotifications = std::make_shared(g_dbNtf.get(), "NOTIFICATIONS"); g_redisClient = std::make_shared(g_db.get()); + g_asicState->setBuffered(false); // in sync mode, always false + clear_local_state(); g_asicInitViewMode = false; diff --git a/lib/src/sai_redis_switch.cpp b/lib/src/sai_redis_switch.cpp index f664232d2..36248ccc7 100644 --- a/lib/src/sai_redis_switch.cpp +++ b/lib/src/sai_redis_switch.cpp @@ -7,6 +7,7 @@ volatile bool g_asicInitViewMode = false; // default mode is apply mode volatile bool g_useTempView = false; +volatile bool g_syncMode = false; sai_status_t sai_redis_internal_notify_syncd( _In_ const std::string& key) @@ -266,7 +267,26 @@ sai_status_t redis_set_switch_attribute( g_useTempView = attr->value.booldata; return SAI_STATUS_SUCCESS; + case SAI_REDIS_SWITCH_ATTR_SYNC_MODE: + + g_syncMode = attr->value.booldata; + + if (g_syncMode) + { + SWSS_LOG_NOTICE("disabling buffered pipeline in sync mode"); + g_asicState->setBuffered(false); + } + + return SAI_STATUS_SUCCESS; + case SAI_REDIS_SWITCH_ATTR_USE_PIPELINE: + + if (g_syncMode) + { + SWSS_LOG_WARN("use pipeline is not supported in sync mode"); + return SAI_STATUS_NOT_SUPPORTED; + } + g_asicState->setBuffered(attr->value.booldata); return SAI_STATUS_SUCCESS; diff --git a/saiplayer/saiplayer.cpp b/saiplayer/saiplayer.cpp index a15bab185..0eb1f6235 100644 --- a/saiplayer/saiplayer.cpp +++ b/saiplayer/saiplayer.cpp @@ -964,6 +964,54 @@ sai_status_t handle_bulk_route( return status; } + else if (api == (sai_common_api_t)SAI_COMMON_API_BULK_CREATE) + { + std::vector attr_count; + + std::vector attr_list; + + // route can have multiple attributes, so we need to handle them all + for (const auto &alist: attributes) + { + attr_list.push_back(alist->get_attr_list()); + attr_count.push_back(alist->get_attr_count()); + } + + SWSS_LOG_NOTICE("executing BULK route create with %zu routes", attr_count.size()); + + sai_status_t status = sai_bulk_create_route_entry( + (uint32_t)routes.size(), + routes.data(), + attr_count.data(), + attr_list.data(), + SAI_BULK_OP_ERROR_MODE_IGNORE_ERROR, // TODO we need to get that from recording + statuses.data()); + + if (status != SAI_STATUS_SUCCESS) + { + // Entire API fails, so no need to compare statuses. + return status; + } + + for (size_t i = 0; i < statuses.size(); ++i) + { + if (statuses[i] != recorded_statuses[i]) + { + /* + * If recorded statuses are different than received, throw + * exception since data don't match. + */ + + SWSS_LOG_THROW("recorded status is %s but returned is %s on %s", + sai_serialize_status(recorded_statuses[i]).c_str(), + sai_serialize_status(statuses[i]).c_str(), + object_ids[i].c_str()); + } + } + + return status; + + } else { SWSS_LOG_THROW("api %d is not supported in bulk route", api); @@ -981,7 +1029,8 @@ void processBulk( return; } - if (api != (sai_common_api_t)SAI_COMMON_API_BULK_SET) + if (api != (sai_common_api_t)SAI_COMMON_API_BULK_SET && + api != (sai_common_api_t)SAI_COMMON_API_BULK_CREATE) { SWSS_LOG_THROW("bulk common api %d is not supported yet, FIXME", api); } @@ -1154,6 +1203,9 @@ int replay(int argc, char **argv) case 'S': processBulk((sai_common_api_t)SAI_COMMON_API_BULK_SET, line); continue; + case 'C': + processBulk((sai_common_api_t)SAI_COMMON_API_BULK_CREATE, line); + continue; case 'g': api = SAI_COMMON_API_GET; break; diff --git a/syncd/scripts/syncd_init_common.sh b/syncd/scripts/syncd_init_common.sh index 7c808446f..ad568bb5c 100755 --- a/syncd/scripts/syncd_init_common.sh +++ b/syncd/scripts/syncd_init_common.sh @@ -59,9 +59,9 @@ function set_start_type() { if [ x"$WARM_BOOT" == x"true" ]; then CMD_ARGS+=" -t warm" - elif [ $FAST_REBOOT == "yes" ]; then + elif [ x"$FAST_REBOOT" == x"yes" ]; then CMD_ARGS+=" -t fast" - elif [ $FASTFAST_REBOOT == "yes" ]; then + elif [ x"$FASTFAST_REBOOT" == x"yes" ]; then CMD_ARGS+=" -t fastfast" fi } diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 096cdb493..991b96486 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -103,6 +103,7 @@ struct cmdOptions bool run_rpc_server; std::string portMapFile; #endif // SAITHRIFT + bool syncMode; ~cmdOptions() {} }; @@ -133,11 +134,11 @@ void notify_OA_about_syncd_exception() if (notifications != NULL) { std::vector entry; - + SWSS_LOG_NOTICE("sending switch_shutdown_request notification to OA"); - + notifications->send("switch_shutdown_request", "", entry); - + SWSS_LOG_NOTICE("notification send successfull"); } } @@ -157,27 +158,27 @@ void sai_diag_shell( SWSS_LOG_ENTER(); sai_status_t status; - + /* * This is currently blocking API on broadcom, it will block until we exit * shell. */ - + while (true) { sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_SWITCH_SHELL_ENABLE; attr.value.booldata = true; - + status = sai_metadata_sai_switch_api->set_switch_attribute(switch_id, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to enable switch shell: %s", sai_serialize_status(status).c_str()); return; } - + sleep(1); } } @@ -214,14 +215,14 @@ sai_object_type_t redis_sai_object_type_query( { return SAI_OBJECT_TYPE_NULL; } - + sai_object_type_t ot = (sai_object_type_t)((object_id >> OT_POSITION) & 0xFF); - + if (!sai_metadata_is_object_type_valid(ot)) { SWSS_LOG_THROW("invalid object id 0x%lx", object_id); } - + return ot; } @@ -231,12 +232,12 @@ int redis_get_switch_id_index( SWSS_LOG_ENTER(); sai_object_type_t switch_object_type = redis_sai_object_type_query(switch_id); - + if (switch_object_type == SAI_OBJECT_TYPE_SWITCH) { return (int)((switch_id >> SWID_POSITION) & 0xFF); } - + SWSS_LOG_THROW("object type of switch %s is %s, should be SWITCH", sai_serialize_object_id(switch_id).c_str(), sai_serialize_object_type(switch_object_type).c_str()); @@ -251,30 +252,30 @@ sai_object_id_t redis_sai_switch_id_query( { return oid; } - + sai_object_type_t object_type = redis_sai_object_type_query(oid); - + if (object_type == SAI_OBJECT_TYPE_NULL) { SWSS_LOG_THROW("invalid object type of oid 0x%lx", oid); } - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { return oid; } - + /* * Each VID contains switch index at constant position. * * We extract this index from VID and we create switch ID (VID) for * specific object. We can do this for each object. */ - + int sw_index = (int)((oid >> SWID_POSITION) & 0xFF); - + sai_object_id_t switch_id = redis_construct_object_id(SAI_OBJECT_TYPE_SWITCH, sw_index, sw_index); - + return switch_id; } @@ -287,38 +288,38 @@ sai_object_id_t redis_create_virtual_object_id( /* * NOTE: switch ID is VID switch ID from sairedis. */ - + /* * Check if object type is in valid range. */ - + if (!sai_metadata_is_object_type_valid(object_type)) { SWSS_LOG_THROW("invalid object type: %s", sai_serialize_object_type(object_type).c_str()); } - + /* * Switch id is deterministic and it comes from sairedis so make check here * that we will not use this for creating switch VIDs. */ - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { SWSS_LOG_THROW("this function should not be used to create VID for switch id"); } - + uint64_t virtual_id = g_redisClient->incr(VIDCOUNTER); - + int switch_index = redis_get_switch_id_index(switch_id); - + sai_object_id_t vid = redis_construct_object_id(object_type, switch_index, virtual_id); - + auto info = sai_metadata_get_object_type_info(object_type); - + SWSS_LOG_DEBUG("created virtual object id 0x%lx for object type %s", vid, info->objecttypename); - + return vid; } @@ -389,11 +390,11 @@ sai_object_id_t translate_rid_to_vid( */ std::string str_vid = *pvid; - + sai_deserialize_object_id(str_vid, vid); - + SWSS_LOG_DEBUG("translated RID 0x%lx to VID 0x%lx", rid, vid); - + return vid; } @@ -502,60 +503,60 @@ void translate_rid_to_vid_list( sai_attribute_t &attr = attr_list[i]; auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %x, attribute %d", object_type, attr.id); } - + /* * TODO: Many times we do switch for list of attributes to perform some * operation on each oid from that attribute, we should provide clever * way via sai metadata utils to get that. */ - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: attr.value.oid = translate_rid_to_vid(attr.value.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: translate_list_rid_to_vid(attr.value.objlist, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) attr.value.aclfield.data.oid = translate_rid_to_vid(attr.value.aclfield.data.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) translate_list_rid_to_vid(attr.value.aclfield.data.objlist, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) attr.value.aclaction.parameter.oid = translate_rid_to_vid(attr.value.aclaction.parameter.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) translate_list_rid_to_vid(attr.value.aclaction.parameter.objlist, switch_id); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } } @@ -575,23 +576,23 @@ sai_object_id_t translate_vid_to_rid( if (vid == SAI_NULL_OBJECT_ID) { SWSS_LOG_DEBUG("translated VID null to RID null"); - + return SAI_NULL_OBJECT_ID; } - + auto it = local_vid_to_rid.find(vid); - + if (it != local_vid_to_rid.end()) { return it->second; } - + std::string str_vid = sai_serialize_object_id(vid); - + std::string str_rid; - + auto prid = g_redisClient->hget(VIDTORID, str_vid); - + if (prid == NULL) { if (isInitViewMode()) @@ -608,28 +609,28 @@ sai_object_id_t translate_vid_to_rid( * like buffer limitations etc, mostly probably this will happen on * SWITCH object. */ - + SWSS_LOG_THROW("can't get RID in init view mode - don't query created objects"); } - + SWSS_LOG_THROW("unable to get RID for VID: 0x%lx", vid); } - + str_rid = *prid; - + sai_object_id_t rid; - + sai_deserialize_object_id(str_rid, rid); - + /* * We got this RID from redis db, so put it also to local db so it will be * faster to retrieve it late on. */ - + local_vid_to_rid[vid] = rid; - + SWSS_LOG_DEBUG("translated VID 0x%lx to RID 0x%lx", vid, rid); - + return rid; } @@ -673,60 +674,60 @@ void translate_vid_to_rid_list( * All id's received from sairedis should be virtual, so lets translate * them to real id's before we execute actual api. */ - + for (uint32_t i = 0; i < attr_count; i++) { sai_attribute_t &attr = attr_list[i]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %x, attribute %d", object_type, attr.id); } - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: attr.value.oid = translate_vid_to_rid(attr.value.oid); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: translate_list_vid_to_rid(attr.value.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) attr.value.aclfield.data.oid = translate_vid_to_rid(attr.value.aclfield.data.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) translate_list_vid_to_rid(attr.value.aclfield.data.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) attr.value.aclaction.parameter.oid = translate_vid_to_rid(attr.value.aclaction.parameter.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) translate_list_vid_to_rid(attr.value.aclaction.parameter.objlist); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } } @@ -744,18 +745,18 @@ void snoop_get_attr( * Note: str_object_type + ":" + str_object_id is meta_key we can us that * here later on. */ - + std::string str_object_type = sai_serialize_object_type(object_type); - + std::string prefix = ""; - + if (isInitViewMode()) { prefix = TEMP_PREFIX; } - + std::string key = prefix + (ASIC_STATE_TABLE + (":" + str_object_type + ":" + str_object_id)); - + SWSS_LOG_DEBUG("%s", key.c_str()); @@ -772,20 +773,20 @@ void snoop_get_oid( /* * If snooped oid is NULL then we don't need take any action. */ - + return; } - + /* * We need use redis version of object type query here since we are * operating on VID value, and syncd is compiled against real SAI * implementation which has different function sai_object_type_query. */ - + sai_object_type_t object_type = redis_sai_object_type_query(vid); - + std::string str_vid = sai_serialize_object_id(vid); - + snoop_get_attr(object_type, str_vid, "NULL", "NULL"); } @@ -808,9 +809,9 @@ void snoop_get_attr_value( SWSS_LOG_ENTER(); std::string value = sai_serialize_attr_value(*meta, attr); - + SWSS_LOG_DEBUG("%s:%s", meta->attridname, value.c_str()); - + snoop_get_attr(meta->objecttype, str_object_id, meta->attridname, value); } @@ -826,94 +827,94 @@ void snoop_get_response( * NOTE: this method is operating on VIDs, all RIDs were translated outside * this method. */ - + /* * Vlan (including vlan 1) will need to be put into TEMP view this should * also be valid for all objects that were queried. */ - + for (uint32_t idx = 0; idx < attr_count; ++idx) { const sai_attribute_t &attr = attr_list[idx]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %d, attribute %d", object_type, attr.id); } - + /* * We should snoop oid values even if they are readonly we just note in * temp view that those objects exist on switch. */ - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: snoop_get_oid(attr.value.oid); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: snoop_get_oid_list(attr.value.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) snoop_get_oid(attr.value.aclfield.data.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) snoop_get_oid_list(attr.value.aclfield.data.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) snoop_get_oid(attr.value.aclaction.parameter.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) snoop_get_oid_list(attr.value.aclaction.parameter.objlist); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } - + if (SAI_HAS_FLAG_READ_ONLY(meta->flags)) { /* * If value is read only, we skip it, since after syncd restart we * won't be able to set/create it anyway. */ - + continue; } - + if (meta->objecttype == SAI_OBJECT_TYPE_PORT && meta->attrid == SAI_PORT_ATTR_HW_LANE_LIST) { /* * Skip port lanes for now since we don't create ports. */ - + SWSS_LOG_INFO("skipping %s for %s", meta->attridname, str_object_id.c_str()); continue; } - + /* * Put non readonly, and non oid attribute value to temp view. * @@ -923,7 +924,7 @@ void snoop_get_response( * Similar action can happen when we will do this on asicSet during * apply view. */ - + snoop_get_attr_value(str_object_id, meta, attr); } } @@ -939,25 +940,25 @@ void internal_syncd_get_send( SWSS_LOG_ENTER(); std::vector entry; - + if (status == SAI_STATUS_SUCCESS) { translate_rid_to_vid_list(object_type, switch_id, attr_count, attr_list); - + /* * Normal serialization + translate RID to VID. */ - + entry = SaiAttributeList::serialize_attr_list( object_type, attr_count, attr_list, false); - + /* * All oid values here are VIDs. */ - + snoop_get_response(object_type, str_object_id, attr_count, attr_list); } else if (status == SAI_STATUS_BUFFER_OVERFLOW) @@ -971,7 +972,7 @@ void internal_syncd_get_send( * different attributes can have different lists, many of them may * serialize only count, and will need to support that on the receiver. */ - + entry = SaiAttributeList::serialize_attr_list( object_type, attr_count, @@ -984,27 +985,54 @@ void internal_syncd_get_send( * Some other error, don't send attributes at all. */ } - + for (const auto &e: entry) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(e).c_str(), fvValue(e).c_str()); } - + std::string str_status = sai_serialize_status(status); - + SWSS_LOG_INFO("sending response for GET api with status: %s", str_status.c_str()); - + /* * Since we have only one get at a time, we don't have to serialize object * type and object id, only get status is required to be returned. Get * response will not put any data to table, only queue is used. */ - + getResponse->set(str_status, entry, "getresponse"); - + SWSS_LOG_INFO("response for GET api was send"); } +void internal_syncd_api_send_response( + _In_ sai_common_api_t api, + _In_ sai_status_t status) +{ + SWSS_LOG_ENTER(); + + /* + * By default synchronous mode is disabled and can be enabled by command + * line on syncd start. This will also require to enable synchronous mode + * in OA/sairedis because same GET RESPONSE channel is used to generate + * response for sairedis quad API. + */ + + if (!options.syncMode) + return; + + std::vector entry; + + std::string str_status = sai_serialize_status(status); + + SWSS_LOG_INFO("sending response for %d api with status: %s", api, str_status.c_str()); + + getResponse->set(str_status, entry, "getresponse"); + + SWSS_LOG_INFO("response for %d api was send", api); +} + const char* profile_get_value( _In_ sai_switch_profile_id_t profile_id, _In_ const char* variable) @@ -1016,17 +1044,17 @@ const char* profile_get_value( SWSS_LOG_WARN("variable is null"); return NULL; } - + auto it = gProfileMap.find(variable); - + if (it == gProfileMap.end()) { SWSS_LOG_NOTICE("%s: NULL", variable); return NULL; } - + SWSS_LOG_NOTICE("%s: %s", variable, it->second.c_str()); - + return it->second.c_str(); } @@ -1042,30 +1070,30 @@ int profile_get_next_value( if (value == NULL) { SWSS_LOG_INFO("resetting profile map iterator"); - + gProfileIter = gProfileMap.begin(); return 0; } - + if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return -1; } - + if (gProfileIter == gProfileMap.end()) { SWSS_LOG_INFO("iterator reached end"); return -1; } - + *variable = gProfileIter->first.c_str(); *value = gProfileIter->second.c_str(); - + SWSS_LOG_INFO("key: %s:%s", *variable, *value); - + gProfileIter++; - + return 0; } @@ -1081,13 +1109,13 @@ void startDiagShell() if (options.diagShell) { SWSS_LOG_NOTICE("starting diag shell thread"); - + /* * TODO actual switch id must be supplied */ - + std::thread diag_shell_thread = std::thread(sai_diag_shell, SAI_NULL_OBJECT_ID); - + diag_shell_thread.detach(); } } @@ -1098,19 +1126,19 @@ void on_switch_create( SWSS_LOG_ENTER(); sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid); - + if (switches.size() > 0) { SWSS_LOG_THROW("creating multiple switches is not supported yet, FIXME"); } - + /* * All needed data to populate switch should be obtained inside SaiSwitch * constructor, like getting all queues, ports, etc. */ - + switches[switch_vid] = std::make_shared(switch_vid, switch_rid); - + startDiagShell(); } @@ -1133,7 +1161,7 @@ void on_switch_remove( * * To support multiple switches this function needs to be refactored. */ - + SWSS_LOG_THROW("remove switch is not implemented, FIXME"); } @@ -1187,52 +1215,52 @@ sai_status_t handle_generic( * TODO: Could deserialize to meta key and then we could combine with non * object id. */ - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + SWSS_LOG_DEBUG("calling %s for %s", sai_serialize_common_api(api).c_str(), sai_serialize_object_type(object_type).c_str()); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = object_id; - + /* * We need to do translate vid/rid except for create, since create will * create new RID value, and we will have to map them to VID we received in * create query. */ - + /* * TODO: use metadata utils. */ - + auto info = sai_metadata_get_object_type_info(object_type); - + if (info->isnonobjectid) { SWSS_LOG_THROW("passing non object id %s as generic object", info->objecttypename); } - + switch (api) { case SAI_COMMON_API_CREATE: - + { /* * Object id is VID, we can use it to extract switch id. */ - + sai_object_id_t switch_id = redis_sai_switch_id_query(object_id); - + if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_THROW("invalid switch_id translated from VID 0x%lx", object_id); } - + if (object_type != SAI_OBJECT_TYPE_SWITCH) { /* @@ -1241,7 +1269,7 @@ sai_status_t handle_generic( * since rid doesn't exist yet, so skip translate for switch, * but use translate for all other objects. */ - + switch_id = translate_vid_to_rid(switch_id); } else @@ -1252,41 +1280,41 @@ sai_status_t handle_generic( * NOTE: to support multiple switches we need support * here for create. */ - + SWSS_LOG_THROW("creating multiple switches is not supported yet, FIXME"); } } - + sai_status_t status = info->create(&meta_key, switch_id, attr_count, attr_list); - + if (status == SAI_STATUS_SUCCESS) { sai_object_id_t real_object_id = meta_key.objectkey.key.object_id; - + /* * Object was created so new object id was generated we * need to save virtual id's to redis db. */ - + std::string str_vid = sai_serialize_object_id(object_id); std::string str_rid = sai_serialize_object_id(real_object_id); - + /* * TODO: This must be ATOMIC. * * To support multiple switches vid/rid map must be per switch. */ - + { - + g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); - + save_rid_and_vid_to_local(real_object_id, object_id); } - + SWSS_LOG_INFO("saved VID %s to RID %s", str_vid.c_str(), str_rid.c_str()); - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_create(switch_id); @@ -1294,36 +1322,36 @@ sai_status_t handle_generic( SWSS_LOG_NOTICE("Initialize gSwitchId with ID = 0x%lx", gSwitchId); } } - + return status; } - + case SAI_COMMON_API_REMOVE: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + sai_status_t status = info->remove(&meta_key); - + if (status == SAI_STATUS_SUCCESS) { std::string str_vid = sai_serialize_object_id(object_id); std::string str_rid = sai_serialize_object_id(rid); - + /* * TODO: This must be ATOMIC. */ - + { - + g_redisClient->hdel(VIDTORID, str_vid); g_redisClient->hdel(RIDTOVID, str_rid); - + remove_rid_and_vid_from_local(rid, object_id); } - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_remove(object_id); @@ -1351,48 +1379,48 @@ sai_status_t handle_generic( * also needs to be of internal/vendor default but we * can already deduce that. */ - + sai_object_id_t switch_vid = redis_sai_switch_id_query(object_id); - + if (switches.at(switch_vid)->isDiscoveredRid(rid)) { switches.at(switch_vid)->removeExistingObjectReference(rid); } } } - + return status; } - + case SAI_COMMON_API_SET: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + sai_status_t status = info->set(&meta_key, attr_list); - + if (is_set_attribute_workaround(meta_key.objecttype, attr_list->id, status)) { return SAI_STATUS_SUCCESS; } - + return status; } - + case SAI_COMMON_API_GET: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + return info->get(&meta_key, attr_count, attr_list); } - + default: - + SWSS_LOG_THROW("common api (%s) is not implemented", sai_serialize_common_api(api).c_str()); } } @@ -1403,25 +1431,25 @@ void translate_vid_to_rid_non_object_id( SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(meta_key.objecttype); - + if (info->isobjectid) { meta_key.objectkey.key.object_id = translate_vid_to_rid(meta_key.objectkey.key.object_id); - + return; } - + for (size_t j = 0; j < info->structmemberscount; ++j) { const sai_struct_member_info_t *m = info->structmembers[j]; - + if (m->membervaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID) { sai_object_id_t vid = m->getoid(&meta_key); - + sai_object_id_t rid = translate_vid_to_rid(vid); - + m->setoid(&meta_key, rid); } } @@ -1436,23 +1464,23 @@ sai_status_t handle_non_object_id( SWSS_LOG_ENTER(); translate_vid_to_rid_non_object_id(meta_key); - + auto info = sai_metadata_get_object_type_info(meta_key.objecttype); - + switch (api) { case SAI_COMMON_API_CREATE: return info->create(&meta_key, SAI_NULL_OBJECT_ID, attr_count, attr_list); - + case SAI_COMMON_API_REMOVE: return info->remove(&meta_key); - + case SAI_COMMON_API_SET: return info->set(&meta_key, attr_list); - + case SAI_COMMON_API_GET: return info->get(&meta_key, attr_count, attr_list); - + default: SWSS_LOG_THROW("other apis not implemented"); } @@ -1464,11 +1492,11 @@ void sendNotifyResponse( SWSS_LOG_ENTER(); std::string str_status = sai_serialize_status(status); - + std::vector entry; - - SWSS_LOG_NOTICE("sending response: %s", str_status.c_str()); - + + SWSS_LOG_INFO("sending response: %s", str_status.c_str()); + getResponse->set(str_status, entry, "notify"); } @@ -1477,11 +1505,11 @@ void clearTempView() SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("clearing current TEMP VIEW"); - + SWSS_LOG_TIMER("clear temp view"); - + std::string pattern = TEMP_PREFIX + (ASIC_STATE_TABLE + std::string(":*")); - + /* * TODO this must be ATOMIC, and could use lua script. * @@ -1493,11 +1521,11 @@ void clearTempView() { g_redisClient->del(key); } - + /* * Also clear list of objects removed in init view mode. */ - + initViewRemovedVidSet.clear(); } @@ -1525,10 +1553,10 @@ void InspectAsic() } auto str_object_type = key.substr(start + 1, mid - start - 1); auto str_object_id = key.substr(mid + 1); - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + // Find all the attrid from ASIC DB, and use them to query ASIC auto hash = g_redisClient->hgetall(key); std::vector values; @@ -1536,28 +1564,28 @@ void InspectAsic() { const std::string &skey = kv.first; const std::string &svalue = kv.second; - + swss::FieldValueTuple fvt(skey, svalue); - + values.push_back(fvt); } - + SaiAttributeList list(object_type, values, false); - + sai_attribute_t *attr_list = list.get_attr_list(); - + uint32_t attr_count = list.get_attr_count(); - + SWSS_LOG_DEBUG("attr count: %u", list.get_attr_count()); - + if (attr_count == 0) { // TODO: how to check ASIC on ASIC DB key with NULL:NULL hash continue; // Just ignore } - + auto info = sai_metadata_get_object_type_info(object_type); - + // Call SAI Get API on this key sai_status_t status; switch (object_type) @@ -1566,38 +1594,38 @@ void InspectAsic() { sai_fdb_entry_t fdb_entry; sai_deserialize_fdb_entry(str_object_id, fdb_entry); - + fdb_entry.switch_id = translate_vid_to_rid(fdb_entry.switch_id); fdb_entry.bv_id = translate_vid_to_rid(fdb_entry.bv_id); - + status = sai_metadata_sai_fdb_api->get_fdb_entry_attribute(&fdb_entry, attr_count, attr_list); break; } - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: { sai_neighbor_entry_t neighbor_entry; sai_deserialize_neighbor_entry(str_object_id, neighbor_entry); - + neighbor_entry.switch_id = translate_vid_to_rid(neighbor_entry.switch_id); neighbor_entry.rif_id = translate_vid_to_rid(neighbor_entry.rif_id); - + status = sai_metadata_sai_neighbor_api->get_neighbor_entry_attribute(&neighbor_entry, attr_count, attr_list); break; } - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: { sai_route_entry_t route_entry; sai_deserialize_route_entry(str_object_id, route_entry); - + route_entry.switch_id = translate_vid_to_rid(route_entry.switch_id); route_entry.vr_id = translate_vid_to_rid(route_entry.vr_id); - + status = sai_metadata_sai_route_api->get_route_entry_attribute(&route_entry, attr_count, attr_list); break; } - + default: { if (info->isnonobjectid) @@ -1606,20 +1634,20 @@ void InspectAsic() sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); } - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = translate_vid_to_rid(object_id); - + status = info->get(&meta_key, attr_count, attr_list); break; } } - + if (status == SAI_STATUS_NOT_IMPLEMENTED) { SWSS_LOG_ERROR("not implemented get api: %s", str_object_type.c_str()); @@ -1628,25 +1656,25 @@ void InspectAsic() { SWSS_LOG_ERROR("failed to execute get api: %s", sai_serialize_status(status).c_str()); } - + // Compare fields and values from ASIC_DB and SAI response // Log the difference for (uint32_t index = 0; index < attr_count; ++index) { const sai_attribute_t *attr = &attr_list[index]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr->id); - + if (meta == NULL) { SWSS_LOG_ERROR("FATAL: failed to find metadata for object type %d and attr id %d", object_type, attr->id); break; } - + std::string str_attr_id = sai_serialize_attr_id(*meta); - + std::string str_attr_value = sai_serialize_attr_value(*meta, *attr, false); - + std::string hash_attr_value = hash[str_attr_id]; if (hash_attr_value == str_attr_value) { @@ -1666,19 +1694,19 @@ sai_status_t onApplyViewInFastFastBoot() sai_switch_api_t* sai_switch_api = nullptr; sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_FAST_API_ENABLE; attr.value.booldata = false; - + sai_status_t status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_FAST_API_ENABLE=false: %s", sai_serialize_status(status).c_str()); } - + return status; } @@ -1690,14 +1718,14 @@ sai_status_t notifySyncd( if (!options.useTempView) { SWSS_LOG_NOTICE("received %s, ignored since TEMP VIEW is not used, returning success", op.c_str()); - + sendNotifyResponse(SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; } - + static bool firstInitWasPerformed = false; - + if (g_veryFirstRun && firstInitWasPerformed && op == SYNCD_INIT_VIEW) { /* @@ -1706,95 +1734,95 @@ sai_status_t notifySyncd( * already exists and will fail with creating multiple switches * error. */ - + g_veryFirstRun = false; } else if (g_veryFirstRun) { SWSS_LOG_NOTICE("very first run is TRUE, op = %s", op.c_str()); - + sai_status_t status = SAI_STATUS_SUCCESS; - + /* * On the very first start of syncd, "compile" view is directly applied * on device, since it will make it easier to switch to new asic state * later on when we restart orch agent. */ - + if (op == SYNCD_INIT_VIEW) { /* * On first start we just do "apply" directly on asic so we set * init to false instead of true. */ - + g_asicInitViewMode = false; - + firstInitWasPerformed = true; - + /* * We need to clear current temp view to make space for new one. */ - + clearTempView(); } else if (op == SYNCD_APPLY_VIEW) { g_veryFirstRun = false; - + g_asicInitViewMode = false; - + if (options.startType == SAI_FASTFAST_BOOT) { /* fastfast boot configuration end */ status = onApplyViewInFastFastBoot(); } - + SWSS_LOG_NOTICE("setting very first run to FALSE, op = %s", op.c_str()); } else { SWSS_LOG_THROW("unknown operation: %s", op.c_str()); } - + sendNotifyResponse(status); - + return status; } - + if (op == SYNCD_INIT_VIEW) { if (g_asicInitViewMode) { SWSS_LOG_WARN("syncd is already in asic INIT VIEW mode, but received init again, orchagent restarted before apply?"); } - + g_asicInitViewMode = true; - + clearTempView(); - + /* * TODO: Currently as WARN to be easier to spot, later should be NOTICE. */ - + SWSS_LOG_WARN("syncd switched to INIT VIEW mode, all op will be saved to TEMP view"); - + sendNotifyResponse(SAI_STATUS_SUCCESS); } else if (op == SYNCD_APPLY_VIEW) { g_asicInitViewMode = false; - + /* * TODO: Currently as WARN to be easier to spot, later should be NOTICE. */ - + SWSS_LOG_WARN("syncd received APPLY VIEW, will translate"); - + sai_status_t status = syncdApplyView(); - + sendNotifyResponse(status); - + if (status == SAI_STATUS_SUCCESS) { /* @@ -1802,7 +1830,7 @@ sai_status_t notifySyncd( * need to clear local db, and all new VIDs will be queried using * redis. */ - + local_rid_to_vid.clear(); local_vid_to_rid.clear(); } @@ -1813,27 +1841,27 @@ sai_status_t notifySyncd( * executed, on asic, or asic is inconsistent state then we should * die or hang */ - + return status; } } else if (op == SYNCD_INSPECT_ASIC) { SWSS_LOG_NOTICE("syncd switched to INSPECT ASIC mode"); - + InspectAsic(); - + sendNotifyResponse(SAI_STATUS_SUCCESS); } else { SWSS_LOG_ERROR("unknown operation: %s", op.c_str()); - + sendNotifyResponse(SAI_STATUS_NOT_IMPLEMENTED); - + SWSS_LOG_THROW("notify syncd %s operation failed", op.c_str()); } - + return SAI_STATUS_SUCCESS; } @@ -1851,10 +1879,10 @@ std::vector extractCounterIdsGeneric( std::string field = fvField(v); T counterId; deserializeIdFn(field.c_str(), &counterId); - + counterIdList.push_back(counterId); } - + return counterIdList; } @@ -1872,7 +1900,7 @@ sai_status_t getStatsGeneric( kco, deserializeIdFn); counters.resize(counter_ids.size()); - + return getStatsFn( object_id, (uint32_t)counter_ids.size(), @@ -1892,7 +1920,7 @@ sai_status_t clearStatsGeneric( const std::vector counter_ids = extractCounterIdsGeneric( kco, deserializeIdFn); - + return clearStatsFn( object_id, static_cast(counter_ids.size()), @@ -1907,17 +1935,17 @@ sai_status_t processGetStatsEvent( const std::string &key = kfvKey(kco); const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_id_t rid = translate_vid_to_rid(object_id); sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + std::vector result; - + sai_status_t status = SAI_STATUS_SUCCESS; - + switch (object_type) { case SAI_OBJECT_TYPE_PORT: @@ -1948,9 +1976,9 @@ sai_status_t processGetStatsEvent( SWSS_LOG_ERROR("SAI object type %s not supported", str_object_type.c_str()); status = SAI_STATUS_NOT_SUPPORTED; } - + std::vector entry; - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to get stats"); @@ -1963,9 +1991,9 @@ sai_status_t processGetStatsEvent( entry.emplace_back(fvField(values[i]), std::to_string(result[i])); } } - + getResponse->set(sai_serialize_status(status), entry, "getresponse"); - + return status; } @@ -1977,7 +2005,7 @@ sai_status_t processClearStatsEvent( const std::string &key = kfvKey(kco); const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_id_t rid; @@ -1990,7 +2018,7 @@ sai_status_t processClearStatsEvent( getResponse->set(sai_serialize_status(status), fvTuples, "getresponse"); return status; } - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); switch (object_type) @@ -2006,7 +2034,7 @@ sai_status_t processClearStatsEvent( SWSS_LOG_ERROR("SAI object type %s not supported", str_object_type.c_str()); status = SAI_STATUS_NOT_SUPPORTED; } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to clear stats"); @@ -2018,7 +2046,7 @@ sai_status_t processClearStatsEvent( fvTuples.emplace_back(fvField(fv), ""); } } - + getResponse->set(sai_serialize_status(status), fvTuples, "getresponse"); return status; } @@ -2033,7 +2061,7 @@ void on_switch_create_in_init_view( /* * This needs to be refactored if we need multiple switch support. */ - + /* * We can have multiple switches here, but each switch is identified by * SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO. This attribute is treated as key, @@ -2058,7 +2086,7 @@ void on_switch_create_in_init_view( * Since we are creating switch here, we are sure that this switch don't * have any oid attributes set, so we can pass all attributes */ - + /* * Multiple switches scenario with changed order: * @@ -2072,7 +2100,7 @@ void on_switch_create_in_init_view( * * Currently we don't have good solution for that so we will throw in that case. */ - + if (switches.size() == 0) { /* @@ -2084,16 +2112,16 @@ void on_switch_create_in_init_view( * This scenario can happen when you start syncd on empty database and * then you quit and restart it again. */ - + sai_object_id_t switch_rid; - + sai_status_t status; - + { SWSS_LOG_TIMER("cold boot: create switch"); status = sai_metadata_sai_switch_api->create_switch(&switch_rid, attr_count, attr_list); } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to create switch in init view mode: %s", @@ -2109,27 +2137,27 @@ void on_switch_create_in_init_view( * Object was created so new object id was generated we * need to save virtual id's to redis db. */ - + std::string str_vid = sai_serialize_object_id(switch_vid); std::string str_rid = sai_serialize_object_id(switch_rid); - + SWSS_LOG_NOTICE("created real switch VID %s to RID %s in init view mode", str_vid.c_str(), str_rid.c_str()); - + /* * TODO: This must be ATOMIC. * * To support multiple switches vid/rid map must be per switch. */ - + g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); - + save_rid_and_vid_to_local(switch_rid, switch_vid); - + /* * Make switch initialization and get all default data. */ - + switches[switch_vid] = std::make_shared(switch_vid, switch_rid); } else if (switches.size() == 1) @@ -2139,29 +2167,29 @@ void on_switch_create_in_init_view( * info and we need to know that current switch VID also should match * since it's deterministic created. */ - + auto sw = switches.begin()->second; - + /* * Switches VID must match, since it's deterministic. */ - + if (switch_vid != sw->getVid()) { SWSS_LOG_THROW("created switch VID don't match: previous %s, current: %s", sai_serialize_object_id(switch_vid).c_str(), sai_serialize_object_id(sw->getVid()).c_str()); } - + /* * Also hardware info also must match. */ - + std::string currentHw = sw->getHardwareInfo(); std::string newHw; - + auto attr = sai_metadata_get_attr_by_id(SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO, attr_count, attr_list); - + if (attr == NULL) { /* @@ -2171,15 +2199,15 @@ void on_switch_create_in_init_view( else { SWSS_LOG_DEBUG("new switch contains hardware info of length %u", attr->value.s8list.count); - + newHw = std::string((char*)attr->value.s8list.list, attr->value.s8list.count); } - + if (currentHw != newHw) { SWSS_LOG_THROW("hardware info missmatch: current '%s' vs new '%s'", currentHw.c_str(), newHw.c_str()); } - + SWSS_LOG_NOTICE("current switch hardware info: '%s'", currentHw.c_str()); } else @@ -2203,17 +2231,17 @@ sai_status_t processEventInInitViewMode( * but if that happen, this id will be treated as "new" object instead of * existing one. */ - + /* * TODO: use metadata utils. */ - + auto info = sai_metadata_get_object_type_info(object_type); - + switch (api) { case SAI_COMMON_API_CREATE: - + if (info->isnonobjectid) { /* @@ -2224,26 +2252,28 @@ sai_status_t processEventInInitViewMode( { sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + /* * Object ID here is actual VID returned from redis during * creation this is floating VID in init view mode. */ - + SWSS_LOG_DEBUG("generic create (init view) for %s, floating VID: %s", sai_serialize_object_type(object_type).c_str(), sai_serialize_object_id(object_id).c_str()); - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_create_in_init_view(object_id, attr_count, attr_list); } } - + + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_REMOVE: - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { /* @@ -2254,10 +2284,10 @@ sai_status_t processEventInInitViewMode( * * To support multiple switches this case must be refactored. */ - + SWSS_LOG_THROW("remove switch (%s) is not supported in init view mode yet! FIXME", str_object_id.c_str()); } - + if (!info->isnonobjectid) { /* @@ -2270,28 +2300,32 @@ sai_status_t processEventInInitViewMode( * need to have a list of removed objects, and then only * populate objects which not exist on removed list. */ - + sai_object_id_t object_vid; sai_deserialize_object_id(str_object_id, object_vid); - + initViewRemovedVidSet.insert(object_vid); } - + + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_SET: - + /* * We support SET api on all objects in init view mode. */ - + + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_GET: - + { sai_status_t status; - + if (info->isnonobjectid) { /* @@ -2300,20 +2334,20 @@ sai_status_t processEventInInitViewMode( * since user explicitly know what attributes were set, similar * for other non object id types. */ - + SWSS_LOG_ERROR("get is not supported on %s in init view mode", sai_serialize_object_type(object_type).c_str()); - + status = SAI_STATUS_NOT_SUPPORTED; } else { sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + SWSS_LOG_DEBUG("generic get (init view) for object type %s:%s", sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); - + /* * Object must exists, we can't call GET on created object * in init view mode, get here can be called on existing @@ -2328,19 +2362,19 @@ sai_status_t processEventInInitViewMode( * Translate vid to rid will make sure that object exist * and it have RID defined, so we can query it. */ - + sai_object_id_t rid = translate_vid_to_rid(object_id); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = rid; - + status = info->get(&meta_key, attr_count, attr_list); } - + sai_object_id_t switch_id; - + if (switches.size() == 1) { /* @@ -2352,7 +2386,7 @@ sai_status_t processEventInInitViewMode( * can extract switch id, we could also have this method * inside metadata to get meta key. */ - + switch_id = switches.begin()->second->getVid(); } else @@ -2361,17 +2395,17 @@ sai_status_t processEventInInitViewMode( * This needs to be updated to support multiple switches * scenario. */ - + SWSS_LOG_THROW("multiple switches are not supported yet: %zu", switches.size()); } - + internal_syncd_get_send(object_type, str_object_id, switch_id, status, attr_count, attr_list); - + return status; } - + default: - + SWSS_LOG_THROW("common api (%s) is not implemented in init view mode", sai_serialize_common_api(api).c_str()); } @@ -2384,39 +2418,39 @@ sai_object_id_t extractSwitchVid( SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(object_type); - + /* * Could be replaced by meta_key. */ - + sai_fdb_entry_t fdb_entry; sai_neighbor_entry_t neighbor_entry; sai_route_entry_t route_entry; sai_object_id_t oid; - + switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: sai_deserialize_fdb_entry(str_object_id, fdb_entry); return fdb_entry.switch_id; - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: sai_deserialize_neighbor_entry(str_object_id, neighbor_entry); return neighbor_entry.switch_id; - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: sai_deserialize_route_entry(str_object_id, route_entry); return route_entry.switch_id; - + default: - + if (info->isnonobjectid) { SWSS_LOG_THROW("passing non object id %s as generic object", info->objecttypename); } - + sai_deserialize_object_id(str_object_id, oid); - + return redis_sai_switch_id_query(oid); } } @@ -2433,16 +2467,16 @@ sai_status_t handle_bulk_generic( * Since we don't have asic support yet for bulk api, just execute one by * one. */ - + for (size_t idx = 0; idx < object_ids.size(); ++idx) { sai_status_t status = SAI_STATUS_FAILURE; - + auto &list = attributes[idx]; - + sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); - + sai_object_meta_key_t meta_key; meta_key.objecttype = object_type; switch (object_type) @@ -2459,7 +2493,7 @@ sai_status_t handle_bulk_generic( default: SWSS_LOG_THROW("invalid object_type: %s", sai_serialize_object_type(object_type).c_str()); } - + if (api == (sai_common_api_t)SAI_COMMON_API_BULK_SET) { status = handle_non_object_id(meta_key, SAI_COMMON_API_SET, attr_count, attr_list); @@ -2476,13 +2510,14 @@ sai_status_t handle_bulk_generic( { SWSS_LOG_THROW("api %d is not supported in bulk route", api); } - + if (status != SAI_STATUS_SUCCESS) { + internal_syncd_api_send_response(api, status); return status; } } - + return SAI_STATUS_SUCCESS; } @@ -2494,80 +2529,80 @@ sai_status_t processBulkEvent( SWSS_LOG_ENTER(); const std::string &key = kfvKey(kco); - + std::string str_object_type = key.substr(0, key.find(":")); - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + const std::vector &values = kfvFieldsValues(kco); - + // key = str_object_id // val = attrid=attrvalue|... - + std::vector object_ids; - + std::vector> attributes; - + for (const auto &fvt: values) { std::string str_object_id = fvField(fvt); std::string joined = fvValue(fvt); - + // decode values - + auto v = swss::tokenize(joined, '|'); - + object_ids.push_back(str_object_id); - + std::vector entries; // attributes per object id - + for (size_t i = 0; i < v.size(); ++i) { const std::string item = v.at(i); - + auto start = item.find_first_of("="); - + auto field = item.substr(0, start); auto value = item.substr(start + 1); - + swss::FieldValueTuple entry(field, value); - + entries.push_back(entry); } - + // since now we converted this to proper list, we can extract attributes - + std::shared_ptr list = std::make_shared(object_type, entries, false); - + attributes.push_back(list); } - + SWSS_LOG_NOTICE("bulk %s execute with %zu items", str_object_type.c_str(), object_ids.size()); - + if (isInitViewMode()) { SWSS_LOG_THROW("bulk api (%d) is not supported in init view mode", api); } - + if (api != SAI_COMMON_API_BULK_GET) { // translate attributes for all objects - + for (auto &list: attributes) { sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); - + translate_vid_to_rid_list(object_type, attr_count, attr_list); } } - + sai_status_t status; - + switch (object_type) { case SAI_OBJECT_TYPE_ROUTE_ENTRY: @@ -2575,18 +2610,20 @@ sai_status_t processBulkEvent( case SAI_OBJECT_TYPE_FDB_ENTRY: status = handle_bulk_generic(object_type, object_ids, api, attributes); break; - + default: SWSS_LOG_THROW("bulk api for %s is not supported yet, FIXME", sai_serialize_object_type(object_type).c_str()); } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to execute bulk api: %s", sai_serialize_status(status).c_str()); } - + + internal_syncd_api_send_response(api, status); + return status; } @@ -2597,38 +2634,38 @@ sai_status_t processFdbFlush( const std::string &key = kfvKey(kco); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t switch_vid; - + sai_deserialize_object_id(str_object_id, switch_vid); - + sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid); - + const std::vector &values = kfvFieldsValues(kco); - + for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SaiAttributeList list(SAI_OBJECT_TYPE_FDB_FLUSH, values, false); - + /* * Attribute list can't be const since we will use it to translate VID to * RID in place. */ - + sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); - + translate_vid_to_rid_list(SAI_OBJECT_TYPE_FDB_FLUSH, attr_count, attr_list); - + sai_status_t status = sai_metadata_sai_fdb_api->flush_fdb_entries(switch_rid, attr_count, attr_list); - + std::vector en; - + getResponse->set(sai_serialize_status(status), en, "flushresponse"); - + return status; } @@ -2638,13 +2675,13 @@ sai_status_t processEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + swss::KeyOpFieldsValuesTuple kco; - + sai_status_t status = SAI_STATUS_SUCCESS; - + do { - + if (isInitViewMode()) { /* @@ -2652,34 +2689,34 @@ sai_status_t processEvent( * specify temporary view prefix in consumer since consumer puts data * to redis db. */ - + consumer.pop(kco, TEMP_PREFIX); } else { consumer.pop(kco); } - + const std::string &key = kfvKey(kco); const std::string &op = kfvOp(kco); - + if (key.length() == 0) { SWSS_LOG_DEBUG("no elements in m_buffer"); return status; } - + /* * TODO: Key is serialized meta_key, we could use deserialize * to extract it here. */ - + const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + SWSS_LOG_INFO("key: %s op: %s", key.c_str(), op.c_str()); - + sai_common_api_t api = SAI_COMMON_API_MAX; - + if (op == "create") { api = SAI_COMMON_API_CREATE; @@ -2724,42 +2761,42 @@ sai_status_t processEvent( { SWSS_LOG_THROW("api '%s' is not implemented", op.c_str()); } - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + /* * TODO: use metadata utils is object type valid. */ - + if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX) { SWSS_LOG_THROW("undefined object type %s", sai_serialize_object_type(object_type).c_str()); } - + const std::vector &values = kfvFieldsValues(kco); - + for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SaiAttributeList list(object_type, values, false); - + /* * Attribute list can't be const since we will use it to translate VID to * RID in place. */ - + sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); - + /* * NOTE: This check pointers must be executed before init view mode, since * this methods replaces pointers from orchagent memory space to syncd * memory space. */ - + if (object_type == SAI_OBJECT_TYPE_SWITCH && (api == SAI_COMMON_API_CREATE || api == SAI_COMMON_API_SET)) { /* @@ -2768,15 +2805,15 @@ sai_status_t processEvent( * will internally check whether pointer is null or not, so we here * will receive all notifications, but redis only those that were set. */ - + check_notifications_pointers(attr_count, attr_list); } - + if (isInitViewMode()) { return processEventInInitViewMode(object_type, str_object_id, api, attr_count, attr_list); } - + if (api != SAI_COMMON_API_GET) { /* @@ -2784,51 +2821,51 @@ sai_status_t processEvent( * buffer so then all OIDs will be NULL, and translation will also * convert them to NULL. */ - + SWSS_LOG_DEBUG("translating VID to RIDs on all attributes"); - + translate_vid_to_rid_list(object_type, attr_count, attr_list); } - + // TODO use metadata utils auto info = sai_metadata_get_object_type_info(object_type); - + /* * TODO use sai meta key deserialize */ - + if (info->isnonobjectid) { sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; - + switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: sai_deserialize_fdb_entry(str_object_id, meta_key.objectkey.key.fdb_entry); break; - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: sai_deserialize_neighbor_entry(str_object_id, meta_key.objectkey.key.neighbor_entry); break; - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: sai_deserialize_route_entry(str_object_id, meta_key.objectkey.key.route_entry); break; - + default: - + SWSS_LOG_THROW("non object id %s is not supported yet, FIXME", info->objecttypename); } - + status = handle_non_object_id(meta_key, api, attr_count, attr_list); } else { status = handle_generic(object_type, str_object_id, api, attr_count, attr_list); } - + if (api == SAI_COMMON_API_GET) { if (status != SAI_STATUS_SUCCESS) @@ -2838,42 +2875,49 @@ sai_status_t processEvent( op.c_str(), sai_serialize_status(status).c_str()); } - + /* * Extracting switch is double work here, we can avoid this when we * will use meta_key. */ - + sai_object_id_t switch_vid = extractSwitchVid(object_type, str_object_id); - + internal_syncd_get_send(object_type, str_object_id, switch_vid, status, attr_count, attr_list); } else if (status != SAI_STATUS_SUCCESS) { + internal_syncd_api_send_response(api, status); + if (!info->isnonobjectid && api == SAI_COMMON_API_SET) { sai_object_id_t vid; sai_deserialize_object_id(str_object_id, vid); - + sai_object_id_t rid = translate_vid_to_rid(vid); - + SWSS_LOG_ERROR("VID: %s RID: %s", sai_serialize_object_id(vid).c_str(), sai_serialize_object_id(rid).c_str()); } - + for (const auto &v: values) { SWSS_LOG_ERROR("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SWSS_LOG_THROW("failed to execute api: %s, key: %s, status: %s", op.c_str(), key.c_str(), sai_serialize_status(status).c_str()); } + else // non GET api, status is SUCCESS + { + internal_syncd_api_send_response(api, status); + } + } while (!consumer.empty()); - + return status; } @@ -2887,22 +2931,22 @@ void processFlexCounterGroupEvent( std::lock_guard lock(g_mutex); consumer.pop(kco); } - + const auto &groupName = kfvKey(kco); const auto &op = kfvOp(kco); const auto values = kfvFieldsValues(kco); - + if (op == DEL_COMMAND) { FlexCounter::removeCounterPlugin(groupName); return; } - + for (const auto& valuePair : values) { const auto field = fvField(valuePair); const auto value = fvValue(valuePair); - + if (op == SET_COMMAND) { if (field == POLL_INTERVAL_FIELD) @@ -2965,16 +3009,16 @@ bool tryPopFlexCounterEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + if (g_flexCounterEventQueue.empty()) { return false; } - + kco = g_flexCounterEventQueue.front(); - + g_flexCounterEventQueue.pop(); - + return true; } @@ -2984,7 +3028,7 @@ void pushFlexCounterEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + g_flexCounterEventQueue.push(kco); } @@ -2998,17 +3042,17 @@ void processFlexCounterEventThread() while (g_processFlexCounterEventThreadRun) { swss::KeyOpFieldsValuesTuple kco; - + if (tryPopFlexCounterEvent(kco)) { if (!processFlexCounterEvent(kco)) { // event was not successfully processed, put it again to the queue - + pushFlexCounterEvent(kco); } } - + sleep(1); } } @@ -3019,19 +3063,19 @@ void processFlexCounterEvent( SWSS_LOG_ENTER(); swss::KeyOpFieldsValuesTuple kco; - + { std::lock_guard lock(g_mutex); consumer.pop(kco); } - + // because flex counter event can arrive independently (on RIF interface) // it may happen that it will be picked up from the select api before // actual interface will be created, and subscription for counters will // fail, so let's process each request in the thread and use queue for // arriving events, and failed events will be put back to the queue until // they will be processed - + pushFlexCounterEvent(kco); } @@ -3042,35 +3086,34 @@ bool processFlexCounterEvent( const auto &key = kfvKey(kco); const std::string &op = kfvOp(kco); - + std::size_t delimiter = key.find_first_of(":"); if (delimiter == std::string::npos) { SWSS_LOG_ERROR("Failed to parse the key %s", key.c_str()); - + return true; // if key is invalid there is no need to process this event again } - + const auto groupName = key.substr(0, delimiter); const auto vidStr = key.substr(delimiter+1); - + sai_object_id_t vid = SAI_NULL_OBJECT_ID; sai_deserialize_object_id(vidStr, vid); sai_object_id_t rid; { std::lock_guard lock(g_mutex); if (!try_translate_vid_to_rid(vid, rid)) - { - SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", - sai_serialize_object_id(vid).c_str()); - + { + SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", + sai_serialize_object_id(vid).c_str()); return false; } } - + sai_object_type_t objectType = redis_sai_object_type_query(vid); // VID and RID will have the same object type std::string objectTypeStr = sai_serialize_object_type(objectType); - + if (op == DEL_COMMAND) { if (objectType == SAI_OBJECT_TYPE_PORT) @@ -3098,7 +3141,7 @@ bool processFlexCounterEvent( SWSS_LOG_ERROR("Object type for removal not supported, %s", objectTypeStr.c_str()); } } - + const auto values = kfvFieldsValues(kco); std::vector counterIds; std::string statsMode; @@ -3106,11 +3149,11 @@ bool processFlexCounterEvent( { const auto field = fvField(valuePair); const auto value = fvValue(valuePair); - + if (op == SET_COMMAND) { auto idStrings = swss::tokenize(value, ','); - + if (objectType == SAI_OBJECT_TYPE_PORT && field == PORT_COUNTER_ID_LIST) { std::vector portCounterIds; @@ -3120,7 +3163,7 @@ bool processFlexCounterEvent( sai_deserialize_port_stat(str.c_str(), &stat); portCounterIds.push_back(stat); } - + FlexCounter::setPortCounterList(vid, rid, groupName, portCounterIds); } else if (objectType == SAI_OBJECT_TYPE_QUEUE && field == QUEUE_COUNTER_ID_LIST) @@ -3132,7 +3175,7 @@ bool processFlexCounterEvent( sai_deserialize_queue_stat(str.c_str(), &stat); queueCounterIds.push_back(stat); } - + FlexCounter::setQueueCounterList(vid, rid, groupName, queueCounterIds); } else if (objectType == SAI_OBJECT_TYPE_QUEUE && field == QUEUE_ATTR_ID_LIST) @@ -3144,7 +3187,7 @@ bool processFlexCounterEvent( sai_deserialize_queue_attr(str, attr); queueAttrIds.push_back(attr); } - + FlexCounter::setQueueAttrList(vid, rid, groupName, queueAttrIds); } else if (objectType == SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP && field == PG_COUNTER_ID_LIST) @@ -3156,7 +3199,7 @@ bool processFlexCounterEvent( sai_deserialize_ingress_priority_group_stat(str.c_str(), &stat); pgCounterIds.push_back(stat); } - + FlexCounter::setPriorityGroupCounterList(vid, rid, groupName, pgCounterIds); } else if (objectType == SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP && field == PG_ATTR_ID_LIST) @@ -3168,7 +3211,7 @@ bool processFlexCounterEvent( sai_deserialize_ingress_priority_group_attr(str, attr); pgAttrIds.push_back(attr); } - + FlexCounter::setPriorityGroupAttrList(vid, rid, groupName, pgAttrIds); } else if (objectType == SAI_OBJECT_TYPE_ROUTER_INTERFACE && field == RIF_COUNTER_ID_LIST) @@ -3180,7 +3223,7 @@ bool processFlexCounterEvent( sai_deserialize_router_interface_stat(str.c_str(), &stat); rifCounterIds.push_back(stat); } - + FlexCounter::setRifCounterList(vid, rid, groupName, rifCounterIds); } else if (objectType == SAI_OBJECT_TYPE_BUFFER_POOL && field == BUFFER_POOL_COUNTER_ID_LIST) @@ -3197,7 +3240,7 @@ bool processFlexCounterEvent( } } } - + if (objectType == SAI_OBJECT_TYPE_BUFFER_POOL && counterIds.size()) { std::vector bufferPoolCounterIds; @@ -3207,10 +3250,10 @@ bool processFlexCounterEvent( sai_deserialize_buffer_pool_stat(str.c_str(), &stat); bufferPoolCounterIds.push_back(stat); } - + FlexCounter::setBufferPoolCounterList(vid, rid, groupName, bufferPoolCounterIds, statsMode); } - + return true; } @@ -3218,7 +3261,7 @@ void printUsage() { SWSS_LOG_ENTER(); - std::cout << "Usage: syncd [-N] [-U] [-d] [-p profile] [-i interval] [-t [cold|warm|fast|fastfast]] [-h] [-u] [-S]" << std::endl; + std::cout << "Usage: syncd [-N] [-U] [-d] [-p profile] [-i interval] [-t [cold|warm|fast|fastfast]] [-h] [-u] [-S] [-s]" << std::endl; std::cout << " -N --nocounters" << std::endl; std::cout << " Disable counter thread" << std::endl; std::cout << " -d --diag" << std::endl; @@ -3243,6 +3286,8 @@ void printUsage() std::cout << " -m --portmap" << std::endl; std::cout << " Specify port map file" << std::endl; #endif // SAITHRIFT + std::cout << " -s --syncMode" << std::endl; + std::cout << " Enable synchronous mode" << std::endl; std::cout << " -h --help" << std::endl; std::cout << " Print out this message" << std::endl; } @@ -3253,6 +3298,7 @@ void handleCmdLine(int argc, char **argv) options.disableExitSleep = false; options.enableUnittests = false; + options.syncMode = false; #ifdef SAITHRIFT options.run_rpc_server = false; @@ -3277,50 +3323,51 @@ void handleCmdLine(int argc, char **argv) { "rpcserver", no_argument, 0, 'r' }, { "portmap", required_argument, 0, 'm' }, #endif // SAITHRIFT + { "syncMode", no_argument, 0, 's' }, { 0, 0, 0, 0 } }; - + int option_index = 0; - + int c = getopt_long(argc, argv, optstring, long_options, &option_index); - + if (c == -1) { break; } - + switch (c) { case 'U': SWSS_LOG_NOTICE("enable unittests"); options.enableUnittests = true; break; - + case 'C': SWSS_LOG_NOTICE("enable consistency check"); g_enableConsistencyCheck = true; break; - + case 'u': SWSS_LOG_NOTICE("enable use temp view"); options.useTempView = true; break; - + case 'S': SWSS_LOG_NOTICE("disable crash sleep"); options.disableExitSleep = true; break; - + case 'd': SWSS_LOG_NOTICE("enable diag shell"); options.diagShell = true; break; - + case 'p': SWSS_LOG_NOTICE("profile map file: %s", optarg); options.profileMapFile = std::string(optarg); break; - + case 't': SWSS_LOG_NOTICE("start type: %s", optarg); if (std::string(optarg) == "cold") @@ -3357,15 +3404,20 @@ void handleCmdLine(int argc, char **argv) break; #endif // SAITHRIFT + case 's': + SWSS_LOG_NOTICE("enable synchronous mode"); + options.syncMode = true; + break; + case 'h': printUsage(); exit(EXIT_SUCCESS); - + case '?': SWSS_LOG_WARN("unknown option %c", optopt); printUsage(); exit(EXIT_FAILURE); - + default: SWSS_LOG_ERROR("getopt_long failure"); exit(EXIT_FAILURE); @@ -3381,44 +3433,44 @@ void handleProfileMap(const std::string& profileMapFile) { return; } - + std::ifstream profile(profileMapFile); - + if (!profile.is_open()) { SWSS_LOG_ERROR("failed to open profile map file: %s : %s", profileMapFile.c_str(), strerror(errno)); exit(EXIT_FAILURE); } - + // Provide default value at boot up time and let sai profile value // Override following values if existing. // SAI reads these values at start up time. It would be too late to // set these values later when WARM BOOT is detected. gProfileMap[SAI_KEY_WARM_BOOT_WRITE_FILE] = DEF_SAI_WARM_BOOT_DATA_FILE; gProfileMap[SAI_KEY_WARM_BOOT_READ_FILE] = DEF_SAI_WARM_BOOT_DATA_FILE; - + std::string line; - + while(getline(profile, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) { continue; } - + size_t pos = line.find("="); - + if (pos == std::string::npos) { SWSS_LOG_WARN("not found '=' in line %s", line.c_str()); continue; } - + std::string key = line.substr(0, pos); std::string value = line.substr(pos + 1); - + gProfileMap[key] = value; - + SWSS_LOG_INFO("insert: %s:%s", key.c_str(), value.c_str()); } } @@ -3435,39 +3487,39 @@ void handlePortMap(const std::string& portMapFile) { return; } - + std::ifstream portmap(portMapFile); - + if (!portmap.is_open()) { std::cerr << "failed to open port map file:" << portMapFile.c_str() << " : "<< strerror(errno) << std::endl; exit(EXIT_FAILURE); } - + std::string line; - + while(getline(portmap, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) { continue; } - + std::istringstream iss(line); std::string name, lanes, alias; iss >> name >> lanes >> alias; - + iss.clear(); iss.str(lanes); std::string lane_str; std::set lane_set; - + while (getline(iss, lane_str, ',')) { int lane = stoi(lane_str); lane_set.insert(lane); } - + gPortMap.insert(std::pair,std::string>(lane_set, name)); } } @@ -3478,9 +3530,9 @@ typedef enum _syncd_restart_type_t SYNCD_RESTART_TYPE_COLD, SYNCD_RESTART_TYPE_WARM, - + SYNCD_RESTART_TYPE_FAST, - + SYNCD_RESTART_TYPE_PRE_SHUTDOWN, } syncd_restart_type_t; @@ -3492,35 +3544,35 @@ syncd_restart_type_t handleRestartQuery(swss::NotificationConsumer &restartQuery std::string op; std::string data; std::vector values; - + restartQuery.pop(op, data, values); - + SWSS_LOG_DEBUG("op = %s", op.c_str()); - + if (op == "COLD") { SWSS_LOG_NOTICE("received COLD switch shutdown event"); return SYNCD_RESTART_TYPE_COLD; } - + if (op == "WARM") { SWSS_LOG_NOTICE("received WARM switch shutdown event"); return SYNCD_RESTART_TYPE_WARM; } - + if (op == "FAST") { SWSS_LOG_NOTICE("received FAST switch shutdown event"); return SYNCD_RESTART_TYPE_FAST; } - + if (op == "PRE-SHUTDOWN") { SWSS_LOG_NOTICE("received PRE_SHUTDOWN switch event"); return SYNCD_RESTART_TYPE_PRE_SHUTDOWN; } - + SWSS_LOG_WARN("received '%s' unknown switch shutdown event, assuming COLD", op.c_str()); return SYNCD_RESTART_TYPE_COLD; } @@ -3542,13 +3594,13 @@ bool isVeryFirstRun() * TODO we need to fix this, since when there will be queue, it will still think * this is first run, let's query HIDDEN ? */ - + auto keys = g_redisClient->keys(HIDDEN); - + bool firstRun = keys.size() == 0; - + SWSS_LOG_NOTICE("First Run: %s", firstRun ? "True" : "False"); - + return firstRun; } @@ -3565,7 +3617,7 @@ int get_enum_value_from_name( return metadata->values[idx]; } } - + SWSS_LOG_ERROR("not found %s", name); return 0; } @@ -3575,7 +3627,7 @@ void saiLoglevelNotify(std::string apiStr, std::string prioStr) SWSS_LOG_ENTER(); using namespace swss; - + static const std::map saiLoglevelMap = { { "SAI_LOG_LEVEL_CRITICAL", SAI_LOG_LEVEL_CRITICAL }, { "SAI_LOG_LEVEL_ERROR", SAI_LOG_LEVEL_ERROR }, @@ -3584,24 +3636,24 @@ void saiLoglevelNotify(std::string apiStr, std::string prioStr) { "SAI_LOG_LEVEL_INFO", SAI_LOG_LEVEL_INFO }, { "SAI_LOG_LEVEL_DEBUG", SAI_LOG_LEVEL_DEBUG }, }; - + if (saiLoglevelMap.find(prioStr) == saiLoglevelMap.end()) { SWSS_LOG_ERROR("Invalid SAI loglevel %s %s", apiStr.c_str(), prioStr.c_str()); return; } - + sai_api_t api = (sai_api_t)get_enum_value_from_name(apiStr.c_str(), &sai_metadata_enum_sai_api_t); - + sai_status_t status = sai_log_set(api, saiLoglevelMap.at(prioStr)); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_INFO("Failed to set %s on %s: %s", prioStr.c_str(), apiStr.c_str(), sai_serialize_status(status).c_str()); return; } - + SWSS_LOG_NOTICE("Setting SAI loglevel %s to %s", apiStr.c_str(), prioStr.c_str()); } @@ -3612,7 +3664,7 @@ void set_sai_api_loglevel() /* * We start from 1 since 0 is SAI_API_UNSPECIFIED. */ - + for (uint32_t idx = 1; idx < sai_metadata_enum_sai_api_t.valuescount; ++idx) { swss::Logger::linkToDb(sai_metadata_enum_sai_api_t.valuesnames[idx], saiLoglevelNotify, "SAI_LOG_LEVEL_NOTICE"); @@ -3626,7 +3678,7 @@ void set_sai_api_log_min_prio(const std::string &prioStr) /* * We start from 1 since 0 is SAI_API_UNSPECIFIED. */ - + for (uint32_t idx = 1; idx < sai_metadata_enum_sai_api_t.valuescount; ++idx) { const auto& api_name = sai_metadata_enum_sai_api_t.valuesnames[idx]; @@ -3646,9 +3698,9 @@ void onSyncdStart(bool warmStart) * will generate new id's for ports, this may cause race condition so we * need to use a lock here to prevent that. */ - + SWSS_LOG_TIMER("on syncd start"); - + if (warmStart) { /* @@ -3662,20 +3714,20 @@ void onSyncdStart(bool warmStart) * * If we want to support multiple switches, this needs to be adjusted. */ - + performWarmRestart(); - + SWSS_LOG_NOTICE("skipping hard reinit since WARM start was performed"); return; } - + SWSS_LOG_NOTICE("performing hard reinit since COLD start was performed"); - + /* * Switch was restarted in hard way, we need to perform hard reinit and * recreate switches map. */ - + hardReinit(); } @@ -3699,14 +3751,14 @@ void sai_meta_log_syncd( // SWSS_LOG_ENTER() is omitted since this is logging for metadata char buffer[0x1000]; - + va_list ap; va_start(ap, format); vsnprintf(buffer, 0x1000, format, ap); va_end(ap); - + swss::Logger::Priority p = swss::Logger::SWSS_NOTICE; - + switch (log_level) { case SAI_LOG_LEVEL_DEBUG: @@ -3726,12 +3778,12 @@ void sai_meta_log_syncd( case SAI_LOG_LEVEL_CRITICAL: p = swss::Logger::SWSS_CRIT; break; - + default: p = swss::Logger::SWSS_NOTICE; break; } - + swss::Logger::getInstance().write(p, ":- %s: %s", func, buffer); } @@ -3748,13 +3800,13 @@ int syncd_main(int argc, char **argv) swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG); SWSS_LOG_ENTER(); - + swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE); - + set_sai_api_loglevel(); - + swss::Logger::linkToDbNative("syncd"); - + swss::WarmStart::initialize("syncd", "syncd"); swss::WarmStart::checkWarmStart("syncd", "syncd"); @@ -3764,9 +3816,9 @@ int syncd_main(int argc, char **argv) #pragma GCC diagnostic pop meta_init_db(); - + handleCmdLine(argc, argv); - + handleProfileMap(options.profileMapFile); #ifdef SAITHRIFT @@ -3781,59 +3833,59 @@ int syncd_main(int argc, char **argv) std::shared_ptr dbFlexCounter = std::make_shared(FLEX_COUNTER_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::shared_ptr dbState = std::make_shared(STATE_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::unique_ptr warmRestartTable = std::unique_ptr(new swss::Table(dbState.get(), STATE_WARM_RESTART_TABLE_NAME)); - + g_redisClient = std::make_shared(dbAsic.get()); - + std::shared_ptr asicState = std::make_shared(dbAsic.get(), ASIC_STATE_TABLE); std::shared_ptr restartQuery = std::make_shared(dbAsic.get(), "RESTARTQUERY"); std::shared_ptr flexCounter = std::make_shared(dbFlexCounter.get(), FLEX_COUNTER_TABLE); std::shared_ptr flexCounterGroup = std::make_shared(dbFlexCounter.get(), FLEX_COUNTER_GROUP_TABLE); - + /* * At the end we cant use producer consumer concept since if one process * will restart there may be something in the queue also "remove" from * response queue will also trigger another "response". */ - + getResponse = std::make_shared(dbAsic.get(), "GETRESPONSE"); notifications = std::make_shared(dbNtf.get(), "NOTIFICATIONS"); - + g_veryFirstRun = isVeryFirstRun(); - + /* ignore warm logic here if syncd starts in Mellanox fastfast boot mode */ if (swss::WarmStart::isWarmStart() && (options.startType != SAI_FASTFAST_BOOT)) { options.startType = SAI_WARM_BOOT; } - + if (options.startType == SAI_WARM_BOOT) { const char *warmBootReadFile = profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE); - + SWSS_LOG_NOTICE("using warmBootReadFile: '%s'", warmBootReadFile); - + if (warmBootReadFile == NULL || access(warmBootReadFile, F_OK) == -1) { SWSS_LOG_WARN("user requested warmStart but warmBootReadFile is not specified or not accesible, forcing cold start"); - + options.startType = SAI_COLD_BOOT; } } - + if (options.startType == SAI_WARM_BOOT && g_veryFirstRun) { SWSS_LOG_WARN("warm start requested, but this is very first syncd start, forcing cold start"); - + /* * We force cold start since if it's first run then redis db is not * complete so redis asic view will not reflect warm boot asic state, * if this happen then orch agent needs to be restarted as well to * repopulate asic view. */ - + options.startType = SAI_COLD_BOOT; } - + if (options.startType == SAI_FASTFAST_BOOT) { /* @@ -3844,23 +3896,23 @@ int syncd_main(int argc, char **argv) } else { gProfileMap[SAI_KEY_BOOT_TYPE] = std::to_string(options.startType); } - + sai_status_t status = sai_api_initialize(0, (sai_service_method_table_t*)&test_services); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("fail to sai_api_initialize: %d", status); return EXIT_FAILURE; } - + sai_apis_t apis; int failed = sai_metadata_apis_query(sai_api_query, &apis); - + if (failed > 0) { SWSS_LOG_NOTICE("sai_api_query failed for %d apis", failed); } - + /* * TODO: user should create switch from OA, so shell should be started only * after we create switch. @@ -3875,59 +3927,59 @@ int syncd_main(int argc, char **argv) #endif // SAITHRIFT SWSS_LOG_NOTICE("syncd started"); - + syncd_restart_type_t shutdownType = SYNCD_RESTART_TYPE_COLD; - + sai_switch_api_t *sai_switch_api = NULL; sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api); - + volatile bool runMainLoop = true; - + std::shared_ptr s = std::make_shared(); - + try { SWSS_LOG_NOTICE("before onSyncdStart"); onSyncdStart(options.startType == SAI_WARM_BOOT); SWSS_LOG_NOTICE("after onSyncdStart"); - + // create notifications processing thread after we create_switch to // make sure, we have switch_id translated to VID before we start // processing possible quick fdb notifications, and pointer for // notification queue is created before we create switch startNotificationsProcessingThread(); - + SWSS_LOG_NOTICE("syncd listening for events"); - + s->addSelectable(asicState.get()); s->addSelectable(restartQuery.get()); s->addSelectable(flexCounter.get()); s->addSelectable(flexCounterGroup.get()); - + SWSS_LOG_NOTICE("starting main loop"); } catch(const std::exception &e) { SWSS_LOG_ERROR("Runtime error during syncd init: %s", e.what()); - + notify_OA_about_syncd_exception(); - + s = std::make_shared(); - + s->addSelectable(restartQuery.get()); - + SWSS_LOG_NOTICE("starting main loop, ONLY restart query"); - + if (options.disableExitSleep) runMainLoop = false; } - + TimerWatchdog twd(30 * 1000000); // watch for executions over 30 seconds - + twd.setCallback(timerWatchdogCallback); - + g_processFlexCounterEventThreadRun = true; - + g_processFlexCounterEventThread = std::make_shared(processFlexCounterEventThread); @@ -3936,11 +3988,11 @@ int syncd_main(int argc, char **argv) try { swss::Selectable *sel = NULL; - + int result = s->select(&sel); - + twd.setStartTime(); - + if (sel == restartQuery.get()) { /* @@ -3950,16 +4002,16 @@ int syncd_main(int argc, char **argv) * this may lead to forget populate object table which will * lead to unable to find some objects. */ - + SWSS_LOG_NOTICE("is asic queue empty: %d",asicState->empty()); - + while (!asicState->empty()) { processEvent(*asicState.get()); } - + SWSS_LOG_NOTICE("drained queue"); - + shutdownType = handleRestartQuery(*restartQuery); if (shutdownType != SYNCD_RESTART_TYPE_PRE_SHUTDOWN) { @@ -3967,54 +4019,54 @@ int syncd_main(int argc, char **argv) runMainLoop = false; break; } - + // Handle switch pre-shutdown and wait for the final shutdown // event - + SWSS_LOG_TIMER("warm pre-shutdown"); - + FlexCounter::removeAllCounters(); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_RESTART_WARM=true: %s for pre-shutdown", sai_serialize_status(status).c_str()); - + shutdownType = SYNCD_RESTART_TYPE_COLD; - + warmRestartTable->hset("warm-shutdown", "state", "set-flag-failed"); continue; } - + attr.id = SAI_SWITCH_ATTR_PRE_SHUTDOWN; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status == SAI_STATUS_SUCCESS) { warmRestartTable->hset("warm-shutdown", "state", "pre-shutdown-succeeded"); - + s = std::make_shared(); // make sure previous select is destroyed - + s->addSelectable(restartQuery.get()); - + SWSS_LOG_NOTICE("switched to PRE_SHUTDOWN, from now on accepting only shurdown requests"); } else { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_PRE_SHUTDOWN=true: %s", sai_serialize_status(status).c_str()); - + warmRestartTable->hset("warm-shutdown", "state", "pre-shutdown-failed"); - + // Restore cold shutdown. attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = false; @@ -4033,53 +4085,53 @@ int syncd_main(int argc, char **argv) { processEvent(*(swss::ConsumerTable*)sel); } - + twd.setEndTime(); } catch(const std::exception &e) { SWSS_LOG_ERROR("Runtime error: %s", e.what()); - + notify_OA_about_syncd_exception(); - + s = std::make_shared(); - + s->addSelectable(restartQuery.get()); - + if (options.disableExitSleep) runMainLoop = false; - + // make sure that if second exception will arise, then we break the loop options.disableExitSleep = true; - + twd.setEndTime(); } } - + if (shutdownType == SYNCD_RESTART_TYPE_WARM) { const char *warmBootWriteFile = profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE); - + SWSS_LOG_NOTICE("using warmBootWriteFile: '%s'", warmBootWriteFile); - + if (warmBootWriteFile == NULL) { SWSS_LOG_WARN("user requested warm shutdown but warmBootWriteFile is not specified, forcing cold shutdown"); - + shutdownType = SYNCD_RESTART_TYPE_COLD; warmRestartTable->hset("warm-shutdown", "state", "warm-shutdown-failed"); } else { SWSS_LOG_NOTICE("Warm Reboot requested, keeping data plane running"); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_RESTART_WARM=true: %s, fall back to cold restart", @@ -4089,7 +4141,7 @@ int syncd_main(int argc, char **argv) } } } - + SWSS_LOG_NOTICE("Removing the switch gSwitchId=0x%lx", gSwitchId); #ifdef SAI_SUPPORT_UNINIT_DATA_PLANE_ON_REMOVAL @@ -4097,14 +4149,14 @@ int syncd_main(int argc, char **argv) if (shutdownType == SYNCD_RESTART_TYPE_FAST || shutdownType == SYNCD_RESTART_TYPE_WARM) { SWSS_LOG_NOTICE("Fast/warm reboot requested, keeping data plane running"); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL; attr.value.booldata = false; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL=false: %s", @@ -4115,25 +4167,25 @@ int syncd_main(int argc, char **argv) #endif g_processFlexCounterEventThreadRun = false; - + g_processFlexCounterEventThread->join(); - + FlexCounter::removeAllCounters(); - + { SWSS_LOG_TIMER("remove switch"); status = sai_switch_api->remove_switch(gSwitchId); } - + // Stop notification thread after removing switch stopNotificationsProcessingThread(); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_NOTICE("Can't delete a switch. gSwitchId=0x%lx status=%s", gSwitchId, sai_serialize_status(status).c_str()); } - + if (shutdownType == SYNCD_RESTART_TYPE_WARM) { warmRestartTable->hset("warm-shutdown", "state", @@ -4141,17 +4193,17 @@ int syncd_main(int argc, char **argv) "warm-shutdown-succeeded": "warm-shutdown-failed"); } - + SWSS_LOG_NOTICE("calling api uninitialize"); - + status = sai_api_uninitialize(); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to uninitialize api: %s", sai_serialize_status(status).c_str()); } - + SWSS_LOG_NOTICE("uninitialize finished"); - + return EXIT_SUCCESS; } diff --git a/tests/aspell.en.pws b/tests/aspell.en.pws index 3430c32b3..21b18b89e 100644 --- a/tests/aspell.en.pws +++ b/tests/aspell.en.pws @@ -244,3 +244,5 @@ VXLAN workaroung xoff xon +booldata +setBuffered From 7497a35608627705676b3a64961ac9b894f70d6c Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 19 Jul 2019 18:15:20 -0700 Subject: [PATCH 07/20] Revert "Revert "resolved merge conflict"" This reverts commit e840a6b0f4d2df1679d654796f4e303f73d98abe. --- syncd/syncd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 991b96486..eb9a2b258 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -3106,7 +3106,7 @@ bool processFlexCounterEvent( if (!try_translate_vid_to_rid(vid, rid)) { SWSS_LOG_WARN("port VID %s, was not found (probably port was removed/splitted) and will remove from counters now", - sai_serialize_object_id(vid).c_str()); + sai_serialize_object_id(vid).c_str()); return false; } } From b265a8b665dc889ac4507e2ffcbf0b5a8205a6a7 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 20 Jul 2019 20:32:22 -0700 Subject: [PATCH 08/20] Update syncd.cpp --- syncd/syncd.cpp | 988 ++++++++++++++++++++++++------------------------ 1 file changed, 494 insertions(+), 494 deletions(-) diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index eb9a2b258..3d5a176e9 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -134,11 +134,11 @@ void notify_OA_about_syncd_exception() if (notifications != NULL) { std::vector entry; - + SWSS_LOG_NOTICE("sending switch_shutdown_request notification to OA"); - + notifications->send("switch_shutdown_request", "", entry); - + SWSS_LOG_NOTICE("notification send successfull"); } } @@ -158,27 +158,27 @@ void sai_diag_shell( SWSS_LOG_ENTER(); sai_status_t status; - + /* * This is currently blocking API on broadcom, it will block until we exit * shell. */ - + while (true) { sai_attribute_t attr; attr.id = SAI_SWITCH_ATTR_SWITCH_SHELL_ENABLE; attr.value.booldata = true; - + status = sai_metadata_sai_switch_api->set_switch_attribute(switch_id, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to enable switch shell: %s", sai_serialize_status(status).c_str()); return; } - + sleep(1); } } @@ -215,14 +215,14 @@ sai_object_type_t redis_sai_object_type_query( { return SAI_OBJECT_TYPE_NULL; } - + sai_object_type_t ot = (sai_object_type_t)((object_id >> OT_POSITION) & 0xFF); - + if (!sai_metadata_is_object_type_valid(ot)) { SWSS_LOG_THROW("invalid object id 0x%lx", object_id); } - + return ot; } @@ -232,12 +232,12 @@ int redis_get_switch_id_index( SWSS_LOG_ENTER(); sai_object_type_t switch_object_type = redis_sai_object_type_query(switch_id); - + if (switch_object_type == SAI_OBJECT_TYPE_SWITCH) { return (int)((switch_id >> SWID_POSITION) & 0xFF); } - + SWSS_LOG_THROW("object type of switch %s is %s, should be SWITCH", sai_serialize_object_id(switch_id).c_str(), sai_serialize_object_type(switch_object_type).c_str()); @@ -252,30 +252,30 @@ sai_object_id_t redis_sai_switch_id_query( { return oid; } - + sai_object_type_t object_type = redis_sai_object_type_query(oid); - + if (object_type == SAI_OBJECT_TYPE_NULL) { SWSS_LOG_THROW("invalid object type of oid 0x%lx", oid); } - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { return oid; } - + /* * Each VID contains switch index at constant position. * * We extract this index from VID and we create switch ID (VID) for * specific object. We can do this for each object. */ - + int sw_index = (int)((oid >> SWID_POSITION) & 0xFF); - + sai_object_id_t switch_id = redis_construct_object_id(SAI_OBJECT_TYPE_SWITCH, sw_index, sw_index); - + return switch_id; } @@ -288,38 +288,38 @@ sai_object_id_t redis_create_virtual_object_id( /* * NOTE: switch ID is VID switch ID from sairedis. */ - + /* * Check if object type is in valid range. */ - + if (!sai_metadata_is_object_type_valid(object_type)) { SWSS_LOG_THROW("invalid object type: %s", sai_serialize_object_type(object_type).c_str()); } - + /* * Switch id is deterministic and it comes from sairedis so make check here * that we will not use this for creating switch VIDs. */ - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { SWSS_LOG_THROW("this function should not be used to create VID for switch id"); } - + uint64_t virtual_id = g_redisClient->incr(VIDCOUNTER); - + int switch_index = redis_get_switch_id_index(switch_id); - + sai_object_id_t vid = redis_construct_object_id(object_type, switch_index, virtual_id); - + auto info = sai_metadata_get_object_type_info(object_type); - + SWSS_LOG_DEBUG("created virtual object id 0x%lx for object type %s", vid, info->objecttypename); - + return vid; } @@ -390,11 +390,11 @@ sai_object_id_t translate_rid_to_vid( */ std::string str_vid = *pvid; - + sai_deserialize_object_id(str_vid, vid); - + SWSS_LOG_DEBUG("translated RID 0x%lx to VID 0x%lx", rid, vid); - + return vid; } @@ -503,60 +503,60 @@ void translate_rid_to_vid_list( sai_attribute_t &attr = attr_list[i]; auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %x, attribute %d", object_type, attr.id); } - + /* * TODO: Many times we do switch for list of attributes to perform some * operation on each oid from that attribute, we should provide clever * way via sai metadata utils to get that. */ - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: attr.value.oid = translate_rid_to_vid(attr.value.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: translate_list_rid_to_vid(attr.value.objlist, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) attr.value.aclfield.data.oid = translate_rid_to_vid(attr.value.aclfield.data.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) translate_list_rid_to_vid(attr.value.aclfield.data.objlist, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) attr.value.aclaction.parameter.oid = translate_rid_to_vid(attr.value.aclaction.parameter.oid, switch_id); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) translate_list_rid_to_vid(attr.value.aclaction.parameter.objlist, switch_id); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } } @@ -576,23 +576,23 @@ sai_object_id_t translate_vid_to_rid( if (vid == SAI_NULL_OBJECT_ID) { SWSS_LOG_DEBUG("translated VID null to RID null"); - + return SAI_NULL_OBJECT_ID; } - + auto it = local_vid_to_rid.find(vid); - + if (it != local_vid_to_rid.end()) { return it->second; } - + std::string str_vid = sai_serialize_object_id(vid); - + std::string str_rid; - + auto prid = g_redisClient->hget(VIDTORID, str_vid); - + if (prid == NULL) { if (isInitViewMode()) @@ -609,28 +609,28 @@ sai_object_id_t translate_vid_to_rid( * like buffer limitations etc, mostly probably this will happen on * SWITCH object. */ - + SWSS_LOG_THROW("can't get RID in init view mode - don't query created objects"); } - + SWSS_LOG_THROW("unable to get RID for VID: 0x%lx", vid); } - + str_rid = *prid; - + sai_object_id_t rid; - + sai_deserialize_object_id(str_rid, rid); - + /* * We got this RID from redis db, so put it also to local db so it will be * faster to retrieve it late on. */ - + local_vid_to_rid[vid] = rid; - + SWSS_LOG_DEBUG("translated VID 0x%lx to RID 0x%lx", vid, rid); - + return rid; } @@ -674,60 +674,60 @@ void translate_vid_to_rid_list( * All id's received from sairedis should be virtual, so lets translate * them to real id's before we execute actual api. */ - + for (uint32_t i = 0; i < attr_count; i++) { sai_attribute_t &attr = attr_list[i]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %x, attribute %d", object_type, attr.id); } - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: attr.value.oid = translate_vid_to_rid(attr.value.oid); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: translate_list_vid_to_rid(attr.value.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) attr.value.aclfield.data.oid = translate_vid_to_rid(attr.value.aclfield.data.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) translate_list_vid_to_rid(attr.value.aclfield.data.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) attr.value.aclaction.parameter.oid = translate_vid_to_rid(attr.value.aclaction.parameter.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) translate_list_vid_to_rid(attr.value.aclaction.parameter.objlist); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } } @@ -745,18 +745,18 @@ void snoop_get_attr( * Note: str_object_type + ":" + str_object_id is meta_key we can us that * here later on. */ - + std::string str_object_type = sai_serialize_object_type(object_type); - + std::string prefix = ""; - + if (isInitViewMode()) { prefix = TEMP_PREFIX; } - + std::string key = prefix + (ASIC_STATE_TABLE + (":" + str_object_type + ":" + str_object_id)); - + SWSS_LOG_DEBUG("%s", key.c_str()); @@ -773,20 +773,20 @@ void snoop_get_oid( /* * If snooped oid is NULL then we don't need take any action. */ - + return; } - + /* * We need use redis version of object type query here since we are * operating on VID value, and syncd is compiled against real SAI * implementation which has different function sai_object_type_query. */ - + sai_object_type_t object_type = redis_sai_object_type_query(vid); - + std::string str_vid = sai_serialize_object_id(vid); - + snoop_get_attr(object_type, str_vid, "NULL", "NULL"); } @@ -809,9 +809,9 @@ void snoop_get_attr_value( SWSS_LOG_ENTER(); std::string value = sai_serialize_attr_value(*meta, attr); - + SWSS_LOG_DEBUG("%s:%s", meta->attridname, value.c_str()); - + snoop_get_attr(meta->objecttype, str_object_id, meta->attridname, value); } @@ -827,94 +827,94 @@ void snoop_get_response( * NOTE: this method is operating on VIDs, all RIDs were translated outside * this method. */ - + /* * Vlan (including vlan 1) will need to be put into TEMP view this should * also be valid for all objects that were queried. */ - + for (uint32_t idx = 0; idx < attr_count; ++idx) { const sai_attribute_t &attr = attr_list[idx]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %d, attribute %d", object_type, attr.id); } - + /* * We should snoop oid values even if they are readonly we just note in * temp view that those objects exist on switch. */ - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: snoop_get_oid(attr.value.oid); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: snoop_get_oid_list(attr.value.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) snoop_get_oid(attr.value.aclfield.data.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) snoop_get_oid_list(attr.value.aclfield.data.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) snoop_get_oid(attr.value.aclaction.parameter.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) snoop_get_oid_list(attr.value.aclaction.parameter.objlist); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } - + if (SAI_HAS_FLAG_READ_ONLY(meta->flags)) { /* * If value is read only, we skip it, since after syncd restart we * won't be able to set/create it anyway. */ - + continue; } - + if (meta->objecttype == SAI_OBJECT_TYPE_PORT && meta->attrid == SAI_PORT_ATTR_HW_LANE_LIST) { /* * Skip port lanes for now since we don't create ports. */ - + SWSS_LOG_INFO("skipping %s for %s", meta->attridname, str_object_id.c_str()); continue; } - + /* * Put non readonly, and non oid attribute value to temp view. * @@ -924,7 +924,7 @@ void snoop_get_response( * Similar action can happen when we will do this on asicSet during * apply view. */ - + snoop_get_attr_value(str_object_id, meta, attr); } } @@ -940,25 +940,25 @@ void internal_syncd_get_send( SWSS_LOG_ENTER(); std::vector entry; - + if (status == SAI_STATUS_SUCCESS) { translate_rid_to_vid_list(object_type, switch_id, attr_count, attr_list); - + /* * Normal serialization + translate RID to VID. */ - + entry = SaiAttributeList::serialize_attr_list( object_type, attr_count, attr_list, false); - + /* * All oid values here are VIDs. */ - + snoop_get_response(object_type, str_object_id, attr_count, attr_list); } else if (status == SAI_STATUS_BUFFER_OVERFLOW) @@ -972,7 +972,7 @@ void internal_syncd_get_send( * different attributes can have different lists, many of them may * serialize only count, and will need to support that on the receiver. */ - + entry = SaiAttributeList::serialize_attr_list( object_type, attr_count, @@ -985,24 +985,24 @@ void internal_syncd_get_send( * Some other error, don't send attributes at all. */ } - + for (const auto &e: entry) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(e).c_str(), fvValue(e).c_str()); } - + std::string str_status = sai_serialize_status(status); - + SWSS_LOG_INFO("sending response for GET api with status: %s", str_status.c_str()); - + /* * Since we have only one get at a time, we don't have to serialize object * type and object id, only get status is required to be returned. Get * response will not put any data to table, only queue is used. */ - + getResponse->set(str_status, entry, "getresponse"); - + SWSS_LOG_INFO("response for GET api was send"); } @@ -1018,18 +1018,18 @@ void internal_syncd_api_send_response( * in OA/sairedis because same GET RESPONSE channel is used to generate * response for sairedis quad API. */ - + if (!options.syncMode) return; - + std::vector entry; - + std::string str_status = sai_serialize_status(status); - + SWSS_LOG_INFO("sending response for %d api with status: %s", api, str_status.c_str()); - + getResponse->set(str_status, entry, "getresponse"); - + SWSS_LOG_INFO("response for %d api was send", api); } @@ -1044,17 +1044,17 @@ const char* profile_get_value( SWSS_LOG_WARN("variable is null"); return NULL; } - + auto it = gProfileMap.find(variable); - + if (it == gProfileMap.end()) { SWSS_LOG_NOTICE("%s: NULL", variable); return NULL; } - + SWSS_LOG_NOTICE("%s: %s", variable, it->second.c_str()); - + return it->second.c_str(); } @@ -1070,30 +1070,30 @@ int profile_get_next_value( if (value == NULL) { SWSS_LOG_INFO("resetting profile map iterator"); - + gProfileIter = gProfileMap.begin(); return 0; } - + if (variable == NULL) { SWSS_LOG_WARN("variable is null"); return -1; } - + if (gProfileIter == gProfileMap.end()) { SWSS_LOG_INFO("iterator reached end"); return -1; } - + *variable = gProfileIter->first.c_str(); *value = gProfileIter->second.c_str(); - + SWSS_LOG_INFO("key: %s:%s", *variable, *value); - + gProfileIter++; - + return 0; } @@ -1109,13 +1109,13 @@ void startDiagShell() if (options.diagShell) { SWSS_LOG_NOTICE("starting diag shell thread"); - + /* * TODO actual switch id must be supplied */ - + std::thread diag_shell_thread = std::thread(sai_diag_shell, SAI_NULL_OBJECT_ID); - + diag_shell_thread.detach(); } } @@ -1126,19 +1126,19 @@ void on_switch_create( SWSS_LOG_ENTER(); sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid); - + if (switches.size() > 0) { SWSS_LOG_THROW("creating multiple switches is not supported yet, FIXME"); } - + /* * All needed data to populate switch should be obtained inside SaiSwitch * constructor, like getting all queues, ports, etc. */ - + switches[switch_vid] = std::make_shared(switch_vid, switch_rid); - + startDiagShell(); } @@ -1161,7 +1161,7 @@ void on_switch_remove( * * To support multiple switches this function needs to be refactored. */ - + SWSS_LOG_THROW("remove switch is not implemented, FIXME"); } @@ -1215,52 +1215,52 @@ sai_status_t handle_generic( * TODO: Could deserialize to meta key and then we could combine with non * object id. */ - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + SWSS_LOG_DEBUG("calling %s for %s", sai_serialize_common_api(api).c_str(), sai_serialize_object_type(object_type).c_str()); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = object_id; - + /* * We need to do translate vid/rid except for create, since create will * create new RID value, and we will have to map them to VID we received in * create query. */ - + /* * TODO: use metadata utils. */ - + auto info = sai_metadata_get_object_type_info(object_type); - + if (info->isnonobjectid) { SWSS_LOG_THROW("passing non object id %s as generic object", info->objecttypename); } - + switch (api) { case SAI_COMMON_API_CREATE: - + { /* * Object id is VID, we can use it to extract switch id. */ - + sai_object_id_t switch_id = redis_sai_switch_id_query(object_id); - + if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_THROW("invalid switch_id translated from VID 0x%lx", object_id); } - + if (object_type != SAI_OBJECT_TYPE_SWITCH) { /* @@ -1269,7 +1269,7 @@ sai_status_t handle_generic( * since rid doesn't exist yet, so skip translate for switch, * but use translate for all other objects. */ - + switch_id = translate_vid_to_rid(switch_id); } else @@ -1280,41 +1280,41 @@ sai_status_t handle_generic( * NOTE: to support multiple switches we need support * here for create. */ - + SWSS_LOG_THROW("creating multiple switches is not supported yet, FIXME"); } } - + sai_status_t status = info->create(&meta_key, switch_id, attr_count, attr_list); - + if (status == SAI_STATUS_SUCCESS) { sai_object_id_t real_object_id = meta_key.objectkey.key.object_id; - + /* * Object was created so new object id was generated we * need to save virtual id's to redis db. */ - + std::string str_vid = sai_serialize_object_id(object_id); std::string str_rid = sai_serialize_object_id(real_object_id); - + /* * TODO: This must be ATOMIC. * * To support multiple switches vid/rid map must be per switch. */ - + { - + g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); - + save_rid_and_vid_to_local(real_object_id, object_id); } - + SWSS_LOG_INFO("saved VID %s to RID %s", str_vid.c_str(), str_rid.c_str()); - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_create(switch_id); @@ -1322,36 +1322,36 @@ sai_status_t handle_generic( SWSS_LOG_NOTICE("Initialize gSwitchId with ID = 0x%lx", gSwitchId); } } - + return status; } - + case SAI_COMMON_API_REMOVE: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + sai_status_t status = info->remove(&meta_key); - + if (status == SAI_STATUS_SUCCESS) { std::string str_vid = sai_serialize_object_id(object_id); std::string str_rid = sai_serialize_object_id(rid); - + /* * TODO: This must be ATOMIC. */ - + { - + g_redisClient->hdel(VIDTORID, str_vid); g_redisClient->hdel(RIDTOVID, str_rid); - + remove_rid_and_vid_from_local(rid, object_id); } - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_remove(object_id); @@ -1379,48 +1379,48 @@ sai_status_t handle_generic( * also needs to be of internal/vendor default but we * can already deduce that. */ - + sai_object_id_t switch_vid = redis_sai_switch_id_query(object_id); - + if (switches.at(switch_vid)->isDiscoveredRid(rid)) { switches.at(switch_vid)->removeExistingObjectReference(rid); } } } - + return status; } - + case SAI_COMMON_API_SET: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + sai_status_t status = info->set(&meta_key, attr_list); - + if (is_set_attribute_workaround(meta_key.objecttype, attr_list->id, status)) { return SAI_STATUS_SUCCESS; } - + return status; } - + case SAI_COMMON_API_GET: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + return info->get(&meta_key, attr_count, attr_list); } - + default: - + SWSS_LOG_THROW("common api (%s) is not implemented", sai_serialize_common_api(api).c_str()); } } @@ -1431,25 +1431,25 @@ void translate_vid_to_rid_non_object_id( SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(meta_key.objecttype); - + if (info->isobjectid) { meta_key.objectkey.key.object_id = translate_vid_to_rid(meta_key.objectkey.key.object_id); - + return; } - + for (size_t j = 0; j < info->structmemberscount; ++j) { const sai_struct_member_info_t *m = info->structmembers[j]; - + if (m->membervaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID) { sai_object_id_t vid = m->getoid(&meta_key); - + sai_object_id_t rid = translate_vid_to_rid(vid); - + m->setoid(&meta_key, rid); } } @@ -1464,23 +1464,23 @@ sai_status_t handle_non_object_id( SWSS_LOG_ENTER(); translate_vid_to_rid_non_object_id(meta_key); - + auto info = sai_metadata_get_object_type_info(meta_key.objecttype); - + switch (api) { case SAI_COMMON_API_CREATE: return info->create(&meta_key, SAI_NULL_OBJECT_ID, attr_count, attr_list); - + case SAI_COMMON_API_REMOVE: return info->remove(&meta_key); - + case SAI_COMMON_API_SET: return info->set(&meta_key, attr_list); - + case SAI_COMMON_API_GET: return info->get(&meta_key, attr_count, attr_list); - + default: SWSS_LOG_THROW("other apis not implemented"); } @@ -1492,11 +1492,11 @@ void sendNotifyResponse( SWSS_LOG_ENTER(); std::string str_status = sai_serialize_status(status); - + std::vector entry; - + SWSS_LOG_INFO("sending response: %s", str_status.c_str()); - + getResponse->set(str_status, entry, "notify"); } @@ -1505,11 +1505,11 @@ void clearTempView() SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("clearing current TEMP VIEW"); - + SWSS_LOG_TIMER("clear temp view"); - + std::string pattern = TEMP_PREFIX + (ASIC_STATE_TABLE + std::string(":*")); - + /* * TODO this must be ATOMIC, and could use lua script. * @@ -1521,11 +1521,11 @@ void clearTempView() { g_redisClient->del(key); } - + /* * Also clear list of objects removed in init view mode. */ - + initViewRemovedVidSet.clear(); } @@ -1553,10 +1553,10 @@ void InspectAsic() } auto str_object_type = key.substr(start + 1, mid - start - 1); auto str_object_id = key.substr(mid + 1); - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + // Find all the attrid from ASIC DB, and use them to query ASIC auto hash = g_redisClient->hgetall(key); std::vector values; @@ -1564,28 +1564,28 @@ void InspectAsic() { const std::string &skey = kv.first; const std::string &svalue = kv.second; - + swss::FieldValueTuple fvt(skey, svalue); - + values.push_back(fvt); } - + SaiAttributeList list(object_type, values, false); - + sai_attribute_t *attr_list = list.get_attr_list(); - + uint32_t attr_count = list.get_attr_count(); - + SWSS_LOG_DEBUG("attr count: %u", list.get_attr_count()); - + if (attr_count == 0) { // TODO: how to check ASIC on ASIC DB key with NULL:NULL hash continue; // Just ignore } - + auto info = sai_metadata_get_object_type_info(object_type); - + // Call SAI Get API on this key sai_status_t status; switch (object_type) @@ -1594,38 +1594,38 @@ void InspectAsic() { sai_fdb_entry_t fdb_entry; sai_deserialize_fdb_entry(str_object_id, fdb_entry); - + fdb_entry.switch_id = translate_vid_to_rid(fdb_entry.switch_id); fdb_entry.bv_id = translate_vid_to_rid(fdb_entry.bv_id); - + status = sai_metadata_sai_fdb_api->get_fdb_entry_attribute(&fdb_entry, attr_count, attr_list); break; } - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: { sai_neighbor_entry_t neighbor_entry; sai_deserialize_neighbor_entry(str_object_id, neighbor_entry); - + neighbor_entry.switch_id = translate_vid_to_rid(neighbor_entry.switch_id); neighbor_entry.rif_id = translate_vid_to_rid(neighbor_entry.rif_id); - + status = sai_metadata_sai_neighbor_api->get_neighbor_entry_attribute(&neighbor_entry, attr_count, attr_list); break; } - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: { sai_route_entry_t route_entry; sai_deserialize_route_entry(str_object_id, route_entry); - + route_entry.switch_id = translate_vid_to_rid(route_entry.switch_id); route_entry.vr_id = translate_vid_to_rid(route_entry.vr_id); - + status = sai_metadata_sai_route_api->get_route_entry_attribute(&route_entry, attr_count, attr_list); break; } - + default: { if (info->isnonobjectid) @@ -1634,20 +1634,20 @@ void InspectAsic() sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); } - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = translate_vid_to_rid(object_id); - + status = info->get(&meta_key, attr_count, attr_list); break; } } - + if (status == SAI_STATUS_NOT_IMPLEMENTED) { SWSS_LOG_ERROR("not implemented get api: %s", str_object_type.c_str()); @@ -1656,25 +1656,25 @@ void InspectAsic() { SWSS_LOG_ERROR("failed to execute get api: %s", sai_serialize_status(status).c_str()); } - + // Compare fields and values from ASIC_DB and SAI response // Log the difference for (uint32_t index = 0; index < attr_count; ++index) { const sai_attribute_t *attr = &attr_list[index]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr->id); - + if (meta == NULL) { SWSS_LOG_ERROR("FATAL: failed to find metadata for object type %d and attr id %d", object_type, attr->id); break; } - + std::string str_attr_id = sai_serialize_attr_id(*meta); - + std::string str_attr_value = sai_serialize_attr_value(*meta, *attr, false); - + std::string hash_attr_value = hash[str_attr_id]; if (hash_attr_value == str_attr_value) { @@ -1694,19 +1694,19 @@ sai_status_t onApplyViewInFastFastBoot() sai_switch_api_t* sai_switch_api = nullptr; sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_FAST_API_ENABLE; attr.value.booldata = false; - + sai_status_t status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_FAST_API_ENABLE=false: %s", sai_serialize_status(status).c_str()); } - + return status; } @@ -1718,14 +1718,14 @@ sai_status_t notifySyncd( if (!options.useTempView) { SWSS_LOG_NOTICE("received %s, ignored since TEMP VIEW is not used, returning success", op.c_str()); - + sendNotifyResponse(SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; } - + static bool firstInitWasPerformed = false; - + if (g_veryFirstRun && firstInitWasPerformed && op == SYNCD_INIT_VIEW) { /* @@ -1734,95 +1734,95 @@ sai_status_t notifySyncd( * already exists and will fail with creating multiple switches * error. */ - + g_veryFirstRun = false; } else if (g_veryFirstRun) { SWSS_LOG_NOTICE("very first run is TRUE, op = %s", op.c_str()); - + sai_status_t status = SAI_STATUS_SUCCESS; - + /* * On the very first start of syncd, "compile" view is directly applied * on device, since it will make it easier to switch to new asic state * later on when we restart orch agent. */ - + if (op == SYNCD_INIT_VIEW) { /* * On first start we just do "apply" directly on asic so we set * init to false instead of true. */ - + g_asicInitViewMode = false; - + firstInitWasPerformed = true; - + /* * We need to clear current temp view to make space for new one. */ - + clearTempView(); } else if (op == SYNCD_APPLY_VIEW) { g_veryFirstRun = false; - + g_asicInitViewMode = false; - + if (options.startType == SAI_FASTFAST_BOOT) { /* fastfast boot configuration end */ status = onApplyViewInFastFastBoot(); } - + SWSS_LOG_NOTICE("setting very first run to FALSE, op = %s", op.c_str()); } else { SWSS_LOG_THROW("unknown operation: %s", op.c_str()); } - + sendNotifyResponse(status); - + return status; } - + if (op == SYNCD_INIT_VIEW) { if (g_asicInitViewMode) { SWSS_LOG_WARN("syncd is already in asic INIT VIEW mode, but received init again, orchagent restarted before apply?"); } - + g_asicInitViewMode = true; - + clearTempView(); - + /* * TODO: Currently as WARN to be easier to spot, later should be NOTICE. */ - + SWSS_LOG_WARN("syncd switched to INIT VIEW mode, all op will be saved to TEMP view"); - + sendNotifyResponse(SAI_STATUS_SUCCESS); } else if (op == SYNCD_APPLY_VIEW) { g_asicInitViewMode = false; - + /* * TODO: Currently as WARN to be easier to spot, later should be NOTICE. */ - + SWSS_LOG_WARN("syncd received APPLY VIEW, will translate"); - + sai_status_t status = syncdApplyView(); - + sendNotifyResponse(status); - + if (status == SAI_STATUS_SUCCESS) { /* @@ -1830,7 +1830,7 @@ sai_status_t notifySyncd( * need to clear local db, and all new VIDs will be queried using * redis. */ - + local_rid_to_vid.clear(); local_vid_to_rid.clear(); } @@ -1841,27 +1841,27 @@ sai_status_t notifySyncd( * executed, on asic, or asic is inconsistent state then we should * die or hang */ - + return status; } } else if (op == SYNCD_INSPECT_ASIC) { SWSS_LOG_NOTICE("syncd switched to INSPECT ASIC mode"); - + InspectAsic(); - + sendNotifyResponse(SAI_STATUS_SUCCESS); } else { SWSS_LOG_ERROR("unknown operation: %s", op.c_str()); - + sendNotifyResponse(SAI_STATUS_NOT_IMPLEMENTED); - + SWSS_LOG_THROW("notify syncd %s operation failed", op.c_str()); } - + return SAI_STATUS_SUCCESS; } @@ -1879,10 +1879,10 @@ std::vector extractCounterIdsGeneric( std::string field = fvField(v); T counterId; deserializeIdFn(field.c_str(), &counterId); - + counterIdList.push_back(counterId); } - + return counterIdList; } @@ -1900,7 +1900,7 @@ sai_status_t getStatsGeneric( kco, deserializeIdFn); counters.resize(counter_ids.size()); - + return getStatsFn( object_id, (uint32_t)counter_ids.size(), @@ -1920,7 +1920,7 @@ sai_status_t clearStatsGeneric( const std::vector counter_ids = extractCounterIdsGeneric( kco, deserializeIdFn); - + return clearStatsFn( object_id, static_cast(counter_ids.size()), @@ -1935,17 +1935,17 @@ sai_status_t processGetStatsEvent( const std::string &key = kfvKey(kco); const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_id_t rid = translate_vid_to_rid(object_id); sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + std::vector result; - + sai_status_t status = SAI_STATUS_SUCCESS; - + switch (object_type) { case SAI_OBJECT_TYPE_PORT: @@ -1976,9 +1976,9 @@ sai_status_t processGetStatsEvent( SWSS_LOG_ERROR("SAI object type %s not supported", str_object_type.c_str()); status = SAI_STATUS_NOT_SUPPORTED; } - + std::vector entry; - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to get stats"); @@ -1991,9 +1991,9 @@ sai_status_t processGetStatsEvent( entry.emplace_back(fvField(values[i]), std::to_string(result[i])); } } - + getResponse->set(sai_serialize_status(status), entry, "getresponse"); - + return status; } @@ -2005,7 +2005,7 @@ sai_status_t processClearStatsEvent( const std::string &key = kfvKey(kco); const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_id_t rid; @@ -2018,7 +2018,7 @@ sai_status_t processClearStatsEvent( getResponse->set(sai_serialize_status(status), fvTuples, "getresponse"); return status; } - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); switch (object_type) @@ -2034,7 +2034,7 @@ sai_status_t processClearStatsEvent( SWSS_LOG_ERROR("SAI object type %s not supported", str_object_type.c_str()); status = SAI_STATUS_NOT_SUPPORTED; } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to clear stats"); @@ -2046,7 +2046,7 @@ sai_status_t processClearStatsEvent( fvTuples.emplace_back(fvField(fv), ""); } } - + getResponse->set(sai_serialize_status(status), fvTuples, "getresponse"); return status; } @@ -2061,7 +2061,7 @@ void on_switch_create_in_init_view( /* * This needs to be refactored if we need multiple switch support. */ - + /* * We can have multiple switches here, but each switch is identified by * SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO. This attribute is treated as key, @@ -2086,7 +2086,7 @@ void on_switch_create_in_init_view( * Since we are creating switch here, we are sure that this switch don't * have any oid attributes set, so we can pass all attributes */ - + /* * Multiple switches scenario with changed order: * @@ -2100,7 +2100,7 @@ void on_switch_create_in_init_view( * * Currently we don't have good solution for that so we will throw in that case. */ - + if (switches.size() == 0) { /* @@ -2112,16 +2112,16 @@ void on_switch_create_in_init_view( * This scenario can happen when you start syncd on empty database and * then you quit and restart it again. */ - + sai_object_id_t switch_rid; - + sai_status_t status; - + { SWSS_LOG_TIMER("cold boot: create switch"); status = sai_metadata_sai_switch_api->create_switch(&switch_rid, attr_count, attr_list); } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to create switch in init view mode: %s", @@ -2137,27 +2137,27 @@ void on_switch_create_in_init_view( * Object was created so new object id was generated we * need to save virtual id's to redis db. */ - + std::string str_vid = sai_serialize_object_id(switch_vid); std::string str_rid = sai_serialize_object_id(switch_rid); - + SWSS_LOG_NOTICE("created real switch VID %s to RID %s in init view mode", str_vid.c_str(), str_rid.c_str()); - + /* * TODO: This must be ATOMIC. * * To support multiple switches vid/rid map must be per switch. */ - + g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); - + save_rid_and_vid_to_local(switch_rid, switch_vid); - + /* * Make switch initialization and get all default data. */ - + switches[switch_vid] = std::make_shared(switch_vid, switch_rid); } else if (switches.size() == 1) @@ -2167,29 +2167,29 @@ void on_switch_create_in_init_view( * info and we need to know that current switch VID also should match * since it's deterministic created. */ - + auto sw = switches.begin()->second; - + /* * Switches VID must match, since it's deterministic. */ - + if (switch_vid != sw->getVid()) { SWSS_LOG_THROW("created switch VID don't match: previous %s, current: %s", sai_serialize_object_id(switch_vid).c_str(), sai_serialize_object_id(sw->getVid()).c_str()); } - + /* * Also hardware info also must match. */ - + std::string currentHw = sw->getHardwareInfo(); std::string newHw; - + auto attr = sai_metadata_get_attr_by_id(SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO, attr_count, attr_list); - + if (attr == NULL) { /* @@ -2199,15 +2199,15 @@ void on_switch_create_in_init_view( else { SWSS_LOG_DEBUG("new switch contains hardware info of length %u", attr->value.s8list.count); - + newHw = std::string((char*)attr->value.s8list.list, attr->value.s8list.count); } - + if (currentHw != newHw) { SWSS_LOG_THROW("hardware info missmatch: current '%s' vs new '%s'", currentHw.c_str(), newHw.c_str()); } - + SWSS_LOG_NOTICE("current switch hardware info: '%s'", currentHw.c_str()); } else @@ -2231,17 +2231,17 @@ sai_status_t processEventInInitViewMode( * but if that happen, this id will be treated as "new" object instead of * existing one. */ - + /* * TODO: use metadata utils. */ - + auto info = sai_metadata_get_object_type_info(object_type); - + switch (api) { case SAI_COMMON_API_CREATE: - + if (info->isnonobjectid) { /* @@ -2252,28 +2252,28 @@ sai_status_t processEventInInitViewMode( { sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + /* * Object ID here is actual VID returned from redis during * creation this is floating VID in init view mode. */ - + SWSS_LOG_DEBUG("generic create (init view) for %s, floating VID: %s", sai_serialize_object_type(object_type).c_str(), sai_serialize_object_id(object_id).c_str()); - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_create_in_init_view(object_id, attr_count, attr_list); } } - + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_REMOVE: - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { /* @@ -2284,10 +2284,10 @@ sai_status_t processEventInInitViewMode( * * To support multiple switches this case must be refactored. */ - + SWSS_LOG_THROW("remove switch (%s) is not supported in init view mode yet! FIXME", str_object_id.c_str()); } - + if (!info->isnonobjectid) { /* @@ -2300,32 +2300,32 @@ sai_status_t processEventInInitViewMode( * need to have a list of removed objects, and then only * populate objects which not exist on removed list. */ - + sai_object_id_t object_vid; sai_deserialize_object_id(str_object_id, object_vid); - + initViewRemovedVidSet.insert(object_vid); } - + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_SET: - + /* * We support SET api on all objects in init view mode. */ - + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_GET: - + { sai_status_t status; - + if (info->isnonobjectid) { /* @@ -2334,20 +2334,20 @@ sai_status_t processEventInInitViewMode( * since user explicitly know what attributes were set, similar * for other non object id types. */ - + SWSS_LOG_ERROR("get is not supported on %s in init view mode", sai_serialize_object_type(object_type).c_str()); - + status = SAI_STATUS_NOT_SUPPORTED; } else { sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + SWSS_LOG_DEBUG("generic get (init view) for object type %s:%s", sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); - + /* * Object must exists, we can't call GET on created object * in init view mode, get here can be called on existing @@ -2362,19 +2362,19 @@ sai_status_t processEventInInitViewMode( * Translate vid to rid will make sure that object exist * and it have RID defined, so we can query it. */ - + sai_object_id_t rid = translate_vid_to_rid(object_id); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = rid; - + status = info->get(&meta_key, attr_count, attr_list); } - + sai_object_id_t switch_id; - + if (switches.size() == 1) { /* @@ -2386,7 +2386,7 @@ sai_status_t processEventInInitViewMode( * can extract switch id, we could also have this method * inside metadata to get meta key. */ - + switch_id = switches.begin()->second->getVid(); } else @@ -2395,17 +2395,17 @@ sai_status_t processEventInInitViewMode( * This needs to be updated to support multiple switches * scenario. */ - + SWSS_LOG_THROW("multiple switches are not supported yet: %zu", switches.size()); } - + internal_syncd_get_send(object_type, str_object_id, switch_id, status, attr_count, attr_list); - + return status; } - + default: - + SWSS_LOG_THROW("common api (%s) is not implemented in init view mode", sai_serialize_common_api(api).c_str()); } @@ -2418,39 +2418,39 @@ sai_object_id_t extractSwitchVid( SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(object_type); - + /* * Could be replaced by meta_key. */ - + sai_fdb_entry_t fdb_entry; sai_neighbor_entry_t neighbor_entry; sai_route_entry_t route_entry; sai_object_id_t oid; - + switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: sai_deserialize_fdb_entry(str_object_id, fdb_entry); return fdb_entry.switch_id; - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: sai_deserialize_neighbor_entry(str_object_id, neighbor_entry); return neighbor_entry.switch_id; - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: sai_deserialize_route_entry(str_object_id, route_entry); return route_entry.switch_id; - + default: - + if (info->isnonobjectid) { SWSS_LOG_THROW("passing non object id %s as generic object", info->objecttypename); } - + sai_deserialize_object_id(str_object_id, oid); - + return redis_sai_switch_id_query(oid); } } @@ -2467,16 +2467,16 @@ sai_status_t handle_bulk_generic( * Since we don't have asic support yet for bulk api, just execute one by * one. */ - + for (size_t idx = 0; idx < object_ids.size(); ++idx) { sai_status_t status = SAI_STATUS_FAILURE; - + auto &list = attributes[idx]; - + sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); - + sai_object_meta_key_t meta_key; meta_key.objecttype = object_type; switch (object_type) @@ -2493,7 +2493,7 @@ sai_status_t handle_bulk_generic( default: SWSS_LOG_THROW("invalid object_type: %s", sai_serialize_object_type(object_type).c_str()); } - + if (api == (sai_common_api_t)SAI_COMMON_API_BULK_SET) { status = handle_non_object_id(meta_key, SAI_COMMON_API_SET, attr_count, attr_list); @@ -2510,14 +2510,14 @@ sai_status_t handle_bulk_generic( { SWSS_LOG_THROW("api %d is not supported in bulk route", api); } - + if (status != SAI_STATUS_SUCCESS) { internal_syncd_api_send_response(api, status); return status; } } - + return SAI_STATUS_SUCCESS; } @@ -2529,80 +2529,80 @@ sai_status_t processBulkEvent( SWSS_LOG_ENTER(); const std::string &key = kfvKey(kco); - + std::string str_object_type = key.substr(0, key.find(":")); - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + const std::vector &values = kfvFieldsValues(kco); - + // key = str_object_id // val = attrid=attrvalue|... - + std::vector object_ids; - + std::vector> attributes; - + for (const auto &fvt: values) { std::string str_object_id = fvField(fvt); std::string joined = fvValue(fvt); - + // decode values - + auto v = swss::tokenize(joined, '|'); - + object_ids.push_back(str_object_id); - + std::vector entries; // attributes per object id - + for (size_t i = 0; i < v.size(); ++i) { const std::string item = v.at(i); - + auto start = item.find_first_of("="); - + auto field = item.substr(0, start); auto value = item.substr(start + 1); - + swss::FieldValueTuple entry(field, value); - + entries.push_back(entry); } - + // since now we converted this to proper list, we can extract attributes - + std::shared_ptr list = std::make_shared(object_type, entries, false); - + attributes.push_back(list); } - + SWSS_LOG_NOTICE("bulk %s execute with %zu items", str_object_type.c_str(), object_ids.size()); - + if (isInitViewMode()) { SWSS_LOG_THROW("bulk api (%d) is not supported in init view mode", api); } - + if (api != SAI_COMMON_API_BULK_GET) { // translate attributes for all objects - + for (auto &list: attributes) { sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); - + translate_vid_to_rid_list(object_type, attr_count, attr_list); } } - + sai_status_t status; - + switch (object_type) { case SAI_OBJECT_TYPE_ROUTE_ENTRY: @@ -2610,20 +2610,20 @@ sai_status_t processBulkEvent( case SAI_OBJECT_TYPE_FDB_ENTRY: status = handle_bulk_generic(object_type, object_ids, api, attributes); break; - + default: SWSS_LOG_THROW("bulk api for %s is not supported yet, FIXME", sai_serialize_object_type(object_type).c_str()); } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to execute bulk api: %s", sai_serialize_status(status).c_str()); } - + internal_syncd_api_send_response(api, status); - + return status; } @@ -2634,38 +2634,38 @@ sai_status_t processFdbFlush( const std::string &key = kfvKey(kco); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t switch_vid; - + sai_deserialize_object_id(str_object_id, switch_vid); - + sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid); - + const std::vector &values = kfvFieldsValues(kco); - + for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SaiAttributeList list(SAI_OBJECT_TYPE_FDB_FLUSH, values, false); - + /* * Attribute list can't be const since we will use it to translate VID to * RID in place. */ - + sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); - + translate_vid_to_rid_list(SAI_OBJECT_TYPE_FDB_FLUSH, attr_count, attr_list); - + sai_status_t status = sai_metadata_sai_fdb_api->flush_fdb_entries(switch_rid, attr_count, attr_list); - + std::vector en; - + getResponse->set(sai_serialize_status(status), en, "flushresponse"); - + return status; } @@ -2675,13 +2675,13 @@ sai_status_t processEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + swss::KeyOpFieldsValuesTuple kco; - + sai_status_t status = SAI_STATUS_SUCCESS; - + do { - + if (isInitViewMode()) { /* @@ -2689,34 +2689,34 @@ sai_status_t processEvent( * specify temporary view prefix in consumer since consumer puts data * to redis db. */ - + consumer.pop(kco, TEMP_PREFIX); } else { consumer.pop(kco); } - + const std::string &key = kfvKey(kco); const std::string &op = kfvOp(kco); - + if (key.length() == 0) { SWSS_LOG_DEBUG("no elements in m_buffer"); return status; } - + /* * TODO: Key is serialized meta_key, we could use deserialize * to extract it here. */ - + const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + SWSS_LOG_INFO("key: %s op: %s", key.c_str(), op.c_str()); - + sai_common_api_t api = SAI_COMMON_API_MAX; - + if (op == "create") { api = SAI_COMMON_API_CREATE; @@ -2761,42 +2761,42 @@ sai_status_t processEvent( { SWSS_LOG_THROW("api '%s' is not implemented", op.c_str()); } - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + /* * TODO: use metadata utils is object type valid. */ - + if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX) { SWSS_LOG_THROW("undefined object type %s", sai_serialize_object_type(object_type).c_str()); } - + const std::vector &values = kfvFieldsValues(kco); - + for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SaiAttributeList list(object_type, values, false); - + /* * Attribute list can't be const since we will use it to translate VID to * RID in place. */ - + sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); - + /* * NOTE: This check pointers must be executed before init view mode, since * this methods replaces pointers from orchagent memory space to syncd * memory space. */ - + if (object_type == SAI_OBJECT_TYPE_SWITCH && (api == SAI_COMMON_API_CREATE || api == SAI_COMMON_API_SET)) { /* @@ -2805,15 +2805,15 @@ sai_status_t processEvent( * will internally check whether pointer is null or not, so we here * will receive all notifications, but redis only those that were set. */ - + check_notifications_pointers(attr_count, attr_list); } - + if (isInitViewMode()) { return processEventInInitViewMode(object_type, str_object_id, api, attr_count, attr_list); } - + if (api != SAI_COMMON_API_GET) { /* @@ -2821,51 +2821,51 @@ sai_status_t processEvent( * buffer so then all OIDs will be NULL, and translation will also * convert them to NULL. */ - + SWSS_LOG_DEBUG("translating VID to RIDs on all attributes"); - + translate_vid_to_rid_list(object_type, attr_count, attr_list); } - + // TODO use metadata utils auto info = sai_metadata_get_object_type_info(object_type); - + /* * TODO use sai meta key deserialize */ - + if (info->isnonobjectid) { sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; - + switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: sai_deserialize_fdb_entry(str_object_id, meta_key.objectkey.key.fdb_entry); break; - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: sai_deserialize_neighbor_entry(str_object_id, meta_key.objectkey.key.neighbor_entry); break; - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: sai_deserialize_route_entry(str_object_id, meta_key.objectkey.key.route_entry); break; - + default: - + SWSS_LOG_THROW("non object id %s is not supported yet, FIXME", info->objecttypename); } - + status = handle_non_object_id(meta_key, api, attr_count, attr_list); } else { status = handle_generic(object_type, str_object_id, api, attr_count, attr_list); } - + if (api == SAI_COMMON_API_GET) { if (status != SAI_STATUS_SUCCESS) @@ -2875,37 +2875,37 @@ sai_status_t processEvent( op.c_str(), sai_serialize_status(status).c_str()); } - + /* * Extracting switch is double work here, we can avoid this when we * will use meta_key. */ - + sai_object_id_t switch_vid = extractSwitchVid(object_type, str_object_id); - + internal_syncd_get_send(object_type, str_object_id, switch_vid, status, attr_count, attr_list); } else if (status != SAI_STATUS_SUCCESS) { internal_syncd_api_send_response(api, status); - + if (!info->isnonobjectid && api == SAI_COMMON_API_SET) { sai_object_id_t vid; sai_deserialize_object_id(str_object_id, vid); - + sai_object_id_t rid = translate_vid_to_rid(vid); - + SWSS_LOG_ERROR("VID: %s RID: %s", sai_serialize_object_id(vid).c_str(), sai_serialize_object_id(rid).c_str()); } - + for (const auto &v: values) { SWSS_LOG_ERROR("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SWSS_LOG_THROW("failed to execute api: %s, key: %s, status: %s", op.c_str(), key.c_str(), @@ -2915,9 +2915,9 @@ sai_status_t processEvent( { internal_syncd_api_send_response(api, status); } - + } while (!consumer.empty()); - + return status; } @@ -2931,22 +2931,22 @@ void processFlexCounterGroupEvent( std::lock_guard lock(g_mutex); consumer.pop(kco); } - + const auto &groupName = kfvKey(kco); const auto &op = kfvOp(kco); const auto values = kfvFieldsValues(kco); - + if (op == DEL_COMMAND) { FlexCounter::removeCounterPlugin(groupName); return; } - + for (const auto& valuePair : values) { const auto field = fvField(valuePair); const auto value = fvValue(valuePair); - + if (op == SET_COMMAND) { if (field == POLL_INTERVAL_FIELD) @@ -3009,16 +3009,16 @@ bool tryPopFlexCounterEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + if (g_flexCounterEventQueue.empty()) { return false; } - + kco = g_flexCounterEventQueue.front(); - + g_flexCounterEventQueue.pop(); - + return true; } @@ -3028,7 +3028,7 @@ void pushFlexCounterEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + g_flexCounterEventQueue.push(kco); } @@ -3042,17 +3042,17 @@ void processFlexCounterEventThread() while (g_processFlexCounterEventThreadRun) { swss::KeyOpFieldsValuesTuple kco; - + if (tryPopFlexCounterEvent(kco)) { if (!processFlexCounterEvent(kco)) { // event was not successfully processed, put it again to the queue - + pushFlexCounterEvent(kco); } } - + sleep(1); } } @@ -3063,19 +3063,19 @@ void processFlexCounterEvent( SWSS_LOG_ENTER(); swss::KeyOpFieldsValuesTuple kco; - + { std::lock_guard lock(g_mutex); consumer.pop(kco); } - + // because flex counter event can arrive independently (on RIF interface) // it may happen that it will be picked up from the select api before // actual interface will be created, and subscription for counters will // fail, so let's process each request in the thread and use queue for // arriving events, and failed events will be put back to the queue until // they will be processed - + pushFlexCounterEvent(kco); } @@ -3086,18 +3086,18 @@ bool processFlexCounterEvent( const auto &key = kfvKey(kco); const std::string &op = kfvOp(kco); - + std::size_t delimiter = key.find_first_of(":"); if (delimiter == std::string::npos) { SWSS_LOG_ERROR("Failed to parse the key %s", key.c_str()); - + return true; // if key is invalid there is no need to process this event again } - + const auto groupName = key.substr(0, delimiter); const auto vidStr = key.substr(delimiter+1); - + sai_object_id_t vid = SAI_NULL_OBJECT_ID; sai_deserialize_object_id(vidStr, vid); sai_object_id_t rid; @@ -3110,10 +3110,10 @@ bool processFlexCounterEvent( return false; } } - + sai_object_type_t objectType = redis_sai_object_type_query(vid); // VID and RID will have the same object type std::string objectTypeStr = sai_serialize_object_type(objectType); - + if (op == DEL_COMMAND) { if (objectType == SAI_OBJECT_TYPE_PORT) From bad91f1e681988f0a636d99ae21acf2baff56d98 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 20 Jul 2019 21:03:39 -0700 Subject: [PATCH 09/20] Update syncd.cpp --- syncd/syncd.cpp | 474 ++++++++++++++++++++++++------------------------ 1 file changed, 237 insertions(+), 237 deletions(-) diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 3d5a176e9..adb13dd7c 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -136,7 +136,7 @@ void notify_OA_about_syncd_exception() std::vector entry; SWSS_LOG_NOTICE("sending switch_shutdown_request notification to OA"); - + notifications->send("switch_shutdown_request", "", entry); SWSS_LOG_NOTICE("notification send successfull"); @@ -544,19 +544,19 @@ void translate_rid_to_vid_list( if (attr.value.aclaction.enable) translate_list_rid_to_vid(attr.value.aclaction.parameter.objlist, switch_id); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } } @@ -576,7 +576,7 @@ sai_object_id_t translate_vid_to_rid( if (vid == SAI_NULL_OBJECT_ID) { SWSS_LOG_DEBUG("translated VID null to RID null"); - + return SAI_NULL_OBJECT_ID; } @@ -612,7 +612,7 @@ sai_object_id_t translate_vid_to_rid( SWSS_LOG_THROW("can't get RID in init view mode - don't query created objects"); } - + SWSS_LOG_THROW("unable to get RID for VID: 0x%lx", vid); } @@ -630,7 +630,7 @@ sai_object_id_t translate_vid_to_rid( local_vid_to_rid[vid] = rid; SWSS_LOG_DEBUG("translated VID 0x%lx to RID 0x%lx", vid, rid); - + return rid; } @@ -674,60 +674,60 @@ void translate_vid_to_rid_list( * All id's received from sairedis should be virtual, so lets translate * them to real id's before we execute actual api. */ - + for (uint32_t i = 0; i < attr_count; i++) { sai_attribute_t &attr = attr_list[i]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %x, attribute %d", object_type, attr.id); } - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: attr.value.oid = translate_vid_to_rid(attr.value.oid); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: translate_list_vid_to_rid(attr.value.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) attr.value.aclfield.data.oid = translate_vid_to_rid(attr.value.aclfield.data.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) translate_list_vid_to_rid(attr.value.aclfield.data.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) attr.value.aclaction.parameter.oid = translate_vid_to_rid(attr.value.aclaction.parameter.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) translate_list_vid_to_rid(attr.value.aclaction.parameter.objlist); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } } @@ -745,18 +745,18 @@ void snoop_get_attr( * Note: str_object_type + ":" + str_object_id is meta_key we can us that * here later on. */ - + std::string str_object_type = sai_serialize_object_type(object_type); - + std::string prefix = ""; - + if (isInitViewMode()) { prefix = TEMP_PREFIX; } - + std::string key = prefix + (ASIC_STATE_TABLE + (":" + str_object_type + ":" + str_object_id)); - + SWSS_LOG_DEBUG("%s", key.c_str()); @@ -773,20 +773,20 @@ void snoop_get_oid( /* * If snooped oid is NULL then we don't need take any action. */ - + return; } - + /* * We need use redis version of object type query here since we are * operating on VID value, and syncd is compiled against real SAI * implementation which has different function sai_object_type_query. */ - + sai_object_type_t object_type = redis_sai_object_type_query(vid); - + std::string str_vid = sai_serialize_object_id(vid); - + snoop_get_attr(object_type, str_vid, "NULL", "NULL"); } @@ -809,9 +809,9 @@ void snoop_get_attr_value( SWSS_LOG_ENTER(); std::string value = sai_serialize_attr_value(*meta, attr); - + SWSS_LOG_DEBUG("%s:%s", meta->attridname, value.c_str()); - + snoop_get_attr(meta->objecttype, str_object_id, meta->attridname, value); } @@ -832,89 +832,89 @@ void snoop_get_response( * Vlan (including vlan 1) will need to be put into TEMP view this should * also be valid for all objects that were queried. */ - + for (uint32_t idx = 0; idx < attr_count; ++idx) { const sai_attribute_t &attr = attr_list[idx]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr.id); - + if (meta == NULL) { SWSS_LOG_THROW("unable to get metadata for object type %d, attribute %d", object_type, attr.id); } - + /* * We should snoop oid values even if they are readonly we just note in * temp view that those objects exist on switch. */ - + switch (meta->attrvaluetype) { case SAI_ATTR_VALUE_TYPE_OBJECT_ID: snoop_get_oid(attr.value.oid); break; - + case SAI_ATTR_VALUE_TYPE_OBJECT_LIST: snoop_get_oid_list(attr.value.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_ID: if (attr.value.aclfield.enable) snoop_get_oid(attr.value.aclfield.data.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_FIELD_DATA_OBJECT_LIST: if (attr.value.aclfield.enable) snoop_get_oid_list(attr.value.aclfield.data.objlist); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_ID: if (attr.value.aclaction.enable) snoop_get_oid(attr.value.aclaction.parameter.oid); break; - + case SAI_ATTR_VALUE_TYPE_ACL_ACTION_DATA_OBJECT_LIST: if (attr.value.aclaction.enable) snoop_get_oid_list(attr.value.aclaction.parameter.objlist); break; - + default: - + /* * If in future new attribute with object id will be added this * will make sure that we will need to add handler here. */ - + if (meta->isoidattribute) { SWSS_LOG_THROW("attribute %s is object id, but not processed, FIXME", meta->attridname); } - + break; } - + if (SAI_HAS_FLAG_READ_ONLY(meta->flags)) { /* * If value is read only, we skip it, since after syncd restart we * won't be able to set/create it anyway. */ - + continue; } - + if (meta->objecttype == SAI_OBJECT_TYPE_PORT && meta->attrid == SAI_PORT_ATTR_HW_LANE_LIST) { /* * Skip port lanes for now since we don't create ports. */ - + SWSS_LOG_INFO("skipping %s for %s", meta->attridname, str_object_id.c_str()); continue; } - + /* * Put non readonly, and non oid attribute value to temp view. * @@ -924,7 +924,7 @@ void snoop_get_response( * Similar action can happen when we will do this on asicSet during * apply view. */ - + snoop_get_attr_value(str_object_id, meta, attr); } } @@ -940,25 +940,25 @@ void internal_syncd_get_send( SWSS_LOG_ENTER(); std::vector entry; - + if (status == SAI_STATUS_SUCCESS) { translate_rid_to_vid_list(object_type, switch_id, attr_count, attr_list); - + /* * Normal serialization + translate RID to VID. */ - + entry = SaiAttributeList::serialize_attr_list( object_type, attr_count, attr_list, false); - + /* * All oid values here are VIDs. */ - + snoop_get_response(object_type, str_object_id, attr_count, attr_list); } else if (status == SAI_STATUS_BUFFER_OVERFLOW) @@ -972,7 +972,7 @@ void internal_syncd_get_send( * different attributes can have different lists, many of them may * serialize only count, and will need to support that on the receiver. */ - + entry = SaiAttributeList::serialize_attr_list( object_type, attr_count, @@ -985,24 +985,24 @@ void internal_syncd_get_send( * Some other error, don't send attributes at all. */ } - + for (const auto &e: entry) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(e).c_str(), fvValue(e).c_str()); } - + std::string str_status = sai_serialize_status(status); - + SWSS_LOG_INFO("sending response for GET api with status: %s", str_status.c_str()); - + /* * Since we have only one get at a time, we don't have to serialize object * type and object id, only get status is required to be returned. Get * response will not put any data to table, only queue is used. */ - + getResponse->set(str_status, entry, "getresponse"); - + SWSS_LOG_INFO("response for GET api was send"); } @@ -1018,16 +1018,16 @@ void internal_syncd_api_send_response( * in OA/sairedis because same GET RESPONSE channel is used to generate * response for sairedis quad API. */ - + if (!options.syncMode) return; - + std::vector entry; - + std::string str_status = sai_serialize_status(status); - + SWSS_LOG_INFO("sending response for %d api with status: %s", api, str_status.c_str()); - + getResponse->set(str_status, entry, "getresponse"); SWSS_LOG_INFO("response for %d api was send", api); @@ -1046,15 +1046,15 @@ const char* profile_get_value( } auto it = gProfileMap.find(variable); - + if (it == gProfileMap.end()) { SWSS_LOG_NOTICE("%s: NULL", variable); return NULL; } - + SWSS_LOG_NOTICE("%s: %s", variable, it->second.c_str()); - + return it->second.c_str(); } @@ -1070,11 +1070,11 @@ int profile_get_next_value( if (value == NULL) { SWSS_LOG_INFO("resetting profile map iterator"); - + gProfileIter = gProfileMap.begin(); return 0; } - + if (variable == NULL) { SWSS_LOG_WARN("variable is null"); @@ -1086,14 +1086,14 @@ int profile_get_next_value( SWSS_LOG_INFO("iterator reached end"); return -1; } - + *variable = gProfileIter->first.c_str(); *value = gProfileIter->second.c_str(); - + SWSS_LOG_INFO("key: %s:%s", *variable, *value); - + gProfileIter++; - + return 0; } @@ -1109,13 +1109,13 @@ void startDiagShell() if (options.diagShell) { SWSS_LOG_NOTICE("starting diag shell thread"); - + /* * TODO actual switch id must be supplied */ - + std::thread diag_shell_thread = std::thread(sai_diag_shell, SAI_NULL_OBJECT_ID); - + diag_shell_thread.detach(); } } @@ -1126,19 +1126,19 @@ void on_switch_create( SWSS_LOG_ENTER(); sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid); - + if (switches.size() > 0) { SWSS_LOG_THROW("creating multiple switches is not supported yet, FIXME"); } - + /* * All needed data to populate switch should be obtained inside SaiSwitch * constructor, like getting all queues, ports, etc. */ - + switches[switch_vid] = std::make_shared(switch_vid, switch_rid); - + startDiagShell(); } @@ -1161,7 +1161,7 @@ void on_switch_remove( * * To support multiple switches this function needs to be refactored. */ - + SWSS_LOG_THROW("remove switch is not implemented, FIXME"); } @@ -1215,31 +1215,31 @@ sai_status_t handle_generic( * TODO: Could deserialize to meta key and then we could combine with non * object id. */ - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + SWSS_LOG_DEBUG("calling %s for %s", sai_serialize_common_api(api).c_str(), sai_serialize_object_type(object_type).c_str()); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = object_id; - + /* * We need to do translate vid/rid except for create, since create will * create new RID value, and we will have to map them to VID we received in * create query. */ - + /* * TODO: use metadata utils. */ auto info = sai_metadata_get_object_type_info(object_type); - + if (info->isnonobjectid) { SWSS_LOG_THROW("passing non object id %s as generic object", info->objecttypename); @@ -1248,19 +1248,19 @@ sai_status_t handle_generic( switch (api) { case SAI_COMMON_API_CREATE: - + { /* * Object id is VID, we can use it to extract switch id. */ - + sai_object_id_t switch_id = redis_sai_switch_id_query(object_id); - + if (switch_id == SAI_NULL_OBJECT_ID) { SWSS_LOG_THROW("invalid switch_id translated from VID 0x%lx", object_id); } - + if (object_type != SAI_OBJECT_TYPE_SWITCH) { /* @@ -1269,7 +1269,7 @@ sai_status_t handle_generic( * since rid doesn't exist yet, so skip translate for switch, * but use translate for all other objects. */ - + switch_id = translate_vid_to_rid(switch_id); } else @@ -1280,39 +1280,39 @@ sai_status_t handle_generic( * NOTE: to support multiple switches we need support * here for create. */ - + SWSS_LOG_THROW("creating multiple switches is not supported yet, FIXME"); } } - + sai_status_t status = info->create(&meta_key, switch_id, attr_count, attr_list); - + if (status == SAI_STATUS_SUCCESS) { sai_object_id_t real_object_id = meta_key.objectkey.key.object_id; - + /* * Object was created so new object id was generated we * need to save virtual id's to redis db. */ - + std::string str_vid = sai_serialize_object_id(object_id); std::string str_rid = sai_serialize_object_id(real_object_id); - + /* * TODO: This must be ATOMIC. * * To support multiple switches vid/rid map must be per switch. */ - + { - + g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); - + save_rid_and_vid_to_local(real_object_id, object_id); } - + SWSS_LOG_INFO("saved VID %s to RID %s", str_vid.c_str(), str_rid.c_str()); if (object_type == SAI_OBJECT_TYPE_SWITCH) @@ -1322,36 +1322,36 @@ sai_status_t handle_generic( SWSS_LOG_NOTICE("Initialize gSwitchId with ID = 0x%lx", gSwitchId); } } - + return status; } - + case SAI_COMMON_API_REMOVE: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + sai_status_t status = info->remove(&meta_key); - + if (status == SAI_STATUS_SUCCESS) { std::string str_vid = sai_serialize_object_id(object_id); std::string str_rid = sai_serialize_object_id(rid); - + /* * TODO: This must be ATOMIC. */ - + { - + g_redisClient->hdel(VIDTORID, str_vid); g_redisClient->hdel(RIDTOVID, str_rid); - + remove_rid_and_vid_from_local(rid, object_id); } - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_remove(object_id); @@ -1379,48 +1379,48 @@ sai_status_t handle_generic( * also needs to be of internal/vendor default but we * can already deduce that. */ - + sai_object_id_t switch_vid = redis_sai_switch_id_query(object_id); - + if (switches.at(switch_vid)->isDiscoveredRid(rid)) { switches.at(switch_vid)->removeExistingObjectReference(rid); } } } - + return status; } - + case SAI_COMMON_API_SET: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + sai_status_t status = info->set(&meta_key, attr_list); - + if (is_set_attribute_workaround(meta_key.objecttype, attr_list->id, status)) { return SAI_STATUS_SUCCESS; } - + return status; } - + case SAI_COMMON_API_GET: - + { sai_object_id_t rid = translate_vid_to_rid(object_id); - + meta_key.objectkey.key.object_id = rid; - + return info->get(&meta_key, attr_count, attr_list); } - + default: - + SWSS_LOG_THROW("common api (%s) is not implemented", sai_serialize_common_api(api).c_str()); } } @@ -1431,25 +1431,25 @@ void translate_vid_to_rid_non_object_id( SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(meta_key.objecttype); - + if (info->isobjectid) { meta_key.objectkey.key.object_id = translate_vid_to_rid(meta_key.objectkey.key.object_id); - + return; } - + for (size_t j = 0; j < info->structmemberscount; ++j) { const sai_struct_member_info_t *m = info->structmembers[j]; - + if (m->membervaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID) { sai_object_id_t vid = m->getoid(&meta_key); - + sai_object_id_t rid = translate_vid_to_rid(vid); - + m->setoid(&meta_key, rid); } } @@ -1464,23 +1464,23 @@ sai_status_t handle_non_object_id( SWSS_LOG_ENTER(); translate_vid_to_rid_non_object_id(meta_key); - + auto info = sai_metadata_get_object_type_info(meta_key.objecttype); - + switch (api) { case SAI_COMMON_API_CREATE: return info->create(&meta_key, SAI_NULL_OBJECT_ID, attr_count, attr_list); - + case SAI_COMMON_API_REMOVE: return info->remove(&meta_key); - + case SAI_COMMON_API_SET: return info->set(&meta_key, attr_list); - + case SAI_COMMON_API_GET: return info->get(&meta_key, attr_count, attr_list); - + default: SWSS_LOG_THROW("other apis not implemented"); } @@ -1492,11 +1492,11 @@ void sendNotifyResponse( SWSS_LOG_ENTER(); std::string str_status = sai_serialize_status(status); - + std::vector entry; - + SWSS_LOG_INFO("sending response: %s", str_status.c_str()); - + getResponse->set(str_status, entry, "notify"); } @@ -1505,11 +1505,11 @@ void clearTempView() SWSS_LOG_ENTER(); SWSS_LOG_NOTICE("clearing current TEMP VIEW"); - + SWSS_LOG_TIMER("clear temp view"); - + std::string pattern = TEMP_PREFIX + (ASIC_STATE_TABLE + std::string(":*")); - + /* * TODO this must be ATOMIC, and could use lua script. * @@ -1521,11 +1521,11 @@ void clearTempView() { g_redisClient->del(key); } - + /* * Also clear list of objects removed in init view mode. */ - + initViewRemovedVidSet.clear(); } @@ -1553,10 +1553,10 @@ void InspectAsic() } auto str_object_type = key.substr(start + 1, mid - start - 1); auto str_object_id = key.substr(mid + 1); - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + // Find all the attrid from ASIC DB, and use them to query ASIC auto hash = g_redisClient->hgetall(key); std::vector values; @@ -1564,28 +1564,28 @@ void InspectAsic() { const std::string &skey = kv.first; const std::string &svalue = kv.second; - + swss::FieldValueTuple fvt(skey, svalue); - + values.push_back(fvt); } - + SaiAttributeList list(object_type, values, false); - + sai_attribute_t *attr_list = list.get_attr_list(); - + uint32_t attr_count = list.get_attr_count(); - + SWSS_LOG_DEBUG("attr count: %u", list.get_attr_count()); - + if (attr_count == 0) { // TODO: how to check ASIC on ASIC DB key with NULL:NULL hash continue; // Just ignore } - + auto info = sai_metadata_get_object_type_info(object_type); - + // Call SAI Get API on this key sai_status_t status; switch (object_type) @@ -1594,38 +1594,38 @@ void InspectAsic() { sai_fdb_entry_t fdb_entry; sai_deserialize_fdb_entry(str_object_id, fdb_entry); - + fdb_entry.switch_id = translate_vid_to_rid(fdb_entry.switch_id); fdb_entry.bv_id = translate_vid_to_rid(fdb_entry.bv_id); - + status = sai_metadata_sai_fdb_api->get_fdb_entry_attribute(&fdb_entry, attr_count, attr_list); break; } - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: { sai_neighbor_entry_t neighbor_entry; sai_deserialize_neighbor_entry(str_object_id, neighbor_entry); - + neighbor_entry.switch_id = translate_vid_to_rid(neighbor_entry.switch_id); neighbor_entry.rif_id = translate_vid_to_rid(neighbor_entry.rif_id); - + status = sai_metadata_sai_neighbor_api->get_neighbor_entry_attribute(&neighbor_entry, attr_count, attr_list); break; } - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: { sai_route_entry_t route_entry; sai_deserialize_route_entry(str_object_id, route_entry); - + route_entry.switch_id = translate_vid_to_rid(route_entry.switch_id); route_entry.vr_id = translate_vid_to_rid(route_entry.vr_id); - + status = sai_metadata_sai_route_api->get_route_entry_attribute(&route_entry, attr_count, attr_list); break; } - + default: { if (info->isnonobjectid) @@ -1634,20 +1634,20 @@ void InspectAsic() sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); } - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = translate_vid_to_rid(object_id); - + status = info->get(&meta_key, attr_count, attr_list); break; } } - + if (status == SAI_STATUS_NOT_IMPLEMENTED) { SWSS_LOG_ERROR("not implemented get api: %s", str_object_type.c_str()); @@ -1656,25 +1656,25 @@ void InspectAsic() { SWSS_LOG_ERROR("failed to execute get api: %s", sai_serialize_status(status).c_str()); } - + // Compare fields and values from ASIC_DB and SAI response // Log the difference for (uint32_t index = 0; index < attr_count; ++index) { const sai_attribute_t *attr = &attr_list[index]; - + auto meta = sai_metadata_get_attr_metadata(object_type, attr->id); - + if (meta == NULL) { SWSS_LOG_ERROR("FATAL: failed to find metadata for object type %d and attr id %d", object_type, attr->id); break; } - + std::string str_attr_id = sai_serialize_attr_id(*meta); - + std::string str_attr_value = sai_serialize_attr_value(*meta, *attr, false); - + std::string hash_attr_value = hash[str_attr_id]; if (hash_attr_value == str_attr_value) { @@ -1694,19 +1694,19 @@ sai_status_t onApplyViewInFastFastBoot() sai_switch_api_t* sai_switch_api = nullptr; sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_FAST_API_ENABLE; attr.value.booldata = false; - + sai_status_t status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_FAST_API_ENABLE=false: %s", sai_serialize_status(status).c_str()); } - + return status; } @@ -1718,14 +1718,14 @@ sai_status_t notifySyncd( if (!options.useTempView) { SWSS_LOG_NOTICE("received %s, ignored since TEMP VIEW is not used, returning success", op.c_str()); - + sendNotifyResponse(SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; } - + static bool firstInitWasPerformed = false; - + if (g_veryFirstRun && firstInitWasPerformed && op == SYNCD_INIT_VIEW) { /* @@ -1734,95 +1734,95 @@ sai_status_t notifySyncd( * already exists and will fail with creating multiple switches * error. */ - + g_veryFirstRun = false; } else if (g_veryFirstRun) { SWSS_LOG_NOTICE("very first run is TRUE, op = %s", op.c_str()); - + sai_status_t status = SAI_STATUS_SUCCESS; - + /* * On the very first start of syncd, "compile" view is directly applied * on device, since it will make it easier to switch to new asic state * later on when we restart orch agent. */ - + if (op == SYNCD_INIT_VIEW) { /* * On first start we just do "apply" directly on asic so we set * init to false instead of true. */ - + g_asicInitViewMode = false; - + firstInitWasPerformed = true; - + /* * We need to clear current temp view to make space for new one. */ - + clearTempView(); } else if (op == SYNCD_APPLY_VIEW) { g_veryFirstRun = false; - + g_asicInitViewMode = false; - + if (options.startType == SAI_FASTFAST_BOOT) { /* fastfast boot configuration end */ status = onApplyViewInFastFastBoot(); } - + SWSS_LOG_NOTICE("setting very first run to FALSE, op = %s", op.c_str()); } else { SWSS_LOG_THROW("unknown operation: %s", op.c_str()); } - + sendNotifyResponse(status); - + return status; } - + if (op == SYNCD_INIT_VIEW) { if (g_asicInitViewMode) { SWSS_LOG_WARN("syncd is already in asic INIT VIEW mode, but received init again, orchagent restarted before apply?"); } - + g_asicInitViewMode = true; - + clearTempView(); - + /* * TODO: Currently as WARN to be easier to spot, later should be NOTICE. */ - + SWSS_LOG_WARN("syncd switched to INIT VIEW mode, all op will be saved to TEMP view"); - + sendNotifyResponse(SAI_STATUS_SUCCESS); } else if (op == SYNCD_APPLY_VIEW) { g_asicInitViewMode = false; - + /* * TODO: Currently as WARN to be easier to spot, later should be NOTICE. */ SWSS_LOG_WARN("syncd received APPLY VIEW, will translate"); - + sai_status_t status = syncdApplyView(); - + sendNotifyResponse(status); - + if (status == SAI_STATUS_SUCCESS) { /* @@ -1830,7 +1830,7 @@ sai_status_t notifySyncd( * need to clear local db, and all new VIDs will be queried using * redis. */ - + local_rid_to_vid.clear(); local_vid_to_rid.clear(); } @@ -1841,27 +1841,27 @@ sai_status_t notifySyncd( * executed, on asic, or asic is inconsistent state then we should * die or hang */ - + return status; } } else if (op == SYNCD_INSPECT_ASIC) { SWSS_LOG_NOTICE("syncd switched to INSPECT ASIC mode"); - + InspectAsic(); - + sendNotifyResponse(SAI_STATUS_SUCCESS); } else { SWSS_LOG_ERROR("unknown operation: %s", op.c_str()); - + sendNotifyResponse(SAI_STATUS_NOT_IMPLEMENTED); - + SWSS_LOG_THROW("notify syncd %s operation failed", op.c_str()); } - + return SAI_STATUS_SUCCESS; } @@ -1879,10 +1879,10 @@ std::vector extractCounterIdsGeneric( std::string field = fvField(v); T counterId; deserializeIdFn(field.c_str(), &counterId); - + counterIdList.push_back(counterId); } - + return counterIdList; } @@ -1900,7 +1900,7 @@ sai_status_t getStatsGeneric( kco, deserializeIdFn); counters.resize(counter_ids.size()); - + return getStatsFn( object_id, (uint32_t)counter_ids.size(), @@ -1920,7 +1920,7 @@ sai_status_t clearStatsGeneric( const std::vector counter_ids = extractCounterIdsGeneric( kco, deserializeIdFn); - + return clearStatsFn( object_id, static_cast(counter_ids.size()), @@ -1935,17 +1935,17 @@ sai_status_t processGetStatsEvent( const std::string &key = kfvKey(kco); const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_id_t rid = translate_vid_to_rid(object_id); sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + std::vector result; - + sai_status_t status = SAI_STATUS_SUCCESS; - + switch (object_type) { case SAI_OBJECT_TYPE_PORT: @@ -1976,9 +1976,9 @@ sai_status_t processGetStatsEvent( SWSS_LOG_ERROR("SAI object type %s not supported", str_object_type.c_str()); status = SAI_STATUS_NOT_SUPPORTED; } - + std::vector entry; - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to get stats"); @@ -1991,9 +1991,9 @@ sai_status_t processGetStatsEvent( entry.emplace_back(fvField(values[i]), std::to_string(result[i])); } } - + getResponse->set(sai_serialize_status(status), entry, "getresponse"); - + return status; } From bf400a9ded6f15928ab90ee00b5a86f9c44c2f2f Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 20 Jul 2019 21:19:48 -0700 Subject: [PATCH 10/20] Update syncd.cpp --- syncd/syncd.cpp | 402 ++++++++++++++++++++++++------------------------ 1 file changed, 201 insertions(+), 201 deletions(-) diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index adb13dd7c..3f40bd36d 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -1029,7 +1029,7 @@ void internal_syncd_api_send_response( SWSS_LOG_INFO("sending response for %d api with status: %s", api, str_status.c_str()); getResponse->set(str_status, entry, "getresponse"); - + SWSS_LOG_INFO("response for %d api was send", api); } @@ -2005,7 +2005,7 @@ sai_status_t processClearStatsEvent( const std::string &key = kfvKey(kco); const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); sai_object_id_t rid; @@ -2018,7 +2018,7 @@ sai_status_t processClearStatsEvent( getResponse->set(sai_serialize_status(status), fvTuples, "getresponse"); return status; } - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); switch (object_type) @@ -2034,7 +2034,7 @@ sai_status_t processClearStatsEvent( SWSS_LOG_ERROR("SAI object type %s not supported", str_object_type.c_str()); status = SAI_STATUS_NOT_SUPPORTED; } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to clear stats"); @@ -2046,7 +2046,7 @@ sai_status_t processClearStatsEvent( fvTuples.emplace_back(fvField(fv), ""); } } - + getResponse->set(sai_serialize_status(status), fvTuples, "getresponse"); return status; } @@ -2061,7 +2061,7 @@ void on_switch_create_in_init_view( /* * This needs to be refactored if we need multiple switch support. */ - + /* * We can have multiple switches here, but each switch is identified by * SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO. This attribute is treated as key, @@ -2086,7 +2086,7 @@ void on_switch_create_in_init_view( * Since we are creating switch here, we are sure that this switch don't * have any oid attributes set, so we can pass all attributes */ - + /* * Multiple switches scenario with changed order: * @@ -2100,7 +2100,7 @@ void on_switch_create_in_init_view( * * Currently we don't have good solution for that so we will throw in that case. */ - + if (switches.size() == 0) { /* @@ -2112,16 +2112,16 @@ void on_switch_create_in_init_view( * This scenario can happen when you start syncd on empty database and * then you quit and restart it again. */ - + sai_object_id_t switch_rid; - + sai_status_t status; - + { SWSS_LOG_TIMER("cold boot: create switch"); status = sai_metadata_sai_switch_api->create_switch(&switch_rid, attr_count, attr_list); } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to create switch in init view mode: %s", @@ -2137,27 +2137,27 @@ void on_switch_create_in_init_view( * Object was created so new object id was generated we * need to save virtual id's to redis db. */ - + std::string str_vid = sai_serialize_object_id(switch_vid); std::string str_rid = sai_serialize_object_id(switch_rid); - + SWSS_LOG_NOTICE("created real switch VID %s to RID %s in init view mode", str_vid.c_str(), str_rid.c_str()); - + /* * TODO: This must be ATOMIC. * * To support multiple switches vid/rid map must be per switch. */ - + g_redisClient->hset(VIDTORID, str_vid, str_rid); g_redisClient->hset(RIDTOVID, str_rid, str_vid); - + save_rid_and_vid_to_local(switch_rid, switch_vid); - + /* * Make switch initialization and get all default data. */ - + switches[switch_vid] = std::make_shared(switch_vid, switch_rid); } else if (switches.size() == 1) @@ -2167,29 +2167,29 @@ void on_switch_create_in_init_view( * info and we need to know that current switch VID also should match * since it's deterministic created. */ - + auto sw = switches.begin()->second; - + /* * Switches VID must match, since it's deterministic. */ - + if (switch_vid != sw->getVid()) { SWSS_LOG_THROW("created switch VID don't match: previous %s, current: %s", sai_serialize_object_id(switch_vid).c_str(), sai_serialize_object_id(sw->getVid()).c_str()); } - + /* * Also hardware info also must match. */ - + std::string currentHw = sw->getHardwareInfo(); std::string newHw; - + auto attr = sai_metadata_get_attr_by_id(SAI_SWITCH_ATTR_SWITCH_HARDWARE_INFO, attr_count, attr_list); - + if (attr == NULL) { /* @@ -2199,15 +2199,15 @@ void on_switch_create_in_init_view( else { SWSS_LOG_DEBUG("new switch contains hardware info of length %u", attr->value.s8list.count); - + newHw = std::string((char*)attr->value.s8list.list, attr->value.s8list.count); } - + if (currentHw != newHw) { SWSS_LOG_THROW("hardware info missmatch: current '%s' vs new '%s'", currentHw.c_str(), newHw.c_str()); } - + SWSS_LOG_NOTICE("current switch hardware info: '%s'", currentHw.c_str()); } else @@ -2231,17 +2231,17 @@ sai_status_t processEventInInitViewMode( * but if that happen, this id will be treated as "new" object instead of * existing one. */ - + /* * TODO: use metadata utils. */ - + auto info = sai_metadata_get_object_type_info(object_type); - + switch (api) { case SAI_COMMON_API_CREATE: - + if (info->isnonobjectid) { /* @@ -2252,28 +2252,28 @@ sai_status_t processEventInInitViewMode( { sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + /* * Object ID here is actual VID returned from redis during * creation this is floating VID in init view mode. */ - + SWSS_LOG_DEBUG("generic create (init view) for %s, floating VID: %s", sai_serialize_object_type(object_type).c_str(), sai_serialize_object_id(object_id).c_str()); - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { on_switch_create_in_init_view(object_id, attr_count, attr_list); } } - + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_REMOVE: - + if (object_type == SAI_OBJECT_TYPE_SWITCH) { /* @@ -2284,10 +2284,10 @@ sai_status_t processEventInInitViewMode( * * To support multiple switches this case must be refactored. */ - + SWSS_LOG_THROW("remove switch (%s) is not supported in init view mode yet! FIXME", str_object_id.c_str()); } - + if (!info->isnonobjectid) { /* @@ -2300,32 +2300,32 @@ sai_status_t processEventInInitViewMode( * need to have a list of removed objects, and then only * populate objects which not exist on removed list. */ - + sai_object_id_t object_vid; sai_deserialize_object_id(str_object_id, object_vid); - + initViewRemovedVidSet.insert(object_vid); } - + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_SET: - + /* * We support SET api on all objects in init view mode. */ - + internal_syncd_api_send_response(api, SAI_STATUS_SUCCESS); - + return SAI_STATUS_SUCCESS; - + case SAI_COMMON_API_GET: - + { sai_status_t status; - + if (info->isnonobjectid) { /* @@ -2334,20 +2334,20 @@ sai_status_t processEventInInitViewMode( * since user explicitly know what attributes were set, similar * for other non object id types. */ - + SWSS_LOG_ERROR("get is not supported on %s in init view mode", sai_serialize_object_type(object_type).c_str()); - + status = SAI_STATUS_NOT_SUPPORTED; } else { sai_object_id_t object_id; sai_deserialize_object_id(str_object_id, object_id); - + SWSS_LOG_DEBUG("generic get (init view) for object type %s:%s", sai_serialize_object_type(object_type).c_str(), str_object_id.c_str()); - + /* * Object must exists, we can't call GET on created object * in init view mode, get here can be called on existing @@ -2362,19 +2362,19 @@ sai_status_t processEventInInitViewMode( * Translate vid to rid will make sure that object exist * and it have RID defined, so we can query it. */ - + sai_object_id_t rid = translate_vid_to_rid(object_id); - + sai_object_meta_key_t meta_key; - + meta_key.objecttype = object_type; meta_key.objectkey.key.object_id = rid; - + status = info->get(&meta_key, attr_count, attr_list); } - + sai_object_id_t switch_id; - + if (switches.size() == 1) { /* @@ -2386,7 +2386,7 @@ sai_status_t processEventInInitViewMode( * can extract switch id, we could also have this method * inside metadata to get meta key. */ - + switch_id = switches.begin()->second->getVid(); } else @@ -2395,17 +2395,17 @@ sai_status_t processEventInInitViewMode( * This needs to be updated to support multiple switches * scenario. */ - + SWSS_LOG_THROW("multiple switches are not supported yet: %zu", switches.size()); } - + internal_syncd_get_send(object_type, str_object_id, switch_id, status, attr_count, attr_list); - + return status; } - + default: - + SWSS_LOG_THROW("common api (%s) is not implemented in init view mode", sai_serialize_common_api(api).c_str()); } @@ -2418,39 +2418,39 @@ sai_object_id_t extractSwitchVid( SWSS_LOG_ENTER(); auto info = sai_metadata_get_object_type_info(object_type); - + /* * Could be replaced by meta_key. */ - + sai_fdb_entry_t fdb_entry; sai_neighbor_entry_t neighbor_entry; sai_route_entry_t route_entry; sai_object_id_t oid; - + switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: sai_deserialize_fdb_entry(str_object_id, fdb_entry); return fdb_entry.switch_id; - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: sai_deserialize_neighbor_entry(str_object_id, neighbor_entry); return neighbor_entry.switch_id; - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: sai_deserialize_route_entry(str_object_id, route_entry); return route_entry.switch_id; - + default: - + if (info->isnonobjectid) { SWSS_LOG_THROW("passing non object id %s as generic object", info->objecttypename); } - + sai_deserialize_object_id(str_object_id, oid); - + return redis_sai_switch_id_query(oid); } } @@ -2467,16 +2467,16 @@ sai_status_t handle_bulk_generic( * Since we don't have asic support yet for bulk api, just execute one by * one. */ - + for (size_t idx = 0; idx < object_ids.size(); ++idx) { sai_status_t status = SAI_STATUS_FAILURE; - + auto &list = attributes[idx]; - + sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); - + sai_object_meta_key_t meta_key; meta_key.objecttype = object_type; switch (object_type) @@ -2493,7 +2493,7 @@ sai_status_t handle_bulk_generic( default: SWSS_LOG_THROW("invalid object_type: %s", sai_serialize_object_type(object_type).c_str()); } - + if (api == (sai_common_api_t)SAI_COMMON_API_BULK_SET) { status = handle_non_object_id(meta_key, SAI_COMMON_API_SET, attr_count, attr_list); @@ -2510,14 +2510,14 @@ sai_status_t handle_bulk_generic( { SWSS_LOG_THROW("api %d is not supported in bulk route", api); } - + if (status != SAI_STATUS_SUCCESS) { internal_syncd_api_send_response(api, status); return status; } } - + return SAI_STATUS_SUCCESS; } @@ -2529,80 +2529,80 @@ sai_status_t processBulkEvent( SWSS_LOG_ENTER(); const std::string &key = kfvKey(kco); - + std::string str_object_type = key.substr(0, key.find(":")); - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + const std::vector &values = kfvFieldsValues(kco); - + // key = str_object_id // val = attrid=attrvalue|... - + std::vector object_ids; - + std::vector> attributes; - + for (const auto &fvt: values) { std::string str_object_id = fvField(fvt); std::string joined = fvValue(fvt); - + // decode values - + auto v = swss::tokenize(joined, '|'); - + object_ids.push_back(str_object_id); - + std::vector entries; // attributes per object id - + for (size_t i = 0; i < v.size(); ++i) { const std::string item = v.at(i); - + auto start = item.find_first_of("="); - + auto field = item.substr(0, start); auto value = item.substr(start + 1); - + swss::FieldValueTuple entry(field, value); - + entries.push_back(entry); } - + // since now we converted this to proper list, we can extract attributes - + std::shared_ptr list = std::make_shared(object_type, entries, false); - + attributes.push_back(list); } - + SWSS_LOG_NOTICE("bulk %s execute with %zu items", str_object_type.c_str(), object_ids.size()); - + if (isInitViewMode()) { SWSS_LOG_THROW("bulk api (%d) is not supported in init view mode", api); } - + if (api != SAI_COMMON_API_BULK_GET) { // translate attributes for all objects - + for (auto &list: attributes) { sai_attribute_t *attr_list = list->get_attr_list(); uint32_t attr_count = list->get_attr_count(); - + translate_vid_to_rid_list(object_type, attr_count, attr_list); } } - + sai_status_t status; - + switch (object_type) { case SAI_OBJECT_TYPE_ROUTE_ENTRY: @@ -2610,20 +2610,20 @@ sai_status_t processBulkEvent( case SAI_OBJECT_TYPE_FDB_ENTRY: status = handle_bulk_generic(object_type, object_ids, api, attributes); break; - + default: SWSS_LOG_THROW("bulk api for %s is not supported yet, FIXME", sai_serialize_object_type(object_type).c_str()); } - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_THROW("failed to execute bulk api: %s", sai_serialize_status(status).c_str()); } - + internal_syncd_api_send_response(api, status); - + return status; } @@ -2634,38 +2634,38 @@ sai_status_t processFdbFlush( const std::string &key = kfvKey(kco); const std::string &str_object_id = key.substr(key.find(":") + 1); - + sai_object_id_t switch_vid; - + sai_deserialize_object_id(str_object_id, switch_vid); - + sai_object_id_t switch_rid = translate_vid_to_rid(switch_vid); - + const std::vector &values = kfvFieldsValues(kco); - + for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SaiAttributeList list(SAI_OBJECT_TYPE_FDB_FLUSH, values, false); - + /* * Attribute list can't be const since we will use it to translate VID to * RID in place. */ - + sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); - + translate_vid_to_rid_list(SAI_OBJECT_TYPE_FDB_FLUSH, attr_count, attr_list); - + sai_status_t status = sai_metadata_sai_fdb_api->flush_fdb_entries(switch_rid, attr_count, attr_list); - + std::vector en; - + getResponse->set(sai_serialize_status(status), en, "flushresponse"); - + return status; } @@ -2675,13 +2675,13 @@ sai_status_t processEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + swss::KeyOpFieldsValuesTuple kco; - + sai_status_t status = SAI_STATUS_SUCCESS; - + do { - + if (isInitViewMode()) { /* @@ -2689,34 +2689,34 @@ sai_status_t processEvent( * specify temporary view prefix in consumer since consumer puts data * to redis db. */ - + consumer.pop(kco, TEMP_PREFIX); } else { consumer.pop(kco); } - + const std::string &key = kfvKey(kco); const std::string &op = kfvOp(kco); - + if (key.length() == 0) { SWSS_LOG_DEBUG("no elements in m_buffer"); return status; } - + /* * TODO: Key is serialized meta_key, we could use deserialize * to extract it here. */ - + const std::string &str_object_type = key.substr(0, key.find(":")); const std::string &str_object_id = key.substr(key.find(":") + 1); - + SWSS_LOG_INFO("key: %s op: %s", key.c_str(), op.c_str()); - + sai_common_api_t api = SAI_COMMON_API_MAX; - + if (op == "create") { api = SAI_COMMON_API_CREATE; @@ -2761,42 +2761,42 @@ sai_status_t processEvent( { SWSS_LOG_THROW("api '%s' is not implemented", op.c_str()); } - + sai_object_type_t object_type; sai_deserialize_object_type(str_object_type, object_type); - + /* * TODO: use metadata utils is object type valid. */ - + if (object_type == SAI_OBJECT_TYPE_NULL || object_type >= SAI_OBJECT_TYPE_EXTENSIONS_MAX) { SWSS_LOG_THROW("undefined object type %s", sai_serialize_object_type(object_type).c_str()); } - + const std::vector &values = kfvFieldsValues(kco); - + for (const auto &v: values) { SWSS_LOG_DEBUG("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SaiAttributeList list(object_type, values, false); - + /* * Attribute list can't be const since we will use it to translate VID to * RID in place. */ - + sai_attribute_t *attr_list = list.get_attr_list(); uint32_t attr_count = list.get_attr_count(); - + /* * NOTE: This check pointers must be executed before init view mode, since * this methods replaces pointers from orchagent memory space to syncd * memory space. */ - + if (object_type == SAI_OBJECT_TYPE_SWITCH && (api == SAI_COMMON_API_CREATE || api == SAI_COMMON_API_SET)) { /* @@ -2805,15 +2805,15 @@ sai_status_t processEvent( * will internally check whether pointer is null or not, so we here * will receive all notifications, but redis only those that were set. */ - + check_notifications_pointers(attr_count, attr_list); } - + if (isInitViewMode()) { return processEventInInitViewMode(object_type, str_object_id, api, attr_count, attr_list); } - + if (api != SAI_COMMON_API_GET) { /* @@ -2821,51 +2821,51 @@ sai_status_t processEvent( * buffer so then all OIDs will be NULL, and translation will also * convert them to NULL. */ - + SWSS_LOG_DEBUG("translating VID to RIDs on all attributes"); - + translate_vid_to_rid_list(object_type, attr_count, attr_list); } - + // TODO use metadata utils auto info = sai_metadata_get_object_type_info(object_type); - + /* * TODO use sai meta key deserialize */ - + if (info->isnonobjectid) { sai_object_meta_key_t meta_key; meta_key.objecttype = object_type; - + switch (object_type) { case SAI_OBJECT_TYPE_FDB_ENTRY: sai_deserialize_fdb_entry(str_object_id, meta_key.objectkey.key.fdb_entry); break; - + case SAI_OBJECT_TYPE_NEIGHBOR_ENTRY: sai_deserialize_neighbor_entry(str_object_id, meta_key.objectkey.key.neighbor_entry); break; - + case SAI_OBJECT_TYPE_ROUTE_ENTRY: sai_deserialize_route_entry(str_object_id, meta_key.objectkey.key.route_entry); break; - + default: - + SWSS_LOG_THROW("non object id %s is not supported yet, FIXME", info->objecttypename); } - + status = handle_non_object_id(meta_key, api, attr_count, attr_list); } else { status = handle_generic(object_type, str_object_id, api, attr_count, attr_list); } - + if (api == SAI_COMMON_API_GET) { if (status != SAI_STATUS_SUCCESS) @@ -2875,37 +2875,37 @@ sai_status_t processEvent( op.c_str(), sai_serialize_status(status).c_str()); } - + /* * Extracting switch is double work here, we can avoid this when we * will use meta_key. */ - + sai_object_id_t switch_vid = extractSwitchVid(object_type, str_object_id); - + internal_syncd_get_send(object_type, str_object_id, switch_vid, status, attr_count, attr_list); } else if (status != SAI_STATUS_SUCCESS) { internal_syncd_api_send_response(api, status); - + if (!info->isnonobjectid && api == SAI_COMMON_API_SET) { sai_object_id_t vid; sai_deserialize_object_id(str_object_id, vid); - + sai_object_id_t rid = translate_vid_to_rid(vid); - + SWSS_LOG_ERROR("VID: %s RID: %s", sai_serialize_object_id(vid).c_str(), sai_serialize_object_id(rid).c_str()); } - + for (const auto &v: values) { SWSS_LOG_ERROR("attr: %s: %s", fvField(v).c_str(), fvValue(v).c_str()); } - + SWSS_LOG_THROW("failed to execute api: %s, key: %s, status: %s", op.c_str(), key.c_str(), @@ -2915,9 +2915,9 @@ sai_status_t processEvent( { internal_syncd_api_send_response(api, status); } - + } while (!consumer.empty()); - + return status; } @@ -2931,22 +2931,22 @@ void processFlexCounterGroupEvent( std::lock_guard lock(g_mutex); consumer.pop(kco); } - + const auto &groupName = kfvKey(kco); const auto &op = kfvOp(kco); const auto values = kfvFieldsValues(kco); - + if (op == DEL_COMMAND) { FlexCounter::removeCounterPlugin(groupName); return; } - + for (const auto& valuePair : values) { const auto field = fvField(valuePair); const auto value = fvValue(valuePair); - + if (op == SET_COMMAND) { if (field == POLL_INTERVAL_FIELD) @@ -3009,16 +3009,16 @@ bool tryPopFlexCounterEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + if (g_flexCounterEventQueue.empty()) { return false; } - + kco = g_flexCounterEventQueue.front(); - + g_flexCounterEventQueue.pop(); - + return true; } @@ -3028,7 +3028,7 @@ void pushFlexCounterEvent( SWSS_LOG_ENTER(); std::lock_guard lock(g_mutex); - + g_flexCounterEventQueue.push(kco); } @@ -3042,17 +3042,17 @@ void processFlexCounterEventThread() while (g_processFlexCounterEventThreadRun) { swss::KeyOpFieldsValuesTuple kco; - + if (tryPopFlexCounterEvent(kco)) { if (!processFlexCounterEvent(kco)) { // event was not successfully processed, put it again to the queue - + pushFlexCounterEvent(kco); } } - + sleep(1); } } @@ -3063,19 +3063,19 @@ void processFlexCounterEvent( SWSS_LOG_ENTER(); swss::KeyOpFieldsValuesTuple kco; - + { std::lock_guard lock(g_mutex); consumer.pop(kco); } - + // because flex counter event can arrive independently (on RIF interface) // it may happen that it will be picked up from the select api before // actual interface will be created, and subscription for counters will // fail, so let's process each request in the thread and use queue for // arriving events, and failed events will be put back to the queue until // they will be processed - + pushFlexCounterEvent(kco); } @@ -3086,18 +3086,18 @@ bool processFlexCounterEvent( const auto &key = kfvKey(kco); const std::string &op = kfvOp(kco); - + std::size_t delimiter = key.find_first_of(":"); if (delimiter == std::string::npos) { SWSS_LOG_ERROR("Failed to parse the key %s", key.c_str()); - + return true; // if key is invalid there is no need to process this event again } - + const auto groupName = key.substr(0, delimiter); const auto vidStr = key.substr(delimiter+1); - + sai_object_id_t vid = SAI_NULL_OBJECT_ID; sai_deserialize_object_id(vidStr, vid); sai_object_id_t rid; @@ -3113,7 +3113,7 @@ bool processFlexCounterEvent( sai_object_type_t objectType = redis_sai_object_type_query(vid); // VID and RID will have the same object type std::string objectTypeStr = sai_serialize_object_type(objectType); - + if (op == DEL_COMMAND) { if (objectType == SAI_OBJECT_TYPE_PORT) @@ -3141,7 +3141,7 @@ bool processFlexCounterEvent( SWSS_LOG_ERROR("Object type for removal not supported, %s", objectTypeStr.c_str()); } } - + const auto values = kfvFieldsValues(kco); std::vector counterIds; std::string statsMode; @@ -3149,11 +3149,11 @@ bool processFlexCounterEvent( { const auto field = fvField(valuePair); const auto value = fvValue(valuePair); - + if (op == SET_COMMAND) { auto idStrings = swss::tokenize(value, ','); - + if (objectType == SAI_OBJECT_TYPE_PORT && field == PORT_COUNTER_ID_LIST) { std::vector portCounterIds; @@ -3163,7 +3163,7 @@ bool processFlexCounterEvent( sai_deserialize_port_stat(str.c_str(), &stat); portCounterIds.push_back(stat); } - + FlexCounter::setPortCounterList(vid, rid, groupName, portCounterIds); } else if (objectType == SAI_OBJECT_TYPE_QUEUE && field == QUEUE_COUNTER_ID_LIST) @@ -3175,7 +3175,7 @@ bool processFlexCounterEvent( sai_deserialize_queue_stat(str.c_str(), &stat); queueCounterIds.push_back(stat); } - + FlexCounter::setQueueCounterList(vid, rid, groupName, queueCounterIds); } else if (objectType == SAI_OBJECT_TYPE_QUEUE && field == QUEUE_ATTR_ID_LIST) @@ -3187,7 +3187,7 @@ bool processFlexCounterEvent( sai_deserialize_queue_attr(str, attr); queueAttrIds.push_back(attr); } - + FlexCounter::setQueueAttrList(vid, rid, groupName, queueAttrIds); } else if (objectType == SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP && field == PG_COUNTER_ID_LIST) From d29f99a6606b19dee38c81085225f9fa352c243f Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 20 Jul 2019 22:09:55 -0700 Subject: [PATCH 11/20] Update syncd.cpp --- syncd/syncd.cpp | 338 ++++++++++++++++++++++++------------------------ 1 file changed, 169 insertions(+), 169 deletions(-) diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index 3f40bd36d..bcf36ae0d 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -3199,7 +3199,7 @@ bool processFlexCounterEvent( sai_deserialize_ingress_priority_group_stat(str.c_str(), &stat); pgCounterIds.push_back(stat); } - + FlexCounter::setPriorityGroupCounterList(vid, rid, groupName, pgCounterIds); } else if (objectType == SAI_OBJECT_TYPE_INGRESS_PRIORITY_GROUP && field == PG_ATTR_ID_LIST) @@ -3211,7 +3211,7 @@ bool processFlexCounterEvent( sai_deserialize_ingress_priority_group_attr(str, attr); pgAttrIds.push_back(attr); } - + FlexCounter::setPriorityGroupAttrList(vid, rid, groupName, pgAttrIds); } else if (objectType == SAI_OBJECT_TYPE_ROUTER_INTERFACE && field == RIF_COUNTER_ID_LIST) @@ -3223,7 +3223,7 @@ bool processFlexCounterEvent( sai_deserialize_router_interface_stat(str.c_str(), &stat); rifCounterIds.push_back(stat); } - + FlexCounter::setRifCounterList(vid, rid, groupName, rifCounterIds); } else if (objectType == SAI_OBJECT_TYPE_BUFFER_POOL && field == BUFFER_POOL_COUNTER_ID_LIST) @@ -3240,7 +3240,7 @@ bool processFlexCounterEvent( } } } - + if (objectType == SAI_OBJECT_TYPE_BUFFER_POOL && counterIds.size()) { std::vector bufferPoolCounterIds; @@ -3250,10 +3250,10 @@ bool processFlexCounterEvent( sai_deserialize_buffer_pool_stat(str.c_str(), &stat); bufferPoolCounterIds.push_back(stat); } - + FlexCounter::setBufferPoolCounterList(vid, rid, groupName, bufferPoolCounterIds, statsMode); } - + return true; } @@ -3326,48 +3326,48 @@ void handleCmdLine(int argc, char **argv) { "syncMode", no_argument, 0, 's' }, { 0, 0, 0, 0 } }; - + int option_index = 0; - + int c = getopt_long(argc, argv, optstring, long_options, &option_index); - + if (c == -1) { break; } - + switch (c) { case 'U': SWSS_LOG_NOTICE("enable unittests"); options.enableUnittests = true; break; - + case 'C': SWSS_LOG_NOTICE("enable consistency check"); g_enableConsistencyCheck = true; break; - + case 'u': SWSS_LOG_NOTICE("enable use temp view"); options.useTempView = true; break; - + case 'S': SWSS_LOG_NOTICE("disable crash sleep"); options.disableExitSleep = true; break; - + case 'd': SWSS_LOG_NOTICE("enable diag shell"); options.diagShell = true; break; - + case 'p': SWSS_LOG_NOTICE("profile map file: %s", optarg); options.profileMapFile = std::string(optarg); break; - + case 't': SWSS_LOG_NOTICE("start type: %s", optarg); if (std::string(optarg) == "cold") @@ -3408,16 +3408,16 @@ void handleCmdLine(int argc, char **argv) SWSS_LOG_NOTICE("enable synchronous mode"); options.syncMode = true; break; - + case 'h': printUsage(); exit(EXIT_SUCCESS); - + case '?': SWSS_LOG_WARN("unknown option %c", optopt); printUsage(); exit(EXIT_FAILURE); - + default: SWSS_LOG_ERROR("getopt_long failure"); exit(EXIT_FAILURE); @@ -3433,44 +3433,44 @@ void handleProfileMap(const std::string& profileMapFile) { return; } - + std::ifstream profile(profileMapFile); - + if (!profile.is_open()) { SWSS_LOG_ERROR("failed to open profile map file: %s : %s", profileMapFile.c_str(), strerror(errno)); exit(EXIT_FAILURE); } - + // Provide default value at boot up time and let sai profile value // Override following values if existing. // SAI reads these values at start up time. It would be too late to // set these values later when WARM BOOT is detected. gProfileMap[SAI_KEY_WARM_BOOT_WRITE_FILE] = DEF_SAI_WARM_BOOT_DATA_FILE; gProfileMap[SAI_KEY_WARM_BOOT_READ_FILE] = DEF_SAI_WARM_BOOT_DATA_FILE; - + std::string line; - + while(getline(profile, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) { continue; } - + size_t pos = line.find("="); - + if (pos == std::string::npos) { SWSS_LOG_WARN("not found '=' in line %s", line.c_str()); continue; } - + std::string key = line.substr(0, pos); std::string value = line.substr(pos + 1); - + gProfileMap[key] = value; - + SWSS_LOG_INFO("insert: %s:%s", key.c_str(), value.c_str()); } } @@ -3487,39 +3487,39 @@ void handlePortMap(const std::string& portMapFile) { return; } - + std::ifstream portmap(portMapFile); - + if (!portmap.is_open()) { std::cerr << "failed to open port map file:" << portMapFile.c_str() << " : "<< strerror(errno) << std::endl; exit(EXIT_FAILURE); } - + std::string line; - + while(getline(portmap, line)) { if (line.size() > 0 && (line[0] == '#' || line[0] == ';')) { continue; } - + std::istringstream iss(line); std::string name, lanes, alias; iss >> name >> lanes >> alias; - + iss.clear(); iss.str(lanes); std::string lane_str; std::set lane_set; - + while (getline(iss, lane_str, ',')) { int lane = stoi(lane_str); lane_set.insert(lane); } - + gPortMap.insert(std::pair,std::string>(lane_set, name)); } } @@ -3530,9 +3530,9 @@ typedef enum _syncd_restart_type_t SYNCD_RESTART_TYPE_COLD, SYNCD_RESTART_TYPE_WARM, - + SYNCD_RESTART_TYPE_FAST, - + SYNCD_RESTART_TYPE_PRE_SHUTDOWN, } syncd_restart_type_t; @@ -3544,35 +3544,35 @@ syncd_restart_type_t handleRestartQuery(swss::NotificationConsumer &restartQuery std::string op; std::string data; std::vector values; - + restartQuery.pop(op, data, values); - + SWSS_LOG_DEBUG("op = %s", op.c_str()); - + if (op == "COLD") { SWSS_LOG_NOTICE("received COLD switch shutdown event"); return SYNCD_RESTART_TYPE_COLD; } - + if (op == "WARM") { SWSS_LOG_NOTICE("received WARM switch shutdown event"); return SYNCD_RESTART_TYPE_WARM; } - + if (op == "FAST") { SWSS_LOG_NOTICE("received FAST switch shutdown event"); return SYNCD_RESTART_TYPE_FAST; } - + if (op == "PRE-SHUTDOWN") { SWSS_LOG_NOTICE("received PRE_SHUTDOWN switch event"); return SYNCD_RESTART_TYPE_PRE_SHUTDOWN; } - + SWSS_LOG_WARN("received '%s' unknown switch shutdown event, assuming COLD", op.c_str()); return SYNCD_RESTART_TYPE_COLD; } @@ -3594,13 +3594,13 @@ bool isVeryFirstRun() * TODO we need to fix this, since when there will be queue, it will still think * this is first run, let's query HIDDEN ? */ - + auto keys = g_redisClient->keys(HIDDEN); - + bool firstRun = keys.size() == 0; - + SWSS_LOG_NOTICE("First Run: %s", firstRun ? "True" : "False"); - + return firstRun; } @@ -3617,7 +3617,7 @@ int get_enum_value_from_name( return metadata->values[idx]; } } - + SWSS_LOG_ERROR("not found %s", name); return 0; } @@ -3627,7 +3627,7 @@ void saiLoglevelNotify(std::string apiStr, std::string prioStr) SWSS_LOG_ENTER(); using namespace swss; - + static const std::map saiLoglevelMap = { { "SAI_LOG_LEVEL_CRITICAL", SAI_LOG_LEVEL_CRITICAL }, { "SAI_LOG_LEVEL_ERROR", SAI_LOG_LEVEL_ERROR }, @@ -3636,24 +3636,24 @@ void saiLoglevelNotify(std::string apiStr, std::string prioStr) { "SAI_LOG_LEVEL_INFO", SAI_LOG_LEVEL_INFO }, { "SAI_LOG_LEVEL_DEBUG", SAI_LOG_LEVEL_DEBUG }, }; - + if (saiLoglevelMap.find(prioStr) == saiLoglevelMap.end()) { SWSS_LOG_ERROR("Invalid SAI loglevel %s %s", apiStr.c_str(), prioStr.c_str()); return; } - + sai_api_t api = (sai_api_t)get_enum_value_from_name(apiStr.c_str(), &sai_metadata_enum_sai_api_t); - + sai_status_t status = sai_log_set(api, saiLoglevelMap.at(prioStr)); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_INFO("Failed to set %s on %s: %s", prioStr.c_str(), apiStr.c_str(), sai_serialize_status(status).c_str()); return; } - + SWSS_LOG_NOTICE("Setting SAI loglevel %s to %s", apiStr.c_str(), prioStr.c_str()); } @@ -3664,7 +3664,7 @@ void set_sai_api_loglevel() /* * We start from 1 since 0 is SAI_API_UNSPECIFIED. */ - + for (uint32_t idx = 1; idx < sai_metadata_enum_sai_api_t.valuescount; ++idx) { swss::Logger::linkToDb(sai_metadata_enum_sai_api_t.valuesnames[idx], saiLoglevelNotify, "SAI_LOG_LEVEL_NOTICE"); @@ -3678,7 +3678,7 @@ void set_sai_api_log_min_prio(const std::string &prioStr) /* * We start from 1 since 0 is SAI_API_UNSPECIFIED. */ - + for (uint32_t idx = 1; idx < sai_metadata_enum_sai_api_t.valuescount; ++idx) { const auto& api_name = sai_metadata_enum_sai_api_t.valuesnames[idx]; @@ -3698,9 +3698,9 @@ void onSyncdStart(bool warmStart) * will generate new id's for ports, this may cause race condition so we * need to use a lock here to prevent that. */ - + SWSS_LOG_TIMER("on syncd start"); - + if (warmStart) { /* @@ -3714,20 +3714,20 @@ void onSyncdStart(bool warmStart) * * If we want to support multiple switches, this needs to be adjusted. */ - + performWarmRestart(); - + SWSS_LOG_NOTICE("skipping hard reinit since WARM start was performed"); return; } - + SWSS_LOG_NOTICE("performing hard reinit since COLD start was performed"); - + /* * Switch was restarted in hard way, we need to perform hard reinit and * recreate switches map. */ - + hardReinit(); } @@ -3751,14 +3751,14 @@ void sai_meta_log_syncd( // SWSS_LOG_ENTER() is omitted since this is logging for metadata char buffer[0x1000]; - + va_list ap; va_start(ap, format); vsnprintf(buffer, 0x1000, format, ap); va_end(ap); - + swss::Logger::Priority p = swss::Logger::SWSS_NOTICE; - + switch (log_level) { case SAI_LOG_LEVEL_DEBUG: @@ -3778,12 +3778,12 @@ void sai_meta_log_syncd( case SAI_LOG_LEVEL_CRITICAL: p = swss::Logger::SWSS_CRIT; break; - + default: p = swss::Logger::SWSS_NOTICE; break; } - + swss::Logger::getInstance().write(p, ":- %s: %s", func, buffer); } @@ -3800,13 +3800,13 @@ int syncd_main(int argc, char **argv) swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_DEBUG); SWSS_LOG_ENTER(); - + swss::Logger::getInstance().setMinPrio(swss::Logger::SWSS_NOTICE); - + set_sai_api_loglevel(); - + swss::Logger::linkToDbNative("syncd"); - + swss::WarmStart::initialize("syncd", "syncd"); swss::WarmStart::checkWarmStart("syncd", "syncd"); @@ -3816,9 +3816,9 @@ int syncd_main(int argc, char **argv) #pragma GCC diagnostic pop meta_init_db(); - + handleCmdLine(argc, argv); - + handleProfileMap(options.profileMapFile); #ifdef SAITHRIFT @@ -3833,59 +3833,59 @@ int syncd_main(int argc, char **argv) std::shared_ptr dbFlexCounter = std::make_shared(FLEX_COUNTER_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::shared_ptr dbState = std::make_shared(STATE_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::unique_ptr warmRestartTable = std::unique_ptr(new swss::Table(dbState.get(), STATE_WARM_RESTART_TABLE_NAME)); - + g_redisClient = std::make_shared(dbAsic.get()); - + std::shared_ptr asicState = std::make_shared(dbAsic.get(), ASIC_STATE_TABLE); std::shared_ptr restartQuery = std::make_shared(dbAsic.get(), "RESTARTQUERY"); std::shared_ptr flexCounter = std::make_shared(dbFlexCounter.get(), FLEX_COUNTER_TABLE); std::shared_ptr flexCounterGroup = std::make_shared(dbFlexCounter.get(), FLEX_COUNTER_GROUP_TABLE); - + /* * At the end we cant use producer consumer concept since if one process * will restart there may be something in the queue also "remove" from * response queue will also trigger another "response". */ - + getResponse = std::make_shared(dbAsic.get(), "GETRESPONSE"); notifications = std::make_shared(dbNtf.get(), "NOTIFICATIONS"); - + g_veryFirstRun = isVeryFirstRun(); - + /* ignore warm logic here if syncd starts in Mellanox fastfast boot mode */ if (swss::WarmStart::isWarmStart() && (options.startType != SAI_FASTFAST_BOOT)) { options.startType = SAI_WARM_BOOT; } - + if (options.startType == SAI_WARM_BOOT) { const char *warmBootReadFile = profile_get_value(0, SAI_KEY_WARM_BOOT_READ_FILE); - + SWSS_LOG_NOTICE("using warmBootReadFile: '%s'", warmBootReadFile); - + if (warmBootReadFile == NULL || access(warmBootReadFile, F_OK) == -1) { SWSS_LOG_WARN("user requested warmStart but warmBootReadFile is not specified or not accesible, forcing cold start"); - + options.startType = SAI_COLD_BOOT; } } - + if (options.startType == SAI_WARM_BOOT && g_veryFirstRun) { SWSS_LOG_WARN("warm start requested, but this is very first syncd start, forcing cold start"); - + /* * We force cold start since if it's first run then redis db is not * complete so redis asic view will not reflect warm boot asic state, * if this happen then orch agent needs to be restarted as well to * repopulate asic view. */ - + options.startType = SAI_COLD_BOOT; } - + if (options.startType == SAI_FASTFAST_BOOT) { /* @@ -3896,23 +3896,23 @@ int syncd_main(int argc, char **argv) } else { gProfileMap[SAI_KEY_BOOT_TYPE] = std::to_string(options.startType); } - + sai_status_t status = sai_api_initialize(0, (sai_service_method_table_t*)&test_services); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("fail to sai_api_initialize: %d", status); return EXIT_FAILURE; } - + sai_apis_t apis; int failed = sai_metadata_apis_query(sai_api_query, &apis); - + if (failed > 0) { SWSS_LOG_NOTICE("sai_api_query failed for %d apis", failed); } - + /* * TODO: user should create switch from OA, so shell should be started only * after we create switch. @@ -3927,59 +3927,59 @@ int syncd_main(int argc, char **argv) #endif // SAITHRIFT SWSS_LOG_NOTICE("syncd started"); - + syncd_restart_type_t shutdownType = SYNCD_RESTART_TYPE_COLD; - + sai_switch_api_t *sai_switch_api = NULL; sai_api_query(SAI_API_SWITCH, (void**)&sai_switch_api); - + volatile bool runMainLoop = true; - + std::shared_ptr s = std::make_shared(); - + try { SWSS_LOG_NOTICE("before onSyncdStart"); onSyncdStart(options.startType == SAI_WARM_BOOT); SWSS_LOG_NOTICE("after onSyncdStart"); - + // create notifications processing thread after we create_switch to // make sure, we have switch_id translated to VID before we start // processing possible quick fdb notifications, and pointer for // notification queue is created before we create switch startNotificationsProcessingThread(); - + SWSS_LOG_NOTICE("syncd listening for events"); - + s->addSelectable(asicState.get()); s->addSelectable(restartQuery.get()); s->addSelectable(flexCounter.get()); s->addSelectable(flexCounterGroup.get()); - + SWSS_LOG_NOTICE("starting main loop"); } catch(const std::exception &e) { SWSS_LOG_ERROR("Runtime error during syncd init: %s", e.what()); - + notify_OA_about_syncd_exception(); - + s = std::make_shared(); - + s->addSelectable(restartQuery.get()); - + SWSS_LOG_NOTICE("starting main loop, ONLY restart query"); - + if (options.disableExitSleep) runMainLoop = false; } - + TimerWatchdog twd(30 * 1000000); // watch for executions over 30 seconds - + twd.setCallback(timerWatchdogCallback); - + g_processFlexCounterEventThreadRun = true; - + g_processFlexCounterEventThread = std::make_shared(processFlexCounterEventThread); @@ -3988,11 +3988,11 @@ int syncd_main(int argc, char **argv) try { swss::Selectable *sel = NULL; - + int result = s->select(&sel); - + twd.setStartTime(); - + if (sel == restartQuery.get()) { /* @@ -4002,16 +4002,16 @@ int syncd_main(int argc, char **argv) * this may lead to forget populate object table which will * lead to unable to find some objects. */ - + SWSS_LOG_NOTICE("is asic queue empty: %d",asicState->empty()); - + while (!asicState->empty()) { processEvent(*asicState.get()); } - + SWSS_LOG_NOTICE("drained queue"); - + shutdownType = handleRestartQuery(*restartQuery); if (shutdownType != SYNCD_RESTART_TYPE_PRE_SHUTDOWN) { @@ -4019,54 +4019,54 @@ int syncd_main(int argc, char **argv) runMainLoop = false; break; } - + // Handle switch pre-shutdown and wait for the final shutdown // event - + SWSS_LOG_TIMER("warm pre-shutdown"); - + FlexCounter::removeAllCounters(); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_RESTART_WARM=true: %s for pre-shutdown", sai_serialize_status(status).c_str()); - + shutdownType = SYNCD_RESTART_TYPE_COLD; - + warmRestartTable->hset("warm-shutdown", "state", "set-flag-failed"); continue; } - + attr.id = SAI_SWITCH_ATTR_PRE_SHUTDOWN; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status == SAI_STATUS_SUCCESS) { warmRestartTable->hset("warm-shutdown", "state", "pre-shutdown-succeeded"); - + s = std::make_shared(); // make sure previous select is destroyed - + s->addSelectable(restartQuery.get()); - + SWSS_LOG_NOTICE("switched to PRE_SHUTDOWN, from now on accepting only shurdown requests"); } else { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_PRE_SHUTDOWN=true: %s", sai_serialize_status(status).c_str()); - + warmRestartTable->hset("warm-shutdown", "state", "pre-shutdown-failed"); - + // Restore cold shutdown. attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = false; @@ -4085,53 +4085,53 @@ int syncd_main(int argc, char **argv) { processEvent(*(swss::ConsumerTable*)sel); } - + twd.setEndTime(); } catch(const std::exception &e) { SWSS_LOG_ERROR("Runtime error: %s", e.what()); - + notify_OA_about_syncd_exception(); - + s = std::make_shared(); - + s->addSelectable(restartQuery.get()); - + if (options.disableExitSleep) runMainLoop = false; - + // make sure that if second exception will arise, then we break the loop options.disableExitSleep = true; - + twd.setEndTime(); } } - + if (shutdownType == SYNCD_RESTART_TYPE_WARM) { const char *warmBootWriteFile = profile_get_value(0, SAI_KEY_WARM_BOOT_WRITE_FILE); - + SWSS_LOG_NOTICE("using warmBootWriteFile: '%s'", warmBootWriteFile); - + if (warmBootWriteFile == NULL) { SWSS_LOG_WARN("user requested warm shutdown but warmBootWriteFile is not specified, forcing cold shutdown"); - + shutdownType = SYNCD_RESTART_TYPE_COLD; warmRestartTable->hset("warm-shutdown", "state", "warm-shutdown-failed"); } else { SWSS_LOG_NOTICE("Warm Reboot requested, keeping data plane running"); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_RESTART_WARM; attr.value.booldata = true; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_RESTART_WARM=true: %s, fall back to cold restart", @@ -4141,7 +4141,7 @@ int syncd_main(int argc, char **argv) } } } - + SWSS_LOG_NOTICE("Removing the switch gSwitchId=0x%lx", gSwitchId); #ifdef SAI_SUPPORT_UNINIT_DATA_PLANE_ON_REMOVAL @@ -4149,14 +4149,14 @@ int syncd_main(int argc, char **argv) if (shutdownType == SYNCD_RESTART_TYPE_FAST || shutdownType == SYNCD_RESTART_TYPE_WARM) { SWSS_LOG_NOTICE("Fast/warm reboot requested, keeping data plane running"); - + sai_attribute_t attr; - + attr.id = SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL; attr.value.booldata = false; - + status = sai_switch_api->set_switch_attribute(gSwitchId, &attr); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("Failed to set SAI_SWITCH_ATTR_UNINIT_DATA_PLANE_ON_REMOVAL=false: %s", @@ -4167,25 +4167,25 @@ int syncd_main(int argc, char **argv) #endif g_processFlexCounterEventThreadRun = false; - + g_processFlexCounterEventThread->join(); - + FlexCounter::removeAllCounters(); - + { SWSS_LOG_TIMER("remove switch"); status = sai_switch_api->remove_switch(gSwitchId); } - + // Stop notification thread after removing switch stopNotificationsProcessingThread(); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_NOTICE("Can't delete a switch. gSwitchId=0x%lx status=%s", gSwitchId, sai_serialize_status(status).c_str()); } - + if (shutdownType == SYNCD_RESTART_TYPE_WARM) { warmRestartTable->hset("warm-shutdown", "state", @@ -4193,17 +4193,17 @@ int syncd_main(int argc, char **argv) "warm-shutdown-succeeded": "warm-shutdown-failed"); } - + SWSS_LOG_NOTICE("calling api uninitialize"); - + status = sai_api_uninitialize(); - + if (status != SAI_STATUS_SUCCESS) { SWSS_LOG_ERROR("failed to uninitialize api: %s", sai_serialize_status(status).c_str()); } - + SWSS_LOG_NOTICE("uninitialize finished"); - + return EXIT_SUCCESS; } From 647ef2ba2b0801dcfcf20d44c974c4337ce8fb44 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Sat, 7 Sep 2019 18:29:01 -0700 Subject: [PATCH 12/20] Layer 2 Forwarding Enhancements Layer 2 Forwarding Enhancements --- vslib/src/sai_vs_fdb.cpp | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/vslib/src/sai_vs_fdb.cpp b/vslib/src/sai_vs_fdb.cpp index 3a6974d25..d56af2970 100644 --- a/vslib/src/sai_vs_fdb.cpp +++ b/vslib/src/sai_vs_fdb.cpp @@ -68,6 +68,56 @@ bool doesFdbEntryNotMatchFlushAttr( return false; } +void sendFdbDelNotification( + _In_ const fdb_info_t &fi) +{ + SWSS_LOG_ENTER(); + + sai_attribute_t attrs[2]; + + attrs[0].id = SAI_FDB_ENTRY_ATTR_TYPE; + attrs[0].value.s32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; + + attrs[1].id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; + attrs[1].value.oid = fi.bridge_port_id; + + sai_fdb_event_notification_data_t data; + + data.event_type = SAI_FDB_EVENT_AGED; + + data.fdb_entry = fi.fdb_entry; + + data.attr_count = 2; + data.attr = attrs; + + // update metadata DB + meta_sai_on_fdb_event(1, &data); + + sai_attribute_t attr; + + attr.id = SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY; + + sai_status_t status = vs_generic_get(SAI_OBJECT_TYPE_SWITCH, data.fdb_entry.switch_id, 1, &attr); + + if (status != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("failed to get fdb event notify from switch %s", + sai_serialize_object_id(data.fdb_entry.switch_id).c_str()); + return; + } + + std::string s = sai_serialize_fdb_event_ntf(1, &data); + + SWSS_LOG_DEBUG("calling user fdb event callback: %s", s.c_str()); + + sai_fdb_event_notification_fn ntf = (sai_fdb_event_notification_fn)attr.value.ptr; + + if (ntf != NULL) + { + ntf(1, &data); + } +} + sai_status_t internal_vs_flush_fdb_entries( _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, @@ -156,10 +206,21 @@ sai_status_t internal_vs_flush_fdb_entries( * data base. */ + fi.bridge_port_id = it->second.at("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID")->getAttr()->value.oid; + + SWSS_LOG_INFO("FDBDelNotification: fdb_entry:%s bpid:%s", sai_serialize_fdb_entry(fi.fdb_entry).c_str(), sai_serialize_object_id(fi.bridge_port_id).c_str()); + it = fdbs.erase(it); + + sendFdbDelNotification(fi); } } + /* Sending notification for each fdb entry individually above, as a single + * response causes syncd to delete ASIC_DB entries in a loop and + * stuck for long time when a large number of FDB entries are present. + */ +#if 0 /* * We can have 3 attributes (so far) to flush by: * - entry type @@ -278,6 +339,7 @@ sai_status_t internal_vs_flush_fdb_entries( // TODO: we can add config entry to send notifications 1 by 1 as option to consolidated +#endif return SAI_STATUS_SUCCESS; } From 652d159c96274fa28d46bb9bb3ab688058326b2f Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 13 Sep 2019 17:25:56 -0700 Subject: [PATCH 13/20] Update sai_redis_notifications.cpp --- lib/src/sai_redis_notifications.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/sai_redis_notifications.cpp b/lib/src/sai_redis_notifications.cpp index 22d2b20bd..8115e7506 100644 --- a/lib/src/sai_redis_notifications.cpp +++ b/lib/src/sai_redis_notifications.cpp @@ -216,7 +216,11 @@ void handle_notification( } else if (notification == "fdb_event") { - handle_fdb_event(data); + /* The fdb handling is moved to fdbOrch so that both + * reference count updates (sai_redis and portsOrch) + * happen in same context to avoid any mismatch. + */ + /* handle_fdb_event(data);*/ } else if (notification == "port_state_change") { From f77057fb3d312a942d42c75f3ebf5fc6e52d0cc4 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Fri, 20 Sep 2019 09:02:54 -0700 Subject: [PATCH 14/20] Update sai_redis_notifications.cpp moved sai redis fdb event processing back to notification thread --- lib/src/sai_redis_notifications.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/src/sai_redis_notifications.cpp b/lib/src/sai_redis_notifications.cpp index 8115e7506..22d2b20bd 100644 --- a/lib/src/sai_redis_notifications.cpp +++ b/lib/src/sai_redis_notifications.cpp @@ -216,11 +216,7 @@ void handle_notification( } else if (notification == "fdb_event") { - /* The fdb handling is moved to fdbOrch so that both - * reference count updates (sai_redis and portsOrch) - * happen in same context to avoid any mismatch. - */ - /* handle_fdb_event(data);*/ + handle_fdb_event(data); } else if (notification == "port_state_change") { From 541d09d5ce9ae6589848a23815892907785c163a Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Mon, 23 Sep 2019 15:46:10 -0700 Subject: [PATCH 15/20] Update sai_vs_fdb.cpp uncomment meta_sai_on_fdb_event() to update local SAIDB --- vslib/src/sai_vs_fdb.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/vslib/src/sai_vs_fdb.cpp b/vslib/src/sai_vs_fdb.cpp index d56af2970..ddc513da9 100644 --- a/vslib/src/sai_vs_fdb.cpp +++ b/vslib/src/sai_vs_fdb.cpp @@ -220,7 +220,7 @@ sai_status_t internal_vs_flush_fdb_entries( * response causes syncd to delete ASIC_DB entries in a loop and * stuck for long time when a large number of FDB entries are present. */ -#if 0 + /* * We can have 3 attributes (so far) to flush by: * - entry type @@ -274,7 +274,12 @@ sai_status_t internal_vs_flush_fdb_entries( SWSS_LOG_NOTICE("generating fdb flush notifications"); + /* notification has been sent for individual mac delete, so + * not sending the bulk flush notification + */ +#if 0 sai_fdb_event_notification_fn ntf = (sai_fdb_event_notification_fn)attr.value.ptr; +#endif sai_fdb_event_notification_data_t data; sai_attribute_t attrs[2]; @@ -313,11 +318,16 @@ sai_status_t internal_vs_flush_fdb_entries( attrs[0].value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; meta_sai_on_fdb_event(1, &data); // update metadata - + + /* notification has been sent for individual mac delete, so + * not sending the bulk flush notification + */ +#if 0 if (ntf != NULL) { ntf(1, &data); } +#endif } if (dynamic_fdbs.size() > 0) @@ -328,18 +338,21 @@ sai_status_t internal_vs_flush_fdb_entries( attrs[0].value.s32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; meta_sai_on_fdb_event(1, &data); // update metadata - + + /* notification has been sent for individual mac delete, so + * not sending the bulk flush notification + */ +#if 0 if (ntf != NULL) { ntf(1, &data); } - +#endif SWSS_LOG_NOTICE("1"); } // TODO: we can add config entry to send notifications 1 by 1 as option to consolidated -#endif return SAI_STATUS_SUCCESS; } From 3ff9a2f782a72b18e304f3728851938c805853c1 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Tue, 24 Sep 2019 11:14:54 -0700 Subject: [PATCH 16/20] Update sai_vs_fdb.cpp --- vslib/src/sai_vs_fdb.cpp | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/vslib/src/sai_vs_fdb.cpp b/vslib/src/sai_vs_fdb.cpp index ddc513da9..ae0e81cfe 100644 --- a/vslib/src/sai_vs_fdb.cpp +++ b/vslib/src/sai_vs_fdb.cpp @@ -220,7 +220,7 @@ sai_status_t internal_vs_flush_fdb_entries( * response causes syncd to delete ASIC_DB entries in a loop and * stuck for long time when a large number of FDB entries are present. */ - +#if 0 /* * We can have 3 attributes (so far) to flush by: * - entry type @@ -274,12 +274,8 @@ sai_status_t internal_vs_flush_fdb_entries( SWSS_LOG_NOTICE("generating fdb flush notifications"); - /* notification has been sent for individual mac delete, so - * not sending the bulk flush notification - */ -#if 0 sai_fdb_event_notification_fn ntf = (sai_fdb_event_notification_fn)attr.value.ptr; -#endif + sai_fdb_event_notification_data_t data; sai_attribute_t attrs[2]; @@ -319,15 +315,10 @@ sai_status_t internal_vs_flush_fdb_entries( meta_sai_on_fdb_event(1, &data); // update metadata - /* notification has been sent for individual mac delete, so - * not sending the bulk flush notification - */ -#if 0 if (ntf != NULL) { ntf(1, &data); } -#endif } if (dynamic_fdbs.size() > 0) @@ -338,21 +329,17 @@ sai_status_t internal_vs_flush_fdb_entries( attrs[0].value.s32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; meta_sai_on_fdb_event(1, &data); // update metadata - - /* notification has been sent for individual mac delete, so - * not sending the bulk flush notification - */ -#if 0 + if (ntf != NULL) { ntf(1, &data); } -#endif + SWSS_LOG_NOTICE("1"); } // TODO: we can add config entry to send notifications 1 by 1 as option to consolidated - +#endif return SAI_STATUS_SUCCESS; } From f57dd52887e215d75a281d6d0e77049b81773214 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Mon, 7 Oct 2019 17:53:31 -0700 Subject: [PATCH 17/20] fdb flush event handling Added support for handling per port, per vlan and per port-vlan flush event from SAI. Also, doing ASIC_DB flsh in lua script --- syncd/syncd.cpp | 10 +++++- syncd/syncd.h | 2 ++ syncd/syncd_notifications.cpp | 68 +++++++++++++++++++++++------------ vslib/src/sai_vs_fdb.cpp | 62 -------------------------------- 4 files changed, 57 insertions(+), 85 deletions(-) diff --git a/syncd/syncd.cpp b/syncd/syncd.cpp index ca3137389..65e8dde0a 100644 --- a/syncd/syncd.cpp +++ b/syncd/syncd.cpp @@ -8,6 +8,7 @@ #include "swss/warm_restart.h" #include "swss/table.h" +#include "swss/redisapi.h" #include "TimerWatchdog.h" @@ -35,6 +36,7 @@ extern "C" { */ std::mutex g_mutex; +std::shared_ptr dbAsic; std::shared_ptr g_redisClient; std::shared_ptr getResponse; std::shared_ptr notifications; @@ -89,6 +91,9 @@ volatile bool g_asicInitViewMode = false; */ sai_object_id_t gSwitchId; +string fdbFlushSha; +string fdbFlushLuaScriptName = "fdb_flush.lua"; + struct cmdOptions { bool diagShell; @@ -3756,7 +3761,7 @@ int syncd_main(int argc, char **argv) } #endif // SAITHRIFT - std::shared_ptr dbAsic = std::make_shared(ASIC_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); + dbAsic = std::make_shared(ASIC_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::shared_ptr dbNtf = std::make_shared(ASIC_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::shared_ptr dbFlexCounter = std::make_shared(FLEX_COUNTER_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); std::shared_ptr dbState = std::make_shared(STATE_DB, swss::DBConnector::DEFAULT_UNIXSOCKET, 0); @@ -3778,6 +3783,9 @@ int syncd_main(int argc, char **argv) getResponse = std::make_shared(dbAsic.get(), "GETRESPONSE"); notifications = std::make_shared(dbNtf.get(), "NOTIFICATIONS"); + string fdbFlushLuaScript = swss::loadLuaScript(fdbFlushLuaScriptName); + fdbFlushSha = swss::loadRedisScript(dbAsic.get(), fdbFlushLuaScript); + g_veryFirstRun = isVeryFirstRun(); /* ignore warm logic here if syncd starts in Mellanox fastfast boot mode */ diff --git a/syncd/syncd.h b/syncd/syncd.h index 59974b205..ca8e7f9b3 100644 --- a/syncd/syncd.h +++ b/syncd/syncd.h @@ -93,6 +93,8 @@ sai_object_type_t getObjectTypeFromVid( extern std::shared_ptr notifications; extern std::shared_ptr g_redisClient; +extern std::shared_ptr dbAsic; +extern std::string fdbFlushSha; extern bool g_enableConsistencyCheck; diff --git a/syncd/syncd_notifications.cpp b/syncd/syncd_notifications.cpp index 0d751018c..da8bb10bc 100644 --- a/syncd/syncd_notifications.cpp +++ b/syncd/syncd_notifications.cpp @@ -108,6 +108,7 @@ void redisPutFdbEntryToAsicView( { sai_object_id_t bv_id = fdb->fdb_entry.bv_id; sai_object_id_t port_oid = 0; + int flush_static = 0; for (uint32_t i = 0; i < fdb->attr_count; i++) { @@ -115,6 +116,10 @@ void redisPutFdbEntryToAsicView( { port_oid = fdb->attr[i].value.oid; } + else if(fdb->attr[i].id == SAI_FDB_ENTRY_ATTR_TYPE) + { + flush_static = (fdb->attr[i].value.s32 == SAI_FDB_ENTRY_TYPE_STATIC) ? 1 : 0; + } } @@ -138,24 +143,14 @@ void redisPutFdbEntryToAsicView( */ SWSS_LOG_NOTICE("received a flush all fdb event"); std::string pattern = ASIC_STATE_TABLE + std::string(":SAI_OBJECT_TYPE_FDB_ENTRY:*"); - for (const auto &fdbkey: g_redisClient->keys(pattern)) - { - /* we only remove dynamic fdb entries here, static fdb entries need to be deleted manually by user instead of flush */ - auto pEntryType = g_redisClient->hget(fdbkey, "SAI_FDB_ENTRY_ATTR_TYPE"); - if (pEntryType != NULL) - { - std::string strEntryType = *pEntryType; - if (strEntryType == "SAI_FDB_ENTRY_TYPE_DYNAMIC") - { - SWSS_LOG_DEBUG("remove fdb entry %s for SAI_FDB_EVENT_FLUSHED",fdbkey.c_str()); - g_redisClient->del(fdbkey); - } - } - else - { - SWSS_LOG_ERROR("found unknown type fdb entry, key %s", fdbkey.c_str()); - } - } + swss::RedisCommand command; + command.format( + "EVALSHA %s 3 %s %s %s", + fdbFlushSha.c_str(), + pattern.c_str(), + "", + std::to_string(flush_static).c_str()); + swss::RedisReply r(dbAsic.get(), command); } else if (port_oid && !bv_id) { @@ -176,7 +171,18 @@ void redisPutFdbEntryToAsicView( ] }] */ - SWSS_LOG_ERROR("received a flush port fdb event, port_oid = 0x%" PRIx64 ", bv_id = 0x%" PRIx64 ", unsupported", port_oid, bv_id); + SWSS_LOG_NOTICE("received a flush port fdb event, port_oid = 0x%lx, bv_id = 0x%lx", port_oid, bv_id); + std::string pattern = ASIC_STATE_TABLE + std::string(":SAI_OBJECT_TYPE_FDB_ENTRY:*"); + std::string port_str = sai_serialize_object_id(port_oid); + SWSS_LOG_NOTICE("pattern %s port_str %s", pattern.c_str(), port_str.c_str()); + swss::RedisCommand command; + command.format( + "EVALSHA %s 3 %s %s %s", + fdbFlushSha.c_str(), + pattern.c_str(), + port_str.c_str(), + std::to_string(flush_static).c_str()); + swss::RedisReply r(dbAsic.get(), command); } else if (!port_oid && bv_id) { @@ -197,12 +203,30 @@ void redisPutFdbEntryToAsicView( ] }] */ - SWSS_LOG_ERROR("received a flush vlan fdb event, port_oid = 0x%" PRIx64 ", bv_id = 0x%" PRIx64 ", unsupported", port_oid, bv_id); - + SWSS_LOG_NOTICE("received a flush vlan fdb event, port_oid = 0x%lx, bv_id = 0x%lx", port_oid, bv_id); + std::string pattern = ASIC_STATE_TABLE + std::string(":SAI_OBJECT_TYPE_FDB_ENTRY:*") + sai_serialize_object_id(bv_id) + std::string("*"); + swss::RedisCommand command; + command.format( + "EVALSHA %s 3 %s %s %s", + fdbFlushSha.c_str(), + pattern.c_str(), + "", + std::to_string(flush_static).c_str()); + swss::RedisReply r(dbAsic.get(), command); } else { - SWSS_LOG_ERROR("received a flush fdb event, port_oid = 0x%" PRIx64 ", bv_id = 0x%" PRIx64 ", unsupported", port_oid, bv_id); + SWSS_LOG_NOTICE("received a flush fdb event, port_oid = 0x%lx, bv_id = 0x%lx", port_oid, bv_id); + std::string pattern = ASIC_STATE_TABLE + std::string(":SAI_OBJECT_TYPE_FDB_ENTRY:*") + sai_serialize_object_id(bv_id) + std::string("*"); + std::string port_str = sai_serialize_object_id(port_oid); + swss::RedisCommand command; + command.format( + "EVALSHA %s 3 %s %s %s", + fdbFlushSha.c_str(), + pattern.c_str(), + port_str.c_str(), + std::to_string(flush_static).c_str()); + swss::RedisReply r(dbAsic.get(), command); } return; diff --git a/vslib/src/sai_vs_fdb.cpp b/vslib/src/sai_vs_fdb.cpp index ae0e81cfe..15dedd1c7 100644 --- a/vslib/src/sai_vs_fdb.cpp +++ b/vslib/src/sai_vs_fdb.cpp @@ -68,56 +68,6 @@ bool doesFdbEntryNotMatchFlushAttr( return false; } -void sendFdbDelNotification( - _In_ const fdb_info_t &fi) -{ - SWSS_LOG_ENTER(); - - sai_attribute_t attrs[2]; - - attrs[0].id = SAI_FDB_ENTRY_ATTR_TYPE; - attrs[0].value.s32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; - - attrs[1].id = SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID; - attrs[1].value.oid = fi.bridge_port_id; - - sai_fdb_event_notification_data_t data; - - data.event_type = SAI_FDB_EVENT_AGED; - - data.fdb_entry = fi.fdb_entry; - - data.attr_count = 2; - data.attr = attrs; - - // update metadata DB - meta_sai_on_fdb_event(1, &data); - - sai_attribute_t attr; - - attr.id = SAI_SWITCH_ATTR_FDB_EVENT_NOTIFY; - - sai_status_t status = vs_generic_get(SAI_OBJECT_TYPE_SWITCH, data.fdb_entry.switch_id, 1, &attr); - - if (status != SAI_STATUS_SUCCESS) - { - SWSS_LOG_ERROR("failed to get fdb event notify from switch %s", - sai_serialize_object_id(data.fdb_entry.switch_id).c_str()); - return; - } - - std::string s = sai_serialize_fdb_event_ntf(1, &data); - - SWSS_LOG_DEBUG("calling user fdb event callback: %s", s.c_str()); - - sai_fdb_event_notification_fn ntf = (sai_fdb_event_notification_fn)attr.value.ptr; - - if (ntf != NULL) - { - ntf(1, &data); - } -} - sai_status_t internal_vs_flush_fdb_entries( _In_ sai_object_id_t switch_id, _In_ uint32_t attr_count, @@ -206,21 +156,10 @@ sai_status_t internal_vs_flush_fdb_entries( * data base. */ - fi.bridge_port_id = it->second.at("SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID")->getAttr()->value.oid; - - SWSS_LOG_INFO("FDBDelNotification: fdb_entry:%s bpid:%s", sai_serialize_fdb_entry(fi.fdb_entry).c_str(), sai_serialize_object_id(fi.bridge_port_id).c_str()); - it = fdbs.erase(it); - - sendFdbDelNotification(fi); } } - /* Sending notification for each fdb entry individually above, as a single - * response causes syncd to delete ASIC_DB entries in a loop and - * stuck for long time when a large number of FDB entries are present. - */ -#if 0 /* * We can have 3 attributes (so far) to flush by: * - entry type @@ -339,7 +278,6 @@ sai_status_t internal_vs_flush_fdb_entries( } // TODO: we can add config entry to send notifications 1 by 1 as option to consolidated -#endif return SAI_STATUS_SUCCESS; } From fd77ed2412ff0f3fe0cb621ada0fd49205129594 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Mon, 7 Oct 2019 17:57:01 -0700 Subject: [PATCH 18/20] Update sai_vs_fdb.cpp --- vslib/src/sai_vs_fdb.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vslib/src/sai_vs_fdb.cpp b/vslib/src/sai_vs_fdb.cpp index 15dedd1c7..3a6974d25 100644 --- a/vslib/src/sai_vs_fdb.cpp +++ b/vslib/src/sai_vs_fdb.cpp @@ -215,7 +215,6 @@ sai_status_t internal_vs_flush_fdb_entries( sai_fdb_event_notification_fn ntf = (sai_fdb_event_notification_fn)attr.value.ptr; - sai_fdb_event_notification_data_t data; sai_attribute_t attrs[2]; @@ -253,7 +252,7 @@ sai_status_t internal_vs_flush_fdb_entries( attrs[0].value.s32 = SAI_FDB_ENTRY_TYPE_STATIC; meta_sai_on_fdb_event(1, &data); // update metadata - + if (ntf != NULL) { ntf(1, &data); @@ -268,7 +267,7 @@ sai_status_t internal_vs_flush_fdb_entries( attrs[0].value.s32 = SAI_FDB_ENTRY_TYPE_DYNAMIC; meta_sai_on_fdb_event(1, &data); // update metadata - + if (ntf != NULL) { ntf(1, &data); @@ -278,6 +277,7 @@ sai_status_t internal_vs_flush_fdb_entries( } // TODO: we can add config entry to send notifications 1 by 1 as option to consolidated + return SAI_STATUS_SUCCESS; } From 410cc016ac95ef23df3b2b0cd210f820adf5ce94 Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Tue, 5 Nov 2019 13:11:54 -0800 Subject: [PATCH 19/20] fix build failure --- .DS_Store | Bin 0 -> 6148 bytes syncd/syncd.cpp | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2e808335e02b496ea3cfe9140d5bbc7b7503e404 GIT binary patch literal 6148 zcmeH~!D<3Q42J(y3qmg*dz@GB4F<7K&=(NhOJUK&(n4>0>udKHYtWer5jm9GM7+z?~AX`R0AI=F4SooxG;^+CtybPsZFx=Mt@$ j8m*W=ycNHm(dbAsic.get(), "GETRESPONSE"); notifications = std::make_shared(dbNtf.get(), "NOTIFICATIONS"); - string fdbFlushLuaScript = swss::loadLuaScript(fdbFlushLuaScriptName); + std::string fdbFlushLuaScript = swss::loadLuaScript(fdbFlushLuaScriptName); fdbFlushSha = swss::loadRedisScript(dbAsic.get(), fdbFlushLuaScript); g_veryFirstRun = isVeryFirstRun(); From 7b13bb8e5e54a7a8908cf118ba4afd65fef4ef9b Mon Sep 17 00:00:00 2001 From: anilkpandey <47642449+anilkpandey@users.noreply.github.com> Date: Tue, 26 Nov 2019 09:37:45 -0800 Subject: [PATCH 20/20] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 2e808335e02b496ea3cfe9140d5bbc7b7503e404..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~!D<3Q42J(y3qmg*dz@GB4F<7K&=(NhOJUK&(n4>0>udKHYtWer5jm9GM7+z?~AX`R0AI=F4SooxG;^+CtybPsZFx=Mt@$ j8m*W=ycNHm