diff --git a/lib/inc/SkipRecordAttrContainer.h b/lib/inc/SkipRecordAttrContainer.h new file mode 100644 index 000000000000..1e8f3701c84b --- /dev/null +++ b/lib/inc/SkipRecordAttrContainer.h @@ -0,0 +1,53 @@ +#pragma once + +extern "C" { +#include "sai.h" +} + +#include +#include + +namespace sairedis +{ + /** + * @brief Skip record attributes container. + * + * This container will hold attributes that can be skipped when recording + * GET api, for example statistics attributes and *_AVAILABLE_*. + * + * Since orch agent can query those frequently it can produce large + * recording files without meaningful information. + * + * Any attribute can be added to this container, but only non oid attributes + * will be accepted. + */ + class SkipRecordAttrContainer + { + public: + + SkipRecordAttrContainer(); + + virtual ~SkipRecordAttrContainer() = default; + + public: + + bool add( + _In_ sai_object_type_t objectType, + _In_ sai_attr_id_t attrId); + + bool remove( + _In_ sai_object_type_t objectType, + _In_ sai_attr_id_t attrId); + + void clear(); + + bool canSkipRecording( + _In_ sai_object_type_t objectType, + _In_ uint32_t count, + _In_ sai_attribute_t* attrList) const; + + private: + + std::map> m_map; + }; +} diff --git a/lib/src/Makefile.am b/lib/src/Makefile.am index 5f85bbab6204..38a38decafc0 100644 --- a/lib/src/Makefile.am +++ b/lib/src/Makefile.am @@ -59,6 +59,7 @@ libsairedis_la_SOURCES = \ sai_redis_notifications.cpp \ sai_redis_record.cpp \ Globals.cpp \ + SkipRecordAttrContainer.cpp \ Switch.cpp \ SwitchContainer.cpp diff --git a/lib/src/SkipRecordAttrContainer.cpp b/lib/src/SkipRecordAttrContainer.cpp new file mode 100644 index 000000000000..159b2391f35c --- /dev/null +++ b/lib/src/SkipRecordAttrContainer.cpp @@ -0,0 +1,129 @@ +#include "SkipRecordAttrContainer.h" + +extern "C" { +#include "saimetadata.h" +} + +#include "swss/logger.h" + +using namespace sairedis; + +SkipRecordAttrContainer::SkipRecordAttrContainer() +{ + SWSS_LOG_ENTER(); + + // default set of attributes to skip recording + + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_IPV4_ROUTE_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_IPV6_ROUTE_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEXTHOP_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEXTHOP_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_IPV4_NEIGHBOR_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_IPV6_NEIGHBOR_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_L2MC_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_DOUBLE_NAT_ENTRY); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_ACL_TABLE); + add(SAI_OBJECT_TYPE_SWITCH, SAI_SWITCH_ATTR_AVAILABLE_ACL_TABLE_GROUP); + + add(SAI_OBJECT_TYPE_ACL_TABLE, SAI_ACL_TABLE_ATTR_AVAILABLE_ACL_ENTRY); + add(SAI_OBJECT_TYPE_ACL_TABLE, SAI_ACL_TABLE_ATTR_AVAILABLE_ACL_COUNTER); +} + +bool SkipRecordAttrContainer::add( + _In_ sai_object_type_t objectType, + _In_ sai_attr_id_t attrId) +{ + SWSS_LOG_ENTER(); + + auto md = sai_metadata_get_attr_metadata(objectType, attrId); + + if (md == NULL) + { + SWSS_LOG_WARN("failed to get metadata for %d:%d", objectType, attrId); + + return false; + } + + if (md->isoidattribute) + { + SWSS_LOG_WARN("%s is OID attribute, will not add to container", md->attridname); + + return false; + } + + m_map[objectType].insert(attrId); + + SWSS_LOG_DEBUG("added %s to container", md->attridname); + + return true; +} + +bool SkipRecordAttrContainer::remove( + _In_ sai_object_type_t objectType, + _In_ sai_attr_id_t attrId) +{ + SWSS_LOG_ENTER(); + + auto it = m_map.find(objectType); + + if (it == m_map.end()) + { + return false; + } + + auto its = it->second.find(attrId); + + if (its == it->second.end()) + { + return false; + } + + it->second.erase(its); + + return true; +} + +void SkipRecordAttrContainer::clear() +{ + SWSS_LOG_ENTER(); + + m_map.clear(); +} + +bool SkipRecordAttrContainer::canSkipRecording( + _In_ sai_object_type_t objectType, + _In_ uint32_t count, + _In_ sai_attribute_t* attrList) const +{ + SWSS_LOG_ENTER(); + + if (count == 0) + return false; + + if (!attrList) + return false; + + auto it = m_map.find(objectType); + + if (it == m_map.end()) + return false; + + // we can skip if all attributes on list are present in container + + auto& set = it->second; + + for (uint32_t idx = 0; idx < count; idx++) + { + if (set.find(attrList[idx].id) == set.end()) + return false; + } + + return true; +} + diff --git a/lib/src/sai_redis_generic_get.cpp b/lib/src/sai_redis_generic_get.cpp index da28156de9e6..f750ac847747 100644 --- a/lib/src/sai_redis_generic_get.cpp +++ b/lib/src/sai_redis_generic_get.cpp @@ -2,6 +2,12 @@ #include "meta/sai_serialize.h" #include "meta/saiattributelist.h" +#include "SkipRecordAttrContainer.h" + +using namespace sairedis; + +static auto g_skipRecordAttrContainer = std::make_shared(); + sai_status_t internal_redis_get_process( _In_ sai_object_type_t object_type, _In_ uint32_t attr_count, @@ -153,6 +159,8 @@ sai_status_t internal_redis_generic_get( { SWSS_LOG_ENTER(); + bool skipRecord = g_skipRecordAttrContainer->canSkipRecording(object_type, attr_count, attr_list); + /* * Since user may reuse buffers, then oid list buffers maybe not cleared * and contain some garbage, let's clean them so we send all oids as null to @@ -173,7 +181,7 @@ sai_status_t internal_redis_generic_get( SWSS_LOG_DEBUG("generic get key: %s, fields: %lu", key.c_str(), entry.size()); - if (g_record) + if (g_record && !skipRecord) { recordLine("g|" + key + "|" + joinFieldValues(entry)); } @@ -218,7 +226,7 @@ sai_status_t internal_redis_generic_get( attr_list, kco); - if (g_record) + if (g_record && !skipRecord) { const std::string &str_status = kfvKey(kco); const std::vector &values = kfvFieldsValues(kco); @@ -236,7 +244,7 @@ sai_status_t internal_redis_generic_get( break; } - if (g_record) + if (g_record && !skipRecord) { recordLine("G|SAI_STATUS_FAILURE"); }