meta/Meta.h (414 lines of code) (raw):
#pragma once
#include "SaiInterface.h"
#include "SaiAttrWrapper.h"
#include "SaiObjectCollection.h"
#include "PortRelatedSet.h"
#include "AttrKeyMap.h"
#include "OidRefCounter.h"
#include "swss/table.h"
#include <vector>
#include <memory>
#include <set>
#define DEFAULT_VLAN_NUMBER 1
#define MINIMUM_VLAN_NUMBER 1
#define MAXIMUM_VLAN_NUMBER 4094
namespace saimeta
{
class Meta:
public sairedis::SaiInterface
{
public:
using sairedis::SaiInterface::set; // name hiding
Meta(
_In_ std::shared_ptr<SaiInterface> impl);
virtual ~Meta() = default;
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:
void meta_init_db();
bool isEmpty() const;
void dump() const;
public: // notifications
void meta_sai_on_fdb_event(
_In_ uint32_t count,
_In_ const sai_fdb_event_notification_data_t *data);
void meta_sai_on_nat_event(
_In_ uint32_t count,
_In_ const sai_nat_event_notification_data_t *data);
void meta_sai_on_switch_state_change(
_In_ sai_object_id_t switch_id,
_In_ sai_switch_oper_status_t switch_oper_status);
void meta_sai_on_switch_asic_sdk_health_event(
_In_ sai_object_id_t switch_id,
_In_ sai_switch_asic_sdk_health_severity_t severity,
_In_ sai_timespec_t timestamp,
_In_ sai_switch_asic_sdk_health_category_t category,
_In_ sai_switch_health_data_t data,
_In_ const sai_u8_list_t description);
void meta_sai_on_switch_shutdown_request(
_In_ sai_object_id_t switch_id);
void meta_sai_on_port_state_change(
_In_ uint32_t count,
_In_ const sai_port_oper_status_notification_t *data);
void meta_sai_on_queue_pfc_deadlock_notification(
_In_ uint32_t count,
_In_ const sai_queue_deadlock_notification_data_t *data);
void meta_sai_on_bfd_session_state_change(
_In_ uint32_t count,
_In_ const sai_bfd_session_state_notification_t *data);
void meta_sai_on_port_host_tx_ready_change(
_In_ sai_object_id_t port_id,
_In_ sai_object_id_t switch_id,
_In_ sai_port_host_tx_ready_status_t host_tx_ready_status);
void meta_sai_on_twamp_session_event(
_In_ uint32_t count,
_In_ const sai_twamp_session_event_notification_data_t *data);
private: // notifications helpers
void meta_sai_on_fdb_flush_event_consolidated(
_In_ const sai_fdb_event_notification_data_t& data);
void meta_fdb_event_snoop_oid(
_In_ sai_object_id_t oid);
void meta_sai_on_fdb_event_single(
_In_ const sai_fdb_event_notification_data_t& data);
void meta_sai_on_nat_event_single(
_In_ const sai_nat_event_notification_data_t& data);
void meta_sai_on_port_state_change_single(
_In_ const sai_port_oper_status_notification_t& data);
void meta_sai_on_queue_pfc_deadlock_notification_single(
_In_ const sai_queue_deadlock_notification_data_t& data);
void meta_sai_on_bfd_session_state_change_single(
_In_ const sai_bfd_session_state_notification_t& data);
void meta_sai_on_twamp_session_event_single(
_In_ const sai_twamp_session_event_notification_data_t& data);
private: // validation helpers
sai_status_t meta_generic_validation_objlist(
_In_ const sai_attr_metadata_t& md,
_In_ sai_object_id_t switch_id,
_In_ uint32_t count,
_In_ const sai_object_id_t* list);
sai_status_t meta_genetic_validation_list(
_In_ const sai_attr_metadata_t& md,
_In_ uint32_t count,
_In_ const void* list);
sai_status_t meta_generic_validate_non_object_on_create(
_In_ const sai_object_meta_key_t& meta_key,
_In_ sai_object_id_t switch_id);
sai_object_id_t meta_extract_switch_id(
_In_ const sai_object_meta_key_t& meta_key,
_In_ sai_object_id_t switch_id);
std::shared_ptr<SaiAttrWrapper> get_object_previous_attr(
_In_ const sai_object_meta_key_t& metaKey,
_In_ const sai_attr_metadata_t& md);
std::vector<const sai_attr_metadata_t*> get_attributes_metadata(
_In_ sai_object_type_t objecttype);
void meta_generic_validation_post_get_objlist(
_In_ const sai_object_meta_key_t& meta_key,
_In_ const sai_attr_metadata_t& md,
_In_ sai_object_id_t switch_id,
_In_ uint32_t count,
_In_ const sai_object_id_t* list);
public:
static bool is_ipv6_mask_valid(
_In_ const uint8_t* mask);
private: // unit tests helpers
bool meta_unittests_get_and_erase_set_readonly_flag(
_In_ const sai_attr_metadata_t& md);
public:
/**
* @brief Enable unittest globally.
*
* @param[in] enable If set to true unittests are enabled.
*/
void meta_unittests_enable(
_In_ bool enable);
/**
* @brief Indicates whether unittests are enabled;
*/
bool meta_unittests_enabled();
/**
* @brief Allow to perform SET operation on READ_ONLY attribute only once.
*
* This function relaxes metadata checking on SET operation, it allows to
* perform SET api on READ_ONLY attribute only once on specific object type and
* specific attribute.
*
* Once means that SET operation is only relaxed for the very next SET call on
* that specific object type and attribute id.
*
* Function is explicitly named ONCE, since it will force test developer to not
* forget that SET check is relaxed, and not forget for future unittests.
*
* Function is provided for more flexible testing using virtual switch. Since
* some of the read only attributes maybe very complex to simulate (for example
* resources used by actual asic when adding next hop or next hop group), then
* it's easier to write such unittest:
*
* TestCase:
* 1. meta_unittests_allow_readonly_set_once(x,y);
* 2. object_x_api->set_attribute(object_id, attr, foo); // attr.id == y
* 3. object_x_api->get_attribute(object_id, 1, attr); // attr.id == y
* 4. check if get result is equal to set result.
*
* On real ASIC, even after allowing SET on read only attribute, actual SET
* should fail.
*
* It can be dangerous to set any readonly attribute to different values since
* internal metadata logic maybe using that value and in some cases metadata
* database may get out of sync and cause unexpected results in api calls up to
* application crash.
*
* This function is not thread safe.
*
* @param[in] object_type Object type on which SET will be possible.
* @param[in] attr_id Attribute ID on which SET will be possible.
*
* @return #SAI_STATUS_SUCCESS on success Failure status code on error
*/
sai_status_t meta_unittests_allow_readonly_set_once(
_In_ sai_object_type_t object_type,
_In_ int32_t attr_id);
public: // unittests method helpers
int32_t getObjectReferenceCount(
_In_ sai_object_id_t oid) const;
bool objectExists(
_In_ const sai_object_meta_key_t& mk) const;
private: // port helpers
sai_status_t meta_port_remove_validation(
_In_ const sai_object_meta_key_t& meta_key);
bool meta_is_object_in_default_state(
_In_ sai_object_id_t oid);
void post_port_remove(
_In_ const sai_object_meta_key_t& meta_key);
void meta_post_port_get(
_In_ const sai_object_meta_key_t& meta_key,
_In_ sai_object_id_t switch_id,
_In_ const uint32_t attr_count,
_In_ const sai_attribute_t *attr_list);
void meta_add_port_to_related_map(
_In_ sai_object_id_t port_id,
_In_ const sai_object_list_t& list);
public: // validation post QUAD
void meta_generic_validation_post_create(
_In_ const sai_object_meta_key_t& meta_key,
_In_ sai_object_id_t switch_id,
_In_ const uint32_t attr_count,
_In_ const sai_attribute_t *attr_list);
void meta_generic_validation_post_remove(
_In_ const sai_object_meta_key_t& meta_key);
void meta_generic_validation_post_set(
_In_ const sai_object_meta_key_t& meta_key,
_In_ const sai_attribute_t *attr);
void meta_generic_validation_post_get(
_In_ const sai_object_meta_key_t& meta_key,
_In_ sai_object_id_t switch_id,
_In_ const uint32_t attr_count,
_In_ const sai_attribute_t *attr_list);
private: // validation QUAD
sai_status_t meta_generic_validation_create(
_In_ const sai_object_meta_key_t& meta_key,
_In_ sai_object_id_t switch_id,
_In_ const uint32_t attr_count,
_In_ const sai_attribute_t *attr_list);
sai_status_t meta_generic_validation_remove(
_In_ const sai_object_meta_key_t& meta_key);
sai_status_t meta_generic_validation_set(
_In_ const sai_object_meta_key_t& meta_key,
_In_ const sai_attribute_t *attr);
sai_status_t meta_generic_validation_get(
_In_ const sai_object_meta_key_t& meta_key,
_In_ const uint32_t attr_count,
_In_ sai_attribute_t *attr_list);
protected: // stats
sai_status_t meta_validate_stats(
_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,
_In_ sai_stats_mode_t mode);
private: // validate OID
sai_status_t meta_sai_validate_oid(
_In_ sai_object_type_t object_type,
_In_ const sai_object_id_t* object_id,
_In_ sai_object_id_t switch_id,
_In_ bool create);
private: // validate ENTRY
sai_status_t meta_sai_validate_fdb_entry(
_In_ const sai_fdb_entry_t* fdb_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_mcast_fdb_entry(
_In_ const sai_mcast_fdb_entry_t* mcast_fdb_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_neighbor_entry(
_In_ const sai_neighbor_entry_t* neighbor_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_route_entry(
_In_ const sai_route_entry_t* route_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_l2mc_entry(
_In_ const sai_l2mc_entry_t* l2mc_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_ipmc_entry(
_In_ const sai_ipmc_entry_t* ipmc_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_nat_entry(
_In_ const sai_nat_entry_t* nat_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_inseg_entry(
_In_ const sai_inseg_entry_t* inseg_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_my_sid_entry(
_In_ const sai_my_sid_entry_t* my_sid_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_direction_lookup_entry(
_In_ const sai_direction_lookup_entry_t* direction_lookup_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_eni_ether_address_map_entry(
_In_ const sai_eni_ether_address_map_entry_t* eni_ether_address_map_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_vip_entry(
_In_ const sai_vip_entry_t* vip_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_inbound_routing_entry(
_In_ const sai_inbound_routing_entry_t* inbound_routing_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_pa_validation_entry(
_In_ const sai_pa_validation_entry_t* pa_validation_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_outbound_routing_entry(
_In_ const sai_outbound_routing_entry_t* outbound_routing_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_outbound_ca_to_pa_entry(
_In_ const sai_outbound_ca_to_pa_entry_t* outbound_ca_to_pa_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_flow_entry(
_In_ const sai_flow_entry_t* flow_entry,
_In_ bool create,
_In_ bool get = false);
sai_status_t meta_sai_validate_meter_bucket_entry(
_In_ const sai_meter_bucket_entry_t* meter_bucket_entry,
_In_ bool create,
_In_ bool get = false);
public:
/*
* Those functions will be used to recreate virtual switch local metadata state
* after WARM BOOT.
*/
void meta_warm_boot_notify();
void populate(
_In_ const swss::TableDump& dump);
private:
void clean_after_switch_remove(
_In_ sai_object_id_t switchId);
private:
std::shared_ptr<sairedis::SaiInterface> m_implementation;
private: // database objects
/**
* @brief Port related objects set.
*
* Key in map is port OID, and value is set of related objects ids
* like queues, ipgs and scheduler groups.
*
* This map will help to identify objects to be automatically removed
* when port will be removed.
*/
PortRelatedSet m_portRelatedSet;
/*
* Non object ids don't need reference count since they are leafs and can be
* removed at any time.
*/
OidRefCounter m_oids;
SaiObjectCollection m_saiObjectCollection;
AttrKeyMap m_attrKeys;
private: // unittests
std::set<std::string> m_meta_unittests_set_readonly_set;
bool m_unittestsEnabled;
private: // warm boot
bool m_warmBoot;
};
}