diff --git a/doc/SAI-Proposal-Generic-Resource-Monitoring.md b/doc/SAI-Proposal-Generic-Resource-Monitoring.md new file mode 100644 index 000000000..087ea1e80 --- /dev/null +++ b/doc/SAI-Proposal-Generic-Resource-Monitoring.md @@ -0,0 +1,81 @@ +Switch Abstraction Interface Change Proposal + +Title | Generic Resource Query +------------|---------------- +Authors | Mellanox +Status | In review +Type | Standards track +Created | 04/15/2019 +SAI-Version | 1.4 +---------- + +## Overview +SAI manages ASIC resources. It is important for the user to query the current resources usage in the ASIC for different types of SAI objects. +It is also importaint to make as much resources availability exposed as possible. + +## Spec + +This proposal introduces an API for querying resource availability on per object basis. +``` +/** + * @brief Get SAI object type resource availability. + * + * @param[in] switch_id SAI Switch object id + * @param[in] object_type SAI object type + * @param[in] attr_count Number of attributes + * @param[in] attr_list List of attributes that to distinguish resource + * @param[out] count Available objects left + * + * @return #SAI_STATUS_NOT_SUPPORTED if the given object type does not support resource accounting. + * Otherwise, return #SAI_STATUS_SUCCESS. + */ +sai_status_t sai_object_type_get_availability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list, + _Out_ uint64_t *count); +``` + +To help distibguish between different resource pools for the same object type, attributes that are annotated with `@isresourcetype` must be passed to the function with corresponding values. +For example, different types of route entries are distinguished by the following attribute: +``` + /** READ-ONLY */ + + /** + * @brief Route entry IP address family + * + * @type sai_ip_addr_family_t + * @flags READ_ONLY + * @isresourcetype true + */ + SAI_ROUTE_ENTRY_ATTR_IP_ADDR_FAMILY, +``` + +## Examples +``` +sai_attribute_t attr; +sai_status_t status; +uint64_t count; + +attr.id = SAI_ROUTE_ENTRY_ATTR_IP_ADDR_FAMILY; +attr.value.s32 = SAI_IP_ADDR_FAMILY_IPV4; + +/* Get available v4 routes */ +status = sai_object_type_get_availability(g_switch_id, SAI_OBJECT_TYPE_ROUTE, 1, &attr, &count); + +attr.id = SAI_ROUTE_ENTRY_ATTR_IP_ADDR_FAMILY; +attr.value.s32 = SAI_IP_ADDR_FAMILY_IPV6; + +/* Get available v6 routes */ +status = sai_object_type_get_availability(g_switch_id, SAI_OBJECT_TYPE_ROUTE, 1, &attr, &count); + +attr.id = SAI_ACL_ENTRY_ATTR_TABLE_ID; +attr.value.oid = g_table_id; + +/* Get available ACL entries for a given table id */ +status = sai_object_type_get_availability(g_switch_id, SAI_OBJECT_TYPE_ACL_ENTRY, 1, &attr, &count); +``` + +## API behavior for the shared resource pools +If two objects share the same resource pool, e.g. IPv4 and IPv6 routes, then the object availability returned by the API is with an assumption that no other object type from that same pool is going to be created. diff --git a/inc/sai.h b/inc/sai.h index 26375b112..5ebf035c3 100644 --- a/inc/sai.h +++ b/inc/sai.h @@ -267,6 +267,25 @@ sai_object_id_t sai_switch_id_query( sai_status_t sai_dbg_generate_dump( _In_ const char *dump_file_name); +/** + * @brief Get SAI object type resource availability. + * + * @param[in] switch_id SAI Switch object id + * @param[in] object_type SAI object type + * @param[in] attr_count Number of attributes + * @param[in] attr_list List of attributes that to distinguish resource + * @param[out] count Available objects left + * + * @return #SAI_STATUS_NOT_SUPPORTED if the given object type does not support resource accounting. + * Otherwise, return #SAI_STATUS_SUCCESS. + */ +sai_status_t sai_object_type_get_availability( + _In_ sai_object_id_t switch_id, + _In_ sai_object_type_t object_type, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list, + _Out_ uint64_t *count); + /** * @} */ diff --git a/inc/saiacl.h b/inc/saiacl.h index ba4eb9115..4815a01ca 100644 --- a/inc/saiacl.h +++ b/inc/saiacl.h @@ -481,6 +481,7 @@ typedef enum _sai_acl_table_attr_t * @type sai_uint32_t * @flags CREATE_ONLY * @default 0 + * @isresourcetype true */ SAI_ACL_TABLE_ATTR_SIZE, @@ -1128,6 +1129,7 @@ typedef enum _sai_acl_entry_attr_t * @type sai_object_id_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY * @objects SAI_OBJECT_TYPE_ACL_TABLE + * @isresourcetype true */ SAI_ACL_ENTRY_ATTR_TABLE_ID = SAI_ACL_ENTRY_ATTR_START, diff --git a/inc/sainexthop.h b/inc/sainexthop.h index 63a02b226..01eaac5e7 100644 --- a/inc/sainexthop.h +++ b/inc/sainexthop.h @@ -117,6 +117,7 @@ typedef enum _sai_next_hop_attr_t * * @type sai_next_hop_type_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isresourcetype true */ SAI_NEXT_HOP_ATTR_TYPE = SAI_NEXT_HOP_ATTR_START, diff --git a/inc/sainexthopgroup.h b/inc/sainexthopgroup.h index f7095f86a..f32e028b9 100644 --- a/inc/sainexthopgroup.h +++ b/inc/sainexthopgroup.h @@ -106,6 +106,7 @@ typedef enum _sai_next_hop_group_attr_t * * @type sai_next_hop_group_type_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isresourcetype true */ SAI_NEXT_HOP_GROUP_ATTR_TYPE, diff --git a/inc/sairoute.h b/inc/sairoute.h index f1fae34fc..da303a42c 100644 --- a/inc/sairoute.h +++ b/inc/sairoute.h @@ -104,6 +104,17 @@ typedef enum _sai_route_entry_attr_t */ SAI_ROUTE_ENTRY_ATTR_META_DATA, + /** READ-ONLY */ + + /** + * @brief Route entry IP address family + * + * @type sai_ip_addr_family_t + * @flags READ_ONLY + * @isresourcetype true + */ + SAI_ROUTE_ENTRY_ATTR_IP_ADDR_FAMILY, + /** * @brief Attach a counter * diff --git a/inc/saitunnel.h b/inc/saitunnel.h index 1682c011f..a3acf554d 100644 --- a/inc/saitunnel.h +++ b/inc/saitunnel.h @@ -440,6 +440,7 @@ typedef enum _sai_tunnel_attr_t * * @type sai_tunnel_type_t * @flags MANDATORY_ON_CREATE | CREATE_ONLY + * @isresourcetype true */ SAI_TUNNEL_ATTR_TYPE = SAI_TUNNEL_ATTR_START, diff --git a/meta/Doxyfile b/meta/Doxyfile index d6601edc3..1a15c5b03 100644 --- a/meta/Doxyfile +++ b/meta/Doxyfile @@ -218,20 +218,21 @@ TAB_SIZE = 4 # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. -ALIASES += "type =@par Value Type:\n @xmlonly @@type @endxmlonly" -ALIASES += "flags =@par Flags:\n @xmlonly @@flags @endxmlonly" -ALIASES += "objects =@par Allowed object types\n @xmlonly @@objects @endxmlonly" -ALIASES += "allownull =@par Allows NULL object ID\n @xmlonly @@allownull @endxmlonly" -ALIASES += "condition =@par Condition:\n @xmlonly @@condition @endxmlonly" -ALIASES += "validonly =@par Valid only when:\n @xmlonly @@validonly @endxmlonly" -ALIASES += "default =@par Default value:\n @xmlonly @@default @endxmlonly" -ALIASES += "ignore =@par Ignored:\n @xmlonly @@ignore @endxmlonly" -ALIASES += "isvlan =@par IsVlan:\n @xmlonly @@isvlan @endxmlonly" -ALIASES += "count =@par Count:\n @xmlonly @@count @endxmlonly" -ALIASES += "range =@par Range:\n @xmlonly @@range @endxmlonly" -ALIASES += "passparam =@par Pass paramater:\n @xmlonly @@passparam @endxmlonly" -ALIASES += "extraparam =@par Extra paramater:\n @xmlonly @@extraparam @endxmlonly" -ALIASES += "suffix =@par Serialize suffix:\n @xmlonly @@suffix @endxmlonly" +ALIASES += "type =@par Value Type:\n @xmlonly @@type @endxmlonly" +ALIASES += "flags =@par Flags:\n @xmlonly @@flags @endxmlonly" +ALIASES += "objects =@par Allowed object types\n @xmlonly @@objects @endxmlonly" +ALIASES += "allownull =@par Allows NULL object ID\n @xmlonly @@allownull @endxmlonly" +ALIASES += "condition =@par Condition:\n @xmlonly @@condition @endxmlonly" +ALIASES += "validonly =@par Valid only when:\n @xmlonly @@validonly @endxmlonly" +ALIASES += "default =@par Default value:\n @xmlonly @@default @endxmlonly" +ALIASES += "ignore =@par Ignored:\n @xmlonly @@ignore @endxmlonly" +ALIASES += "isvlan =@par IsVlan:\n @xmlonly @@isvlan @endxmlonly" +ALIASES += "count =@par Count:\n @xmlonly @@count @endxmlonly" +ALIASES += "range =@par Range:\n @xmlonly @@range @endxmlonly" +ALIASES += "passparam =@par Pass paramater:\n @xmlonly @@passparam @endxmlonly" +ALIASES += "extraparam =@par Extra paramater:\n @xmlonly @@extraparam @endxmlonly" +ALIASES += "suffix =@par Serialize suffix:\n @xmlonly @@suffix @endxmlonly" +ALIASES += "isresourcetype =@par IsResourceType:\n @xmlonly @@isresourcetype @endxmlonly" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" diff --git a/meta/aspell.en.pws b/meta/aspell.en.pws index fcdcb1f18..4c9df8c29 100644 --- a/meta/aspell.en.pws +++ b/meta/aspell.en.pws @@ -77,6 +77,7 @@ ingressing inout isprint isvlan +isresourcetype json linklocal lookup diff --git a/meta/parse.pl b/meta/parse.pl index 2984a04ec..82d4132b6 100755 --- a/meta/parse.pl +++ b/meta/parse.pl @@ -63,17 +63,18 @@ # TAGS HANDLERS my %ATTR_TAGS = ( - "type" , \&ProcessTagType, - "flags" , \&ProcessTagFlags, - "objects" , \&ProcessTagObjects, - "allownull" , \&ProcessTagAllowNull, - "condition" , \&ProcessTagCondition, - "validonly" , \&ProcessTagCondition, # since validonly uses same format as condition - "default" , \&ProcessTagDefault, - "ignore" , \&ProcessTagIgnore, - "isvlan" , \&ProcessTagIsVlan, - "getsave" , \&ProcessTagGetSave, - "range" , \&ProcessTagRange, + "type" , \&ProcessTagType, + "flags" , \&ProcessTagFlags, + "objects" , \&ProcessTagObjects, + "allownull" , \&ProcessTagAllowNull, + "condition" , \&ProcessTagCondition, + "validonly" , \&ProcessTagCondition, # since validonly uses same format as condition + "default" , \&ProcessTagDefault, + "ignore" , \&ProcessTagIgnore, + "isvlan" , \&ProcessTagIsVlan, + "getsave" , \&ProcessTagGetSave, + "range" , \&ProcessTagRange, + "isresourcetype" , \&ProcessTagIsRecourceType, ); my %options = (); @@ -241,6 +242,16 @@ sub ProcessTagIsVlan return undef; } +sub ProcessTagIsRecourceType +{ + my ($type, $value, $val) = @_; + + return $val if $val =~ /^(true|false)$/i; + + LogError "isresourcetype tag value '$val', expected true/false"; + return undef; +} + sub ProcessTagRange { my ($type, $attrName, $value) = @_; @@ -310,7 +321,7 @@ sub ProcessDescription return if scalar@order == 0; - my $rightOrder = 'type:flags(:objects)?(:allownull)?(:isvlan)?(:default)?(:range)?(:condition|:validonly)?'; + my $rightOrder = 'type:flags(:objects)?(:allownull)?(:isvlan)?(:default)?(:range)?(:condition|:validonly)?(:isresourcetype)?'; my $order = join(":",@order); @@ -1100,6 +1111,15 @@ sub ProcessAllowNull return "false"; } +sub ProcessIsResourceType +{ + my ($value,$isresourcetype) = @_; + + return $isresourcetype if defined $isresourcetype; + + return "false"; +} + sub ProcessObjects { my ($attr, $objects) = @_; @@ -1765,6 +1785,7 @@ sub ProcessSingleObjectType my $cap = ProcessCapability($attr, $meta{type}, $enummetadata); my $caplen = ProcessCapabilityLen($attr, $meta{type}); my $isextensionattr = ProcessIsExtensionAttr($attr, $meta{type}); + my $isresourcetype = ProcessIsResourceType($attr, $meta{isresourcetype}); my $ismandatoryoncreate = ($flags =~ /MANDATORY/) ? "true" : "false"; my $iscreateonly = ($flags =~ /CREATE_ONLY/) ? "true" : "false"; @@ -1817,6 +1838,7 @@ sub ProcessSingleObjectType WriteSource ".capability = $cap,"; WriteSource ".capabilitylength = $caplen,"; WriteSource ".isextensionattr = $isextensionattr,"; + WriteSource ".isresourcetype = $isresourcetype,"; WriteSource "};"; diff --git a/meta/saimetadatatypes.h b/meta/saimetadatatypes.h index f70af791d..70d247b3c 100644 --- a/meta/saimetadatatypes.h +++ b/meta/saimetadatatypes.h @@ -999,6 +999,14 @@ typedef struct _sai_attr_metadata_t */ bool isextensionattr; + /** + * @brief Tells if attribute is a resource type. + * + * If true, attribute is used in getting object type availability + * to distinguish between pools of resources. + */ + bool isresourcetype; + } sai_attr_metadata_t; /* diff --git a/meta/saisanitycheck.c b/meta/saisanitycheck.c index 96e860fec..e647caed4 100644 --- a/meta/saisanitycheck.c +++ b/meta/saisanitycheck.c @@ -3102,6 +3102,11 @@ void check_non_object_id_object_attrs() META_ASSERT_NOT_NULL(m); + if (m->isresourcetype && (int)m->flags == SAI_ATTR_FLAGS_READ_ONLY) + { + continue; + } + switch ((int)m->flags) { case SAI_ATTR_FLAGS_MANDATORY_ON_CREATE | SAI_ATTR_FLAGS_CREATE_AND_SET: