From 9aa21a40ba9bc159ac2829d19d7f39d066690571 Mon Sep 17 00:00:00 2001 From: JaiOCP Date: Mon, 11 May 2026 15:43:26 -0700 Subject: [PATCH 1/2] Optimized Forwarding Header Signed-off-by: JaiOCP OFH Support Signed-off-by: JaiOCP Fix gensairpc.pl crash on Doxygen 1.9.8+ by reusing NeedsTwoPassProcessing (#2282) Why: To fix below build error Uncaught exception from user code: at gensairpc.pl line 480. main::assign_attr_types(HASH(0x55e190dc20c8), ARRAY(0x55e190d2d080)) called at gensairpc.pl line 434 main::get_definitions() called at gensairpc.pl line 156 main::assign_attr_types(HASH(0x55e190dc20c8), ARRAY(0x55e190d2d080)) called at gensairpc.pl line 434 main::get_definitions() called at gensairpc.pl line 156 How: gensairpc.pl crashed during SAI thrift build with an uncaught exception at line 480 (assign_attr_types) because its inline Doxygen layout detection was too weak - it only checked sai_8h.xml for any enumvalue presence, missing cases where the new Doxygen 1.9.8+ XML structure requires group__*.xml files to be processed for complete definitions. This caused incomplete parsing, leading to missing types and a croak in assign_attr_types when sai_attribute_value_t could not be found. Changes: - xmlutils.pm: Add NeedsTwoPassProcessing and export it. - parse.pl: Remove local NeedsTwoPassProcessing; use imported version. - gensairpc.pl: Replace inline detection with NeedsTwoPassProcessing() call, fixing the build failure and eliminating code duplication. Signed-off-by: Pavan Naregundi OFH Header Signed-off-by: JaiOCP Count BFD session state changes from UP to DOWN (#2268) Signed-off-by: Chikkegowda Chikkaiah HW FRR switchover notification support for protection groups (#2269) Signed-off-by: Chikkegowda Chikkaiah Port storm control enhancemnets (#2258) (#2258) Signed-off-by: rpmarvell --- ...Proposal-Port-Storm-Control-Enhancement.md | 134 ++++++ doc/SAI-Proposal-HW-FRR.md | 341 ++++++++------- inc/sai.h | 4 + inc/saibfd.h | 5 +- inc/saidebugcounter.h | 18 + inc/sainexthopgroup.h | 44 ++ inc/saiobject.h | 4 + inc/saiofh.h | 404 ++++++++++++++++++ inc/saiofhroute.h | 336 +++++++++++++++ inc/saiport.h | 70 +++ inc/saiswitch.h | 43 ++ inc/saitypes.h | 47 ++ inc/saivirtualrouter.h | 9 + meta/acronyms.txt | 4 + meta/checkheaders.pl | 1 + meta/gensairpc.pl | 12 +- meta/parse.pl | 113 +---- meta/saimetadatatypes.h | 7 +- meta/saisanitycheck.c | 4 + .../sai_rpc_server_helper_functions.tt | 2 +- meta/xmlutils.pm | 104 +++++ 21 files changed, 1448 insertions(+), 258 deletions(-) create mode 100644 doc/QOS/SAI-Proposal-Port-Storm-Control-Enhancement.md create mode 100644 inc/saiofh.h create mode 100644 inc/saiofhroute.h diff --git a/doc/QOS/SAI-Proposal-Port-Storm-Control-Enhancement.md b/doc/QOS/SAI-Proposal-Port-Storm-Control-Enhancement.md new file mode 100644 index 000000000..6d04be2a2 --- /dev/null +++ b/doc/QOS/SAI-Proposal-Port-Storm-Control-Enhancement.md @@ -0,0 +1,134 @@ +# [SAI] Port Storm Control Enhancement +------------------------------------------------------------------------------- + Title | Port storm control enhancement +-------------|----------------------------------------------------------------- + Authors | Rajesh Perumal (Marvell) + Status | Reviewed on 26-Feb-2026 + Type | Standards track + Created | 24-Feb-2026 + SAI-Version | 1.18 +------------------------------------------------------------------------------- + +## Introduction + + +There is a long‑standing mismatch between the SAI storm‑control attribute definitions and how these attributes are interpreted within SONiC. The existing SAI attributes for flood and multicast storm control do not clearly differentiate among unknown unicast, unknown multicast, and known multicast traffic. As a result, vendors and SONiC implementations interpret these attributes differently, leading to inconsistent behavior across platforms. +To improve clarity and alignment, two approaches can be followed: + +To improve clarity and alignment, new, explicit attributes are introduced for each traffic class and the ambiguous ones are deprecated. This resolves the ambiguity present in the current specification and enables consistent implementation across vendors and multiple NOS. +The following section details the selected enhancement approach and the required SAI header updates. + +## Motivation + +The table below highlights the gap between the current SAI attribute descriptions and how these attributes are interpreted within SONiC: + +| Existing SAI Attribute | SAI Description | SONiC usage | +|-------------------------------------------------|------------------------------------------------|------------------------------| +| SAI_PORT_ATTR_FLOOD_STORM_CONTROL_POLICER_ID | Unknown unicast/unknown multicast flood control| Unknown unicast flood control| +| SAI_PORT_ATTR_MULTICAST_STORM_CONTROL_POLICER_ID| Multicast storm control policer on port | Unknown multicast traffic | + +This mismatch creates ambiguity, leads to inconsistent vendor implementations, and results in unclear handling of traffic classes (unknown unicast, unknown multicast, and known multicast). To address this, either the existing SAI attribute definitions must be refined, or new traffic‑specific attributes should be introduced. However, redefining current SAI attributes may introduce backward‑compatibility issues. + +By defining explicit attributes, SAI can present storm‑control behavior more clearly across all network operating systems (including SONiC), reduce implementation confusion, and support future enhancements in storm‑control processing. + + +## SAI Enhancement + +This enhancement proposes to deprecate the existing storm control attributes SAI_PORT_ATTR_FLOOD_STORM_CONTROL_POLICER_ID and SAI_PORT_ATTR_MULTICAST_STORM_CONTROL_POLICER_ID, and replace it with dedicated, traffic‑specific attributes for unknown unicast, known unicast, unknown multicast and known multicast storm control. This provides clear separation of behavior and removes the ambiguity present in the current definition. + +### Deprecated Attributes +``` +--- Old Code ++++ New Code + /** + * @brief Enable flood (unknown unicast or unknown multicast) + * storm control policer on port. ++ * Deprecated. Use SAI_PORT_ATTR_UNKNOWN_UNICAST_STORM_CONTROL_POLICER_ID and SAI_PORT_ATTR_UNKNOWN_MULTICAST_STORM_CONTROL_POLICER_ID + * + * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID ++ * @deprecated true + */ + SAI_PORT_ATTR_FLOOD_STORM_CONTROL_POLICER_ID, +``` +``` +--- Old Code ++++ New Code + /** + * @brief Enable multicast storm control policer on port. ++ * Deprecated. Use SAI_PORT_ATTR_KNOWN_MULTICAST_STORM_CONTROL_POLICER_ID and SAI_PORT_ATTR_UNKNOWN_MULTICAST_STORM_CONTROL_POLICER_ID + * + * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID ++ * @deprecated true + */ + SAI_PORT_ATTR_MULTICAST_STORM_CONTROL_POLICER_ID, +``` + +### New port storm control attributes +``` + /** + * @brief Enable unknown unicast storm control policer on port. + * + * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_UNKNOWN_UNICAST_STORM_CONTROL_POLICER_ID, + + /** + * @brief Enable known unicast storm control policer on port. + * + * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_KNOWN_UNICAST_STORM_CONTROL_POLICER_ID, + + /** + * @brief Enable unknown multicast storm control policer on port. + * + * Set Policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_UNKNOWN_MULTICAST_STORM_CONTROL_POLICER_ID, + + /** + * @brief Enable known multicast storm control policer on port. + * + * Set Policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_KNOWN_MULTICAST_STORM_CONTROL_POLICER_ID, + +``` + +This approach provides more granular storm‑control handling per traffic type. diff --git a/doc/SAI-Proposal-HW-FRR.md b/doc/SAI-Proposal-HW-FRR.md index c0cf837a8..88943c1f9 100755 --- a/doc/SAI-Proposal-HW-FRR.md +++ b/doc/SAI-Proposal-HW-FRR.md @@ -11,150 +11,197 @@ ## 1.0 Introduction -SAI supports SW based FRR where the decision to switch over to the secondary path is triggered by the SW. - -Following is the current SAI workflow for SW based FRR. -- Create a protection NH -nhg_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; -nhg_entry_attrs[0].value.u32 = SAI_NEXT_HOP_GROUP_TYPE_PROTECTION; - -- Create primary and secondary members (Note members can be NHG as well) -nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; -nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; -nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; -nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; - -- Based on the monitoring object, SW sets the following boolean to trigger switchover -nhg_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_ATTR_SET_SWITCHOVER; -nhg_entry_attrs[1].value.u32 = true; -saistatus = sai_set_next_hop_group_attribute_fn(nhg_id, nhg_entry_attrs); - -## 2.0 HW Based Trigger -Main change in this proposal is the trigger. Now SW is not responsible for monitoring an object and triggering the switchover. -HW monitors the configured object and triggers the switch to secondary path based on the state of the monitored object. -For example if a port is being monitored and port goes down then all the NH resolving via this port will be switched over to the secondary path. - -## 3.0 SAI Enhancements -Hardware needs to know ahead of time which NHG/NH are part of the secondary group so as to mark them as backup from the configured primary group. For this reason a hint is needed to identify such NHG/NH. - -This hint is provided using a new NHG type -```c - /** Next hop hardware protection group. This is the group backing up the primary in the protection group type and is managed by hardware */ - SAI_NEXT_HOP_GROUP_TYPE_HW_PROTECTION, -``` - -Additionally port counters are introduced to capture -- How many times port has participated in the failover -- Drops observed during failover - -```c - /** SAI port stat if HW protection switchover events */ - SAI_PORT_STAT_IF_IN_HW_PROTECTION_SWITCHOVER_EVENTS, - - /** SAI port stat if HW protection switchover related packet drops */ - SAI_PORT_STAT_IF_IN_HW_PROTECTION_SWITCHOVER_DROP_PKTS, -``` - -## 4.0 Example Workflow - - -### Topology Example -There are two uplinks from a switch and both are part of the primary and secondary group. -For such case we will -- Create a NHG nhg1 of type PROTECTION and configure NH1/port1 and NH2/port2 NH as primary members -- Create a NHG nhg2 of type HW_PROTECTION with members as NH1/port1 and NH2/port2 -- Set NHG nhg2 as a secondary member of NHG nhg1 - -PROTECTION[nhg1] --> PRIMARY[NH1, NH2], SECONDARY[nhg2] -HW_PROTECTION[nhg2] --> [NH1, NH2] - - - - -```c -nh_1_interface_id = 1 -nh_2_interface_id = 2 -switch_id = 0; - -nhg_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; -nhg_entry_attrs[0].value.u32 = SAI_NEXT_HOP_GROUP_TYPE_PROTECTION; -saistatus = sai_frr_api->create_next_hop_group(&nhg1, switch_id, 1, nhg_entry_attrs); -if (saistatus != SAI_STATUS_SUCCESS) { - return saistatus; -} - -nhg_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; -nhg_entry_attrs[0].value.u32 = SAI_NEXT_HOP_GROUP_TYPE_HW_PROTECTION; -saistatus = sai_frr_api->create_next_hop_group(&nhg2, switch_id, 1, nhg_entry_attrs); -if (saistatus != SAI_STATUS_SUCCESS) { - return saistatus; -} - -nh_entry_attrs[0].id = SAI_NEXT_HOP_ATTR_TYPE; -nh_entry_attrs[0].value.u32 = SAI_NEXT_HOP_TYPE_IP; -nh_entry_attrs[1].id = SAI_NEXT_HOP_ATTR_IP; -CONVERT_STRING_TO_SAI_IPV4(nh_entry_attrs[1].value, "10.1.1.1"); -nh_entry_attrs[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; -nh_entry_attrs[2].value.u64 = nh_1_interface_id; -saistatus = sai_frr_api->create_next_hop(&nh_1_id, switch_id, 2, nh_entry_attrs); -if (saistatus != SAI_STATUS_SUCCESS) { - return saistatus; -} - -nh_entry_attrs[0].id = SAI_NEXT_HOP_ATTR_TYPE; -nh_entry_attrs[0].value.u32 = SAI_NEXT_HOP_TYPE_IP; -nh_entry_attrs[1].id = SAI_NEXT_HOP_ATTR_IP; -CONVERT_STRING_TO_SAI_IPV4(nh_entry_attrs[1].value, "10.1.2.1"); -nh_entry_attrs[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; -nh_entry_attrs[2].value.u64 = nh_2_interface_id; -saistatus = sai_frr_api->create_next_hop(&nh_2_id, switch_id, 2, nh_entry_attrs); -if (saistatus != SAI_STATUS_SUCCESS) { - return saistatus; -} - -// Program the primary NH Group member. -nhgm_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; -nhgm_entry_attrs[0].value.oid = nhg1; -nhgm_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; -nhgm_entry_attrs[1].value.oid = nh_1_id; -nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; -nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; -saistatus = sai_frr_api->create_next_hop_group_member(&nhgm_1_id, switch_id, 2, nhgm_entry_attrs); -if (saistatus != SAI_STATUS_SUCCESS) { - return saistatus; -} - -nhgm_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; -nhgm_entry_attrs[0].value.oid = nhg1; -nhgm_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; -nhgm_entry_attrs[1].value.oid = nh_2_id; -nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; -nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; -saistatus = sai_frr_api->create_next_hop_group_member(&nhgm_1_id, switch_id, 2, nhgm_entry_attrs); -if (saistatus != SAI_STATUS_SUCCESS) { - return saistatus; -} - -// Program the secondary NH Group member. -nhgm_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; -nhgm_entry_attrs[0].value.oid = nhg1; -nhgm_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; -nhgm_entry_attrs[1].value.oid = nhg2; -nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; -nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; -saistatus = sai_frr_api->create_next_hop_group_member(&nhgm_2_id, switch_id, 2, nhgm_entry_attrs); -if (saistatus != SAI_STATUS_SUCCESS) { - return saistatus; -} - -nhgm_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; -nhgm_entry_attrs[0].value.oid = nhg_id; -nhgm_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; -nhgm_entry_attrs[1].value.oid = nh_2_id; -nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; -nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; -saistatus = sai_frr_api->create_next_hop_group_member(&nhgm_3_id, switch_id, 2, nhgm_entry_attrs); -if (saistatus != SAI_STATUS_SUCCESS) { - return saistatus; -} -``` +SAI supports SW based FRR where the decision to switch over to the secondary path is triggered by the SW. + +Following is the current SAI workflow for SW based FRR. +- Create a protection NH +nhg_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; +nhg_entry_attrs[0].value.u32 = SAI_NEXT_HOP_GROUP_TYPE_PROTECTION; + +- Create primary and secondary members (Note members can be NHG as well) +nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; +nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; +nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; +nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; + +- Based on the monitoring object, SW sets the following boolean to trigger switchover +nhg_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_ATTR_SET_SWITCHOVER; +nhg_entry_attrs[1].value.u32 = true; +saistatus = sai_set_next_hop_group_attribute_fn(nhg_id, nhg_entry_attrs); + +## 2.0 HW Based Trigger +Main change in this proposal is the trigger. Now SW is not responsible for monitoring an object and triggering the switchover. +HW monitors the configured object and triggers the switch to secondary path based on the state of the monitored object. +For example if a port is being monitored and port goes down then all the NH resolving via this port will be switched over to the secondary path. + +## 3.0 SAI Enhancements +Hardware needs to know ahead of time which NHG/NH are part of the secondary group so as to mark them as backup from the configured primary group. For this reason a hint is needed to identify such NHG/NH. + +This hint is provided using a new NHG type +```c + /** Next hop hardware protection group. This is the group backing up the primary in the protection group type and is managed by hardware */ + SAI_NEXT_HOP_GROUP_TYPE_HW_PROTECTION, +``` + +Additionally port counters are introduced to capture +- How many times port has participated in the failover +- Drops observed during failover + +```c + /** SAI port stat if HW protection switchover events */ + SAI_PORT_STAT_IF_IN_HW_PROTECTION_SWITCHOVER_EVENTS, + + /** SAI port stat if HW protection switchover related packet drops */ + SAI_PORT_STAT_IF_IN_HW_PROTECTION_SWITCHOVER_DROP_PKTS, +``` + +## 4.0 Example Workflow + + +### Topology Example +There are two uplinks from a switch and both are part of the primary and secondary group. +For such case we will +- Create a NHG nhg1 of type PROTECTION and configure NH1/port1 and NH2/port2 NH as primary members +- Create a NHG nhg2 of type HW_PROTECTION with members as NH1/port1 and NH2/port2 +- Set NHG nhg2 as a secondary member of NHG nhg1 + +PROTECTION[nhg1] --> PRIMARY[NH1, NH2], SECONDARY[nhg2] +HW_PROTECTION[nhg2] --> [NH1, NH2] + + + + +```c +nh_1_interface_id = 1 +nh_2_interface_id = 2 +switch_id = 0; + +nhg_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; +nhg_entry_attrs[0].value.u32 = SAI_NEXT_HOP_GROUP_TYPE_PROTECTION; +saistatus = sai_frr_api->create_next_hop_group(&nhg1, switch_id, 1, nhg_entry_attrs); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +nhg_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; +nhg_entry_attrs[0].value.u32 = SAI_NEXT_HOP_GROUP_TYPE_HW_PROTECTION; +saistatus = sai_frr_api->create_next_hop_group(&nhg2, switch_id, 1, nhg_entry_attrs); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +nh_entry_attrs[0].id = SAI_NEXT_HOP_ATTR_TYPE; +nh_entry_attrs[0].value.u32 = SAI_NEXT_HOP_TYPE_IP; +nh_entry_attrs[1].id = SAI_NEXT_HOP_ATTR_IP; +CONVERT_STRING_TO_SAI_IPV4(nh_entry_attrs[1].value, "10.1.1.1"); +nh_entry_attrs[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; +nh_entry_attrs[2].value.u64 = nh_1_interface_id; +saistatus = sai_frr_api->create_next_hop(&nh_1_id, switch_id, 2, nh_entry_attrs); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +nh_entry_attrs[0].id = SAI_NEXT_HOP_ATTR_TYPE; +nh_entry_attrs[0].value.u32 = SAI_NEXT_HOP_TYPE_IP; +nh_entry_attrs[1].id = SAI_NEXT_HOP_ATTR_IP; +CONVERT_STRING_TO_SAI_IPV4(nh_entry_attrs[1].value, "10.1.2.1"); +nh_entry_attrs[2].id = SAI_NEXT_HOP_ATTR_ROUTER_INTERFACE_ID; +nh_entry_attrs[2].value.u64 = nh_2_interface_id; +saistatus = sai_frr_api->create_next_hop(&nh_2_id, switch_id, 2, nh_entry_attrs); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +// Program the primary NH Group member. +nhgm_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; +nhgm_entry_attrs[0].value.oid = nhg1; +nhgm_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; +nhgm_entry_attrs[1].value.oid = nh_1_id; +nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; +nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; +saistatus = sai_frr_api->create_next_hop_group_member(&nhgm_1_id, switch_id, 2, nhgm_entry_attrs); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +nhgm_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; +nhgm_entry_attrs[0].value.oid = nhg1; +nhgm_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; +nhgm_entry_attrs[1].value.oid = nh_2_id; +nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; +nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; +saistatus = sai_frr_api->create_next_hop_group_member(&nhgm_1_id, switch_id, 2, nhgm_entry_attrs); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +// Program the secondary NH Group member. +nhgm_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; +nhgm_entry_attrs[0].value.oid = nhg1; +nhgm_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; +nhgm_entry_attrs[1].value.oid = nhg2; +nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; +nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; +saistatus = sai_frr_api->create_next_hop_group_member(&nhgm_2_id, switch_id, 2, nhgm_entry_attrs); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} + +nhgm_entry_attrs[0].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; +nhgm_entry_attrs[0].value.oid = nhg_id; +nhgm_entry_attrs[1].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; +nhgm_entry_attrs[1].value.oid = nh_2_id; +nhgm_entry_attrs[2].id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_CONFIGURED_ROLE; +nhgm_entry_attrs[2].value.u32 = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_PRIMARY; +saistatus = sai_frr_api->create_next_hop_group_member(&nhgm_3_id, switch_id, 2, nhgm_entry_attrs); +if (saistatus != SAI_STATUS_SUCCESS) { + return saistatus; +} +``` + +## 5.0 Per-Monitored-Object Switchover Notification + +To provide NOS visibility for HW-triggered FRR, add a switch-level notification callback. +Notification is generated per monitored object, and one monitored object may point to multiple protection groups. + +### Notification + +```c +typedef struct _sai_next_hop_group_hw_protection_switchover_notification_data_t +{ + sai_object_id_t monitored_oid; // monitored object id + sai_next_hop_group_member_observed_role_t new_role // Current role after the switchover + uint32_t switchover_success_count; // number of protection groups switched successfully + sai_object_list_t failed_next_hop_groups; // failed protection-group object ids +} sai_next_hop_group_hw_protection_switchover_notification_data_t; + +typedef void (*sai_next_hop_group_hw_protection_switchover_notification_fn)( + _In_ uint32_t count, + _In_ const sai_next_hop_group_hw_protection_switchover_notification_data_t *data); +``` + +### Switch attribute for callback registration + +```c +SAI_SWITCH_ATTR_NEXT_HOP_GROUP_HW_PROTECTION_SWITCHOVER_NOTIFY +``` + +### Usage example + +```c +switch_attr.id = SAI_SWITCH_ATTR_NEXT_HOP_GROUP_HW_PROTECTION_SWITCHOVER_NOTIFY; +switch_attr.value.ptr = (void*)nhg_hw_protection_switchover_cb; +sai_switch_api->set_switch_attribute(switch_id, &switch_attr); +``` + +Example callback report: +```c + monitored_oid = + new_role = SAI_NEXT_HOP_GROUP_MEMBER_CONFIGURED_ROLE_STANDBY + switchover_success_count = 5 + failed_next_hop_groups.count = 2 + failed_next_hop_groups.list[0] = failed_nhg_oid1 + failed_next_hop_groups.list[1] = failed_nhg_oid2 +``` +In this example, `switchover_success_count = 5` means five protection groups switched over successfully +for the monitored object, while `failed_next_hop_groups.count = 2` means two protection groups failed. diff --git a/inc/sai.h b/inc/sai.h index d8f90c44b..f37e00aee 100644 --- a/inc/sai.h +++ b/inc/sai.h @@ -83,6 +83,8 @@ #include "saiicmpecho.h" #include "saisynce.h" #include "saivirtualchannel.h" +#include "saiofh.h" +#include "saiofhroute.h" /** * @defgroup SAI SAI - Entry point specific API definitions. @@ -155,6 +157,8 @@ typedef enum _sai_api_t SAI_API_PREFIX_COMPRESSION = 53, /**< sai_prefix_compression_api_t */ SAI_API_SYNCE = 54, /**< sai_synce_api_t */ SAI_API_VIRTUAL_CHANNEL = 55, /**< sai_virtual_channel_api_t */ + SAI_API_OFH = 56, /**< sai_ofh_api_t */ + SAI_API_OFH_ROUTE = 57, /**< sai_ofh_route_api_t */ SAI_API_MAX, /**< total number of APIs */ /** diff --git a/inc/saibfd.h b/inc/saibfd.h index 2580afe96..5a9c9d6a7 100644 --- a/inc/saibfd.h +++ b/inc/saibfd.h @@ -589,7 +589,10 @@ typedef enum _sai_bfd_session_stat_t SAI_BFD_SESSION_STAT_OUT_PACKETS, /** Packet Drop stat count */ - SAI_BFD_SESSION_STAT_DROP_PACKETS + SAI_BFD_SESSION_STAT_DROP_PACKETS, + + /** Count transitions where the session state changes from UP to DOWN */ + SAI_BFD_SESSION_STAT_SESSION_UP2DOWN_TRANSITIONS } sai_bfd_session_stat_t; diff --git a/inc/saidebugcounter.h b/inc/saidebugcounter.h index cc9714e8e..76b07dfa8 100644 --- a/inc/saidebugcounter.h +++ b/inc/saidebugcounter.h @@ -331,6 +331,21 @@ typedef enum _sai_in_drop_reason_t /** IPv4 or IPv6 Routing table (LPM) unicast miss */ SAI_IN_DROP_REASON_LPM_MISS = 0x00000039, + /** OFH packet TTL expired */ + SAI_IN_DROP_REASON_OFH_TTL, + + /** OFH Routing table miss */ + SAI_IN_DROP_REASON_OFH_MISS, + + /** OFH Routing table action discard */ + SAI_IN_DROP_REASON_OFH_DISCARD, + + /** OFH VLAN drop */ + SAI_IN_DROP_REASON_OFH_VLAN_DROP, + + /** OFH VLAN to virtual router id drop */ + SAI_IN_DROP_REASON_OFH_VLAN_TO_VRID_DROP, + /** End of in drop reasons */ SAI_IN_DROP_REASON_END, @@ -377,6 +392,9 @@ typedef enum _sai_out_drop_reason_t */ SAI_OUT_DROP_REASON_TUNNEL_LOOPBACK_PACKET_DROP, + /** OFH VLAN drop */ + SAI_OUT_DROP_REASON_OFH_VLAN_DROP, + /** End of out drop reasons */ SAI_OUT_DROP_REASON_END, diff --git a/inc/sainexthopgroup.h b/inc/sainexthopgroup.h index 057067869..a34e9fdf6 100644 --- a/inc/sainexthopgroup.h +++ b/inc/sainexthopgroup.h @@ -111,6 +111,36 @@ typedef enum _sai_next_hop_group_admin_role_t } sai_next_hop_group_admin_role_t; +/** + * @brief Defines the HW protection switchover status + */ +typedef struct _sai_next_hop_group_hw_protection_switchover_notification_data_t +{ + /** + * @brief Monitored object id + * + * @objects SAI_OBJECT_TYPE_PORT, SAI_OBJECT_TYPE_LAG, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_OBJECT_TYPE_VLAN_MEMBER, SAI_OBJECT_TYPE_TUNNEL, SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_OBJECT_TYPE_ICMP_ECHO_SESSION, SAI_OBJECT_TYPE_BFD_SESSION + */ + sai_object_id_t monitored_oid; + + /** + * @brief Current role after the switchover + */ + sai_next_hop_group_member_observed_role_t new_role; + + /** + * @brief Number of protection groups that switched over successfully + */ + uint32_t switchover_success_count; + + /** + * @brief List of protection groups that failed switchover. + * + * @objects SAI_OBJECT_TYPE_NEXT_HOP_GROUP + */ + sai_object_list_t failed_next_hop_groups; +} sai_next_hop_group_hw_protection_switchover_notification_data_t; + /** * @brief Attribute id for next hop */ @@ -683,6 +713,20 @@ typedef sai_status_t (*sai_get_next_hop_group_map_attribute_fn)( _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); +/** + * @brief Next Hop Group HW protection switchover notification callback + * + * Passed as a parameter into sai_initialize_switch(). + * + * @count data[count] + * + * @param[in] count Number of notifications + * @param[in] data Array of notification data + */ +typedef void (*sai_next_hop_group_hw_protection_switchover_notification_fn)( + _In_ uint32_t count, + _In_ const sai_next_hop_group_hw_protection_switchover_notification_data_t *data); + /** * @brief Next Hop methods table retrieved with sai_api_query() */ diff --git a/inc/saiobject.h b/inc/saiobject.h index 84dd67018..f99483a0f 100644 --- a/inc/saiobject.h +++ b/inc/saiobject.h @@ -36,6 +36,7 @@ #include #include #include +#include /* new experimental object type includes */ #include @@ -140,6 +141,9 @@ typedef union _sai_object_key_entry_t /** @validonly object_type == SAI_OBJECT_TYPE_ENI_TRUSTED_VNI_ENTRY */ sai_eni_trusted_vni_entry_t eni_trusted_vni_entry; + /** @validonly object_type == SAI_OBJECT_TYPE_OFH_ROUTE_ENTRY */ + sai_ofh_route_entry_t ofh_route_entry; + /* Add new experimental entries above this line */ } sai_object_key_entry_t; diff --git a/inc/saiofh.h b/inc/saiofh.h new file mode 100644 index 000000000..af73570cc --- /dev/null +++ b/inc/saiofh.h @@ -0,0 +1,404 @@ +/** + * Copyright (c) 2014 Microsoft Open Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS + * FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. + * + * See the Apache Version 2.0 License for specific language governing + * permissions and limitations under the License. + * + * Microsoft would like to thank the following companies for their review and + * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, + * Dell Products, L.P., Facebook, Inc., Marvell International Ltd. + * + * @file saiofh.h + * + * @brief This module defines SAI Optimized Forwarding Header + */ + +#if !defined (__SAIOFH_H_) +#define __SAIOFH_H_ + +#include + +/** + * @defgroup SAIOFH SAI - OFH specific API definitions + * + * @{ + */ + +/** + * @brief OFH types + */ +typedef enum _sai_ofh_type_t +{ + /** + * @brief ESUN + */ + SAI_OFH_TYPE_ESUN, + + /** + * @brief AFH Type 1 + */ + SAI_OFH_TYPE_AFH_TYPE_1, + + /** + * @brief AFH Type 2 + */ + SAI_OFH_TYPE_AFH_TYPE_2, + + /** + * @brief UFH Type 1 + */ + SAI_OFH_TYPE_UFH_TYPE_1, + + /** + * @brief UFH Type 2 + */ + SAI_OFH_TYPE_UFH_TYPE_2, +} sai_ofh_type_t; + +/** + * @brief Attribute Id for SAI OFH object + */ +typedef enum _sai_ofh_attr_t +{ + /** + * @brief Start of attributes + */ + SAI_OFH_ATTR_START, + + /** + * @brief Type of OFH header + * + * @type sai_ofh_type_t + * @flags CREATE_ONLY + * @default SAI_OFH_TYPE_AFH_TYPE_1 + */ + SAI_OFH_ATTR_TYPE = SAI_OFH_ATTR_START, + + /** + * @brief OFH ether type identifier + * + * @type sai_uint16_t + * @flags CREATE_AND_SET + * @isvlan false + * @default 0 + */ + SAI_OFH_ATTR_ETHERTYPE, + + /** + * @brief OFH Version Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_VER_OFFSET, + + /** + * @brief OFH Version Field Width in Bits. + * Value of 0 bits means that field is not configured. + * ESUN Version: 2 bits + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_VER_WIDTH, + + /** + * @brief OFH Flow Label Present Field Bit Offset + * This bit specifies the presence of flow label + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_F_OFFSET, + + /** + * @brief OFH Flow Label Present Field width in Bits. + * Value of 0 bits means that field is not configured. + * ESUN:1 bit AFH:1 bit + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_F_WIDTH, + + /** + * @brief OFH COS Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_COS_OFFSET, + + /** + * @brief OFH COS Field Width in Bits + * Number of bits are 6. Value of 0 bits means that field is not configured + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 6 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_COS_WIDTH, + + /** + * @brief OFH ECN Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_ECN_OFFSET, + + /** + * @brief OFH ECN Field Width in Bits + * Value of 0 bits means that field is not configured + * ESUN: 2 bits + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_ECN_WIDTH, + + /** + * @brief OFH Flow Label Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_FLOW_LABEL_OFFSET, + + /** + * @brief OFH Flow Label Field Width in Bits + * Value of 0 bits means that field is not configured + * ESUN: 16 bits + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_FLOW_LABEL_WIDTH, + + /** + * @brief OFH TTL Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_TTL_OFFSET, + + /** + * @brief OFH TTL Field Width in Bits + * Value of 0 bits means that field is not configured + * ESUN: 4 bits + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_TTL_WIDTH, + + /** + * @brief OFH User Defined Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_UD_OFFSET, + + /** + * @brief OFH User Define Field Width in Bits + * Value of 0 bits means that field is not configured + * ESUN: 2bit user defined + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_ESUN + */ + SAI_OFH_ATTR_UD_WIDTH, + + /** + * @brief OFH AR Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_AR_OFFSET, + + /** + * @brief OFH AR Field Width in Bits + * Number of bits are 1. Value of 0 bits means that field is not configured + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_AR_WIDTH, + + /** + * @brief OFH Congestion Notification Message Eligible Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_C_OFFSET, + + /** + * @brief OFH Congestion Notification Message Eligible Field Width in Bits + * Number of bits are 1. Value of 0 bits means that field is not configured + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_C_WIDTH, + + /** + * @brief OFH Congestion Notification Message Field Bit Offset + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_CNM_OFFSET, + + /** + * @brief OFH Congestion Notification Message Field Width in bits + * Number of bits are 1. Value of 0 bits means that field is not configured + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + * @validonly SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_1 or SAI_OFH_ATTR_TYPE == SAI_OFH_TYPE_AFH_TYPE_2 + */ + SAI_OFH_ATTR_CNM_WIDTH, + + /** + * @brief OFH header size + * + * @type sai_uint8_t + * @flags CREATE_AND_SET + * @default 0 + */ + SAI_OFH_ATTR_HDR_SIZE, + + /** + * @brief End of attributes + */ + SAI_OFH_ATTR_END, + + /** Custom range base value */ + SAI_OFH_ATTR_CUSTOM_RANGE_START = 0x10000000, + + /** End of custom range base */ + SAI_OFH_ATTR_CUSTOM_RANGE_END + +} sai_ofh_attr_t; + +/** + * @brief Create and return a OFH object + * + * @param[out] ofh_id OFH object + * @param[in] switch_id Switch object id + * @param[in] attr_count Number of attributes + * @param[in] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_create_ofh_fn)( + _Out_ sai_object_id_t *ofh_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Deletes a specified OFH object. + * + * @param[in] ofh_id OFH object to be removed. + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_remove_ofh_fn)( + _In_ sai_object_id_t ofh_id); + +/** + * @brief Set OFH attribute value(s). + * + * @param[in] ofh_id TAM id + * @param[in] attr Attribute to set + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_set_ofh_attribute_fn)( + _In_ sai_object_id_t ofh_id, + _In_ const sai_attribute_t *attr); + +/** + * @brief Get values for specified OFH attributes. + * + * @param[in] ofh_id OFH object id + * @param[in] attr_count Number of attributes + * @param[inout] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_get_ofh_attribute_fn)( + _In_ sai_object_id_t ofh_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + +/** + * @brief OFH methods table retrieved with sai_api_query() + */ +typedef struct _sai_ofh_api_t +{ + /** + * @brief SAI OFH API set + */ + sai_create_ofh_fn create_ofh; + sai_remove_ofh_fn remove_ofh; + sai_set_ofh_attribute_fn set_ofh_attribute; + sai_get_ofh_attribute_fn get_ofh_attribute; +} sai_ofh_api_t; + +/** + * @} + */ +#endif /** __SAIOFH_H_ */ diff --git a/inc/saiofhroute.h b/inc/saiofhroute.h new file mode 100644 index 000000000..1740203aa --- /dev/null +++ b/inc/saiofhroute.h @@ -0,0 +1,336 @@ +/** + * Copyright (c) 2014 Microsoft Open Technologies, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT + * LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS + * FOR A PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. + * + * See the Apache Version 2.0 License for specific language governing + * permissions and limitations under the License. + * + * Microsoft would like to thank the following companies for their review and + * assistance with these files: Intel Corporation, Mellanox Technologies Ltd, + * Dell Products, L.P., Facebook, Inc., Marvell International Ltd. + * + * @file saiofhroute.h + * + * @brief This module defines SAI OFH Route Entry interface + */ + +#if !defined (__SAIOFHROUTE_H_) +#define __SAIOFHROUTE_H_ + +#include + +/** + * @defgroup SAIOFHROUTE SAI - OFH Route specific API definitions + * + * @{ + */ + +/** + * @brief Attribute Id for SAI OFH route object + */ +typedef enum _sai_ofh_route_entry_attr_t +{ + /** + * @brief Start of attributes + */ + SAI_OFH_ROUTE_ENTRY_ATTR_START, + + /* READ-WRITE */ + + /** + * @brief Packet action + * + * @type sai_packet_action_t + * @flags CREATE_AND_SET + * @default SAI_PACKET_ACTION_FORWARD + */ + SAI_OFH_ROUTE_ENTRY_ATTR_PACKET_ACTION = SAI_OFH_ROUTE_ENTRY_ATTR_START, + + /** + * @brief Generate User Defined Trap ID for trap/log actions + * + * When it is SAI_NULL_OBJECT_ID, then packet will not be trapped. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_HOSTIF_USER_DEFINED_TRAP + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_OFH_ROUTE_ENTRY_ATTR_USER_TRAP_ID, + + /** + * @brief Next hop or next hop group id for the packet, or a router interface + * in case of directly reachable route, or the CPU port in case of IP2ME route + * + * The next hop id is only effective when the packet action is one of the + * following: FORWARD, COPY, LOG, TRANSIT. + * + * The next hop id can be a generic next hop object, such as next hop, next + * hop group. Directly reachable routes are the IP subnets that are + * directly attached to the router. For such routes, fill the router + * interface id to which the subnet is attached. IP2ME route adds a local + * router IP address. For such routes, fill the CPU port + * (#SAI_SWITCH_ATTR_CPU_PORT). + * When pointing to a next hop group which is empty, the effective routing + * action will be DROP. + * + * When it is SAI_NULL_OBJECT_ID, then packet will be dropped. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP, SAI_OBJECT_TYPE_ROUTER_INTERFACE, SAI_OBJECT_TYPE_PORT + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_OFH_ROUTE_ENTRY_ATTR_NEXT_HOP_ID, + + /** + * @brief User based Meta Data + * + * Value Range #SAI_SWITCH_ATTR_ROUTE_DST_USER_META_DATA_RANGE + * + * @type sai_uint32_t + * @flags CREATE_AND_SET + * @default 0 + */ + SAI_OFH_ROUTE_ENTRY_ATTR_META_DATA, + + /** READ-ONLY */ + + /** + * @brief OFH Route entry type + * + * @type sai_ip_addr_family_t + * @flags READ_ONLY + * @isresourcetype true + */ + SAI_OFH_ROUTE_ENTRY_ATTR_IP_ADDR_FAMILY, + + /** + * @brief Attach a counter + * + * When it is empty, then packet hits won't be counted + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_COUNTER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_OFH_ROUTE_ENTRY_ATTR_COUNTER_ID, + + /** + * @brief End of attributes + */ + SAI_OFH_ROUTE_ENTRY_ATTR_END, + + /** Custom range base value */ + SAI_OFH_ROUTE_ENTRY_ATTR_CUSTOM_RANGE_START = 0x10000000, + + /** End of custom range base */ + SAI_OFH_ROUTE_ENTRY_ATTR_CUSTOM_RANGE_END + +} sai_ofh_route_entry_attr_t; + +/** + * @brief Unicast route entry + */ +typedef struct _sai_ofh_route_entry_t +{ + /** + * @brief Switch ID + * + * @objects SAI_OBJECT_TYPE_SWITCH + */ + sai_object_id_t switch_id; + + /** + * @brief Virtual Router ID + * + * @objects SAI_OBJECT_TYPE_VIRTUAL_ROUTER + */ + sai_object_id_t vr_id; + + /** + * @brief OFH Destination + */ + sai_ofh_addr_and_mask_t destination; + +} sai_ofh_route_entry_t; + +/** + * @brief Create OFH Route + * + * Note: OFH Destination ID/mask expected in Network Byte Order. + * + * @param[in] ofh_route_entry Route entry + * @param[in] attr_count Number of attributes + * @param[in] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_create_ofh_route_entry_fn)( + _In_ const sai_ofh_route_entry_t *ofh_route_entry, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Remove OFH Route + * + * Note: Destination ID/mask expected in Network Byte Order. + * + * @param[in] ofh_route_entry Route entry + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_remove_ofh_route_entry_fn)( + _In_ const sai_ofh_route_entry_t *ofh_route_entry); + +/** + * @brief Set OFH route attribute value + * + * @param[in] ofh_route_entry Route entry + * @param[in] attr Attribute + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_set_ofh_route_entry_attribute_fn)( + _In_ const sai_ofh_route_entry_t *ofh_route_entry, + _In_ const sai_attribute_t *attr); + +/** + * @brief Get OFH route attribute value + * + * @param[in] ofh_route_entry Route entry + * @param[in] attr_count Number of attributes + * @param[inout] attr_list Array of attributes + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_get_ofh_route_entry_attribute_fn)( + _In_ const sai_ofh_route_entry_t *ofh_route_entry, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + +/** + * @brief Bulk create OFH route entry + * + * @param[in] object_count Number of objects to create + * @param[in] ofh_route_entry List of object to create + * @param[in] attr_count List of attr_count. Caller passes the number + * of attribute for each object to create. + * @param[in] attr_list List of attributes for every object. + * @param[in] mode Bulk operation error handling mode. + * @param[out] object_statuses List of status for every object. Caller needs to + * allocate the buffer + * + * @return #SAI_STATUS_SUCCESS on success when all objects are created or + * #SAI_STATUS_FAILURE when any of the objects fails to create. When there is + * failure, Caller is expected to go through the list of returned statuses to + * find out which fails and which succeeds. + */ +typedef sai_status_t (*sai_bulk_create_ofh_route_entry_fn)( + _In_ uint32_t object_count, + _In_ const sai_ofh_route_entry_t *ofh_route_entry, + _In_ const uint32_t *attr_count, + _In_ const sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + +/** + * @brief Bulk remove OFH route entry + * + * @param[in] object_count Number of objects to remove + * @param[in] ofh_route_entry List of objects to remove + * @param[in] mode Bulk operation error handling mode. + * @param[out] object_statuses List of status for every object. Caller needs to + * allocate the buffer + * + * @return #SAI_STATUS_SUCCESS on success when all objects are removed or + * #SAI_STATUS_FAILURE when any of the objects fails to remove. When there is + * failure, Caller is expected to go through the list of returned statuses to + * find out which fails and which succeeds. + */ +typedef sai_status_t (*sai_bulk_remove_ofh_route_entry_fn)( + _In_ uint32_t object_count, + _In_ const sai_ofh_route_entry_t *ofh_route_entry, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + +/** + * @brief Bulk set attribute on OFH route entry + * + * @param[in] object_count Number of objects to set attribute + * @param[in] ofh_route_entry List of objects to set attribute + * @param[in] attr_list List of attributes to set on objects, one attribute per object + * @param[in] mode Bulk operation error handling mode. + * @param[out] object_statuses List of status for every object. Caller needs to + * allocate the buffer + * + * @return #SAI_STATUS_SUCCESS on success when all objects are removed or + * #SAI_STATUS_FAILURE when any of the objects fails to remove. When there is + * failure, Caller is expected to go through the list of returned statuses to + * find out which fails and which succeeds. + */ +typedef sai_status_t (*sai_bulk_set_ofh_route_entry_attribute_fn)( + _In_ uint32_t object_count, + _In_ const sai_ofh_route_entry_t *ofh_route_entry, + _In_ const sai_attribute_t *attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + +/** + * @brief Bulk get attribute on OFH route entry + * + * @param[in] object_count Number of objects to set attribute + * @param[in] ofh_route_entry List of objects to set attribute + * @param[in] attr_count List of attr_count. Caller passes the number + * of attribute for each object to get + * @param[inout] attr_list List of attributes to set on objects, one attribute per object + * @param[in] mode Bulk operation error handling mode + * @param[out] object_statuses List of status for every object. Caller needs to + * allocate the buffer + * + * @return #SAI_STATUS_SUCCESS on success when all objects are removed or + * #SAI_STATUS_FAILURE when any of the objects fails to remove. When there is + * failure, Caller is expected to go through the list of returned statuses to + * find out which fails and which succeeds. + */ +typedef sai_status_t (*sai_bulk_get_ofh_route_entry_attribute_fn)( + _In_ uint32_t object_count, + _In_ const sai_ofh_route_entry_t *ofh_route_entry, + _In_ const uint32_t *attr_count, + _Inout_ sai_attribute_t **attr_list, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + +/** + * @brief OFH Router entry methods table retrieved with sai_api_query() + */ +typedef struct _sai_ofh_route_api_t +{ + sai_create_ofh_route_entry_fn create_ofh_route_entry; + sai_remove_ofh_route_entry_fn remove_ofh_route_entry; + sai_set_ofh_route_entry_attribute_fn set_ofh_route_entry_attribute; + sai_get_ofh_route_entry_attribute_fn get_ofh_route_entry_attribute; + + sai_bulk_create_ofh_route_entry_fn create_ofh_route_entries; + sai_bulk_remove_ofh_route_entry_fn remove_ofh_route_entries; + sai_bulk_set_ofh_route_entry_attribute_fn set_ofh_route_entries_attribute; + sai_bulk_get_ofh_route_entry_attribute_fn get_ofh_route_entries_attribute; + +} sai_ofh_route_api_t; + +/** + * @} + */ +#endif /** __SAIOFHROUTE_H_ */ diff --git a/inc/saiport.h b/inc/saiport.h index 2d85f3f64..10a9e3b65 100644 --- a/inc/saiport.h +++ b/inc/saiport.h @@ -1382,6 +1382,9 @@ typedef enum _sai_port_attr_t * @brief Enable flood (unknown unicast or unknown multicast) * storm control policer on port. * + * Deprecated. Use SAI_PORT_ATTR_UNKNOWN_UNICAST_STORM_CONTROL_POLICER_ID + * and SAI_PORT_ATTR_UNKNOWN_MULTICAST_STORM_CONTROL_POLICER_ID. + * * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port. * * @type sai_object_id_t @@ -1389,6 +1392,7 @@ typedef enum _sai_port_attr_t * @objects SAI_OBJECT_TYPE_POLICER * @allownull true * @default SAI_NULL_OBJECT_ID + * @deprecated true */ SAI_PORT_ATTR_FLOOD_STORM_CONTROL_POLICER_ID, @@ -1408,6 +1412,9 @@ typedef enum _sai_port_attr_t /** * @brief Enable multicast storm control policer on port. * + * Deprecated. Use SAI_PORT_ATTR_KNOWN_MULTICAST_STORM_CONTROL_POLICER_ID + * and SAI_PORT_ATTR_UNKNOWN_MULTICAST_STORM_CONTROL_POLICER_ID. + * * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port. * * @type sai_object_id_t @@ -1415,6 +1422,7 @@ typedef enum _sai_port_attr_t * @objects SAI_OBJECT_TYPE_POLICER * @allownull true * @default SAI_NULL_OBJECT_ID + * @deprecated true */ SAI_PORT_ATTR_MULTICAST_STORM_CONTROL_POLICER_ID, @@ -3267,6 +3275,68 @@ typedef enum _sai_port_attr_t */ SAI_PORT_ATTR_CBFC_CREDIT_POOL_LIST, + /** + * @brief Enable known unicast storm control policer on port. + * + * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_KNOWN_UNICAST_STORM_CONTROL_POLICER_ID, + + /** + * @brief Enable unknown unicast storm control policer on port. + * + * Set policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_UNKNOWN_UNICAST_STORM_CONTROL_POLICER_ID, + + /** + * @brief Enable known multicast storm control policer on port. + * + * Set Policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_KNOWN_MULTICAST_STORM_CONTROL_POLICER_ID, + + /** + * @brief Enable unknown multicast storm control policer on port. + * + * Set Policer id = #SAI_NULL_OBJECT_ID to disable policer on port. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_POLICER + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_UNKNOWN_MULTICAST_STORM_CONTROL_POLICER_ID, + + /** + * @brief OFH headers + * + * @type sai_object_list_t + * @flags CREATE_ONLY + * @objects SAI_OBJECT_TYPE_OFH + * @default empty + */ + SAI_PORT_ATTR_OFH, + /** * @brief End of attributes */ diff --git a/inc/saiswitch.h b/inc/saiswitch.h index 64072c22c..40931d349 100644 --- a/inc/saiswitch.h +++ b/inc/saiswitch.h @@ -3598,6 +3598,49 @@ typedef enum _sai_switch_attr_t */ SAI_SWITCH_ATTR_PTP_SYNTONIZE_ADJUST, + /** + * @brief HW protection switchover notification callback function passed to the adapter. + * + * @type sai_pointer_t sai_next_hop_group_hw_protection_switchover_notification_fn + * @flags CREATE_AND_SET + * @default NULL + */ + SAI_SWITCH_ATTR_NEXT_HOP_GROUP_HW_PROTECTION_SWITCHOVER_NOTIFY, + + /** + * @brief OFH headers + * + * @type sai_object_list_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_OFH + * @default empty + */ + SAI_SWITCH_ATTR_OFH, + + /** + * @brief OFH header max size + * + * @type sai_int8_t + * @flags READ_ONLY + */ + SAI_SWITCH_ATTR_OFH_MAX_SIZE, + + /** + * @brief The OFH Route Table size + * + * @type sai_uint32_t + * @flags READ_ONLY + */ + SAI_SWITCH_ATTR_OFH_ROUTE_TABLE_SIZE, + + /** + * @brief Available OFH routes + * + * @type sai_uint32_t + * @flags READ_ONLY + */ + SAI_SWITCH_ATTR_AVAILABLE_OFH_ROUTE_ENTRY, + /** * @brief End of attributes */ diff --git a/inc/saitypes.h b/inc/saitypes.h index 287a9e0da..e208d95fe 100644 --- a/inc/saitypes.h +++ b/inc/saitypes.h @@ -306,6 +306,8 @@ typedef enum _sai_object_type_t SAI_OBJECT_TYPE_VIRTUAL_CHANNEL = 116, SAI_OBJECT_TYPE_CBFC_CREDIT_POOL = 117, SAI_OBJECT_TYPE_CBFC_CREDIT_PROFILE = 118, + SAI_OBJECT_TYPE_OFH = 119, + SAI_OBJECT_TYPE_OFH_ROUTE_ENTRY = 120, /** Must remain in last position */ SAI_OBJECT_TYPE_MAX, @@ -471,6 +473,51 @@ typedef struct _sai_ip_prefix_list_t sai_ip_prefix_t *list; } sai_ip_prefix_list_t; +typedef enum _sai_ofh_addr_family_t +{ + SAI_OFH_ADDR_FAMILY_ESUN, + + SAI_OFH_ADDR_FAMILY_AFH_T1, + + SAI_OFH_ADDR_FAMILY_AFH_T2, + + SAI_OFH_ADDR_FAMILY_UFH_T1, + + SAI_OFH_ADDR_FAMILY_UFH_T2, +} sai_ofh_addr_family_t; + +/** + * @extraparam sai_ofh_addr_family_t ofh_addr_family + */ +typedef union _sai_ofh_addr_t +{ + /** @validonly ofh_addr_family == SAI_OFH_ADDR_FAMILY_ESUN */ + sai_mac_t esun; + + /** @validonly ofh_addr_family == SAI_OFH_ADDR_FAMILY_AFH_T1 */ + sai_mac_t afh_t1; + + /** @validonly ofh_addr_family == SAI_OFH_ADDR_FAMILY_AFH_T2 */ + sai_mac_t afh_t2; + + /** @validonly ofh_addr_family == SAI_OFH_ADDR_FAMILY_UFH_T1 */ + sai_uint32_t ufh_t1; + + /** @validonly ofh_addr_family == SAI_OFH_ADDR_FAMILY_UFH_T2 */ + sai_uint16_t ufh_t2; +} sai_ofh_addr_t; + +typedef struct _sai_ofh_addr_and_mask_t +{ + sai_ofh_addr_family_t ofh_addr_family; + + /** @passparam ofh_addr_family */ + sai_ofh_addr_t ofh_addr; + + /** @passparam ofh_addr_family */ + sai_ofh_addr_t ofh_mask; +} sai_ofh_addr_and_mask_t; + /** * @brief Attribute data for #SAI_PORT_ATTR_PRBS_RX_STATUS */ diff --git a/inc/saivirtualrouter.h b/inc/saivirtualrouter.h index ea68a902c..56c0394e9 100644 --- a/inc/saivirtualrouter.h +++ b/inc/saivirtualrouter.h @@ -115,6 +115,15 @@ typedef enum _sai_virtual_router_attr_t */ SAI_VIRTUAL_ROUTER_ATTR_LABEL, + /** + * @brief Admin OFH state + * + * @type bool + * @flags CREATE_AND_SET + * @default true + */ + SAI_VIRTUAL_ROUTER_ATTR_ADMIN_OFH_STATE, + /** * @brief End of attributes */ diff --git a/meta/acronyms.txt b/meta/acronyms.txt index d940caaad..a8cf3bab6 100644 --- a/meta/acronyms.txt +++ b/meta/acronyms.txt @@ -2,6 +2,7 @@ ACK - Acknowledgement ACL - Access Control List AES - Advanced Encryption Standard +AFH - AI Fabric Header AN - Association Number AN - Auto Negotiation API - Application Program Interface @@ -56,6 +57,7 @@ EEPROM - Electrically erasable programmable read-only memory ENI - Elastic Network Interface ERSPAN - Encapsulated Remote SPAN ESN - Extended Sequence Number +ESUN - Ethernet for Scale Up Networks EWMA - Exponentially Weighted Moving Average FCS - Frame Check Sequence FD - File Descriptor @@ -117,6 +119,7 @@ NTPCLIENT - Network Time Protocol Client NTPSERVER - Network Time Protocol Server NVGRE - Network Virtualization using Generic Routing Encapsulation OAM - Operations Administration and Maintenance +OFH - Optimized Forwarding Header OUI - Organizationally Unique Identifier P4RT - Programming Protocol-independent Packet Processors Runtime PAM4 - Pulse Amplitude Modulation 4-level @@ -182,6 +185,7 @@ TWAMP - Two-Way Active Measurement Protocol UART - Universal Asynchronous Receiver/Transmitter UDF - User-Defined Field UDP - User Datagram Protocol +UFH - Unified Forwarding Header USD - Ultimate Segment Decapsulation USP - Ultimate Segment Pop USXGMII - Universal Serial 10 Gigabit Media Independent Interface diff --git a/meta/checkheaders.pl b/meta/checkheaders.pl index 037e11818..7ee2026c1 100755 --- a/meta/checkheaders.pl +++ b/meta/checkheaders.pl @@ -199,6 +199,7 @@ sub CheckHash next if $key eq "SAI_PORT_BREAKOUT_MODE_TYPE_MAX"; next if $key eq "SAI_HOSTIF_USER_DEFINED_TRAP_TYPE_CUSTOM_RANGE_BASE"; next if $key eq "SAI_HOSTIF_USER_DEFINED_TRAP_TYPE_END"; + next if $key eq "SAI_OUT_DROP_REASON_END"; # NOTE: some other attributes/enum with END range could be added } diff --git a/meta/gensairpc.pl b/meta/gensairpc.pl index de9dacd64..305011020 100755 --- a/meta/gensairpc.pl +++ b/meta/gensairpc.pl @@ -377,10 +377,18 @@ sub get_definitions { my %apis; my $i = 0; - # Iterate over files - for ( GetSaiXmlFiles($XMLDIR) ) { + my @xml_files = GetSaiXmlFiles($XMLDIR); + if (NeedsTwoPassProcessing()) + { + unshift @xml_files, GetGroupXmlFiles($XMLDIR); + } + + for ( @xml_files ) + { my $xml = ReadXml($_); + next unless defined $xml->{compounddef}[0]; + # Iterate over definitions for ( @{ $xml->{compounddef}[0]->{sectiondef} } ) { if ( $_->{kind} eq 'typedef' or $_->{kind} eq 'enum' ) { diff --git a/meta/parse.pl b/meta/parse.pl index 86c92a512..8e8d86469 100755 --- a/meta/parse.pl +++ b/meta/parse.pl @@ -2695,9 +2695,11 @@ sub ProcessStructValueType my $type = shift; return "SAI_ATTR_VALUE_TYPE_OBJECT_ID" if $type eq "sai_object_id_t"; + return "SAI_ATTR_VALUE_TYPE_OBJECT_LIST" if $type eq "sai_object_list_t"; return "SAI_ATTR_VALUE_TYPE_MAC" if $type eq "sai_mac_t"; return "SAI_ATTR_VALUE_TYPE_IP_ADDRESS" if $type eq "sai_ip_address_t"; return "SAI_ATTR_VALUE_TYPE_IP_PREFIX" if $type eq "sai_ip_prefix_t"; + return "SAI_ATTR_VALUE_TYPE_OFH_ADDR_AND_MASK" if $type eq "sai_ofh_addr_and_mask_t"; return "SAI_ATTR_VALUE_TYPE_PRBS_RX_STATE" if $type eq "sai_prbs_rx_state_t"; return "SAI_ATTR_VALUE_TYPE_UINT16" if $type eq "sai_vlan_id_t"; return "SAI_ATTR_VALUE_TYPE_UINT32" if $type eq "sai_label_id_t"; @@ -2743,7 +2745,7 @@ sub ProcessStructObjects my $type = $struct->{type}; - return "NULL" if not $type eq "sai_object_id_t" and not $type eq "sai_attribute_t*"; + return "NULL" if not $type eq "sai_object_id_t" and not $type eq "sai_object_list_t" and not $type eq "sai_attribute_t*"; WriteSource "const sai_object_type_t sai_metadata_struct_member_sai_${rawname}_t_${key}_allowed_objects[] = {"; @@ -2767,7 +2769,7 @@ sub ProcessStructObjectLen my $type = $struct->{type}; - return 0 if not $type eq "sai_object_id_t" and not $type eq "sai_attribute_t*"; + return 0 if not $type eq "sai_object_id_t" and not $type eq "sai_object_list_t" and not $type eq "sai_attribute_t*"; my @objects = @{ $struct->{objects} }; @@ -4172,13 +4174,13 @@ sub ProcessSingleNonObjectId # allowed entries on object structs - if (not $type =~ /^sai_(nat_entry_data|mac|object_id|vlan_id|ip_address|ip_prefix|acl_chain|label_id|ip6|uint8|uint16|uint32|u32_range|\w+_type)_t$/) + if (not $type =~ /^sai_(nat_entry_data|mac|object_id|object_list|vlan_id|ip_address|ip_prefix|ofh_addr_and_mask|acl_chain|label_id|ip6|uint8|uint16|uint32|u32_range|\w+_type)_t$/) { LogError "struct member $member type '$type' is not allowed on struct $structname"; next; } - next if not $type eq "sai_object_id_t"; + next if not $type eq "sai_object_id_t" and not $type eq "sai_object_list_t"; my $objects = ExtractObjectsFromDesc($structname, $member, $desc); @@ -5298,107 +5300,6 @@ sub CreateSourcePragmaPop WriteSource "#pragma GCC diagnostic pop"; } -sub NeedsTwoPassProcessing -{ - # - # Detect if XML files require two-pass processing based on their structure. - # - # In Doxygen 1.9.8+, the XML structure changed: - # - sai_*.xml files have empty enum/define sections (just sectiondef exists, no memberdefs) - # - group_*.xml files contain the actual enum definitions with enumvalues and defines - # - # In older Doxygen versions: - # - sai_*.xml files contain both defines and enums with enumvalues - # - group_*.xml files don't exist or aren't used - # - # Returns 1 if two-pass processing is needed (new structure): - # - First pass: process all defines from group_*.xml files - # - Second pass: process enums/typedefs/functions from group_*.xml and sai_*.xml files - # - # Returns 0 if single-pass processing is sufficient (old structure): - # - Process sai_*.xml files only - # - - my $sai_file = "$XMLDIR/sai_8h.xml"; - - my $saiacl_file = "$XMLDIR/saiacl_8h.xml"; - - return 1 if not -f $sai_file or not -f $saiacl_file; - - # - # Check sai_8h.xml for enumvalue with name="SAI_API_SWITCH" - # - - my $sai_ref = ReadXml $sai_file; - - return 1 if not defined $sai_ref->{compounddef}[0]; - - my @sai_sections = @{ $sai_ref->{compounddef}[0]->{sectiondef} }; - - my $has_enumvalue = 0; - - for my $section (@sai_sections) - { - next if not $section->{kind} eq "enum"; - - for my $memberdef (@{ $section->{memberdef} }) - { - next if not $memberdef->{kind} eq "enum"; - - if (defined $memberdef->{enumvalue}) - { - for my $enumvalue (@{ $memberdef->{enumvalue} }) - { - if (defined $enumvalue->{name} and defined $enumvalue->{name}[0] and $enumvalue->{name}[0] eq "SAI_API_SWITCH") - { - $has_enumvalue = 1; - - last; - } - } - } - } - - last if $has_enumvalue; - } - - # - # Check saiacl_8h.xml for memberdef kind="define" - # - - my $saiacl_ref = ReadXml $saiacl_file; - - return 1 if not defined $saiacl_ref->{compounddef}[0]; - - my @saiacl_sections = @{ $saiacl_ref->{compounddef}[0]->{sectiondef} }; - - my $has_define = 0; - - for my $section (@saiacl_sections) - { - next if not $section->{kind} eq "define"; - - for my $memberdef (@{ $section->{memberdef} }) - { - if ($memberdef->{kind} eq "define") - { - $has_define = 1; - - last; - } - } - - last if $has_define; - } - - # - # If sai_8h.xml has enumvalues and saiacl_8h.xml has defines, it's old structure (single-pass) - # Otherwise, use two-pass processing (group_*.xml files contain the actual content) - # - - return not ($has_enumvalue and $has_define); -} - sub ProcessXmlFiles { if (NeedsTwoPassProcessing()) @@ -5637,7 +5538,7 @@ sub ProcessNotificationStruct next if $type =~ /^(uint32_t|bool)$/; next if $type =~ /^(sai_twamp_session_stats_data_t)$/; - if ($type =~ /^(sai_object_id_t|sai_attribute_t\*)$/) + if ($type =~ /^(sai_object_id_t|sai_object_list_t|sai_attribute_t\*)$/) { my $objects = ExtractObjectsFromDesc($structname, $member, $desc); diff --git a/meta/saimetadatatypes.h b/meta/saimetadatatypes.h index e332ff216..96de79444 100644 --- a/meta/saimetadatatypes.h +++ b/meta/saimetadatatypes.h @@ -539,7 +539,12 @@ typedef enum _sai_attr_value_type_t /** * @brief Attribute value is 64 bit unsigned integer range list. */ - SAI_ATTR_VALUE_TYPE_UINT64_RANGE_LIST + SAI_ATTR_VALUE_TYPE_UINT64_RANGE_LIST, + + /** + * @brief Attribute value is OFH prefix + */ + SAI_ATTR_VALUE_TYPE_OFH_ADDR_AND_MASK, } sai_attr_value_type_t; /** diff --git a/meta/saisanitycheck.c b/meta/saisanitycheck.c index ae1d23b22..0634acce6 100644 --- a/meta/saisanitycheck.c +++ b/meta/saisanitycheck.c @@ -786,6 +786,7 @@ void check_attr_object_type_provided( case SAI_ATTR_VALUE_TYPE_POINTER: case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: case SAI_ATTR_VALUE_TYPE_IP_PREFIX: + case SAI_ATTR_VALUE_TYPE_OFH_ADDR_AND_MASK: case SAI_ATTR_VALUE_TYPE_PRBS_RX_STATE: case SAI_ATTR_VALUE_TYPE_CHARDATA: case SAI_ATTR_VALUE_TYPE_UINT32_RANGE: @@ -1077,6 +1078,7 @@ void check_attr_default_required( case SAI_ATTR_VALUE_TYPE_MAC: case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: case SAI_ATTR_VALUE_TYPE_IP_PREFIX: + case SAI_ATTR_VALUE_TYPE_OFH_ADDR_AND_MASK: case SAI_ATTR_VALUE_TYPE_PRBS_RX_STATE: case SAI_ATTR_VALUE_TYPE_TIMESPEC: case SAI_ATTR_VALUE_TYPE_IPV4: @@ -3044,6 +3046,7 @@ void check_attr_is_primitive( case SAI_ATTR_VALUE_TYPE_INT8: case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: case SAI_ATTR_VALUE_TYPE_IP_PREFIX: + case SAI_ATTR_VALUE_TYPE_OFH_ADDR_AND_MASK: case SAI_ATTR_VALUE_TYPE_PRBS_RX_STATE: case SAI_ATTR_VALUE_TYPE_MAC: case SAI_ATTR_VALUE_TYPE_OBJECT_ID: @@ -4030,6 +4033,7 @@ void check_non_object_id_object_types() case SAI_ATTR_VALUE_TYPE_UINT32_RANGE: case SAI_ATTR_VALUE_TYPE_IP_ADDRESS: case SAI_ATTR_VALUE_TYPE_IP_PREFIX: + case SAI_ATTR_VALUE_TYPE_OFH_ADDR_AND_MASK: case SAI_ATTR_VALUE_TYPE_OBJECT_ID: case SAI_ATTR_VALUE_TYPE_NAT_ENTRY_DATA: case SAI_ATTR_VALUE_TYPE_ENCRYPT_KEY: diff --git a/meta/templates/sai_rpc_server_helper_functions.tt b/meta/templates/sai_rpc_server_helper_functions.tt index 7ea24b063..1ca1ad545 100644 --- a/meta/templates/sai_rpc_server_helper_functions.tt +++ b/meta/templates/sai_rpc_server_helper_functions.tt @@ -122,7 +122,7 @@ void sai_thrift_parse_[% struct.short_name %](const [% struct.thrift_name %] &th #ifdef UNSUPPORTED /* complex struct members are not supported yet */ [%- END -%] - [% struct.short_name %]->[% member.name %] = thrift_[% struct.short_name %].[% member.name %]; + [% struct.short_name %]->[% member.name %] = static_cast<[% member.type.name %]>(thrift_[% struct.short_name %].[% member.name %]); [%- IF member.type.thrift_name.match(unsupported_fields) -%] #endif diff --git a/meta/xmlutils.pm b/meta/xmlutils.pm index 2aa8c0f6a..de722b0ac 100644 --- a/meta/xmlutils.pm +++ b/meta/xmlutils.pm @@ -568,6 +568,109 @@ sub ExtractStructInfoEx return %Struct; } +sub NeedsTwoPassProcessing +{ + # + # Detect if XML files require two-pass processing based on their structure. + # + # In Doxygen 1.9.8+, the XML structure changed: + # - sai_*.xml files have empty enum/define sections (just sectiondef exists, no memberdefs) + # - group_*.xml files contain the actual enum definitions with enumvalues and defines + # + # In older Doxygen versions: + # - sai_*.xml files contain both defines and enums with enumvalues + # - group_*.xml files don't exist or aren't used + # + # Returns 1 if two-pass processing is needed (new structure): + # - First pass: process all defines from group_*.xml files + # - Second pass: process enums/typedefs/functions from group_*.xml and sai_*.xml files + # + # Returns 0 if single-pass processing is sufficient (old structure): + # - Process sai_*.xml files only + # + + my $XMLDIR = $main::XMLDIR; + + my $sai_file = "$XMLDIR/sai_8h.xml"; + + my $saiacl_file = "$XMLDIR/saiacl_8h.xml"; + + return 1 if not -f $sai_file or not -f $saiacl_file; + + # + # Check sai_8h.xml for enumvalue with name="SAI_API_SWITCH" + # + + my $sai_ref = ReadXml $sai_file; + + return 1 if not defined $sai_ref->{compounddef}[0]; + + my @sai_sections = @{ $sai_ref->{compounddef}[0]->{sectiondef} }; + + my $has_enumvalue = 0; + + for my $section (@sai_sections) + { + next if not $section->{kind} eq "enum"; + + for my $memberdef (@{ $section->{memberdef} }) + { + next if not $memberdef->{kind} eq "enum"; + + if (defined $memberdef->{enumvalue}) + { + for my $enumvalue (@{ $memberdef->{enumvalue} }) + { + if (defined $enumvalue->{name} and defined $enumvalue->{name}[0] and $enumvalue->{name}[0] eq "SAI_API_SWITCH") + { + $has_enumvalue = 1; + + last; + } + } + } + } + + last if $has_enumvalue; + } + + # + # Check saiacl_8h.xml for memberdef kind="define" + # + + my $saiacl_ref = ReadXml $saiacl_file; + + return 1 if not defined $saiacl_ref->{compounddef}[0]; + + my @saiacl_sections = @{ $saiacl_ref->{compounddef}[0]->{sectiondef} }; + + my $has_define = 0; + + for my $section (@saiacl_sections) + { + next if not $section->{kind} eq "define"; + + for my $memberdef (@{ $section->{memberdef} }) + { + if ($memberdef->{kind} eq "define") + { + $has_define = 1; + + last; + } + } + + last if $has_define; + } + + # + # If sai_8h.xml has enumvalues and saiacl_8h.xml has defines, it's old structure (single-pass) + # Otherwise, use two-pass processing (group_*.xml files contain the actual content) + # + + return not ($has_enumvalue and $has_define); +} + sub ExtractDescription { my ($type, $value, $item) = @_; @@ -636,6 +739,7 @@ BEGIN our @ISA = qw(Exporter); our @EXPORT = qw/ ReadXml UnescapeXml GetSaiXmlFiles GetXmlUnionFiles GetGroupXmlFiles + NeedsTwoPassProcessing ExtractDescription ExtractStructInfo ExtractStructInfoEx /; } From 582dac12a269bdaf7d8f6920e77e23afd126a262 Mon Sep 17 00:00:00 2001 From: JaiOCP Date: Fri, 29 May 2026 14:11:43 -0700 Subject: [PATCH 2/2] Merge Conflict Signed-off-by: JaiOCP --- inc/saiport.h | 1 - 1 file changed, 1 deletion(-) diff --git a/inc/saiport.h b/inc/saiport.h index 19dff5084..10a9e3b65 100644 --- a/inc/saiport.h +++ b/inc/saiport.h @@ -3338,7 +3338,6 @@ typedef enum _sai_port_attr_t SAI_PORT_ATTR_OFH, /** - * @brief End of attributes */ SAI_PORT_ATTR_END,