lib/RedisRemoteSaiInterface.h (316 lines of code) (raw):

#pragma once #include "RemoteSaiInterface.h" #include "SwitchContainer.h" #include "VirtualObjectIdManager.h" #include "Recorder.h" #include "RedisVidIndexGenerator.h" #include "SkipRecordAttrContainer.h" #include "RedisChannel.h" #include "SwitchConfigContainer.h" #include "ContextConfig.h" #include "meta/Notification.h" #include "swss/producertable.h" #include "swss/consumertable.h" #include "swss/notificationconsumer.h" #include "swss/selectableevent.h" #include <memory> #include <functional> #include <map> namespace sairedis { class RedisRemoteSaiInterface: public RemoteSaiInterface { public: RedisRemoteSaiInterface( _In_ std::shared_ptr<ContextConfig> contextConfig, _In_ std::function<sai_switch_notifications_t(std::shared_ptr<Notification>)> notificationCallback, _In_ std::shared_ptr<Recorder> recorder); virtual ~RedisRemoteSaiInterface(); public: virtual sai_status_t apiInitialize( _In_ uint64_t flags, _In_ const sai_service_method_table_t *service_method_table) override; virtual sai_status_t apiUninitialize(void) override; public: // SAI interface overrides virtual sai_status_t create( _In_ sai_object_type_t objectType, _Out_ sai_object_id_t* objectId, _In_ sai_object_id_t switchId, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list) override; virtual sai_status_t remove( _In_ sai_object_type_t objectType, _In_ sai_object_id_t objectId) override; virtual sai_status_t set( _In_ sai_object_type_t objectType, _In_ sai_object_id_t objectId, _In_ const sai_attribute_t *attr) override; virtual sai_status_t get( _In_ sai_object_type_t objectType, _In_ sai_object_id_t objectId, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list) override; public: // QUAD ENTRY and BULK QUAD ENTRY SAIREDIS_DECLARE_EVERY_ENTRY(SAIREDIS_SAIINTERFACE_DECLARE_QUAD_ENTRY_OVERRIDE); SAIREDIS_DECLARE_EVERY_BULK_ENTRY(SAIREDIS_SAIINTERFACE_DECLARE_BULK_ENTRY_OVERRIDE); public: // bulk QUAD oid virtual sai_status_t bulkCreate( _In_ sai_object_type_t object_type, _In_ sai_object_id_t switch_id, _In_ uint32_t object_count, _In_ const uint32_t *attr_count, _In_ const sai_attribute_t **attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_object_id_t *object_id, _Out_ sai_status_t *object_statuses) override; virtual sai_status_t bulkRemove( _In_ sai_object_type_t object_type, _In_ uint32_t object_count, _In_ const sai_object_id_t *object_id, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses) override; virtual sai_status_t bulkSet( _In_ sai_object_type_t object_type, _In_ uint32_t object_count, _In_ const sai_object_id_t *object_id, _In_ const sai_attribute_t *attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses) override; virtual sai_status_t bulkGet( _In_ sai_object_type_t object_type, _In_ uint32_t object_count, _In_ const sai_object_id_t *object_id, _In_ const uint32_t *attr_count, _Inout_ sai_attribute_t **attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses) override; public: // stats API virtual sai_status_t getStats( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, _In_ uint32_t number_of_counters, _In_ const sai_stat_id_t *counter_ids, _Out_ uint64_t *counters) override; virtual sai_status_t queryStatsCapability( _In_ sai_object_id_t switch_id, _In_ sai_object_type_t object_type, _Inout_ sai_stat_capability_list_t *stats_capability) override; virtual sai_status_t queryStatsStCapability( _In_ sai_object_id_t switch_id, _In_ sai_object_type_t object_type, _Inout_ sai_stat_st_capability_list_t *stats_capability) override; virtual sai_status_t getStatsExt( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, _In_ uint32_t number_of_counters, _In_ const sai_stat_id_t *counter_ids, _In_ sai_stats_mode_t mode, _Out_ uint64_t *counters) override; virtual sai_status_t clearStats( _In_ sai_object_type_t object_type, _In_ sai_object_id_t object_id, _In_ uint32_t number_of_counters, _In_ const sai_stat_id_t *counter_ids) override; virtual sai_status_t bulkGetStats( _In_ sai_object_id_t switchId, _In_ sai_object_type_t object_type, _In_ uint32_t object_count, _In_ const sai_object_key_t *object_key, _In_ uint32_t number_of_counters, _In_ const sai_stat_id_t *counter_ids, _In_ sai_stats_mode_t mode, _Inout_ sai_status_t *object_statuses, _Out_ uint64_t *counters) override; virtual sai_status_t bulkClearStats( _In_ sai_object_id_t switchId, _In_ sai_object_type_t object_type, _In_ uint32_t object_count, _In_ const sai_object_key_t *object_key, _In_ uint32_t number_of_counters, _In_ const sai_stat_id_t *counter_ids, _In_ sai_stats_mode_t mode, _Inout_ sai_status_t *object_statuses) override; public: // non QUAD API virtual sai_status_t flushFdbEntries( _In_ sai_object_id_t switchId, _In_ uint32_t attrCount, _In_ const sai_attribute_t *attrList) override; public: // SAI API virtual sai_status_t objectTypeGetAvailability( _In_ sai_object_id_t switchId, _In_ sai_object_type_t objectType, _In_ uint32_t attrCount, _In_ const sai_attribute_t *attrList, _Out_ uint64_t *count) override; virtual sai_status_t queryAttributeCapability( _In_ sai_object_id_t switch_id, _In_ sai_object_type_t object_type, _In_ sai_attr_id_t attr_id, _Out_ sai_attr_capability_t *capability) override; virtual sai_status_t queryAttributeEnumValuesCapability( _In_ sai_object_id_t switch_id, _In_ sai_object_type_t object_type, _In_ sai_attr_id_t attr_id, _Inout_ sai_s32_list_t *enum_values_capability) override; virtual sai_object_type_t objectTypeQuery( _In_ sai_object_id_t objectId) override; virtual sai_object_id_t switchIdQuery( _In_ sai_object_id_t objectId) override; virtual sai_status_t logSet( _In_ sai_api_t api, _In_ sai_log_level_t log_level) override; virtual sai_status_t queryApiVersion( _Out_ sai_api_version_t *version) override; public: // notify syncd virtual sai_status_t notifySyncd( _In_ sai_object_id_t switchId, _In_ sai_redis_notify_syncd_t redisNotifySyncd) override; public: /** * @brief Checks whether attribute is custom SAI_REDIS_SWITCH attribute. * * This function should only be used on switch_api set function. */ static bool isRedisAttribute( _In_ sai_object_id_t obejctType, _In_ const sai_attribute_t* attr); sai_status_t setRedisAttribute( _In_ sai_object_id_t switchId, _In_ const sai_attribute_t* attr); void setMeta( _In_ std::weak_ptr<saimeta::Meta> meta); sai_switch_notifications_t syncProcessNotification( _In_ std::shared_ptr<Notification> notification); const std::map<sai_object_id_t, swss::TableDump>& getTableDump() const; bool containsSwitch( _In_ sai_object_id_t switchId) const; private: // QUAD API helpers sai_status_t create( _In_ sai_object_type_t objectType, _In_ const std::string& serializedObjectId, _In_ uint32_t attr_count, _In_ const sai_attribute_t *attr_list); sai_status_t remove( _In_ sai_object_type_t objectType, _In_ const std::string& serializedObjectId); sai_status_t set( _In_ sai_object_type_t objectType, _In_ const std::string& serializedObjectId, _In_ const sai_attribute_t *attr); sai_status_t get( _In_ sai_object_type_t objectType, _In_ const std::string& serializedObjectId, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); private: // bulk QUAD API helpers sai_status_t bulkCreate( _In_ sai_object_type_t object_type, _In_ const std::vector<std::string> &serialized_object_ids, _In_ const uint32_t *attr_count, _In_ const sai_attribute_t **attr_list, _In_ sai_bulk_op_error_mode_t mode, _Inout_ sai_status_t *object_statuses); sai_status_t bulkRemove( _In_ sai_object_type_t object_type, _In_ const std::vector<std::string> &serialized_object_ids, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses); sai_status_t bulkSet( _In_ sai_object_type_t object_type, _In_ const std::vector<std::string> &serialized_object_ids, _In_ const sai_attribute_t *attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses); sai_status_t bulkGet( _In_ sai_object_type_t object_type, _In_ const std::vector<std::string> &serialized_object_ids, _In_ const uint32_t *attr_count, _Inout_ sai_attribute_t **attr_list, _In_ sai_bulk_op_error_mode_t mode, _Out_ sai_status_t *object_statuses); private: // QUAD API response /** * @brief Wait for response. * * Will wait for response from syncd. Method used only for single * object create/remove/set since they have common output which is * sai_status_t. */ sai_status_t waitForResponse( _In_ sai_common_api_t api); /** * @brief Wait for GET response. * * Will wait for response from syncd. Method only used for single * GET object. If status is SUCCESS all values will be deserialized * and transferred to user buffers. If status is BUFFER_OVERFLOW * then all non list values will be transferred, but LIST objects * will only transfer COUNT item of list, without touching user * list at all. */ sai_status_t waitForGetResponse( _In_ sai_object_type_t objectType, _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); private: // bulk QUAD API response /** * @brief Wait for bulk response. * * Will wait for response from syncd. Method used only for bulk * object create/remove/set since they have common output which is * sai_status_t and object_statuses. */ sai_status_t waitForBulkResponse( _In_ sai_common_api_t api, _In_ uint32_t object_count, _Out_ sai_status_t *object_statuses); /** * @brief Wait for bulk GET response. * * Will wait for response from syncd. Method only used for bulk * GET object. If object status is SUCCESS all values will be deserialized * and transferred to user buffers. If object status is BUFFER_OVERFLOW * then all non list values will be transferred, but LIST objects * will only transfer COUNT item of list, without touching user * list at all. */ sai_status_t waitForBulkGetResponse( _In_ sai_object_type_t objectType, _In_ uint32_t object_count, _In_ const uint32_t *attr_count, _Inout_ sai_attribute_t **attr_list, _Out_ sai_status_t *object_statuses); private: // stats API response sai_status_t waitForGetStatsResponse( _In_ uint32_t number_of_counters, _Out_ uint64_t *counters); sai_status_t waitForClearStatsResponse(); private: // non QUAD API response sai_status_t waitForFlushFdbEntriesResponse(); private: // SAI API response sai_status_t waitForQueryAttributeCapabilityResponse( _Out_ sai_attr_capability_t* capability); sai_status_t waitForQueryAttributeEnumValuesCapabilityResponse( _Inout_ sai_s32_list_t* enumValuesCapability); sai_status_t waitForObjectTypeGetAvailabilityResponse( _In_ uint64_t *count); sai_status_t waitForQueryStatsCapabilityResponse( _Inout_ sai_stat_capability_list_t* stats_capability); private: // notify syncd response sai_status_t waitForNotifySyncdResponse(); private: // notification void notificationThreadFunction(); void handleNotification( _In_ const std::string &name, _In_ const std::string &serializedNotification, _In_ const std::vector<swss::FieldValueTuple> &values); sai_status_t setRedisExtensionAttribute( _In_ sai_object_type_t objectType, _In_ sai_object_id_t objectId, _In_ const sai_attribute_t *attr); bool isSaiS8ListValidString( _In_ const sai_s8_list_t &s8list); bool emplaceStrings( _In_ const sai_s8_list_t &field, _In_ const sai_s8_list_t &value, _Out_ std::vector<swss::FieldValueTuple> &entries); bool emplaceStrings( _In_ const char *field, _In_ const sai_s8_list_t &value, _Out_ std::vector<swss::FieldValueTuple> &entries); sai_status_t notifyCounterGroupOperations( _In_ sai_object_id_t objectId, _In_ const sai_redis_flex_counter_group_parameter_t *flexCounterGroupParam); sai_status_t notifyCounterOperations( _In_ sai_object_id_t objectId, _In_ const sai_redis_flex_counter_parameter_t *flexCounterParam); private: sai_status_t sai_redis_notify_syncd( _In_ sai_object_id_t switchId, _In_ const sai_attribute_t *attr); void clear_local_state(); sai_switch_notifications_t processNotification( _In_ std::shared_ptr<Notification> notification); void refreshTableDump(); private: std::shared_ptr<ContextConfig> m_contextConfig; bool m_asicInitViewMode; bool m_useTempView; bool m_syncMode; sai_redis_communication_mode_t m_redisCommunicationMode; bool m_initialized; std::shared_ptr<Recorder> m_recorder; std::shared_ptr<SwitchContainer> m_switchContainer; std::shared_ptr<VirtualObjectIdManager> m_virtualObjectIdManager; std::shared_ptr<swss::DBConnector> m_db; std::shared_ptr<RedisVidIndexGenerator> m_redisVidIndexGenerator; std::weak_ptr<saimeta::Meta> m_meta; std::shared_ptr<SkipRecordAttrContainer> m_skipRecordAttrContainer; std::shared_ptr<Channel> m_communicationChannel; uint64_t m_responseTimeoutMs; std::function<sai_switch_notifications_t(std::shared_ptr<Notification>)> m_notificationCallback; std::map<sai_object_id_t, swss::TableDump> m_tableDump; }; }