void check_objects_for_loops_recursive()

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;
}