in syncd/SaiDiscovery.cpp [37:255]
void SaiDiscovery::discover(
_In_ sai_object_id_t rid,
_Inout_ std::set<sai_object_id_t> &discovered)
{
SWSS_LOG_ENTER();
/*
* NOTE: This method is only good after switch init since we are making
* assumptions that there are no ACL after initialization.
*
* NOTE: Input set could be a map of sets, this way we will also have
* dependency on each oid.
*/
if (rid == SAI_NULL_OBJECT_ID)
{
return;
}
if (discovered.find(rid) != discovered.end())
{
return;
}
sai_object_type_t ot = m_sai->objectTypeQuery(rid);
if (ot == SAI_OBJECT_TYPE_NULL)
{
SWSS_LOG_THROW("objectTypeQuery: rid %s returned NULL object type",
sai_serialize_object_id(rid).c_str());
}
SWSS_LOG_DEBUG("processing %s: %s",
sai_serialize_object_id(rid).c_str(),
sai_serialize_object_type(ot).c_str());
/*
* We will ignore STP ports by now, since when removing bridge port, then
* associated stp port is automatically removed, and we don't use STP in
* out solution. This causing inconsistency with redis ASIC view vs
* actual ASIC asic state.
*
* TODO: This needs to be solved by sending discovered state to sairedis
* metadata db for reference count.
*
* XXX: workaround
*/
if (ot != SAI_OBJECT_TYPE_STP_PORT)
{
discovered.insert(rid);
}
#ifdef SKIP_SAI_PORT_DISCOVERY
if (ot == SAI_OBJECT_TYPE_PORT)
{
return;
}
#endif
const sai_object_type_info_t *info = sai_metadata_get_object_type_info(ot);
/*
* We will query only oid object types
* then we don't need meta key, but we need to add to metadata
* pointers to only generic functions.
*/
sai_object_meta_key_t mk = { .objecttype = ot, .objectkey = { .key = { .object_id = rid } } };
for (int idx = 0; info->attrmetadata[idx] != NULL; ++idx)
{
const sai_attr_metadata_t *md = info->attrmetadata[idx];
/*
* Note that we don't care about ACL object id's since
* we assume that there are no ACLs on switch after init.
*/
sai_attribute_t attr;
attr.id = md->attrid;
if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_ID)
{
if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_CONST)
{
/*
* This means that default value for this object is
* SAI_NULL_OBJECT_ID, since this is discovery after
* create, we don't need to query this attribute.
*/
//continue;
}
if (md->objecttype == SAI_OBJECT_TYPE_STP &&
md->attrid == SAI_STP_ATTR_BRIDGE_ID)
{
// XXX workaround (for mlnx)
SWSS_LOG_WARN("skipping since it causes crash: %s", md->attridname);
continue;
}
if (md->objecttype == SAI_OBJECT_TYPE_BRIDGE_PORT)
{
if (md->attrid == SAI_BRIDGE_PORT_ATTR_TUNNEL_ID ||
md->attrid == SAI_BRIDGE_PORT_ATTR_RIF_ID)
{
/*
* We know that bridge port is bound on PORT, no need
* to query those attributes.
*/
continue;
}
}
SWSS_LOG_DEBUG("getting %s for %s", md->attridname,
sai_serialize_object_id(rid).c_str());
sai_status_t status = m_sai->get(mk.objecttype, mk.objectkey.key.object_id, 1, &attr);
if (status != SAI_STATUS_SUCCESS)
{
/*
* We failed to get value, maybe it's not supported ?
*/
SWSS_LOG_INFO("%s: %s on %s",
md->attridname,
sai_serialize_status(status).c_str(),
sai_serialize_object_id(rid).c_str());
continue;
}
m_defaultOidMap[rid][attr.id] = attr.value.oid;
if (!md->allownullobjectid && attr.value.oid == SAI_NULL_OBJECT_ID)
{
// SWSS_LOG_WARN("got null on %s, but not allowed", md->attridname);
}
if (attr.value.oid != SAI_NULL_OBJECT_ID)
{
ot = m_sai->objectTypeQuery(attr.value.oid);
if (ot == SAI_OBJECT_TYPE_NULL)
{
SWSS_LOG_THROW("when query %s (on %s RID %s) got value %s objectTypeQuery returned NULL object type",
md->attridname,
sai_serialize_object_type(md->objecttype).c_str(),
sai_serialize_object_id(rid).c_str(),
sai_serialize_object_id(attr.value.oid).c_str());
}
}
discover(attr.value.oid, discovered); // recursion
}
else if (md->attrvaluetype == SAI_ATTR_VALUE_TYPE_OBJECT_LIST)
{
if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_EMPTY_LIST)
{
/*
* This means that default value for this object is
* empty list, since this is discovery after
* create, we don't need to query this attribute.
*/
//continue;
}
SWSS_LOG_DEBUG("getting %s for %s", md->attridname,
sai_serialize_object_id(rid).c_str());
sai_object_id_t local[SAI_DISCOVERY_LIST_MAX_ELEMENTS];
attr.value.objlist.count = SAI_DISCOVERY_LIST_MAX_ELEMENTS;
attr.value.objlist.list = local;
sai_status_t status = m_sai->get(mk.objecttype, mk.objectkey.key.object_id, 1, &attr);
if (status != SAI_STATUS_SUCCESS)
{
/*
* We failed to get value, maybe it's not supported ?
*/
SWSS_LOG_INFO("%s: %s on %s",
md->attridname,
sai_serialize_status(status).c_str(),
sai_serialize_object_id(rid).c_str());
continue;
}
SWSS_LOG_DEBUG("list count %s %u", md->attridname, attr.value.objlist.count);
for (uint32_t i = 0; i < attr.value.objlist.count; ++i)
{
sai_object_id_t oid = attr.value.objlist.list[i];
ot = m_sai->objectTypeQuery(oid);
if (ot == SAI_OBJECT_TYPE_NULL)
{
SWSS_LOG_THROW("when query %s (on %s RID %s) got value %s objectTypeQuery returned NULL object type",
md->attridname,
sai_serialize_object_type(md->objecttype).c_str(),
sai_serialize_object_id(rid).c_str(),
sai_serialize_object_id(oid).c_str());
}
discover(oid, discovered); // recursion
}
}
}
}