void check_attr_conditions()

in meta/saisanitycheck.c [1365:1534]


void check_attr_conditions(
        _In_ const sai_attr_metadata_t* md)
{
    META_LOG_ENTER();

    switch (md->conditiontype)
    {
        case SAI_ATTR_CONDITION_TYPE_NONE:
        case SAI_ATTR_CONDITION_TYPE_OR:
        case SAI_ATTR_CONDITION_TYPE_AND:
        case SAI_ATTR_CONDITION_TYPE_MIXED:
            break;

        default:

            META_MD_ASSERT_FAIL(md, "invalid condition type specified: %d", md->conditiontype);
    }

    bool conditional = md->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE;

    if (!conditional && md->conditions != NULL)
    {
        META_MD_ASSERT_FAIL(md, "not conditional but conditions specified");
    }

    if (!conditional)
    {
        META_ASSERT_FALSE(md->isconditional, "marked conditional but is not");
        return;
    }

    META_ASSERT_TRUE(md->isconditional, "marked not conditional but is");

    if (md->conditions == NULL)
    {
        META_MD_ASSERT_FAIL(md, "marked as conditional but no conditions specified");
    }

    switch ((int)md->flags)
    {
        case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET:
        case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY:

            /*
             * If attribute is marked as conditional then it must have flags
             * mandatory on create, otherwise use validonly condition.
             */

            break;

        default:

            META_MD_ASSERT_FAIL(md, "marked as conditional, but invalid creation flags: 0x%x", md->flags);
    }

    /* condition must be the same object type as attribute we check */

    size_t index = 0;

    for (; index < md->conditionslength; ++index)
    {
        const sai_attr_condition_t* c = md->conditions[index];

        if (c->attrid == md->attrid)
        {
            META_MD_ASSERT_FAIL(md, "conditional attr id %d is the same as condition attribute", c->attrid);
        }

        if (md->conditiontype == SAI_ATTR_CONDITION_TYPE_MIXED && c->attrid == SAI_INVALID_ATTRIBUTE_ID)
        {
            switch (c->type)
            {
                case SAI_ATTR_CONDITION_TYPE_OR:
                case SAI_ATTR_CONDITION_TYPE_AND:
                    break;

                default:

                    META_MD_ASSERT_FAIL(md, "conditionwrong sub condition type: %d (expected AND/OR)", c->type);
            }

            continue;
        }

        const sai_attr_metadata_t* cmd = sai_metadata_get_attr_metadata(md->objecttype, c->attrid);

        if (cmd == NULL)
        {
            META_MD_ASSERT_FAIL(md, "conditional attribute id %d was not defined yet in metadata", c->attrid);
        }

        switch (cmd->attrvaluetype)
        {
            case SAI_ATTR_VALUE_TYPE_BOOL:

                META_LOG_DEBUG("attr id: %d cond.bool: %d", c->attrid, c->condition.booldata);

                break;

            case SAI_ATTR_VALUE_TYPE_INT32:

                /*
                 * Currently force conditional int32 attributes to be enum.
                 * This can be relaxed later when needed.
                 */

                if (!cmd->isenum)
                {
                    META_MD_ASSERT_FAIL(md, "conditional attribute %s is not enum type", cmd->attridname);
                }

                if (cmd->isenum)
                {
                    /* condition value can be a number or enum */

                    META_LOG_DEBUG("attr id: %d cond.s32: %d ", c->attrid, c->condition.s32);

                    /* check if condition enum is in condition attribute range */

                    if (sai_metadata_get_enum_value_name(cmd->enummetadata, c->condition.s32) == NULL)
                    {
                        META_MD_ASSERT_FAIL(md, "condition enum %d not found on condition attribute enum range", c->condition.s32);
                    }
                }

                break;

            case SAI_ATTR_VALUE_TYPE_INT8:
            case SAI_ATTR_VALUE_TYPE_INT16:
            case SAI_ATTR_VALUE_TYPE_INT64:
            case SAI_ATTR_VALUE_TYPE_UINT8:
            case SAI_ATTR_VALUE_TYPE_UINT16:
            case SAI_ATTR_VALUE_TYPE_UINT32:
            case SAI_ATTR_VALUE_TYPE_UINT64:

                /* number conditions */

                break;

            default:

                META_MD_ASSERT_FAIL(md, "attr value type %d of conditional attribute is not supported yet", cmd->attrvaluetype);

        }

        if (cmd->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE)
        {
            META_MD_ASSERT_FAIL(md, "conditional attribute is also conditional, not allowed");
        }

        switch ((int)cmd->flags)
        {
            case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY | SAI_ATTR_FLAGS_KEY:
            case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_ONLY:
            case SAI_ATTR_FLAGS_CREATE_ONLY:

                /*
                 * Condition attribute must be create only since if it could
                 * change then other object may be required to pass on creation
                 * time that was not passed.
                 */

                break;

            default:

                META_MD_ASSERT_FAIL(cmd, "attribute must be create only since used in condition for %s", md->attridname);
        }
    }
}