in meta/saisanitycheck.c [4042:4157]
void check_objects_for_loops_recursive(
_In_ const sai_object_type_info_t* info,
_Inout_ sai_object_type_t *visited,
_Inout_ uint32_t *attributes,
_In_ int level)
{
META_LOG_ENTER();
visited[level] = info->objecttype;
int levelidx = 0;
for (; levelidx < level; ++levelidx)
{
if (visited[levelidx] == info->objecttype)
{
/* object type is already defined, so we have a loop */
list_loop(info, visited, attributes, levelidx, level);
return;
}
}
const sai_attr_metadata_t* const* meta = info->attrmetadata;
META_ASSERT_NOT_NULL(meta);
size_t idx = 0;
/* iterate all attributes on non object id type */
for (; meta[idx] != NULL; ++idx)
{
const sai_attr_metadata_t* m = meta[idx];
META_ASSERT_NOT_NULL(m);
if (SAI_HAS_FLAG_READ_ONLY(m->flags))
{
/* skip read only attributes since with those we will have loops for sure */
continue;
}
/* skip known loops */
if (m->objecttype == SAI_OBJECT_TYPE_SRV6_SIDLIST)
{
if (m->attrid == SAI_SRV6_SIDLIST_ATTR_NEXT_HOP_ID)
{
continue;
}
}
if (m->objecttype == SAI_OBJECT_TYPE_PORT)
{
if (m->attrid == SAI_PORT_ATTR_EGRESS_MIRROR_SESSION ||
m->attrid == SAI_PORT_ATTR_INGRESS_MIRROR_SESSION ||
m->attrid == SAI_PORT_ATTR_EGRESS_BLOCK_PORT_LIST ||
m->attrid == SAI_PORT_ATTR_INGRESS_SAMPLE_MIRROR_SESSION ||
m->attrid == SAI_PORT_ATTR_EGRESS_SAMPLE_MIRROR_SESSION)
{
continue;
}
}
if (m->objecttype == SAI_OBJECT_TYPE_SCHEDULER_GROUP &&
m->attrid == SAI_SCHEDULER_GROUP_ATTR_PARENT_NODE)
{
continue;
}
attributes[level] = m->attrid;
size_t j = 0;
for (; j < m->allowedobjecttypeslength; ++j)
{
const sai_object_type_info_t* next = sai_metadata_get_object_type_info(m->allowedobjecttypes[j]);
check_objects_for_loops_recursive(next, visited, attributes, level + 1);
}
}
/* iterate for struct members on non object id object types */
if (info->isnonobjectid)
{
size_t j = 0;
for (; j < info->structmemberscount; ++j)
{
const sai_struct_member_info_t *m = info->structmembers[j];
if (m->membervaluetype != SAI_ATTR_VALUE_TYPE_OBJECT_ID)
{
continue;
}
size_t k = 0;
for (; k < m->allowedobjecttypeslength; k++)
{
const sai_object_type_info_t* next = sai_metadata_get_object_type_info(m->allowedobjecttypes[k]);
check_objects_for_loops_recursive(next, visited, attributes, level + 1);
}
}
}
/* clear level on exit */
visited[level] = SAI_OBJECT_TYPE_NULL;
attributes[level] = 0;
}