diff --git a/doc/SAI-Counter-enhancement-hld.md b/doc/SAI-Counter-enhancement-hld.md index 4dc7bf157..375bc7281 100644 --- a/doc/SAI-Counter-enhancement-hld.md +++ b/doc/SAI-Counter-enhancement-hld.md @@ -2,7 +2,7 @@ ------------------------------------------------------------------------------- Title | SAI counter enahncement -------------|----------------------------------------------------------------- - Authors | Rajkumar P R, Marvell Technology Inc
Ravindranath C K, Marvell Technology Inc
+ Authors | Rajkumar P R, Marvell Technology Inc
Ravindranath C K, Marvell Technology Inc
Status | In review Type | Standards track Created | 01/07/2024 @@ -56,7 +56,7 @@ typedef enum _sai_port_attr_t * @flags CREATE_AND_SET * @default SAI_STATS_COUNT_MODE_PACKET_AND_BYTE */ - SAI_PORT_ATTR_STAT_ENABLED + SAI_PORT_ATTR_STAT_MODE } sai_port_attr_t; ``` @@ -71,7 +71,7 @@ typedef enum _sai_router_interface_attr_t * @flags CREATE_AND_SET * @default SAI_STATS_COUNT_MODE_PACKET_AND_BYTE */ - SAI_ROUTER_INTERFACE_ATTR_STAT_ENABLED + SAI_ROUTER_INTERFACE_ATTR_STAT_MODE } sai_router_interface_attr_t; ``` @@ -86,7 +86,7 @@ typedef enum _sai_vlan_attr_t * @flags CREATE_AND_SET * @default SAI_STATS_COUNT_MODE_PACKET_AND_BYTE */ - SAI_VLAN_ATTR_STAT_ENABLED + SAI_VLAN_ATTR_STAT_MODE } sai_vlan_attr_t; ``` @@ -101,7 +101,7 @@ typedef enum _sai_tunnel_attr_t * @flags CREATE_AND_SET * @default SAI_STATS_COUNT_MODE_PACKET_AND_BYTE */ - SAI_TUNNEL_ATTR_STAT_ENABLED + SAI_TUNNEL_ATTR_STAT_MODE } sai_tunnel_attr_t; ``` @@ -116,7 +116,7 @@ typedef enum _sai_queue_attr_t * @flags CREATE_AND_SET * @default SAI_STATS_COUNT_MODE_PACKET_AND_BYTE */ - SAI_QUEUE_ATTR_STAT_ENABLED + SAI_QUEUE_ATTR_STAT_MODE } sai_queue_attr_t; ``` @@ -131,10 +131,10 @@ sai_attribute_t attr; vector attrs; sai_stats_count_mode_t rifCntMode = SAI_STATS_COUNT_MODE_PACKET_AND_BYTE; -status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_ROUTER_INTERFACE_ATTR_STAT_ENABLED, &rif_capability); +status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_ROUTER_INTERFACE_ATTR_STAT_MODE, &rif_capability); if (status == SAI_STATUS_SUCCESS && rif_capability.create_implemented) { - attr.id = SAI_ROUTER_INTERFACE_ATTR_STAT_ENABLED; + attr.id = SAI_ROUTER_INTERFACE_ATTR_STAT_MODE; /* Read and set the platform default behavior */ if (user_has_set_packet_or_byte_mode) { @@ -157,11 +157,11 @@ sai_attr_capability_t rif_capability; sai_attribute_t attr; sai_stats_count_mode_t rifCntMode = SAI_STATS_COUNT_MODE_PACKET_AND_BYTE; -status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_ROUTER_INTERFACE_ATTR_STAT_ENABLED, &rif_capability); +status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_ROUTER_INTERFACE_ATTR_STAT_MODE, &rif_capability); if (status == SAI_STATUS_SUCCESS && rif_capability.set_implemented) { - attr.id = SAI_ROUTER_INTERFACE_ATTR_STAT_ENABLED; + attr.id = SAI_ROUTER_INTERFACE_ATTR_STAT_MODE; /* Read and set the user configured value */ if (user_has_set_packet_or_byte_mode) { @@ -198,13 +198,13 @@ for (uint32_t cnt = 0; cnt < stats_capability.count; cnt++) } status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, - SAI_ROUTER_INTERFACE_ATTR_STAT_ENABLED, + SAI_ROUTER_INTERFACE_ATTR_STAT_MODE, &rif_capability); if (status == SAI_STATUS_SUCCESS && (rif_capability.create_implemented || rif_capability.set_implemented)) { sai_attribute_t attr; - attr.id = SAI_ROUTER_INTERFACE_ATTR_STAT_ENABLED; + attr.id = SAI_ROUTER_INTERFACE_ATTR_STAT_MODE; status = sai_router_intfs_api->get_router_interface_attr(port.m_rif_id,1, &attr); if(status == SAI_STATUS_SUCCESS && attr.value.s32 == SAI_STATS_COUNT_MODE_NONE) @@ -362,7 +362,6 @@ sai_status_t status = sai_router_intfs_api->create_router_interface(&port.m_rif_ sai_status_t status = SAI_STATUS_SUCCESS; sai_attr_capability_t rif_capability; sai_attribute_t attr; -sai_stats_count_mode_t rifCntMode = SAI_STATS_COUNT_MODE_PACKET_AND_BYTE; sai_object_id_t inCountOid = SAI_NULL_OBJECT_ID; status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, countArr[0], &rif_capability); @@ -461,9 +460,318 @@ else #### Cons -- New workflow with more attributes per object. +- New workflow with more attributes per object. + +### Option 3 +This is an optimization to option 2 to reduce the number of attributes. + +Introduce a new attribute value type holding list of stat_id to counter object. + +**saitypes.h** +``` +typedef struct +{ + /** Object type of the stat enum*/ + sai_object_type_t object_type; + + /** Stat enum value */ + sai_stat_id_t stat_enum; + + /** Counter ObjectId associated with stat enum */ + sai_object_id_t counter_id; + +} sai_counter_id_t; + +typedef struct _sai_counter_list_t +{ + /** Number of stats */ + uint32_t count; + + /** List of stat-id to counter object */ + sai_counter_id_t *list; + +} sai_counter_list_t; + + +typedef union _sai_attribute_value_t +{ + + + /** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_STATID_COUNTER_LIST */ + sai_counter_list_t statidcounterlist; + +} sai_attribute_value_t; + + +``` +**saimetadatypes.h** + +``` +typedef enum _sai_attr_value_type_t +{ + + /** + * @brief Attribute value is STAT enum to COUNTER object list. + */ + SAI_ATTR_VALUE_TYPE_STATID_COUNTER_LIST + +} sai_attr_value_type_t; +``` + +Introduce an attribute for stat-id counter object list in each of the object file. + +**sairouterinterface.h** +``` + * @brief Router interface counter objects + * Counter Object list for supported router interface stats enum + * @type sai_counter_list_t + * @flags CREATE_AND_SET + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_ROUTER_INTERFACE_ATTR_COUNTER_IDS + +``` +**saivlan.h** +``` + * @brief Vlan counter objects + * Counter Object list for supported vlan stats enum + * @type sai_counter_list_t + * @flags CREATE_AND_SET + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_VLAN_ATTR_COUNTER_IDS + +``` +**saitunnel.h** +``` + * @brief Tunnel counter objects + * Counter Object list for supported tunnel stats enum + * @type sai_counter_list_t + * @flags CREATE_AND_SET + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_TUNNEL_ATTR_COUNTER_IDS + +``` +**saiqueue.h** +``` + * @brief Queue counter objects + * Counter Object list for supported queue stats enum + * @type sai_counter_list_t + * @flags CREATE_AND_SET + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_QUEUE_ATTR_COUNTER_IDS + +``` +**saiport.h** +``` + * @brief Port counter objects + * Counter Object list for supported port stats enum + * @type sai_counter_list_t + * @flags CREATE_AND_SET + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_COUNTER_IDS + +``` +#### Sample workflow +Query and save the stats capability during initialization. + +``` + uint32_t ROUTER_INTERFACE_MAX_STAT_ID = 0; + + vector countArr; + vector countOid; /* per routerinterface object */ + vector statList; + sai_stat_capability_list_t values = { .count = 0, .list = nullptr }; + + auto status = sai_query_stats_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, &values); + if ((status != SAI_STATUS_SUCCESS) && (status != SAI_STATUS_BUFFER_OVERFLOW)) + { + return status; + } + + ROUTER_INTERFACE_MAX_STAT_ID = value.count; + statList.resize(values.count); + countArr.resize(values.count); + values.list = statList.data(); + + /* vendor to return actual count with supported stats-id list */ + status = sai_query_stats_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, + &values); + if (status == SAI_STATUS_SUCCESS) + { + for(int32_t idx = 0; idx < values.count; idx ++) + { + countArr[idx] = values.list[idx].stat_enum; + } + } + else + { + /* All stats-id enums are counted */ + } +``` +##### Create Object: +```c +sai_status_t status = SAI_STATUS_SUCCESS; +sai_stat_capability_list_t rif_stats_capability; +sai_attr_capability_t rif_capability; +sai_attribute_t attr; +vector attrs; + +/* Default counting when not supported by vendor SAI, must return + "rif_capability.create_implemented = false" */ +status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_ROUTER_INTERFACE_ATTR_COUNTER_IDS, &rif_capability); +if (status == SAI_STATUS_SUCCESS && rif_capability.create_implemented) +{ + vector oid_list(ROUTER_INTERFACE_MAX_STAT_ID); //Allocate place holder for all stats-ids + attr.value.statidcounterlist.count = static_cast(ROUTER_INTERFACE_MAX_STAT_ID); + attr.value.statidcounterlist.list = oid_list.data(); + + for(int32_t idx = 0; idx < ROUTER_INTERFACE_MAX_STAT_ID; idx ++) + { + /* Create counter object */ + cnt_attr.id = SAI_COUNTER_ATTR_TYPE; + cnt_attr.value.s32 = SAI_COUNTER_TYPE_REGULAR; + cnt_attrs.push_back(cnt_attr); + stat_id = countArr[idx]; + status = sai_counter_api->sai_create_counter(&countOid[idx], gSwitchId, 1, cnt_attrs.data()); + + attr.value.objlist.list[idx].object_type = SAI_OBJECT_TYPE_ROUTER_INTERFACE; + attr.value.objlist.list[idx].stat_enum = stat_id; + attr.value.objlist.list[idx].counter_id = countOid[idx]; + } + attr.id = SAI_ROUTER_INTERFACE_ATTR_COUNTER_IDS; + attrs.push_back(attr); +} + +sai_status_t status = sai_router_intfs_api->create_router_interface(&port.m_rif_id, gSwitchId, (uint32_t)attrs.size(), attrs.data()); +``` +##### Set Object: +```c +/* Example flow to set SAI_ROUTER_INTERFACE_STAT_IN_PACKETS*/ + +sai_status_t status = SAI_STATUS_SUCCESS; +sai_attr_capability_t rif_capability; +sai_attribute_t attr; +sai_object_id_t inCountOid = SAI_NULL_OBJECT_ID; +bool isStatIdFound = false; + +for(int32_t idx = 0; idx < ROUTER_INTERFACE_MAX_STAT_ID; idx ++) +{ + if (countArr[idx] == SAI_ROUTER_INTERFACE_STAT_IN_PACKETS) + { + isStatIdFound = true; + break; + } +} + +status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_ROUTER_INTERFACE_ATTR_COUNTER_IDS, &rif_capability); + +if (status == SAI_STATUS_SUCCESS && rif_capability.set_implemented && isStatIdFound) +{ + if(enable) /* Is specific enum enabled from north-bound */ + { + if(countOid[idx] == SAI_NULL_OBJECT_ID) + { + /* Create counter object for IN_COUNTER */ + cnt_attr.id = SAI_COUNTER_ATTR_TYPE; + cnt_attr.value.s32 = SAI_COUNTER_TYPE_REGULAR; + cnt_attrs.push_back(cnt_attr); + status = sai_counter_api->sai_create_counter(&countOid[idx], gSwitchId, 1, cnt_attrs.data()); + } + } + else + { + if(countOid[idx]) + { + status = sai_counter_api->sai_remove_counter(&countOid[idx]); + } + countOid[idx] = SAI_NULL_OBJECT_ID; + } + + /* Push the updated list to SAI */ + vector oid_list(ROUTER_INTERFACE_MAX_STAT_ID); //Allocate place holder for all stats-ids + attr.value.objlist.count = static_cast(ROUTER_INTERFACE_MAX_STAT_ID); + attr.value.objlist.list = oid_list.data(); + attr.id = SAI_ROUTER_INTERFACE_ATTR_COUNTER_IDS; + for(int32_t idx = 0; idx < ROUTER_INTERFACE_MAX_STAT_ID; idx ++) + { + attr.value.objlist.list[idx].object_type = SAI_OBJECT_TYPE_ROUTER_INTERFACE; + attr.value.objlist.list[idx].stat_enum = countArr[idx]; + attr.value.objlist.list[idx].counter_id = countOid[idx]; + } +} + +sai_status_t status = + sai_router_intfs_api->set_router_interface_attribute(port.m_rif_id, &attr); + +``` +##### Get statistics: +```c +/* Assume, countOid array is updated for the specific router-interface as part of create/set operation.*/ + +status = sai_query_attribute_capability(gSwitchId, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_ROUTER_INTERFACE_ATTR_COUNTER_IDS, &rif_capability); + +if (status == SAI_STATUS_SUCCESS && rif_capability.get_implemented) +{ + sai_stat_id_t stat_ids[] = { SAI_COUNTER_STAT_PACKETS, SAI_COUNTER_STAT_BYTES }; + uint64_t stats[2]; + for(int32_t idx = 0;i < SAI_ROUTER_INTERFACE_STAT_END; i++) + { + if(countOid[idx] != SAI_NULL_OBJECT_ID) + { + status = sai_counter_api->get_counter_stats( + countOid[idx], + 2,/*count packet and byte */ + stat_ids, + stats); + } + } +} +else +{ + /* Existing Behavior */ + + sai_stat_capability_list_t stats_capability; + std::vector stats; + std::vector stats; + status = sai_query_stats_capability( + gSwitchId, + SAI_OBJECT_TYPE_ROUTER_INTERFACE, + stats_capability.data()); + + stats_capability.count = SAI_ROUTER_INTERFACE_STAT_END; + stats_capability.list = stats.data(); + + for (uint32_t cnt = 0; cnt < stats_capability.count; cnt++) + { + supported_counter_ids.push_back(stats_capability.list[cnt]); + } + + status = sai_router_intfs_api->get_router_interface_stats( + rid, + (uint32_t)supported_counter_ids.size(), + (sai_stat_id_t *)supported_counter_ids.data(), + stats.data()); +} + +``` +#### Pros +- Number of attributes reduced to 1 +- Flexiblity to count selective statistics. + +#### Cons + +- New workflow with more attributes per object. -**Prefered: Option 1** +**Prefered: Option 3** ## Warmboot Implications None