syncd/NotificationQueue.h (36 lines of code) (raw):

#pragma once extern "C" { #include <sai.h> #include <saimetadata.h> } #include "swss/table.h" #include <queue> #include <mutex> #include <memory> /** * @brief Default notification queue size limit. * * Value based on typical L2 deployment with 256k MAC entries and * some extra buffer for other events like port-state, q-deadlock etc * * Note: We recently found a case where SAI continuously sending switch notification events * that also caused the queue to keep growing and eventually exhaust all system memory and crashed. * So a new detection/limit scheme is being implemented by keeping track of the last Event * and if the current Event matches the last Event, then the last Event Count will get * incremented and this count will also be used as part of the equation to ensure this * notification should also be dropped if the queue size limit has already reached and not * just dropping FDB events only. * TODO: move to config, also this limit only applies to fdb notifications */ #define DEFAULT_NOTIFICATION_QUEUE_SIZE_LIMIT (300000) #define DEFAULT_NOTIFICATION_CONSECUTIVE_THRESHOLD (1000) namespace syncd { class NotificationQueue { public: NotificationQueue( _In_ size_t limit = DEFAULT_NOTIFICATION_QUEUE_SIZE_LIMIT, _In_ size_t consecutiveThresholdLimit = DEFAULT_NOTIFICATION_CONSECUTIVE_THRESHOLD); virtual ~NotificationQueue(); public: bool enqueue( _In_ const swss::KeyOpFieldsValuesTuple& msg); bool tryDequeue( _Out_ swss::KeyOpFieldsValuesTuple& msg); size_t getQueueSize(); private: std::mutex m_mutex; std::shared_ptr<std::queue<swss::KeyOpFieldsValuesTuple>> m_queue; size_t m_queueSizeLimit; size_t m_thresholdLimit; size_t m_dropCount; size_t m_lastEventCount; std::string m_lastEvent; }; }