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