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