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/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/saiswitch.h b/inc/saiswitch.h index 64072c22c..0a86ed6e5 100644 --- a/inc/saiswitch.h +++ b/inc/saiswitch.h @@ -3561,6 +3561,15 @@ typedef enum _sai_switch_attr_t */ SAI_SWITCH_ATTR_LINK_UP_DEBOUNCE_TIMEOUT, + /** + * @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 Maximum number of timers supported for CSIG bandwidth signal * diff --git a/meta/parse.pl b/meta/parse.pl index 86c92a512..a378f110d 100755 --- a/meta/parse.pl +++ b/meta/parse.pl @@ -2695,6 +2695,7 @@ 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"; @@ -2743,7 +2744,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 +2768,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 +4173,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|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); @@ -5637,7 +5638,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/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