syncd/SaiSwitch.h (101 lines of code) (raw):
#pragma once
extern "C" {
#include "sai.h"
}
#include "meta/SaiInterface.h"
#include "VirtualOidTranslator.h"
#include "RedisClient.h"
#include "SaiSwitchInterface.h"
#include <set>
#include <string>
#include <unordered_map>
#include <vector>
#include <map>
#include <memory>
namespace syncd
{
class SaiSwitch:
public SaiSwitchInterface
{
private:
SaiSwitch(const SaiSwitch&);
SaiSwitch& operator=(const SaiSwitch&);
public:
SaiSwitch(
_In_ sai_object_id_t switch_vid,
_In_ sai_object_id_t switch_rid,
_In_ std::shared_ptr<RedisClient> client,
_In_ std::shared_ptr<VirtualOidTranslator> translator,
_In_ std::shared_ptr<sairedis::SaiInterface> vendorSai,
_In_ bool warmBoot = false);
virtual ~SaiSwitch() = default;
public:
std::string getHardwareInfo() const;
virtual std::unordered_map<sai_object_id_t, sai_object_id_t> getVidToRidMap() const override;
virtual std::unordered_map<sai_object_id_t, sai_object_id_t> getRidToVidMap() const override;
/**
* @brief Indicates whether RID was discovered on switch init.
*
* During switch operation some RIDs are removable, like vlan member.
* If user will remove such RID, then this function will no longer
* return true for that RID.
*
* If in WARM boot mode this function will also return true for objects
* that were user created and present on the switch during init.
*
* @param rid Real ID to be examined.
*
* @return True if RID was discovered during init.
*/
virtual bool isDiscoveredRid(
_In_ sai_object_id_t rid) const override;
/**
* @brief Indicates whether RID was discovered on switch init at cold boot.
*
* During switch operation some RIDs are removable, like vlan member.
* If user will remove such RID, then this function will no longer
* return true for that RID.
*
* @param rid Real ID to be examined.
*
* @return True if RID was discovered during cold boot init.
*/
virtual bool isColdBootDiscoveredRid(
_In_ sai_object_id_t rid) const override;
/**
* @brief Indicates whether RID is one of default switch objects
* like CPU port, default virtual router etc.
*
* @param rid Real object id to examine.
*
* @return True if object is default switch object.
*/
virtual bool isSwitchObjectDefaultRid(
_In_ sai_object_id_t rid) const override;
/**
* @brief Indicates whether object can't be removed.
*
* Checks whether object can be removed. All non discovered objects can
* be removed. All objects from internal attribute can't be removed.
*
* Currently there are some hard coded object types that can't be
* removed like queues, ingress PG, ports. This may not be true for
* some vendors.
*
* @param rid Real object ID to be examined.
*
* @return True if object can't be removed from switch.
*/
virtual bool isNonRemovableRid(
_In_ sai_object_id_t rid) const override;
/*
* Redis Static Methods.
*/
/**
* @brief Gets discovered objects on the switch.
*
* This set can be different from discovered objects after switch init
* when for example default VLAN members will be removed.
*
* This set can't grow, but it can be reduced.
*
* Also if in WARM boot mode it can contain user created objects.
*
* @returns Discovered objects during switch init.
*/
virtual std::set<sai_object_id_t> getDiscoveredRids() const override;
/**
* @brief Remove existing object from the switch.
*
* An ASIC remove operation is performed.
* Function throws when object can't be removed.
*
* @param rid Real object ID.
*/
virtual void removeExistingObject(
_In_ sai_object_id_t rid) override;
/**
* @brief Remove existing object reference only from discovery map.
*
* No ASIC operation is performed.
* Function throws when object was not found.
*
* @param rid Real object ID.
*/
virtual void removeExistingObjectReference(
_In_ sai_object_id_t rid) override;
/**
* @brief Gets switch default MAC address.
*
* @param[out] mac MAC address to be obtained.
*/
virtual void getDefaultMacAddress(
_Out_ sai_mac_t& mac) const override;
/**
* @brief Gets default value of attribute for given object.
*
* This applies to objects discovered after switch init like
* SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID.
*
* If object or attribute is not found, SAI_NULL_OBJECT_ID is returned.
*/
virtual sai_object_id_t getDefaultValueForOidAttr(
_In_ sai_object_id_t rid,
_In_ sai_attr_id_t attr_id) override;
/**
* @brief Get cold boot discovered VIDs.
*
* @return Set of cold boot discovered VIDs after cold boot.
*/
virtual std::set<sai_object_id_t> getColdBootDiscoveredVids() const override;
/**
* @brief Get warm boot discovered VIDs.
*
* @return Set of warm boot discovered VIDs after warm boot.
*/
virtual std::set<sai_object_id_t> getWarmBootDiscoveredVids() const override;
/**
* @brief On post port create.
*
* Performs actions needed after port creation. Will discover new
* queues, ipgs and scheduler groups that belong to new created port,
* and updated ASIC DB accordingly.
*/
virtual void onPostPortCreate(
_In_ sai_object_id_t port_rid,
_In_ sai_object_id_t port_vid) override;
/**
* @brief Post port remove.
*
* Performs actions after port remove. Will remove lanes associated
* with port from redis lane map.
*/
virtual void postPortRemove(
_In_ sai_object_id_t portRid) override;
virtual void collectPortRelatedObjects(
_In_ sai_object_id_t portRid) override;
private:
/*
* SAI Methods.
*/
sai_uint32_t saiGetPortCount() const;
std::string saiGetHardwareInfo() const;
std::vector<sai_object_id_t> saiGetPortList() const;
std::unordered_map<sai_uint32_t, sai_object_id_t> saiGetHardwareLaneMap() const;
/**
* @brief Get port lanes for specific port.
*
* @param port_rid Port RID for which lanes should be retrieved.
*
* @returns Lanes vector.
*/
std::vector<uint32_t> saiGetPortLanes(
_In_ sai_object_id_t port_rid);
/**
* @brief Get MAC address.
*
* Intended use is to get switch default MAC address, for comparison
* logic, when we will try to bring it's default value, in case user
* changed original switch MAC address.
*
* @param[out] mac Obtained MAC address.
*/
void saiGetMacAddress(
_Out_ sai_mac_t &mac) const;
private:
void redisSetDummyAsicStateForRealObjectId(
_In_ sai_object_id_t rid) const;
/**
* @brief Put cold boot discovered VIDs to redis DB.
*
* This method will only be called after cold boot and it will save
* only VIDs that are present on the switch after switch is initialized
* so it will contain only discovered objects. In case of warm boot
* this method will not be called.
*/
void redisSaveColdBootDiscoveredVids() const;
/**
* @brief Update lane map for specific port.
*
* @param port_rid Port RID for which lane map should be updated
*/
void redisUpdatePortLaneMap(
_In_ sai_object_id_t port_rid);
/*
* Helper Methods.
*/
void helperCheckLaneMap();
sai_object_id_t helperGetSwitchAttrOid(
_In_ sai_attr_id_t attr_id);
/**
* @brief Discover helper.
*
* Method will call saiDiscovery and collect all discovered objects.
*/
void helperDiscover();
void helperSaveDiscoveredObjectsToRedis();
void helperInternalOids();
void redisSaveInternalOids(
_In_ sai_object_id_t rid) const;
void helperLoadColdVids();
/*
* Other Methods.
*/
bool isWarmBoot() const;
void checkWarmBootDiscoveredRids();
sai_switch_type_t getSwitchType() const;
private:
std::string m_hardware_info;
sai_mac_t m_default_mac_address;
/*
* NOTE: Those default value will make sense only when we will do hard
* reinit, since when doing warm restart syncd will restart but if for
* example we removed some scheduler groups or added/removed ports,
* those numbers won't match and we will throw.
*
* For that case we need special handling. We will implement that
* later, when this scenario will happen.
*/
/**
* @brief Discovered objects.
*
* Set of object IDs discovered after calling saiDiscovery method.
* This set will contain all objects present on the switch right after
* switch init.
*
* This set depending on the boot, can contain user created objects if
* switch was in WARM boot mode. This set can also change if user
* decides to remove some objects like VLAN_MEMBER.
*/
std::set<sai_object_id_t> m_discovered_rids;
/**
* @brief Default oid map.
*
* This map will contain default created objects and all their "oid"
* attributes and it's default value. This will be needed for bringing
* default values.
*
* TODO later on we need to make this for all attributes.
*
* Example:
* SAI_OBJECT_TYPE_SCHEDULER: oid:0x16
*
* SAI_OBJECT_TYPE_SCHEDULER_GROUP: oid:0x17
* SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID: oid:0x16
*
* m_defaultOidMap[0x17][SAI_SCHEDULER_GROUP_ATTR_SCHEDULER_PROFILE_ID] == 0x16
*/
std::unordered_map<sai_object_id_t, std::unordered_map<sai_attr_id_t, sai_object_id_t>> m_defaultOidMap;
std::shared_ptr<sairedis::SaiInterface> m_vendorSai;
bool m_warmBoot;
std::map<sai_object_id_t, std::set<sai_object_id_t>> m_portRelatedObjects;
std::shared_ptr<VirtualOidTranslator> m_translator;
std::shared_ptr<RedisClient> m_client;
};
}