syncd/AsicView.h (106 lines of code) (raw):
#pragma once
extern "C" {
#include "saimetadata.h"
}
#include "SaiObj.h"
#include "SaiAttr.h"
#include "AsicOperation.h"
#include "swss/table.h"
namespace syncd
{
/**
* @brief Class represents ASIC view
*/
class AsicView
{
public:
typedef std::unordered_map<sai_object_id_t, sai_object_id_t> ObjectIdMap;
typedef std::map<std::string, std::shared_ptr<SaiObj>> StrObjectIdToSaiObjectHash;
typedef std::map<sai_object_id_t, std::shared_ptr<SaiObj>> ObjectIdToSaiObjectHash;
private:
/*
* Copy constructor and assignment operator are marked as private to
* avoid copy of data of entire view. This is not needed for now.
*/
AsicView(const AsicView&) = delete;
AsicView& operator=(const SaiAttr&) = delete;
public:
AsicView();
AsicView(
_In_ const swss::TableDump &dump);
virtual ~AsicView();
public:
/**
* @brief Populates ASIC view from REDIS table dump
*
* @param[in] dump Redis table dump
*
* NOTE: Could be static method that returns AsicView object.
*/
void fromDump(
_In_ const swss::TableDump &dump);
void checkObjectsStatus() const;
sai_object_id_t getSwitchVid() const;
private:
/**
* @brief Release existing VID links (references) based on given attribute.
*
* @param[in] attr Attribute which will be used to obtain oids.
*/
void releaseExisgingLinks(
_In_ const std::shared_ptr<const SaiAttr> &attr);
/**
* @brief Release existing VID links (references) based on given object.
*
* All OID attributes will be scanned and released.
*
* @param[in] obj Object which will be used to obtain attributes and oids
*/
void releaseExisgingLinks(
_In_ const std::shared_ptr<const SaiObj> &obj);
/**
* @brief Release VID reference.
*
* If SET operation was performed on attribute, and attribute was OID
* attribute, then we need to release previous reference to that VID,
* and bind new reference to next OID if present.
*
* @param[in] vid Virtual ID to be released.
*/
void releaseVidReference(
_In_ sai_object_id_t vid);
/**
* @brief Bind new links (references) based on attribute
*
* @param[in] attr Attribute to obtain oids to bind references
*/
void bindNewLinks(
_In_ const std::shared_ptr<const SaiAttr> &attr);
/**
* @brief Bind existing VID links (references) based on given object.
*
* All OID attributes will be scanned and bound.
*
* @param[in] obj Object which will be used to obtain attributes and oids
*/
void bindNewLinks(
_In_ const std::shared_ptr<const SaiObj> &obj);
/**
* @brief Bind new VID reference
*
* If attribute is OID attribute then we need to increase reference
* count on that VID to mark it that it is in use.
*
* @param[in] vid Virtual ID reference to be bind
*/
void bindNewVidReference(
_In_ sai_object_id_t vid);
public:
/**
* @brief Gets VID reference count.
*
* @param vid Virtual ID to obtain reference count.
*
* @return Reference count or -1 if VID was not found.
*/
int getVidReferenceCount(
_In_ sai_object_id_t vid) const;
/**
* @brief Insert new VID reference.
*
* Inserts new reference to be tracked. This also make sure that
* reference doesn't exist yet, as a sanity check if same reference
* would be inserted twice.
*
* @param[in] vid Virtual ID reference to be inserted.
*/
void insertNewVidReference(
_In_ sai_object_id_t vid);
public:
/**
* @brief Gets objects by object type.
*
* @param object_type Object type to be used as filter.
*
* @return List of objects with requested object type.
* Order on list is random.
*/
std::vector<std::shared_ptr<SaiObj>> getObjectsByObjectType(
_In_ sai_object_type_t object_type) const;
/**
* @brief Gets not processed objects by object type.
*
* Call to this method can be expensive, since every time we iterate
* entire list. This list can contain even 10k elements if view will be
* very large.
*
* @param object_type Object type to be used as filter.
*
* @return List of objects with requested object type and marked
* as not processed. Order on list is random.
*/
std::vector<std::shared_ptr<SaiObj>> getNotProcessedObjectsByObjectType(
_In_ sai_object_type_t object_type) const;
/**
* @brief Gets all not processed objects
*
* @return List of all not processed objects. Order on list is random.
*/
std::vector<std::shared_ptr<SaiObj>> getAllNotProcessedObjects() const;
/**
* @brief Create dummy existing object
*
* Function creates dummy object, which is used to indicate that
* this OID object exist in current view. This is used for existing
* objects, like CPU port, default trap group.
*
* @param[in] rid Real ID
* @param[in] vid Virtual ID
*/
std::shared_ptr<SaiObj> createDummyExistingObject(
_In_ sai_object_id_t rid,
_In_ sai_object_id_t vid);
/**
* @brief Generate ASIC set operation on current existing object.
*
* NOTE: In long run, this is serialize, and then we call deserialize
* to execute them on actual ASIC, maybe this is not necessary
* and could be optimized later.
*
* TODO: Set on object id should do release of links (currently done
* outside) and modify dependency tree.
*
* @param currentObj Current object.
* @param attr Attribute to be set on current object.
*/
void asicSetAttribute(
_In_ const std::shared_ptr<SaiObj> ¤tObj,
_In_ const std::shared_ptr<SaiAttr> &attr);
/**
* @brief Generate ASIC create operation for current object.
*
* NOTE: In long run, this is serialize, and then we call
* deserialize to execute them on actual asic, maybe this is not
* necessary and could be optimized later.
*
* TODO: Create on object id attributes should bind references to
* used VIDs of of links (currently done outside) and modify
* dependency tree.
*
* @param currentObject Current object to be created.
*/
void asicCreateObject(
_In_ const std::shared_ptr<SaiObj> ¤tObj);
/**
* @brief Generate ASIC remove operation for current existing object.
*
* @param currentObj Current existing object to be removed.
*/
void asicRemoveObject(
_In_ const std::shared_ptr<SaiObj> ¤tObj);
std::vector<AsicOperation> asicGetWithOptimizedRemoveOperations() const;
std::vector<AsicOperation> asicGetOperations() const;
size_t asicGetOperationsCount() const;
bool hasRid(
_In_ sai_object_id_t rid) const;
bool hasVid(
_In_ sai_object_id_t vid) const;
void dumpRef(const std::string & asicName);
void dumpVidToAsicOperatioId() const;
private:
void populateAttributes(
_In_ std::shared_ptr<SaiObj> &obj,
_In_ const swss::TableMap &map);
/**
* @brief Update non object id VID reference count by specified value.
*
* Method will iterate via all OID struct members in non object id and
* update reference count by specified value.
*
* @param currentObj Current object to be processed.
* @param value Value by which reference will be updated. Can be negative.
*/
void updateNonObjectIdVidReferenceCountByValue(
_In_ const std::shared_ptr<SaiObj> ¤tObj,
_In_ int value);
public:
// TODO convert to something like nonObjectIdMap
StrObjectIdToSaiObjectHash m_soFdbs;
StrObjectIdToSaiObjectHash m_soNeighbors;
StrObjectIdToSaiObjectHash m_soRoutes;
StrObjectIdToSaiObjectHash m_soNatEntries;
StrObjectIdToSaiObjectHash m_soInsegs;
StrObjectIdToSaiObjectHash m_soOids;
StrObjectIdToSaiObjectHash m_soAll;
std::unordered_map<std::string,std::vector<std::string>> m_routesByPrefix;
std::unordered_map<std::string,std::vector<std::string>> m_neighborsByIp;
ObjectIdToSaiObjectHash m_oOids;
std::unordered_map<sai_object_id_t, sai_object_id_t> m_preMatchMap;
/*
* On temp view this needs to be used for actual NEW rids created and
* then reused with rid mapping to create new rid/vid map.
*/
ObjectIdMap m_ridToVid;
ObjectIdMap m_vidToRid;
ObjectIdMap m_removedVidToRid;
std::map<sai_object_type_t, std::unordered_map<std::string,std::string>> m_nonObjectIdMap;
sai_object_id_t m_defaultTrapGroupRid;
private:
bool m_enableRefernceCountLogs;
/**
* @brief Virtual ID reference map.
*
* VID is key, reference count is value.
*/
std::map<sai_object_id_t, int> m_vidReference;
/**
* @brief Asic operation ID.
*
* Since asic resources are limited like number of routes or buffer
* pools, so if we don't match object, at first we created new object
* and then remove previous one. This scenario may not be possible in
* case of limited resources. Advantage here is that this approach is
* making sure that asic data plane disruption will be minimal. But we
* need to switch to remove object first and then create new one. This
* will make sure that we will be able to remove first and then create,
* but in this case we can have some asic data plane disruption.
*
* This asic operation id will be used to figure out what operation
* reduced object reference to zero, so we could move remove operation
* right after this operation instead of the executing all remove
* actions after all set/create.
*
*/
int m_asicOperationId;
/**
* @brief VID to asic operation id map.
*
* Map where key is VID that points to last asic operation id that
* decreased reference on that VID to zero. This mean that if object
* with that VID will be removed, we can move remove operation right
* after asic operation id pointed by this VID.
*/
std::map<sai_object_id_t, int> m_vidToAsicOperationId;
/**
* @brief ASIC operation list.
*
* List contains ASIC operation generated in the same way as SAIREDIS.
*
* KeyOpFieldsValuesTuple is shared to prevent expensive copy when
* adding to vector.
*/
std::vector<AsicOperation> m_asicOperations;
std::vector<AsicOperation> m_asicRemoveOperationsNonObjectId;
std::map<sai_object_type_t, StrObjectIdToSaiObjectHash> m_sotAll;
};
}