void check_attr_validonly()

in meta/saisanitycheck.c [1536:1787]


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

    switch (md->validonlytype)
    {
        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 validonly type specified: %d", md->validonlytype);
    }

    bool conditional = md->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE;

    if (!conditional && md->validonly != NULL)
    {
        META_MD_ASSERT_FAIL(md, "not validonly but validonly specified");
        META_ASSERT_FALSE(md->isvalidonly, "marked validonly but is not");
    }

    if (!conditional)
    {
        return;
    }

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

    META_ASSERT_TRUE(md->isvalidonly, "marked not validonly but is");

    switch ((int)md->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_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET:

            META_MD_ASSERT_FAIL(md, "valid only attribute can't be mandatory on create, use condition");
            break;

        case SAI_ATTR_FLAGS_CREATE_ONLY:

            /*
             * In general valid only attribute should be used only on
             * CREATE_AND_SET flags, since when attribute is CREATE_ONLY it has
             * default value and it can't be changed anyway, and entire purpose
             * of valid only attribute is to allow change during runtime.
             *
             * When attribute CREATE_ONLY is marked as valid only is more like
             * indication that this value will be used in that specific case
             * but you won't be able to change it anyway.
             */

            META_MD_LOG_DEBUG(md, "marked as valid only, on flags CREATE_ONLY, default value is present, should this be CREATE_AND_SET?");

            /* intentional fall through */

        case SAI_ATTR_FLAGS_CREATE_AND_SET:

            /* ok */

            break;

        case SAI_ATTR_FLAGS_READ_ONLY:

            META_MD_ASSERT_FAIL(md, "read only attribute can't be valid only");
            break;

        default:

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

    if (md->defaultvaluetype == SAI_DEFAULT_VALUE_TYPE_NONE)
    {
        /*
         * In struct defaultvalue member can be NULL for some other default
         * value types like empty list or internal etc. Default value is
         * provided for CONST only.
         */

        META_MD_ASSERT_FAIL(md, "expected default value on valid only attribute, but none provided");
    }

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

    size_t index = 0;

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

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

        if (md->validonlytype == 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, "validonly wrong 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, "validonly 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, "validonly 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, "validonly enum %d not found on validonly 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:
                break;

            default:

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

        /*
         * TODO can validonly attribute depend on condition attribute which is not provided?
         * TODO can validonly depend on other validonly?
         */

        if (cmd->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE)
        {
            if (md->objecttype == SAI_OBJECT_TYPE_MIRROR_SESSION &&
                    (md->attrid == SAI_MIRROR_SESSION_ATTR_VLAN_TPID || md->attrid == SAI_MIRROR_SESSION_ATTR_VLAN_ID ||
                     md->attrid == SAI_MIRROR_SESSION_ATTR_VLAN_PRI || md->attrid == SAI_MIRROR_SESSION_ATTR_VLAN_CFI))
            {
                /*
                 * Vlan header attributes are depending on VLAN_HEADER_VALID which is
                 * also valid only for ERSPAN.
                 */
            }
            else if (md->objecttype == SAI_OBJECT_TYPE_NEXT_HOP &&
                    (md->attrid == SAI_NEXT_HOP_ATTR_OUTSEG_TTL_MODE || md->attrid == SAI_NEXT_HOP_ATTR_OUTSEG_TTL_VALUE ||
                     md->attrid == SAI_NEXT_HOP_ATTR_OUTSEG_EXP_MODE || md->attrid == SAI_NEXT_HOP_ATTR_OUTSEG_EXP_VALUE ||
                     md->attrid == SAI_NEXT_HOP_ATTR_QOS_TC_AND_COLOR_TO_MPLS_EXP_MAP))
            {
                /*
                 * MPLS out segment attributes are required for ingress node and valid only for MPLS next hop.
                 */
            }
            else if (md->objecttype == SAI_OBJECT_TYPE_TWAMP_SESSION &&
                    (md->attrid == SAI_TWAMP_SESSION_ATTR_TX_PKT_CNT || md->attrid == SAI_TWAMP_SESSION_ATTR_TX_PKT_PERIOD ||
                     md->attrid == SAI_TWAMP_SESSION_ATTR_TUNNEL_OUTER_VLAN_ID || md->attrid == SAI_TWAMP_SESSION_ATTR_TUNNEL_OUTER_VLAN_PRI ||
                     md->attrid == SAI_TWAMP_SESSION_ATTR_TUNNEL_OUTER_VLAN_CFI || md->attrid == SAI_TWAMP_SESSION_ATTR_VLAN_ID ||
                     md->attrid == SAI_TWAMP_SESSION_ATTR_VLAN_PRI || md->attrid == SAI_TWAMP_SESSION_ATTR_VLAN_CFI))
            {
                /*
                 * TWAMP packet tx mode attributes are depending on TWAMP_PKT_TX_MODE.
                 */
            }
            else
            {
                META_MD_ASSERT_FAIL(md, "validonly attribute is also validonly attribute, not allowed");
            }
        }

        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_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET:
            case SAI_ATTR_FLAGS_CREATE_ONLY:
            case SAI_ATTR_FLAGS_CREATE_AND_SET:

                /*
                 * Valid only attribute can be create_only or create_and_set
                 * conditional attribute can change during runtime and it may
                 * have impact on valid only attribute (it may or may not be
                 * used).
                 */

                break;

            default:

                META_MD_ASSERT_FAIL(cmd, "valid only condition attribute has invalid flags");
        }
    }

    if ((md->conditiontype != SAI_ATTR_CONDITION_TYPE_NONE ) &&
            (md->validonlytype != SAI_ATTR_CONDITION_TYPE_NONE ))
    {
        META_MD_ASSERT_FAIL(md, "attribute is conditional and valid only, not supported");
    }
}