Repository: opencomputeproject/SAI
Pull request #2141: [TAM] SAI TAM enhancements
Author: login: rajkumar38
Labels: name: reviewed
description: PR is discussed in SAI Meeting
Created: 2025-02-19T12:44:54Z | Merged: 2025-03-18T06:39:57Z

This proposal extends SAI TAM 2.0 with,
- enhanced reporting modes (sampling, microburst)
- new GRE transport type and transport attributes for header encapsulation
- collector destination port/lag
- new ACL action attribute to associate the TAM object with specific flow


Diff:
diff --git a/doc/TAM/SAI-TAM-enhancements.md b/doc/TAM/SAI-TAM-enhancements.md
new file mode 100644
index 000000000..71bab2bf8
--- /dev/null
+++ b/doc/TAM/SAI-TAM-enhancements.md
@@ -0,0 +1,391 @@
+# SAI TAM enhancements
+-------------------------------------------------------------------------------
+ Title       | SAI TAM enahncements
+-------------|-----------------------------------------------------------------
+ Authors     |<code> Rajkumar P R, Ganapathasaa K, Ravindranath C K (Marvell Technology Inc) </code>
+ Status      | In review
+ Type        | Standards track
+ Created     | 02/19/2025
+
+-------------------------------------------------------------------------------
+## Overview
+
+This proposal enhances SAI TAM 2.0 by adding new reporting mode (sampling), a new transport type (GRE), header encapsulation attributes, and collector destination options (port/lag).
+Additionally, a new ACL action attribute is added to bind the TAM object to specific flow.
+
+## Requirements
+- Identify a flow using ACL and apply TAM action.
+- Support GRE transport type.
+- New TAM report modes and attributes to support the generation of report sampling.
+- Rate limit reports.
+- Support for missing collector attributes, such as source MAC, destination MAC (needed for GRE header encapsulation), and the destination interface to which reports are transmitted. 
+
+
+## Report Format
+
+Example report generated with transport type GRE and vendor extension header.
+```
+   ------------------
+   |      L2        |
+   ------------------
+   |    IPv4/IPv6   |
+   ------------------
+   |      GRE       |
+   ------------------
+   |   Vendor hdr   |
+   ------------------
+   |  Original pkt  |
+   |  (Truncated)   |
+   ------------------
+   ```
+
+### ACL action - TAM Object
+```c
++    /** Bind a TAM object */
++    SAI_ACL_ACTION_TYPE_TAM_OBJECT = 0x0000003c,
+ } sai_acl_action_type_t;
+
+```
+```c
++    /**
++     * @brief ACL bind point for TAM object
++     *
++     * Bind (or unbind) a TAM object.
++     *
++     * @type sai_acl_action_data_t sai_object_id_t
++     * @flags CREATE_AND_SET
++     * @objects SAI_OBJECT_TYPE_TAM
++     * @allownull true
++     * @default disabled
++     */
++    SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT = SAI_ACL_ENTRY_ATTR_ACTION_START + 0x3c,
++
++    /**
++     * @brief End of Rule Actions
++     */
++    SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT,
+
+```
+### TAM report mode
+#### Sampling
+Sending all the report events can overwhelm the collector. Sampling reduces the load on the collector by only sending
+ 1 in every N events.
+
+```c
++    /** Report in a sampling mode, one report is sent for every n reports */
++    SAI_TAM_REPORT_MODE_SAMPLING,
++
+```
+
+### TAM report attributes
+```c
+
++    /**
++     * @brief Sampling rate (every 1/sample_rate)
++     *
++     * @type sai_uint32_t
++     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
++     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
++     */
++    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
++
++    /**
++     * @brief Maximum report rate per second
++     *
++     * Value 0 to no limit.
++     *
++     * @type sai_uint64_t
++     * @flags CREATE_AND_SET
++     * @default 0
++     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
++     */
++    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
++
++    /**
++     * @brief Maximum reports per burst
++     *
++     * @type sai_uint64_t
++     * @flags CREATE_AND_SET
++     * @default 0
++     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
++     */
++    SAI_TAM_REPORT_ATTR_MAX_REPORT_BURST,
+
+```
+### TAM GRE transport type
+```c
++     /**
++     * @brief Transport GRE
++     */
++    SAI_TAM_TRANSPORT_TYPE_GRE,
+
+} sai_tam_transport_type_t;
+```
+
+### TAM transport attribute to set gre protocol
+```c
++    /**
++     * @brief GRE protocol Id
++     *
++     * @type sai_uint16_t
++     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
++     * @isvlan false
++     * @condition SAI_TAM_TRANSPORT_ATTR_TRANSPORT_TYPE == SAI_TAM_TRANSPORT_TYPE_GRE
++     */
++    SAI_TAM_TRANSPORT_ATTR_GRE_PROTOCOL_TYPE,
+
+```
+
+### TAM collector attributes
+TAM collector is reachable via Desitination interface.
+
+```c
++    /**
++     * @brief Source MAC address
++     *
++     * Note: Applicable only when SAI_TAM_TRANSPORT_ATTR_TRANSPORT_TYPE != SAI_TAM_TRANSPORT_TYPE_NONE
++     *
++     * @type sai_mac_t
++     * @flags CREATE_AND_SET
++     * @default vendor
++     */
++    SAI_TAM_COLLECTOR_ATTR_SRC_MAC,
++
++    /**
++     * @brief Destination MAC address
++     *
++     * Note: Applicable only when SAI_TAM_TRANSPORT_ATTR_TRANSPORT_TYPE != SAI_TAM_TRANSPORT_TYPE_NONE
++     *
++     * @type sai_mac_t
++     * @flags CREATE_AND_SET
++     * @default vendor
++     */
++    SAI_TAM_COLLECTOR_ATTR_DST_MAC,
++
++    /**
++     * @brief Destination used to reach collector
++     * 
++     * @type sai_object_id_t
++     * @flags CREATE_AND_SET
++     * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_SYSTEM_PORT
++     * @allownull true
++     * @default SAI_NULL_OBJECT_ID
++     * @validonly SAI_TAM_COLLECTOR_ATTR_LOCALHOST == false
++     */
++    SAI_TAM_COLLECTOR_ATTR_DESTINATION,
+
+```
+
+## Sample workflow
+1. Create Transport object of type GRE
+
+```c
+   count = 0;
+   attr_list[count].id = SAI_TAM_TRANSPORT_ATTR_TRANSPORT_TYPE;
+   attr_list[count].value.s32 = SAI_TAM_TRANSPORT_TYPE_GRE;
+   count++;
+   attr_list[count].id = SAI_TAM_TRANSPORT_ATTR_GRE_PROTOCOL_TYPE;
+   attr_list[count].value.u16 = 0x8818;
+   count++;
+   
+   rc = tam_api_p->create_tam_transport(&tam_transport_id, switch_id, count, attr_list);
+   ASSERT_EQ(SAI_STATUS_SUCCESS, rc);
+
+```
+2. Create a Collector object
+```c
+    count = 0;
+    memset(attr_list, 0, sizeof(attr_list));
+    attr_list[count].id = SAI_TAM_COLLECTOR_ATTR_TRANSPORT;
+    attr_list[count].value.oid = tam_transport_id;
+    count++;
+    attr_list[count].id = SAI_TAM_COLLECTOR_ATTR_LOCALHOST;
+    attr_list[count].value.oid = false;
+    count++;
+    attr_list[count].id = SAI_TAM_COLLECTOR_ATTR_SRC_IP;
+    attr_list[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
+    attr_list[count].value.ipaddr.addr.ip4 = 0x0101010a;
+    count++;
+    attr_list[count].id = SAI_TAM_COLLECTOR_ATTR_SRC_MAC;
+    memcpy(&attr_list[count].value.mac, &smac, sizeof(sai_mac_t));
+    count++;
+
+    attr_list[count].id = SAI_TAM_COLLECTOR_ATTR_DST_IP;
+    attr_list[count].value.ipaddr.addr_family = SAI_IP_ADDR_FAMILY_IPV4;
+    attr_list[count].value.ipaddr.addr.ip4 = 0x0101010b;
+    count++;
+    attr_list[count].id = SAI_TAM_COLLECTOR_ATTR_DST_MAC;
+    memcpy(&attr_list[count].value.mac, &dmac, sizeof(sai_mac_t));
+    count++;
+    attr_list[count].id = SAI_TAM_COLLECTOR_ATTR_DESTINATION;
+    attr_list[count].value.oid = port2_oid;
+    count++;
+    attr_list[count].id = SAI_TAM_COLLECTOR_ATTR_DSCP_VALUE;
+    attr_list[count].value.u8 = 8;
+    count++;
+
+    rc = tam_api_p->create_tam_collector(&tam_collector_id, switch_id, count, attr_list);
+
+```
+3. Create a report object in sampling mode
+```c
+    count = 0;
+    memset(attr_list, 0, sizeof(attr_list));
+
+    attr_list[count].id = SAI_TAM_REPORT_ATTR_TYPE;
+    attr_list[count].value.s32 = SAI_TAM_REPORT_TYPE_VENDOR_EXTN;
+    count++;
+
+    attr_list[count].id = SAI_TAM_REPORT_ATTR_REPORT_MODE;
+    attr_list[count].value.s32 = SAI_TAM_REPORT_MODE_SAMPLING;
+    count++;
+    attr_list[count].id = SAI_TAM_REPORT_ATTR_SAMPLE_RATE;
+    attr_list[count].value.u32 = 1000;
+    count++;
+    rc = tam_api_p->create_tam_report(&tam_report_id, switch_id, count, attr_list);
+```
+4. Create event threshold object
+```c
+    count = 0;
+    memset(attr_list, 0, sizeof(attr_list));
+
+    attr_list[count].id = SAI_TAM_EVENT_THRESHOLD_ATTR_LATENCY;
+    attr_list[count].value.u32 = 8000; //nsec
+    count++;
+
+    rc = tam_api_p->create_tam_event_threshold(&tam_event_threshold_id, switch_id, count, attr_list);
+
+```
+5. Create an event action object
+```c
+    count = 0;
+    memset(attr_list, 0, sizeof(attr_list));
+
+    attr_list[count].id = SAI_TAM_EVENT_ACTION_ATTR_REPORT_TYPE;
+    attr_list[count].value.oid = tam_report_id;
+    count++;
+
+    rc = tam_api_p->create_tam_event_action(&tam_event_action_id, switch_id, count, attr_list);
+
+```
+6. Create a tam event object
+```c
+    count = 0;
+    memset(attr_list, 0, sizeof(attr_list));
+
+    attr_list[count].id = SAI_TAM_EVENT_ATTR_TYPE;
+    attr_list[count].value.s32 = SAI_TAM_EVENT_TYPE_QUEUE_THRESHOLD;
+    count++;
+
+    attr_list[count].id = SAI_TAM_EVENT_ATTR_ACTION_LIST;
+
+    attr_list[count].value.objlist.count = 1;
+    attr_list[count].value.objlist.list = (sai_object_id_t *)malloc(1*sizeof(sai_object_id_t));
+    attr_list[count].value.objlist.list[0] = tam_event_action_id;
+    count++;
+
+    attr_list[count].id = SAI_TAM_EVENT_ATTR_COLLECTOR_LIST;
+    attr_list[count].value.objlist.count = 1;
+    attr_list[count].value.objlist.list = (sai_object_id_t *)malloc(1*sizeof(sai_object_id_t));
+    attr_list[count].value.objlist.list[0] = tam_collector_id;
+    count++;
+
+    attr_list[count].id = SAI_TAM_EVENT_ATTR_THRESHOLD;
+    attr_list[count].value.oid = tam_event_threshold_id;
+    count++;
+
+    rc = tam_api_p->create_tam_event(&tam_event_id, switch_id, count, attr_list);
+```
+7. Create a TAM object
+```c
+    count = 0;
+    memset(attr_list, 0, sizeof(attr_list));
+
+    attr_list[count].id = SAI_TAM_ATTR_EVENT_OBJECTS_LIST;
+    attr_list[count].value.objlist.count = 1;
+    attr_list[count].value.objlist.list = (sai_object_id_t *)malloc(1*sizeof(sai_object_id_t));
+    attr_list[count].value.objlist.list[0] = tam_event_id;
+    count++;
+
+    attr_list[count].id = SAI_TAM_ATTR_TAM_BIND_POINT_TYPE_LIST;
+    attr_list[count].value.objlist.count = 2;
+    attr_list[count].value.objlist.list = (sai_object_id_t *)malloc(2*sizeof(sai_object_id_t));
+    attr_list[count].value.objlist.list[0] = SAI_TAM_BIND_POINT_TYPE_SWITCH;
+    count++;
+
+    rc = tam_api_p->create_tam(&tam_id, switch_id, count, attr_list);
+```
+
+8. Apply a TAM policy to an ACL flow.
+
+```c
+    bindpoint_type_arr[arr_idx++]    = SAI_ACL_BIND_POINT_TYPE_SWITCH;
+    sai_bindpoint_type_list.list     = bindpoint_type_arr;
+    sai_bindpoint_type_list.count    = arr_idx;
+
+    ...
+
+    attr_list[count].value.s32list = sai_bindpoint_type_list;
+    attr_list[count].id            = SAI_ACL_TABLE_ATTR_ACL_BIND_POINT_TYPE_LIST;
+    count++;
+
+    attr_list[count].id = SAI_ACL_TABLE_ATTR_FIELD_SRC_IP;
+    attr_list[count].value.booldata = true;
+    count++;
+
+    attr_list[count].id = SAI_ACL_TABLE_ATTR_ACL_ACTION_TYPE_LIST;
+    attr_list[count].value.s32list.list = action_list;
+    action_list[action_count++] = SAI_ACL_ACTION_TYPE_TAM_OBJECT;
+    attr_list[count].value.s32list.count = action_count;
+    count++;
+
+    rc = acl_api_p->create_acl_table(&acl_table_oid, switch_id, count, attr_list);
+
+    count = 0;
+    memset(attr_list, 0, sizeof(attr_list));
+
+    attr_list[count].id = SAI_ACL_ENTRY_ATTR_TABLE_ID;
+    attr_list[count].value.oid = acl_table_oid;
+    count++;
+
+    attr_list[count].id        = SAI_ACL_ENTRY_ATTR_PRIORITY;
+    attr_list[count].value.u32 = 0xFFFFFFFF;
+    count++;
+
+    attr_list[count].id = SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP;
+    attr_list[count].value.aclfield.enable = true;
+    attr_list[count].value.aclfield.data.ip4 = 0x01010101;
+    attr_list[count].value.aclfield.mask.ip4 = 0xFFFF0000;
+    count++;
+
+    attr_list[count].id = SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT;
+    attr_list[count].value.aclaction.parameter.oid  = tam_id;
+    attr_list[count].value.aclaction.enable= true;
+    count++;
+
+    rc = acl_api_p->create_acl_entry(&acl_entry_oid, switch_id, count, attr_list);
+```
+
+#### Rate limit tam reports
+Example flow to create tam report object with rate limit configurations.
+Replace above step (3) with below api sequence.
+```c
+    count = 0;
+    memset(attr_list, 0, sizeof(attr_list));
+
+    attr_list[count].id = SAI_TAM_REPORT_ATTR_TYPE;
+    attr_list[count].value.s32 = SAI_TAM_REPORT_TYPE_VENDOR_EXTN;
+    count++;
+
+    attr_list[count].id = SAI_TAM_REPORT_ATTR_REPORT_MODE;
+    attr_list[count].value.s32 = SAI_TAM_REPORT_MODE_ALL;
+    count++;
+    attr_list[count].id = SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE;
+    attr_list[count].value.u32 = 512;
+    count++;
+
+    attr_list[count].id = SAI_TAM_REPORT_ATTR_MAX_REPORT_BURST;
+    attr_list[count].value.u32 = 1024;
+    count++;
+    rc = tam_api_p->create_tam_report(&tam_report_id, switch_id, count, attr_list);
+```
diff --git a/inc/saiacl.h b/inc/saiacl.h
index d0fb90615..c1f2d274f 100644
--- a/inc/saiacl.h
+++ b/inc/saiacl.h
@@ -301,6 +301,9 @@ typedef enum _sai_acl_action_type_t
     /** Set ECMP hash algorithm */
     SAI_ACL_ACTION_TYPE_SET_ECMP_HASH_ALGORITHM = 0x0000003c,
 
+    /** Bind a TAM object */
+    SAI_ACL_ACTION_TYPE_TAM_OBJECT = 0x0000003d,
+
 } sai_acl_action_type_t;
 
 /**
@@ -3340,10 +3343,23 @@ typedef enum _sai_acl_entry_attr_t
      */
     SAI_ACL_ENTRY_ATTR_ACTION_SET_ECMP_HASH_ALGORITHM = SAI_ACL_ENTRY_ATTR_ACTION_START + 0x3c,
 
+    /**
+     * @brief ACL bind point for TAM object
+     *
+     * Bind (or unbind) a TAM object.
+     *
+     * @type sai_acl_action_data_t sai_object_id_t
+     * @flags CREATE_AND_SET
+     * @objects SAI_OBJECT_TYPE_TAM
+     * @allownull true
+     * @default disabled
+     */
+    SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT = SAI_ACL_ENTRY_ATTR_ACTION_START + 0x3d,
+
     /**
      * @brief End of Rule Actions
      */
-    SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_SET_ECMP_HASH_ALGORITHM,
+    SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT,
 
     /**
      * @brief End of ACL Entry attributes
diff --git a/inc/saitam.h b/inc/saitam.h
index 4b31de438..52abdacc5 100644
--- a/inc/saitam.h
+++ b/inc/saitam.h
@@ -1289,6 +1289,9 @@ typedef enum _sai_tam_report_mode_t
     /** Report in a bulk mode */
     SAI_TAM_REPORT_MODE_BULK,
 
+    /** Report in a sampling mode, one report is sent for every n reports */
+    SAI_TAM_REPORT_MODE_SAMPLING,
+
 } sai_tam_report_mode_t;
 
 /**
@@ -1416,6 +1419,37 @@ typedef enum _sai_tam_report_attr_t
      */
     SAI_TAM_REPORT_ATTR_REPORT_INTERVAL_UNIT,
 
+    /**
+     * @brief Sampling rate (every 1/sample_rate)
+     *
+     * @type sai_uint32_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
+     */
+    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
+
+    /**
+     * @brief Maximum report rate per second
+     *
+     * Value 0 to no limit.
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
+
+    /**
+     * @brief Maximum reports per burst
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_BURST,
+
     /**
      * @brief End of Attributes
      */
@@ -1652,6 +1686,11 @@ typedef enum _sai_tam_transport_type_t
      * @brief Transport MIRROR session
      */
     SAI_TAM_TRANSPORT_TYPE_MIRROR,
+
+    /**
+     * @brief Transport GRE
+     */
+    SAI_TAM_TRANSPORT_TYPE_GRE,
 } sai_tam_transport_type_t;
 
 /**
@@ -1733,6 +1772,16 @@ typedef enum _sai_tam_transport_attr_t
      */
     SAI_TAM_TRANSPORT_ATTR_MTU,
 
+    /**
+     * @brief GRE protocol Id
+     *
+     * @type sai_uint16_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @isvlan false
+     * @condition SAI_TAM_TRANSPORT_ATTR_TRANSPORT_TYPE == SAI_TAM_TRANSPORT_TYPE_GRE
+     */
+    SAI_TAM_TRANSPORT_ATTR_GRE_PROTOCOL_TYPE,
+
     /**
      * @brief End of Attributes
      */
@@ -1892,6 +1941,40 @@ typedef enum _sai_tam_collector_attr_t
      */
     SAI_TAM_COLLECTOR_ATTR_HOSTIF_TRAP,
 
+    /**
+     * @brief Source MAC address
+     *
+     * Note: Applicable only when SAI_TAM_TRANSPORT_ATTR_TRANSPORT_TYPE != SAI_TAM_TRANSPORT_TYPE_NONE
+     *
+     * @type sai_mac_t
+     * @flags CREATE_AND_SET
+     * @default vendor
+     */
+    SAI_TAM_COLLECTOR_ATTR_SRC_MAC,
+
+    /**
+     * @brief Destination MAC address
+     *
+     * Note: Applicable only when SAI_TAM_TRANSPORT_ATTR_TRANSPORT_TYPE != SAI_TAM_TRANSPORT_TYPE_NONE
+     *
+     * @type sai_mac_t
+     * @flags CREATE_AND_SET
+     * @default vendor
+     */
+    SAI_TAM_COLLECTOR_ATTR_DST_MAC,
+
+    /**
+     * @brief Destination used to reach collector
+     *
+     * @type sai_object_id_t
+     * @flags CREATE_AND_SET
+     * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_SYSTEM_PORT
+     * @allownull true
+     * @default SAI_NULL_OBJECT_ID
+     * @validonly SAI_TAM_COLLECTOR_ATTR_LOCALHOST == false
+     */
+    SAI_TAM_COLLECTOR_ATTR_DESTINATION,
+
     /**
      * @brief End of Attributes
      */
diff --git a/meta/saisanitycheck.c b/meta/saisanitycheck.c
index 26040194e..c33b4dad2 100644
--- a/meta/saisanitycheck.c
+++ b/meta/saisanitycheck.c
@@ -4298,6 +4298,12 @@ void check_objects_for_loops_recursive(
             continue;
         }
 
+        if (m->objecttype == SAI_OBJECT_TYPE_TAM_COLLECTOR &&
+               m->attrid == SAI_TAM_COLLECTOR_ATTR_DESTINATION)
+        {
+            continue;
+        }
+
         attributes[level] = m->attrid;
 
         size_t j = 0;


Reviews:
user: login: ashutosh-agrawal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-27T17:19:26Z
user: login: ashutosh-agrawal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-27T17:20:31Z
user: login: rajkumar38
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T13:01:44Z
user: login: rajkumar38
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T13:02:11Z
user: login: kcudnik
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-06T14:47:17Z
user: login: ashutosh-agrawal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T23:12:29Z
user: login: rajkumar38
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T09:44:31Z
user: login: ashutosh-agrawal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T17:33:08Z
user: login: rajkumar38
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T09:48:01Z
user: login: ashutosh-agrawal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T17:16:29Z
user: login: rajkumar38
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T08:25:46Z
user: login: ashutosh-agrawal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-14T17:05:55Z
user: login: rajkumar38
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-15T08:17:44Z
user: login: ashutosh-agrawal
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T05:26:25Z
user: login: ashutosh-agrawal
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T05:26:37Z

Review comments:
diff_hunk: @@ -1289,6 +1289,12 @@ typedef enum _sai_tam_report_mode_t
     /** Report in a bulk mode */
     SAI_TAM_REPORT_MODE_BULK,
 
+    /** Report in a probabilistic sampling mode, one report is sent in n events */
path: inc/saitam.h
user: login: ashutosh-agrawal
body: To keep it more generic, should we just call it SAM_REPORT_MODE_SAMPLING and then allow the implementation to decide on the exact sampling mechanism.  An example of this would be SAI_MIRROR_SESSION_ATTR_SAMPLE_RATE.  

Another option would be to attach a samplepacket object to report like we do in tam_int object.
created_at: 2025-02-27T17:19:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1289,6 +1289,12 @@ typedef enum _sai_tam_report_mode_t
     /** Report in a bulk mode */
     SAI_TAM_REPORT_MODE_BULK,
 
+    /** Report in a probabilistic sampling mode, one report is sent in n events */
+    SAI_TAM_REPORT_MODE_PROBABILISTIC_SAMPLING,
+
+    /** Report in a microburst mode, specifying report rate and max number of reports per microburst event */
path: inc/saitam.h
user: login: ashutosh-agrawal
body: If the objective here is to rate-limit the number of reports, then attaching a policer object to tam_report will be more intuitive.
created_at: 2025-02-27T17:20:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1289,6 +1289,12 @@ typedef enum _sai_tam_report_mode_t
     /** Report in a bulk mode */
     SAI_TAM_REPORT_MODE_BULK,
 
+    /** Report in a probabilistic sampling mode, one report is sent in n events */
path: inc/saitam.h
user: login: rajkumar38
body: I have aligned to your first suggestion rephrasing to SAM_REPORT_MODE_SAMPLING.
created_at: 2025-03-06T13:01:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1289,6 +1289,12 @@ typedef enum _sai_tam_report_mode_t
     /** Report in a bulk mode */
     SAI_TAM_REPORT_MODE_BULK,
 
+    /** Report in a probabilistic sampling mode, one report is sent in n events */
+    SAI_TAM_REPORT_MODE_PROBABILISTIC_SAMPLING,
+
+    /** Report in a microburst mode, specifying report rate and max number of reports per microburst event */
path: inc/saitam.h
user: login: rajkumar38
body: Base on last community discussion, all policer attributes may not be applicable and we don't have capability query mechanism based on policer bind point to identify which of these attributes are supported.
We will follow existing SAI attribute names instead of using microburst.

created_at: 2025-03-06T13:02:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1289,6 +1289,12 @@ typedef enum _sai_tam_report_mode_t
     /** Report in a bulk mode */
     SAI_TAM_REPORT_MODE_BULK,
 
+    /** Report in a probabilistic sampling mode, one report is sent in n events */
+    SAI_TAM_REPORT_MODE_PROBABILISTIC_SAMPLING,
+
+    /** Report in a microburst mode, specifying report rate and max number of reports per microburst event */
path: inc/saitam.h
user: login: ashutosh-agrawal
body: Please update the document also to remove references to microburst and also use the updated attribute names.
created_at: 2025-03-11T23:12:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1289,6 +1289,12 @@ typedef enum _sai_tam_report_mode_t
     /** Report in a bulk mode */
     SAI_TAM_REPORT_MODE_BULK,
 
+    /** Report in a probabilistic sampling mode, one report is sent in n events */
+    SAI_TAM_REPORT_MODE_PROBABILISTIC_SAMPLING,
+
+    /** Report in a microburst mode, specifying report rate and max number of reports per microburst event */
path: inc/saitam.h
user: login: rajkumar38
body: Thanks @ashutosh-agrawal . I missed to replace the HLD file. Now I have pushed the changes. Pls review.
created_at: 2025-03-12T09:44:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1416,6 +1419,37 @@ typedef enum _sai_tam_report_attr_t
      */
     SAI_TAM_REPORT_ATTR_REPORT_INTERVAL_UNIT,
 
+    /**
+     * @brief Sampling rate (every 1/sample_rate)
+     *
+     * @type sai_uint32_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
+     */
+    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
+
+    /**
+     * @brief Maximum report rate per second
+     *
+     * Value 0 to no limit.
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
+
+    /**
+     * @brief Maximum reports per burst
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
path: inc/saitam.h
user: login: ashutosh-agrawal
body: What would be the behavior for a default value of 0? Is the implementation expected to sent out zero reports?
created_at: 2025-03-12T17:33:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1416,6 +1419,37 @@ typedef enum _sai_tam_report_attr_t
      */
     SAI_TAM_REPORT_ATTR_REPORT_INTERVAL_UNIT,
 
+    /**
+     * @brief Sampling rate (every 1/sample_rate)
+     *
+     * @type sai_uint32_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
+     */
+    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
+
+    /**
+     * @brief Maximum report rate per second
+     *
+     * Value 0 to no limit.
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
+
+    /**
+     * @brief Maximum reports per burst
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
path: inc/saitam.h
user: login: rajkumar38
body: If value is 0, it means no rate-limit and all reports will be sent out.
created_at: 2025-03-13T09:48:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1416,6 +1419,37 @@ typedef enum _sai_tam_report_attr_t
      */
     SAI_TAM_REPORT_ATTR_REPORT_INTERVAL_UNIT,
 
+    /**
+     * @brief Sampling rate (every 1/sample_rate)
+     *
+     * @type sai_uint32_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
+     */
+    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
+
+    /**
+     * @brief Maximum report rate per second
+     *
+     * Value 0 to no limit.
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
+
+    /**
+     * @brief Maximum reports per burst
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
path: inc/saitam.h
user: login: ashutosh-agrawal
body: I understand the behavior for the MAX_REPORT_RATE attribute and there is a comment there as well. But I'm still unclear on a default value of 0 for MAX_REPORT_BURST.

Let's say MAX_REPORT_RATE is set to 1000 reports/second and MAX_REPORT_BUTST is not set so it defaults to 0. What will be the expected behavior? Is the device expected to ignore the max_report_rate and sent out all reports?
created_at: 2025-03-13T17:16:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1416,6 +1419,37 @@ typedef enum _sai_tam_report_attr_t
      */
     SAI_TAM_REPORT_ATTR_REPORT_INTERVAL_UNIT,
 
+    /**
+     * @brief Sampling rate (every 1/sample_rate)
+     *
+     * @type sai_uint32_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
+     */
+    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
+
+    /**
+     * @brief Maximum report rate per second
+     *
+     * Value 0 to no limit.
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
+
+    /**
+     * @brief Maximum reports per burst
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
path: inc/saitam.h
user: login: rajkumar38
body: In this case, the device should not ignore the MAX_REPORT_RATE. With MAX_REPORT_BURST set to 0, no bursts are allowed, so the transmission rate of reports will be limited to 1000 reports per second. If a burst of traffic is received, it depends on the vendor's implementation whether the excess reports are dropped or delayed.

created_at: 2025-03-14T08:25:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1416,6 +1419,37 @@ typedef enum _sai_tam_report_attr_t
      */
     SAI_TAM_REPORT_ATTR_REPORT_INTERVAL_UNIT,
 
+    /**
+     * @brief Sampling rate (every 1/sample_rate)
+     *
+     * @type sai_uint32_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
+     */
+    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
+
+    /**
+     * @brief Maximum report rate per second
+     *
+     * Value 0 to no limit.
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
+
+    /**
+     * @brief Maximum reports per burst
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
path: inc/saitam.h
user: login: ashutosh-agrawal
body: The behavior you described corresponds to a burst size of 1. Should we change the default to 1?
created_at: 2025-03-14T17:05:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1416,6 +1419,37 @@ typedef enum _sai_tam_report_attr_t
      */
     SAI_TAM_REPORT_ATTR_REPORT_INTERVAL_UNIT,
 
+    /**
+     * @brief Sampling rate (every 1/sample_rate)
+     *
+     * @type sai_uint32_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
+     */
+    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
+
+    /**
+     * @brief Maximum report rate per second
+     *
+     * Value 0 to no limit.
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
+
+    /**
+     * @brief Maximum reports per burst
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
path: inc/saitam.h
user: login: rajkumar38
body: When MAX_REPORT_RATE = 0, rate-limiting is not applicable. With this is, MAX_REPORT_BURST defaulted to value 1 seems incorrect.
To align with existing SAI model (similar to shaper), we can have MAX_REPORT_BURST default as 0 and it's up to the user to configure MAX_REPORT_RATE and MAX_REPORT_BURST with vendor supported values for the rate-limiter to work. 
created_at: 2025-03-15T08:17:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1416,6 +1419,37 @@ typedef enum _sai_tam_report_attr_t
      */
     SAI_TAM_REPORT_ATTR_REPORT_INTERVAL_UNIT,
 
+    /**
+     * @brief Sampling rate (every 1/sample_rate)
+     *
+     * @type sai_uint32_t
+     * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
+     * @condition SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_SAMPLING
+     */
+    SAI_TAM_REPORT_ATTR_SAMPLE_RATE,
+
+    /**
+     * @brief Maximum report rate per second
+     *
+     * Value 0 to no limit.
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
+     * @validonly SAI_TAM_REPORT_ATTR_REPORT_MODE == SAI_TAM_REPORT_MODE_ALL
+     */
+    SAI_TAM_REPORT_ATTR_MAX_REPORT_RATE,
+
+    /**
+     * @brief Maximum reports per burst
+     *
+     * @type sai_uint64_t
+     * @flags CREATE_AND_SET
+     * @default 0
path: inc/saitam.h
user: login: ashutosh-agrawal
body: Hi Raj, I was asking about the case when MAX_REPORT_RATE is non-zero and MAX_REPORT_BURST is not defined. 

But I'm fine with the user properly defining these two values to make the rate-limiter work properly.
created_at: 2025-03-18T05:26:25Z
author_association: CONTRIBUTOR

PR comments:
user: login: tjchadaga
created_at: 2025-02-19T18:03:46Z
body: /azp run
author_association: COLLABORATOR
user: login: azure-pipelines[bot]
created_at: 2025-02-19T18:03:56Z
body: <samp>
Azure Pipelines successfully started running 1 pipeline(s).<br>

</samp>
author_association: NONE
user: login: kcudnik
created_at: 2025-02-19T18:22:05Z
body: please add description and fix build errors
author_association: COLLABORATOR
user: login: kcudnik
created_at: 2025-02-19T18:42:39Z
body: you created object dependency loop
author_association: COLLABORATOR
user: login: rajkumar38
created_at: 2025-02-20T04:08:06Z
body: > you created object dependency loop

Hi @kcudnik ,

Here Port associated with SAI_TAM_COLLECTOR_ATTR_DESTINATION will be different from TAM bind point. Here TAM DESTINATION refers to the network port reachable to external collector where reports are transmitted out. Can you suggest how to resolve this ?

_WARN: LOOP DETECTED on object type: SAI_OBJECT_TYPE_PORT    **-----> Port where original traffic rx/tx**
WARN:  SAI_OBJECT_TYPE_PORT: SAI_PORT_ATTR_QOS_INGRESS_BUFFER_PROFILE_LIST
WARN:  SAI_OBJECT_TYPE_BUFFER_PROFILE: SAI_BUFFER_PROFILE_ATTR_POOL_ID
WARN:  SAI_OBJECT_TYPE_BUFFER_POOL: SAI_BUFFER_POOL_ATTR_TAM
WARN:  SAI_OBJECT_TYPE_TAM: SAI_TAM_ATTR_TELEMETRY_OBJECTS_LIST
WARN:  SAI_OBJECT_TYPE_TAM_TELEMETRY: SAI_TAM_TELEMETRY_ATTR_COLLECTOR_LIST
WARN:  SAI_OBJECT_TYPE_TAM_COLLECTOR: SAI_TAM_COLLECTOR_ATTR_DESTINATION **--> nw port connected to collector**
WARN:  -> SAI_OBJECT_TYPE_PORT
 ASSERT FAILED (on line 4224): LOOP is detected, we can't have loops in graph, please fix attributes
make: *** [Makefile:93: all] Error 1_

author_association: CONTRIBUTOR
user: login: kcudnik
created_at: 2025-02-20T12:47:50Z
body: loop detector is installed to not have loops in dependency graph, not sure how to resolve that, usually to prevent loops you can have objects marked as read_only

that validator is not checking whether port is actually the same port, it's checking that dependency is on port object type,

let's have this discussion on todays SAI meeting, will you be able to join ?
author_association: COLLABORATOR
user: login: rajkumar38
created_at: 2025-02-21T04:04:41Z
body: > loop detector is installed to not have loops in dependency graph, not sure how to resolve that, usually to prevent loops you can have objects marked as read_only
> 
> that validator is not checking whether port is actually the same port, it's checking that dependency is on port object type,
> 
> let's have this discussion on todays SAI meeting, will you be able to join ?

Unfortunately, I couldn't join the call yesterday. I will request a slot next week (02/27) to discuss the proposal.
author_association: CONTRIBUTOR
user: login: kcudnik
created_at: 2025-03-05T18:41:48Z
body: /azp run
author_association: COLLABORATOR
user: login: azure-pipelines[bot]
created_at: 2025-03-05T18:41:59Z
body: <samp>
Azure Pipelines successfully started running 1 pipeline(s).<br>

</samp>
author_association: NONE
user: login: rajkumar38
created_at: 2025-03-06T14:20:21Z
body: > loop detector is installed to not have loops in dependency graph, not sure how to resolve that, usually to prevent loops you can have objects marked as read_only
> 
> that validator is not checking whether port is actually the same port, it's checking that dependency is on port object type,
> 
> let's have this discussion on todays SAI meeting, will you be able to join ?

Hi Kamil,
As discussed in last community meeting, I have added exception in saisanitycheck. Pls review.
author_association: CONTRIBUTOR
user: login: tjchadaga
created_at: 2025-03-11T22:44:09Z
body: @rajkumar38 - could you please resolve branch conflicts?
author_association: COLLABORATOR
user: login: rajkumar38
created_at: 2025-03-12T09:44:47Z
body: > @rajkumar38 - could you please resolve branch conflicts?

Done.
author_association: CONTRIBUTOR
user: login: tjchadaga
created_at: 2025-03-12T16:44:55Z
body: /azp run
author_association: COLLABORATOR
user: login: azure-pipelines[bot]
created_at: 2025-03-12T16:45:04Z
body: <samp>
Azure Pipelines successfully started running 1 pipeline(s).<br>

</samp>
author_association: NONE