syncd/Syncd.h (342 lines of code) (raw):

#pragma once #include "CommandLineOptions.h" #include "FlexCounterManager.h" #include "VendorSai.h" #include "AsicView.h" #include "SaiSwitch.h" #include "VirtualOidTranslator.h" #include "RedisClient.h" #include "NotificationHandler.h" #include "NotificationProcessor.h" #include "SwitchNotifications.h" #include "ServiceMethodTable.h" #include "RedisVidIndexGenerator.h" #include "RequestShutdown.h" #include "ContextConfig.h" #include "BreakConfig.h" #include "NotificationProducerBase.h" #include "TimerWatchdog.h" #include "MdioIpcServer.h" #include "meta/SaiAttributeList.h" #include "meta/SelectableChannel.h" #include "swss/consumertable.h" #include "swss/producertable.h" #include "swss/notificationconsumer.h" #include <memory> namespace syncd { class Syncd { private: Syncd(const Syncd&) = delete; Syncd& operator=(const Syncd&) = delete; public: Syncd( _In_ std::shared_ptr<sairedis::SaiInterface> vendorSai, _In_ std::shared_ptr<CommandLineOptions> cmd, _In_ bool isWarmStart); virtual ~Syncd(); public: bool getAsicInitViewMode() const; void setAsicInitViewMode( _In_ bool enable); bool isInitViewMode() const; bool isVeryFirstRun(); void onSyncdStart( _In_ bool warmStart); void run(); public: // TODO private void processEvent( _In_ sairedis::SelectableChannel& consumer); sai_status_t processQuadEventInInitViewMode( _In_ sai_object_type_t objectType, _In_ const std::string& strObjectId, _In_ sai_common_api_t api, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); void processFlexCounterGroupEvent( _In_ swss::ConsumerTable &consumer); void processFlexCounterEvent( _In_ swss::ConsumerTable &consumer); const char* profileGetValue( _In_ sai_switch_profile_id_t profile_id, _In_ const char* variable); int profileGetNextValue( _In_ sai_switch_profile_id_t profile_id, _Out_ const char** variable, _Out_ const char** value); void performStartupLogic(); void sendShutdownRequest( _In_ sai_object_id_t switchVid); void sendShutdownRequestAfterException(); public: // shutdown actions for all switches sai_status_t removeAllSwitches(); sai_status_t setRestartWarmOnAllSwitches( _In_ bool flag); sai_status_t setFastAPIEnableOnAllSwitches(); sai_status_t setPreShutdownOnAllSwitches(); sai_status_t setUninitDataPlaneOnRemovalOnAllSwitches(); private: void loadProfileMap(); void saiLoglevelNotify( _In_ std::string strApi, _In_ std::string strLogLevel); void setSaiApiLogLevel(); private: sai_status_t processNotifySyncd( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processSingleEvent( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processAttrCapabilityQuery( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processAttrEnumValuesCapabilityQuery( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processObjectTypeGetAvailabilityQuery( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processStatsCapabilityQuery( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processFdbFlush( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processClearStatsEvent( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processGetStatsEvent( _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processQuadEvent( _In_ sai_common_api_t api, _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processBulkQuadEvent( _In_ sai_common_api_t api, _In_ const swss::KeyOpFieldsValuesTuple &kco); sai_status_t processBulkOid( _In_ sai_object_type_t objectType, _In_ const std::vector<std::string> &object_ids, _In_ sai_common_api_t api, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>> &attributes, _In_ const std::vector<std::vector<swss::FieldValueTuple>>& strAttributes); sai_status_t processBulkEntry( _In_ sai_object_type_t objectType, _In_ const std::vector<std::string> &object_ids, _In_ sai_common_api_t api, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>> &attributes, _In_ const std::vector<std::vector<swss::FieldValueTuple>>& strAttributes); sai_status_t processBulkCreateEntry( _In_ sai_object_type_t objectType, _In_ const std::vector<std::string>& objectIds, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>>& attributes, _Out_ std::vector<sai_status_t>& statuses); sai_status_t processBulkRemoveEntry( _In_ sai_object_type_t objectType, _In_ const std::vector<std::string>& objectIds, _Out_ std::vector<sai_status_t>& statuses); sai_status_t processBulkSetEntry( _In_ sai_object_type_t objectType, _In_ const std::vector<std::string>& objectIds, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>>& attributes, _Out_ std::vector<sai_status_t>& statuses); sai_status_t processBulkQuadEventInInitViewMode( _In_ sai_object_type_t objectType, _In_ const std::vector<std::string> &object_ids, _In_ sai_common_api_t api, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>> &attributes, _In_ const std::vector<std::vector<swss::FieldValueTuple>>& strAttributes); sai_status_t processOid( _In_ sai_object_type_t objectType, _In_ const std::string &strObjectId, _In_ sai_common_api_t api, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); sai_status_t processFlexCounterGroupEvent( _In_ const std::string &key, _In_ const std::string &op, _In_ const std::vector<swss::FieldValueTuple> &values, _In_ bool fromAsicChannel=true); sai_status_t processFlexCounterEvent( _In_ const std::string &key, _In_ const std::string &op, _In_ const std::vector<swss::FieldValueTuple> &values, _In_ bool fromAsicChannel=true); private: // process quad oid sai_status_t processOidCreate( _In_ sai_object_type_t objectType, _In_ const std::string &strObjectId, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); sai_status_t processOidRemove( _In_ sai_object_type_t objectType, _In_ const std::string &strObjectId); sai_status_t processOidSet( _In_ sai_object_type_t objectType, _In_ const std::string &strObjectId, _In_ sai_attribute_t *attr); sai_status_t processOidGet( _In_ sai_object_type_t objectType, _In_ const std::string &strObjectId, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); private: // process bulk oid sai_status_t processBulkOidCreate( _In_ sai_object_type_t objectType, _In_ sai_bulk_op_error_mode_t mode, _In_ const std::vector<std::string>& objectIds, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>>& attributes, _Out_ std::vector<sai_status_t>& statuses); sai_status_t processBulkOidSet( _In_ sai_object_type_t objectType, _In_ sai_bulk_op_error_mode_t mode, _In_ const std::vector<std::string>& objectIds, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>>& attributes, _Out_ std::vector<sai_status_t>& statuses); sai_status_t processBulkOidGet( _In_ sai_object_type_t objectType, _In_ sai_bulk_op_error_mode_t mode, _In_ const std::vector<std::string>& objectIds, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>>& attributes, _Out_ std::vector<sai_status_t>& statuses); sai_status_t processBulkOidRemove( _In_ sai_object_type_t objectType, _In_ sai_bulk_op_error_mode_t mode, _In_ const std::vector<std::string>& objectIds, _Out_ std::vector<sai_status_t>& statuses); private: // process quad in init view mode sai_status_t processQuadInInitViewModeCreate( _In_ sai_object_type_t objectType, _In_ const std::string& strObjectId, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); sai_status_t processQuadInInitViewModeRemove( _In_ sai_object_type_t objectType, _In_ const std::string& strObjectId); sai_status_t processQuadInInitViewModeSet( _In_ sai_object_type_t objectType, _In_ const std::string& strObjectId, _In_ sai_attribute_t *attr); sai_status_t processQuadInInitViewModeGet( _In_ sai_object_type_t objectType, _In_ const std::string& strObjectId, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); private: void syncUpdateRedisQuadEvent( _In_ sai_status_t status, _In_ sai_common_api_t api, _In_ const swss::KeyOpFieldsValuesTuple &kco); void syncUpdateRedisBulkQuadEvent( _In_ sai_common_api_t api, _In_ const std::vector<sai_status_t>& statuses, _In_ sai_object_type_t objectType, _In_ const std::vector<std::string>& objectIds, _In_ const std::vector<std::vector<swss::FieldValueTuple>>& strAttributes); public: // TODO to private sai_status_t processEntry( _In_ sai_object_meta_key_t meta_key, _In_ sai_common_api_t api, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); void syncProcessNotification( _In_ const swss::KeyOpFieldsValuesTuple& item); private: void inspectAsic(); void clearTempView(); sai_status_t onApplyViewInFastFastBoot(); sai_status_t applyView(); void dumpComparisonLogicOutput( _In_ const std::vector<std::shared_ptr<AsicView>>& currentViews); void updateRedisDatabase( _In_ const std::vector<std::shared_ptr<AsicView>>& temporaryViews); std::map<sai_object_id_t, swss::TableDump> redisGetAsicView( _In_ const std::string &tableName); void onSwitchCreateInInitViewMode( _In_ sai_object_id_t switch_vid, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); void performWarmRestart(); void performWarmRestartSingleSwitch( _In_ const std::string& key); void startDiagShell( _In_ sai_object_id_t switchRid); void diagShellThreadProc( _In_ sai_object_id_t switchRid); syncd_restart_type_t handleRestartQuery( _In_ swss::NotificationConsumer &restartQuery); private: /** * @brief Send api response. * * This function should be use to send response to sairedis for * create/remove/set API as well as their corresponding bulk versions. * * Should not be used on GET api. */ void sendApiResponse( _In_ sai_common_api_t api, _In_ sai_status_t status, _In_ uint32_t object_count = 0, _In_ sai_status_t * object_statuses = NULL); void sendGetResponse( _In_ sai_object_type_t objectType, _In_ const std::string& strObjectId, _In_ sai_object_id_t switchVid, _In_ sai_status_t status, _In_ uint32_t attr_count, _In_ sai_attribute_t *attr_list); void sendBulkGetResponse( _In_ sai_object_type_t objectType, _In_ const std::vector<std::string>& strObjectIds, _In_ sai_status_t status, _In_ const std::vector<std::shared_ptr<saimeta::SaiAttributeList>>& attributes, _In_ const std::vector<sai_status_t>& statuses); void sendNotifyResponse( _In_ sai_status_t status); private: // snoop get response oids void snoopGetResponse( _In_ sai_object_type_t object_type, _In_ const std::string &strObjectId, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); void snoopGetAttr( _In_ sai_object_type_t objectType, _In_ const std::string& strObjectId, _In_ const std::string& attrId, _In_ const std::string& attrValue); void snoopGetOid( _In_ sai_object_id_t vid); void snoopGetOidList( _In_ const sai_object_list_t& list); void snoopGetAttrValue( _In_ const std::string& strObjectId, _In_ const sai_attr_metadata_t *meta, _In_ const sai_attribute_t& attr); private: std::shared_ptr<CommandLineOptions> m_commandLineOptions; bool m_isWarmStart; bool m_firstInitWasPerformed; SwitchNotifications m_sn; ServiceMethodTable m_smt; sai_service_method_table_t m_test_services; public: // TODO to private bool m_asicInitViewMode; std::shared_ptr<FlexCounterManager> m_manager; /** * @brief set of objects removed by user when we are in init view * mode. Those could be vlan members, bridge ports etc. * * We need this list to later on not put them back to temp view * mode when doing populate existing objects in apply view mode. * * Object ids here a VIDs. */ std::set<sai_object_id_t> m_initViewRemovedVidSet; std::shared_ptr<sairedis::SaiInterface> m_vendorSai; /* * TODO: Those are hard coded values for mlnx integration for v1.0.1 they need * to be updated. * * Also DEVICE_MAC_ADDRESS is not present in saiswitch.h */ std::map<std::string, std::string> m_profileMap; std::map<std::string, std::string>::iterator m_profileIter; /** * @brief Contains map of all created switches. * * This syncd implementation supports only one switch but it's * written in a way that could be extended to use multiple switches * in the future, some refactoring needs to be made in marked * places. * * To support multiple switches VIDTORID and RIDTOVID db entries * needs to be made per switch like HIDDEN and LANES. Best way is * to wrap vid/rid map to functions that will return right key. * * Key is switch VID. */ std::map<sai_object_id_t, std::shared_ptr<syncd::SaiSwitch>> m_switches; bool m_veryFirstRun; std::shared_ptr<VirtualOidTranslator> m_translator; std::shared_ptr<RedisClient> m_client; std::shared_ptr<NotificationHandler> m_handler; std::shared_ptr<syncd::NotificationProcessor> m_processor; std::shared_ptr<sairedis::SelectableChannel> m_selectableChannel; std::shared_ptr<syncd::MdioIpcServer> m_mdioIpcServer; bool m_enableSyncMode; private: /** * @brief Syncd mutex for thread synchronization * * Purpose of this mutex is to synchronize multiple threads like * main thread, counters and notifications as well as all * operations which require multiple Redis DB access. * * For example: query DB for next VID id number, and then put map * RID and VID to Redis. From syncd point of view this entire * operation should be atomic and no other thread should access DB * or make assumption on previous information until entire * operation will finish. * * Mutex must be used in 4 places: * * - notification processing * - main event loop processing * - syncd hard init when switches are created * (notifications could be sent during that) * - in case of exception when sending shutdown request * (other notifications can still arrive at this point) * * * getting flex counter - here we skip using mutex */ std::mutex m_mutex; std::shared_ptr<swss::DBConnector> m_dbAsic; std::shared_ptr<swss::NotificationConsumer> m_restartQuery; std::shared_ptr<swss::DBConnector> m_dbFlexCounter; std::shared_ptr<swss::ConsumerTable> m_flexCounter; std::shared_ptr<swss::ConsumerTable> m_flexCounterGroup; std::shared_ptr<swss::Table> m_flexCounterTable; std::shared_ptr<swss::Table> m_flexCounterGroupTable; std::shared_ptr<NotificationProducerBase> m_notifications; std::shared_ptr<sairedis::SwitchConfigContainer> m_switchConfigContainer; std::shared_ptr<sairedis::RedisVidIndexGenerator> m_redisVidIndexGenerator; std::shared_ptr<sairedis::VirtualObjectIdManager> m_virtualObjectIdManager; std::shared_ptr<sairedis::ContextConfig> m_contextConfig; std::shared_ptr<BreakConfig> m_breakConfig; TimerWatchdog m_timerWatchdog; std::set<sai_object_id_t> m_createdInInitView; }; }