Skip to content

Commit 2ca4288

Browse files
committed
Add SAI TAM per-flow telemetry (TELEMETRY_TYPE_FLOW)
Define the attribute block for SAI_TAM_TELEMETRY_TYPE_FLOW, which previously existed as an enum value with no operational attributes. - saitam.h: add SAI_TAM_TEL_TYPE_ATTR_FLOW_REPORT_INTERVAL_US to configure per-flow streaming cadence (conditional on FLOW type). - saiswitch.h: add switch-level attributes for hardware autonomous flow learning: TAM_FLOW_AUTO_LEARN_ENABLE, _AGING_TIME_S, and the read-only _FAILURES counter. - doc: add SAI-TAM-Flow-Telemetry.md describing the design, IPFIX record schema, cleanup semantics, and sample workflow. Operator-configured flows reuse the existing ACL TAM_OBJECT action; COUNTER_SUBSCRIPTION telemetry is unchanged. Signed-off-by: Aakash Kumar S <saakashkumar@marvell.com>
1 parent c0203c0 commit 2ca4288

3 files changed

Lines changed: 367 additions & 0 deletions

File tree

doc/TAM/SAI-TAM-Flow-Telemetry.md

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
# SAI TAM per-flow telemetry
2+
3+
---
4+
5+
| Title | SAI TAM per-flow telemetry (TELEMETRY_TYPE_FLOW) |
6+
| ------- | ----------------------------------------------------------------------------------- |
7+
| Authors | `Aakash Kumar S, Garvith V` |
8+
| Status | In review |
9+
| Type | Standards track |
10+
| Created | `06/07/2026` |
11+
12+
---
13+
14+
## Overview
15+
16+
This proposal defines the attribute block for `SAI_TAM_TELEMETRY_TYPE_FLOW` and, separately, adds a set of switch-level attributes that configure hardware autonomous flow learning. The FLOW telemetry-type enum value already exists in `sai_tam_telemetry_type_t` with the header comment "All the data relevant to a given flow", but `sai_tam_tel_type_attr_t` currently defines no attributes for it — it is a declared category with no operational specification.
17+
18+
Per-flow telemetry is a distinct capability from object-counter telemetry (`SAI_TAM_TELEMETRY_TYPE_COUNTER_SUBSCRIPTION`): the unit is a flow (identified by a classification key), not a named object (identified by OID). This proposal fills in the FLOW attribute block so that SAI TAM can carry per-flow telemetry. Flows can be populated from two independent sources: operator-configured (an ACL entry with an action referencing the enclosing TAM object) and hardware auto-learned (the ASIC autonomously identifies flows from live traffic, when enabled at the switch level). Both sources can be active simultaneously. `COUNTER_SUBSCRIPTION` is not modified.
19+
20+
## Requirements
21+
22+
- Enable per-flow packet/byte streaming through the existing TAM report/collector chain, using IPFIX records.
23+
- Support operator-configured per-flow monitoring via the existing `SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT` mechanism (no new ACL attribute required).
24+
- Support hardware autonomous flow learning as an independent, switch-level capability that operators can enable or disable at runtime.
25+
- Express operator policy at the intent layer (aging time) — not at the implementation-mechanism layer.
26+
- Leave the internal mechanism by which the implementation learns, ages, or reclaims flows unspecified.
27+
- Do not modify `SAI_TAM_TELEMETRY_TYPE_COUNTER_SUBSCRIPTION` or the existing event-side flow telemetry (`SAI_TAM_EVENT_TYPE_FLOW_STATE / _WATCHLIST / _TCPFLAG`).
28+
29+
## Design summary
30+
31+
The proposal decouples two concerns that were previously entangled:
32+
33+
- **Per-flow telemetry configuration** lives on the FLOW tel_type. It says "produce per-flow IPFIX records at this cadence, wire them through this report chain."
34+
- **Hardware autonomous flow learning** lives on the switch object. It is a HW-plane capability, independent of any specific telemetry configuration. When enabled, the implementation autonomously identifies flows from live traffic.
35+
36+
Flows populated into a FLOW tel_type can come from either source, or both, or neither:
37+
38+
- **Operator-configured flows** appear when the operator creates ACL entries with `SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT` pointing at the TAM object that references the FLOW tel_type. This is the existing SAI mechanism; no new ACL attribute is added.
39+
- **HW-learned flows** appear when `SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE` is true at the switch level. The switch attributes govern operator policy (aging) for autonomous learning.
40+
41+
The two sources are independent. Neither depends on the other.
42+
43+
## FLOW tel_type attributes
44+
45+
The following attributes are added to `sai_tam_tel_type_attr_t` in `saitam.h`. Both apply to `TELEMETRY_TYPE_FLOW` regardless of how flows are populated.
46+
47+
```
48+
+ /**
49+
+ * @brief Streaming cadence per active flow (microseconds)
50+
+ *
51+
+ * Operator-visible cadence at which per-flow records are emitted.
52+
+ * The implementation uses whichever internal mechanism (HW push,
53+
+ * polled read, or otherwise) meets it.
54+
+ *
55+
+ * @type sai_uint32_t
56+
+ * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
57+
+ * @validonly SAI_TAM_TEL_TYPE_ATTR_TAM_TELEMETRY_TYPE == SAI_TAM_TELEMETRY_TYPE_FLOW
58+
+ */
59+
+ SAI_TAM_TEL_TYPE_ATTR_FLOW_REPORT_INTERVAL_US,
60+
```
61+
62+
## Switch attributes for HW autonomous flow learning
63+
64+
The following attributes are added to `sai_switch_attr_t` in `saiswitch.h`. They govern hardware autonomous flow learning independently of any specific tel_type or TAM object.
65+
66+
```
67+
+ /**
68+
+ * @brief Enable hardware autonomous flow learning
69+
+ *
70+
+ * When true, the implementation autonomously identifies new flows
71+
+ * from live traffic and populates them into any FLOW tel_type that
72+
+ * is configured on the switch. When false, only flows explicitly
73+
+ * bound via ACL entries with SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT
74+
+ * populate FLOW tel_types; the implementation does not
75+
+ * autonomously identify new flows.
76+
+ *
77+
+ * The handling of flows that were already being tracked at the
78+
+ * moment this attribute transitions from true to false is
79+
+ * implementation-defined.
80+
+ *
81+
+ * Default is false. Autonomous learning must be explicitly enabled.
82+
+ *
83+
+ * @type bool
84+
+ * @flags CREATE_AND_SET
85+
+ * @default false
86+
+ */
87+
+ SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE,
88+
+
89+
+ /**
90+
+ * @brief Aging time for HW-learned flows (seconds)
91+
+ *
92+
+ * Operator-intent aging: a HW-learned flow idle for more than this
93+
+ * long is eligible for reclaim by the implementation. The reclaim
94+
+ * mechanism (autonomous HW sweep, HW-assisted SW loop, or
95+
+ * otherwise) is deliberately implementation-defined.
96+
+ *
97+
+ * Applies only to flows populated by HW auto-learn. Operator-
98+
+ * configured flows (installed via ACL entries) do not age; the
99+
+ * operator owns their lifetime by adding or removing ACL entries.
100+
+ *
101+
+ * @type sai_uint32_t
102+
+ * @flags MANDATORY_ON_CREATE | CREATE_AND_SET
103+
+ * @validonly SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE == true
104+
+ */
105+
+ SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_AGING_TIME_S,
106+
+
107+
+ /**
108+
+ * @brief HW auto-learn failure count
109+
+ *
110+
+ * Count of new-flow learn attempts that were rejected because the
111+
+ * implementation could not admit the flow (capacity exhausted).
112+
+ * Without this counter, operators would have no way to distinguish
113+
+ * "table running fine" from "table chronically saturated, missing
114+
+ * new flows".
115+
+ *
116+
+ * @type sai_uint64_t
117+
+ * @flags READ_ONLY
118+
+ * @validonly SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE == true
119+
+ */
120+
+ SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_FAILURES,
121+
```
122+
123+
## IPFIX record schema
124+
125+
The FLOW tel_type's IPFIX template is generated by the implementation and retrievable via the existing `SAI_TAM_TEL_TYPE_ATTR_IPFIX_TEMPLATES` attribute. Each record carries, per active flow, per interval:
126+
127+
- Flow key values (one Information Element per key field). The specific fields are determined by the implementation and advertised in the template. For operator-configured flows, the keys correspond to the referencing ACL entry's match fields; for HW-learned flows, the keys correspond to whatever the implementation keys on autonomously.
128+
- Statistics (packet count and byte count at minimum; additional per-flow counters if the implementation supports them and includes them in the advertised template).
129+
- Snapshot timestamp (`observationTimeNanoseconds` — existing RFC 7011 IE).
130+
- Flow-end reason (`flowEndReason` — existing RFC 7011 IE) on the final record for a flow: idle timeout (HW auto-learn aging) or operator-initiated end (ACL entry removed).
131+
- IPFIX sequence number (existing RFC 7011 field) so consumers can detect gaps in the stream.
132+
133+
On flow termination, the implementation SHOULD emit one final record with a non-zero `flowEndReason` before releasing the flow's HW state, so that consumers capture the last counter increment between the previous interval snapshot and termination. This is SHOULD rather than MUST because some implementations may not guarantee it under memory-pressure eviction.
134+
135+
## Cleanup semantics
136+
137+
Stated as a semantic contract, not a prescribed mechanism:
138+
139+
- **HW-learned flows — idle reclaim.** A HW-learned flow idle for longer than `SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_AGING_TIME_S` must eventually be reclaimed. The final record's `flowEndReason` indicates idle timeout. The detection interval and mechanism are implementation-defined.
140+
- **HW-learned flows — capacity exhaustion.** When the implementation cannot admit a new flow because per-flow capacity is exhausted, the new flow is not learned, existing flows continue unchanged, and `SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_FAILURES` is incremented so operators can observe the rejection rate.
141+
- **HW-learned flows — auto-learn disable.** When `SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE` transitions from true to false, the implementation stops autonomously identifying new flows. The handling of HW-learned flows that were already being tracked at the moment of the transition is implementation-defined.
142+
- **Operator-configured flows — operator-driven.** Flows exist as long as their defining ACL entries exist. Removal of an ACL entry (or clearing its `ACTION_TAM_OBJECT` action) causes the corresponding flow to be terminated and a final record emitted. Operator-configured flows do not age; the operator owns their lifetime.
143+
- **Tel_type destruction.** When the application removes the FLOW tel_type object, all state the implementation was maintaining for that tel_type must be released. Whether a final-record burst precedes destruction is implementation-defined; consumers must not depend on it.
144+
145+
## Sample workflow
146+
147+
The following sequences show HW auto-learn mode and operator-configured mode. In practice, both can be active simultaneously — the two mechanisms are independent and either or both can populate flows into the FLOW tel_type.
148+
149+
### Common setup — TAM report and tel_type
150+
151+
1. Create Transport and Collector objects (existing TAM machinery, not shown).
152+
153+
2. Create a report object (for example, of type `SAI_TAM_REPORT_TYPE_IPFIX`).
154+
155+
```
156+
count = 0;
157+
attr_list[count].id = SAI_TAM_REPORT_ATTR_TYPE;
158+
attr_list[count].value.s32 = SAI_TAM_REPORT_TYPE_IPFIX;
159+
count++;
160+
attr_list[count].id = SAI_TAM_REPORT_ATTR_REPORT_MODE;
161+
attr_list[count].value.s32 = SAI_TAM_REPORT_MODE_ALL;
162+
count++;
163+
164+
rc = tam_api_p->create_tam_report(&tam_report_id, switch_id, count, attr_list);
165+
```
166+
167+
3. Create a FLOW tel_type. The tel_type is the same regardless of how flows will be populated.
168+
169+
```
170+
count = 0;
171+
attr_list[count].id = SAI_TAM_TEL_TYPE_ATTR_TAM_TELEMETRY_TYPE;
172+
attr_list[count].value.s32 = SAI_TAM_TELEMETRY_TYPE_FLOW;
173+
count++;
174+
attr_list[count].id = SAI_TAM_TEL_TYPE_ATTR_REPORT_ID;
175+
attr_list[count].value.oid = tam_report_id;
176+
count++;
177+
attr_list[count].id = SAI_TAM_TEL_TYPE_ATTR_FLOW_REPORT_INTERVAL_US;
178+
attr_list[count].value.u32 = 500000; /* 500 ms cadence */
179+
count++;
180+
181+
rc = tam_api_p->create_tam_tel_type(&tam_tel_type_id, switch_id, count, attr_list);
182+
```
183+
184+
4. Create the TAM object referencing the tel_type and bind it at switch scope.
185+
186+
```
187+
count = 0;
188+
attr_list[count].id = SAI_TAM_ATTR_TELEMETRY_OBJECTS_LIST;
189+
attr_list[count].value.objlist.count = 1;
190+
attr_list[count].value.objlist.list = (sai_object_id_t *)malloc(1*sizeof(sai_object_id_t));
191+
attr_list[count].value.objlist.list[0] = tam_tel_type_id;
192+
count++;
193+
194+
bind_point_types[0] = SAI_TAM_BIND_POINT_TYPE_SWITCH;
195+
attr_list[count].id = SAI_TAM_ATTR_TAM_BIND_POINT_TYPE_LIST;
196+
attr_list[count].value.s32list.count = 1;
197+
attr_list[count].value.s32list.list = bind_point_types;
198+
count++;
199+
200+
rc = tam_api_p->create_tam(&tam_id, switch_id, count, attr_list);
201+
```
202+
203+
5. Query the IPFIX template the implementation will use. The existing `SAI_TAM_TEL_TYPE_ATTR_IPFIX_TEMPLATES` attribute returns the FLOW-mode record template once the tel_type is sufficiently configured (`REPORT_ID` set).
204+
205+
```
206+
attr.id = SAI_TAM_TEL_TYPE_ATTR_IPFIX_TEMPLATES;
207+
attr.value.u8list.list = template_buf;
208+
attr.value.u8list.count = sizeof(template_buf);
209+
210+
rc = tam_api_p->get_tam_tel_type_attribute(tam_tel_type_id, 1, &attr);
211+
```
212+
213+
### Enable HW autonomous flow learning
214+
215+
6. Enable HW auto-learn at the switch level. This is independent of any FLOW tel_type — it is a switch-wide capability that, when enabled, causes the implementation to autonomously identify flows.
216+
217+
```
218+
count = 0;
219+
attr_list[count].id = SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE;
220+
attr_list[count].value.booldata = true;
221+
count++;
222+
attr_list[count].id = SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_AGING_TIME_S;
223+
attr_list[count].value.u32 = 60; /* 60 s idle timeout */
224+
count++;
225+
226+
for (int i = 0; i < count; i++) {
227+
rc = switch_api_p->set_switch_attribute(switch_id, &attr_list[i]);
228+
}
229+
```
230+
231+
7. Periodically read the switch-level learn-failure count to observe rejection rate.
232+
233+
```
234+
attr.id = SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_FAILURES;
235+
rc = switch_api_p->get_switch_attribute(switch_id, 1, &attr);
236+
/* attr.value.u64 = cumulative count of rejected learn attempts */
237+
```
238+
239+
8. To disable HW auto-learn later, set the enable attribute to false. The handling of currently-tracked HW-learned flows at that moment is implementation-defined.
240+
241+
```
242+
attr.id = SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE;
243+
attr.value.booldata = false;
244+
rc = switch_api_p->set_switch_attribute(switch_id, &attr);
245+
```
246+
247+
### Operator-configured flows
248+
249+
To monitor specific flows the operator defines (independently of, or in addition to, HW auto-learn):
250+
251+
9. Create an ACL table with `SAI_ACL_ACTION_TYPE_TAM_OBJECT` in its allowed action list.
252+
253+
```
254+
count = 0;
255+
action_list[0] = SAI_ACL_ACTION_TYPE_TAM_OBJECT;
256+
attr_list[count].id = SAI_ACL_TABLE_ATTR_ACL_ACTION_TYPE_LIST;
257+
attr_list[count].value.s32list.list = action_list;
258+
attr_list[count].value.s32list.count = 1;
259+
count++;
260+
/* ... other standard ACL table attributes (stage, bind points, match fields) ... */
261+
262+
rc = acl_api_p->create_acl_table(&acl_table_oid, switch_id, count, attr_list);
263+
```
264+
265+
10. Add ACL entries, each with the `TAM_OBJECT` action pointing at the TAM object. Each such entry defines one monitored flow.
266+
267+
```
268+
count = 0;
269+
attr_list[count].id = SAI_ACL_ENTRY_ATTR_TABLE_ID;
270+
attr_list[count].value.oid = acl_table_oid;
271+
count++;
272+
attr_list[count].id = SAI_ACL_ENTRY_ATTR_FIELD_SRC_IP;
273+
attr_list[count].value.aclfield.enable = true;
274+
attr_list[count].value.aclfield.data.ip4 = 0x0a000001;
275+
attr_list[count].value.aclfield.mask.ip4 = 0xffffffff;
276+
count++;
277+
/* ... other match fields defining this flow ... */
278+
279+
attr_list[count].id = SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT;
280+
attr_list[count].value.aclaction.parameter.oid = tam_id;
281+
attr_list[count].value.aclaction.enable = true;
282+
count++;
283+
284+
rc = acl_api_p->create_acl_entry(&acl_entry_oid, switch_id, count, attr_list);
285+
```
286+
287+
The ACL entry's action tells the implementation "monitor this flow under the referenced TAM object's policy." Removing the entry (or clearing its action) ends that flow's monitoring; a final IPFIX record is emitted.
288+
289+
## Composition with existing TAM machinery
290+
291+
- The FLOW tel_type binds through existing TAM machinery (`SAI_TAM_ATTR_TELEMETRY_OBJECTS_LIST` on the parent TAM object, bound at `SAI_TAM_BIND_POINT_TYPE_SWITCH` by default). No new bind-point type is introduced.
292+
- Operator-configured flows use `SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT`, which already exists in `saiacl.h`. No new ACL attribute or action type is introduced by this proposal.
293+
- The FLOW tel_type coexists with the existing event-side flow telemetry (`SAI_TAM_EVENT_TYPE_FLOW_STATE / _WATCHLIST / _TCPFLAG`). The two paths are independent and composable.
294+
- `SAI_TAM_TELEMETRY_TYPE_COUNTER_SUBSCRIPTION` is unchanged; it continues to serve object-counter telemetry (PORT / QUEUE / BUFFER_POOL / INGRESS_PRIORITY_GROUP).

inc/saiswitch.h

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3616,6 +3616,66 @@ typedef enum _sai_switch_attr_t
36163616
*/
36173617
SAI_SWITCH_ATTR_PERFMON_LIST,
36183618

3619+
/**
3620+
* @brief Enable hardware autonomous flow learning
3621+
*
3622+
* When true, the implementation autonomously identifies new flows
3623+
* from live traffic and populates them into any FLOW tel_type that
3624+
* is configured on the switch. When false, only flows explicitly
3625+
* bound via ACL entries with SAI_ACL_ENTRY_ATTR_ACTION_TAM_OBJECT
3626+
* populate FLOW tel_types; the implementation does not
3627+
* autonomously identify new flows.
3628+
*
3629+
* The handling of flows that were already being tracked at the
3630+
* moment this attribute transitions from true to false is
3631+
* implementation-defined.
3632+
*
3633+
* Default is false. Autonomous learning must be explicitly enabled.
3634+
*
3635+
* @type bool
3636+
* @flags CREATE_AND_SET
3637+
* @default false
3638+
*/
3639+
SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE,
3640+
3641+
/**
3642+
* @brief Aging time for HW-learned flows (seconds)
3643+
*
3644+
* Operator-intent aging: a HW-learned flow idle for more than this
3645+
* long is eligible for reclaim by the implementation. The reclaim
3646+
* mechanism (autonomous HW sweep, HW-assisted SW loop, or
3647+
* otherwise) is deliberately implementation-defined.
3648+
*
3649+
* Applies only to flows populated by HW auto-learn. Operator-
3650+
* configured flows (installed via ACL entries) do not age; the
3651+
* operator owns their lifetime by adding or removing ACL entries.
3652+
*
3653+
* A value of 0 means the implementation chooses its own aging time.
3654+
*
3655+
* @type sai_uint32_t
3656+
* @flags CREATE_AND_SET
3657+
* @default 0
3658+
* @validonly SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE == true
3659+
*/
3660+
SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_AGING_TIME_S,
3661+
3662+
/**
3663+
* @brief HW auto-learn failure count
3664+
*
3665+
* Count of new-flow learn attempts that were rejected because the
3666+
* implementation could not admit the flow (capacity exhausted).
3667+
* Without this counter, operators would have no way to distinguish
3668+
* "table running fine" from "table chronically saturated, missing
3669+
* new flows".
3670+
*
3671+
* Valid only when SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_ENABLE is true;
3672+
* otherwise the returned value is 0.
3673+
*
3674+
* @type sai_uint64_t
3675+
* @flags READ_ONLY
3676+
*/
3677+
SAI_SWITCH_ATTR_TAM_FLOW_AUTO_LEARN_FAILURES,
3678+
36193679
/**
36203680
* @brief End of attributes
36213681
*/

inc/saitam.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,19 @@ typedef enum _sai_tam_tel_type_attr_t
12591259
*/
12601260
SAI_TAM_TEL_TYPE_ATTR_IPFIX_TEMPLATES,
12611261

1262+
/**
1263+
* @brief Streaming cadence per active flow (microseconds)
1264+
*
1265+
* Operator-visible cadence at which per-flow records are emitted.
1266+
* The implementation uses whichever internal mechanism (HW push,
1267+
* polled read, or otherwise) meets it.
1268+
*
1269+
* @type sai_uint32_t
1270+
* @flags MANDATORY_ON_CREATE | CREATE_AND_SET
1271+
* @condition SAI_TAM_TEL_TYPE_ATTR_TAM_TELEMETRY_TYPE == SAI_TAM_TELEMETRY_TYPE_FLOW
1272+
*/
1273+
SAI_TAM_TEL_TYPE_ATTR_FLOW_REPORT_INTERVAL_US,
1274+
12621275
/**
12631276
* @brief End of Attributes
12641277
*/

0 commit comments

Comments
 (0)