diff --git a/doc/ECMP/Class-Based-Forwarding.md b/doc/ECMP/Class-Based-Forwarding.md new file mode 100644 index 000000000..5fca941dd --- /dev/null +++ b/doc/ECMP/Class-Based-Forwarding.md @@ -0,0 +1,211 @@ +# Class-based Forwarding + +Title | Class-based Forwarding +------------|---------------- +Authors | Cisco +Status | In review +Type | Standards track +Created | 04/14/2021 +SAI-Version | 1.8 + +Class-based forwarding provides a method to steer traffic among multiple paths through the network by policy rather than, or in combination with, traditional ECMP/UCMP flow-hashing. + +A new type of next-hop group is introduced: + +``` +typedef enum _sai_next_hop_group_type_t +{ +... + /** Next hop group is class-based, with members selected by Forwarding class */ + SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED, +... +} sai_next_hop_group_type_t; +``` + +The behavior of SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED differs from the traditional SAI_NEXT_HOP_GROUP_TYPE_ECMP, in that each packet will have a Forwarding class that chooses next-hop group member index. + +This is accomplished by directly mapping each forwarding class to the group member index, via map configured to the next-hop group object. + +``` + /** + * @brief Member selection map + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP + * @allownull true + * @default SAI_NULL_OBJECT_ID + * @validonly SAI_NEXT_HOP_GROUP_ATTR_TYPE == SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED + */ + SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP, +``` + +If a packet arrives with a forwarding-class which is not present in the map, the chosen index shall be 0. + +``` +typedef enum _sai_next_hop_group_member_attr_t +{ +... + /** + * @brief Object index in the next-hop group. + * + * Index specifying the strict member's order. + * Allowed value range for is from 0 to SAI_NEXT_HOP_GROUP_ATTR_REAL_SIZE - 1. + * Should only be used if the type of owning group is SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP + * or SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED. + * + * @type sai_uint32_t + * @flags CREATE_ONLY + * @default 0 + */ + SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX, +... +} sai_next_hop_group_member_attr_t; +``` + +If the map selects an index for which a member does not exist, the packet shall be treated as having a next-hop of SAI_NULL_OBJECT_ID, dropping the packet. + +Members of type next-hop or next-hop groups of type ECMP shall be allowed. To allow this, next-hop group member type is extended to allow other next-hop groups: + +``` + /** + * @brief Next hop id + * + * @type sai_object_id_t + * @flags MANDATORY_ON_CREATE | CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP + */ + SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID, +``` + +*Note: While this would also be a means to configure a hierarchical ECMP, hierarchical ECMP is outside the scope of this proposal.* + +The forwarding-class for a packet may be selected via qos-map or ACL. + +``` +typedef enum _sai_qos_map_type_t +{ +... + /** QOS Map to set DSCP to Forwarding class */ + SAI_QOS_MAP_TYPE_DSCP_TO_FORWARDING_CLASS = 0x0000000d, + + /** QOS Map to set EXP to Forwarding class */ + SAI_QOS_MAP_TYPE_MPLS_EXP_TO_FORWARDING_CLASS = 0x0000000e, +... +} sai_qos_map_type_t; +``` + +``` +typedef enum _sai_acl_entry_attr_t +... + /** + * @brief Set Forwarding Class + * + * @type sai_acl_action_data_t sai_uint8_t + * @flags CREATE_AND_SET + * @default disabled + */ + SAI_ACL_ENTRY_ATTR_ACTION_SET_FORWARDING_CLASS, +... +} sai_acl_entry_attr_t; +``` + +If the packet is not assigned a forwarding-class, then the forwarding-class of the packet shall be 0. For example, if no qos-map or ACL is configured. Normal QOS/ACL precedence rules apply; if supported by the implementation, the ACL would override the QOS MAP decision. + +*Resource monitoring considerations:* + +The attribute SAI_SWITCH_ATTR_MAX_NUMBER_OF_FORWARDING_CLASSES may be used to identify the maximum forwarding-class allowed. + +The SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP object is a resource. The sai_object_type_get_availability() API may be used to query the maximum number of permitted maps. + +*Class-based forwarding group configuration example:* +``` +/****************************************************** + * Create a forwarding-class -> index map. + * In this example, map 8 forwarding-classes to 2 members. + * FC 0-5 -> index 0 + * FC 6-7 -> index 1 + ******************************************************/ + const int num_forwarding_classes = 8; + const int num_members = 2; + + sai_object_id_t nh_group_map; + + sai_map_t fc_map[num_forwarding_classes]; + for (int fc = 0; fc < num_forwarding_classes; ++fc) { + fc_map[fc].key = fc; + if (fc >= 6) { + fc_map[fc].value = 1; + } else { + fc_map[fc].value = 0; + } + } + + sai_map_list_t fc_map_list; + fc_map_list.key.count = num_forwarding_classes; + fc_map_list.key.list = fc_map; + + attr.id = SAI_NEXT_HOP_GROUP_MAP_ATTR_TYPE; + attr.value.u32 = SAI_NEXT_HOP_GROUP_MAP_TYPE_FORWARDING_CLASS_TO_INDEX; + attrs.push_back(attr); + + attr.id = SAI_NEXT_HOP_GROUP_MAP_ATTR_MAP_TO_VALUE_LIST; + attr.value.maplist = fc_map_list; + attrs.push_back(attr); + + sai_next_hop_group_api->create_next_hop_group_map( + &nh_group_map, + g_switch_id, + attrs.size(), + attrs.data()); + + /***************************************************** + * Create a class-based forwarding group + *****************************************************/ + attrs.clear(); + + sai_object_id_t nh_group; + + attr.id = SAI_NEXT_HOP_GROUP_ATTR_TYPE; + attr.value.u32 = SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED; + attrs.push_back(attr); + + attr.id = SAI_NEXT_HOP_GROUP_ATTR_CONFIGURED_SIZE; + attr.value.u32 = num_members; + attrs.push_back(attr); + + attr.id = SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP; + attr.value.oid = nh_group_map; + attrs.push_back(attr); + + sai_next_hop_group_api->create_next_hop_group( + &nh_group, + g_switch_id, + attrs.size(), + attrs.data()); + + /***************************************************** + * Create members + *****************************************************/ + attrs.clear(); + + for (index = 0; index < num_members; ++index) { + attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_GROUP_ID; + attr.value.oid = nh_group; + attrs.push_back(attr); + + attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID; + attr.value.oid = destinations[index]; // Next-hop or ECMP group + attrs.push_back(attr); + + attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX; + attr.value.u32 = index; + attrs.push_back(attr); + + sai_next_hop_group_api->create_next_hop_group_member( + &members[member_index], + g_switch_id, + attrs.size(), + attrs.data()); + } +``` diff --git a/doc/behavioral model/pipeline_v9.vsdx b/doc/behavioral model/pipeline_v9.vsdx new file mode 100644 index 000000000..d10a59731 Binary files /dev/null and b/doc/behavioral model/pipeline_v9.vsdx differ diff --git a/inc/saiacl.h b/inc/saiacl.h index b998f6170..ece8e6c2d 100644 --- a/inc/saiacl.h +++ b/inc/saiacl.h @@ -272,7 +272,10 @@ typedef enum _sai_acl_action_type_t SAI_ACL_ACTION_TYPE_SET_ECMP_HASH_ID = 0x00000030, /** Associate with virtual router */ - SAI_ACL_ACTION_TYPE_SET_VRF = 0x00000031 + SAI_ACL_ACTION_TYPE_SET_VRF = 0x00000031, + + /** Set Forwarding class */ + SAI_ACL_ACTION_TYPE_SET_FORWARDING_CLASS = 0x00000034, } sai_acl_action_type_t; @@ -2922,10 +2925,19 @@ typedef enum _sai_acl_entry_attr_t */ SAI_ACL_ENTRY_ATTR_ACTION_SET_VRF = SAI_ACL_ENTRY_ATTR_ACTION_START + 0x31, + /** + * @brief Set Forwarding Class + * + * @type sai_acl_action_data_t sai_uint8_t + * @flags CREATE_AND_SET + * @default disabled + */ + SAI_ACL_ENTRY_ATTR_ACTION_SET_FORWARDING_CLASS = SAI_ACL_ENTRY_ATTR_ACTION_START + 0x34, + /** * @brief End of Rule Actions */ - SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_ADD_VLAN_PRI, + SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_SET_FORWARDING_CLASS, /** * @brief End of ACL Entry attributes diff --git a/inc/sainexthopgroup.h b/inc/sainexthopgroup.h index 99c5a4aef..a0782e3c3 100644 --- a/inc/sainexthopgroup.h +++ b/inc/sainexthopgroup.h @@ -53,6 +53,9 @@ typedef enum _sai_next_hop_group_type_t /** Next hop protection group. Contains primary and backup next hops. */ SAI_NEXT_HOP_GROUP_TYPE_PROTECTION, + /** Next hop group is class-based, with members selected by Forwarding class */ + SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED, + /* Other types of next hop group to be defined in the future, e.g., WCMP */ } sai_next_hop_group_type_t; @@ -151,7 +154,7 @@ typedef enum _sai_next_hop_group_attr_t * @type sai_uint32_t * @flags CREATE_ONLY * @default 0 - * @validonly SAI_NEXT_HOP_GROUP_ATTR_TYPE == SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP + * @validonly SAI_NEXT_HOP_GROUP_ATTR_TYPE == SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP or SAI_NEXT_HOP_GROUP_ATTR_TYPE == SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED * @isresourcetype true */ SAI_NEXT_HOP_GROUP_ATTR_CONFIGURED_SIZE, @@ -169,6 +172,18 @@ typedef enum _sai_next_hop_group_attr_t */ SAI_NEXT_HOP_GROUP_ATTR_REAL_SIZE, + /** + * @brief Next hop group selection map + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP + * @allownull true + * @default SAI_NULL_OBJECT_ID + * @validonly SAI_NEXT_HOP_GROUP_ATTR_TYPE == SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED + */ + SAI_NEXT_HOP_GROUP_ATTR_SELECTION_MAP, + /** * @brief End of attributes */ @@ -203,7 +218,7 @@ typedef enum _sai_next_hop_group_member_attr_t * * @type sai_object_id_t * @flags MANDATORY_ON_CREATE | CREATE_AND_SET - * @objects SAI_OBJECT_TYPE_NEXT_HOP + * @objects SAI_OBJECT_TYPE_NEXT_HOP, SAI_OBJECT_TYPE_NEXT_HOP_GROUP */ SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID, @@ -263,7 +278,8 @@ typedef enum _sai_next_hop_group_member_attr_t * * Index specifying the strict member's order. * Allowed value range for is from 0 to SAI_NEXT_HOP_GROUP_ATTR_REAL_SIZE - 1. - * Should only be used if the type of owning group is SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP. + * Should only be used if the type of owning group is SAI_NEXT_HOP_GROUP_TYPE_FINE_GRAIN_ECMP + * or SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED. * * @type sai_uint32_t * @flags CREATE_ONLY @@ -311,6 +327,50 @@ typedef enum _sai_next_hop_group_member_attr_t } sai_next_hop_group_member_attr_t; +typedef enum _sai_next_hop_group_map_type_t +{ + /** Next hop group map forwarding-class to index */ + SAI_NEXT_HOP_GROUP_MAP_TYPE_FORWARDING_CLASS_TO_INDEX + +} sai_next_hop_group_map_type_t; + +typedef enum _sai_next_hop_group_map_attr_t +{ + /** + * @brief Start of attributes + */ + SAI_NEXT_HOP_GROUP_MAP_ATTR_START, + + /** + * @brief Next hop group map type + * + * @type sai_next_hop_group_map_type_t + * @flags MANDATORY_ON_CREATE | CREATE_ONLY + */ + SAI_NEXT_HOP_GROUP_MAP_ATTR_TYPE = SAI_NEXT_HOP_GROUP_MAP_ATTR_START, + + /** + * @brief Next hop group entries associated with this map. + * + * @type sai_map_list_t + * @flags CREATE_AND_SET + * @default empty + */ + SAI_NEXT_HOP_GROUP_MAP_ATTR_MAP_TO_VALUE_LIST, + + /** + * @brief End of attributes + */ + SAI_NEXT_HOP_GROUP_MAP_ATTR_END, + + /** Custom range base value */ + SAI_NEXT_HOP_GROUP_MAP_ATTR_CUSTOM_RANGE_START = 0x10000000, + + /** End of custom range base */ + SAI_NEXT_HOP_GROUP_MAP_ATTR_CUSTOM_RANGE_END + +} sai_next_hop_group_map_attr_t; + /** * @brief Create next hop group * @@ -390,7 +450,7 @@ typedef sai_status_t (*sai_remove_next_hop_group_member_fn)( _In_ sai_object_id_t next_hop_group_member_id); /** - * @brief Set Next Hop Group attribute + * @brief Set Next Hop Group member attribute * * @param[in] next_hop_group_member_id Next hop group member ID * @param[in] attr Attribute @@ -402,7 +462,7 @@ typedef sai_status_t (*sai_set_next_hop_group_member_attribute_fn)( _In_ const sai_attribute_t *attr); /** - * @brief Get Next Hop Group attribute + * @brief Get Next Hop Group member attribute * * @param[in] next_hop_group_member_id Next hop group member ID * @param[in] attr_count Number of attributes @@ -415,6 +475,58 @@ typedef sai_status_t (*sai_get_next_hop_group_member_attribute_fn)( _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); +/** + * @brief Create next hop group map + * + * @param[out] next_hop_group_map_id Next hop group map id + * @param[in] switch_id Switch 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_next_hop_group_map_fn)( + _Out_ sai_object_id_t *next_hop_group_map_id, + _In_ sai_object_id_t switch_id, + _In_ uint32_t attr_count, + _In_ const sai_attribute_t *attr_list); + +/** + * @brief Remove next hop group map + * + * @param[in] next_hop_group_map_id Next hop group map ID + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_remove_next_hop_group_map_fn)( + _In_ sai_object_id_t next_hop_group_map_id); + +/** + * @brief Set Next Hop Group map attribute + * + * @param[in] next_hop_group_map_id Next hop group map ID + * @param[in] attr Attribute + * + * @return #SAI_STATUS_SUCCESS on success, failure status code on error + */ +typedef sai_status_t (*sai_set_next_hop_group_map_attribute_fn)( + _In_ sai_object_id_t next_hop_group_map_id, + _In_ const sai_attribute_t *attr); + +/** + * @brief Get next hop group map attribute + * + * @param[in] next_hop_group_map_id Next hop group map 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_next_hop_group_map_attribute_fn)( + _In_ sai_object_id_t next_hop_group_map_id, + _In_ uint32_t attr_count, + _Inout_ sai_attribute_t *attr_list); + /** * @brief Next Hop methods table retrieved with sai_api_query() */ @@ -430,6 +542,10 @@ typedef struct _sai_next_hop_group_api_t sai_get_next_hop_group_member_attribute_fn get_next_hop_group_member_attribute; sai_bulk_object_create_fn create_next_hop_group_members; sai_bulk_object_remove_fn remove_next_hop_group_members; + sai_create_next_hop_group_map_fn create_next_hop_group_map; + sai_remove_next_hop_group_map_fn remove_next_hop_group_map; + sai_set_next_hop_group_map_attribute_fn set_next_hop_group_map_attribute; + sai_get_next_hop_group_map_attribute_fn get_next_hop_group_map_attribute; } sai_next_hop_group_api_t; /** diff --git a/inc/saiport.h b/inc/saiport.h index e3e0420c3..cd0ee7331 100644 --- a/inc/saiport.h +++ b/inc/saiport.h @@ -2004,6 +2004,34 @@ typedef enum _sai_port_attr_t */ SAI_PORT_ATTR_PRIORITY_FLOW_CONTROL_FORWARD, + /** + * @brief Enable DSCP -> Forwarding Class MAP on port + * + * Map id = #SAI_NULL_OBJECT_ID to disable map on port. + * Default no map. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_QOS_DSCP_TO_FORWARDING_CLASS_MAP, + + /** + * @brief Enable EXP -> Forwarding Class MAP on port + * + * Map id = #SAI_NULL_OBJECT_ID to disable map on port. + * Default no map. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_PORT_ATTR_QOS_MPLS_EXP_TO_FORWARDING_CLASS_MAP, + /** * @brief End of attributes */ diff --git a/inc/saiqosmap.h b/inc/saiqosmap.h index d723f1546..5b5d867e4 100644 --- a/inc/saiqosmap.h +++ b/inc/saiqosmap.h @@ -77,6 +77,12 @@ typedef enum _sai_qos_map_type_t /** QOS Map to set traffic class and color to EXP */ SAI_QOS_MAP_TYPE_TC_AND_COLOR_TO_MPLS_EXP = 0x0000000c, + /** QOS Map to set DSCP to Forwarding class */ + SAI_QOS_MAP_TYPE_DSCP_TO_FORWARDING_CLASS = 0x0000000d, + + /** QOS Map to set EXP to Forwarding class */ + SAI_QOS_MAP_TYPE_MPLS_EXP_TO_FORWARDING_CLASS = 0x0000000e, + /** Custom range base value */ SAI_QOS_MAP_TYPE_CUSTOM_RANGE_BASE = 0x10000000 diff --git a/inc/saiswitch.h b/inc/saiswitch.h index 362b838b7..7d8498519 100644 --- a/inc/saiswitch.h +++ b/inc/saiswitch.h @@ -1590,7 +1590,7 @@ typedef enum _sai_switch_attr_t * @brief Enable DSCP -> TC MAP on switch. * * MAP id = #SAI_NULL_OBJECT_ID to disable map on switch. - * To enable/disable trust DSCP, Map ID should be added/removed on port. + * To enable/disable trust DSCP, Map ID should be added/removed on switch. * Default no map. * * @type sai_object_id_t @@ -2616,6 +2616,42 @@ typedef enum _sai_switch_attr_t */ SAI_SWITCH_ATTR_AVAILABLE_MY_MAC_ENTRIES, + /** + * @brief Maximum forwarding classes limit + * + * @type sai_uint8_t + * @flags READ_ONLY + */ + SAI_SWITCH_ATTR_MAX_NUMBER_OF_FORWARDING_CLASSES, + + /** + * @brief Enable DSCP -> Forwarding Class MAP on switch + * + * MAP id = #SAI_NULL_OBJECT_ID to disable map on switch. + * Default no map. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_SWITCH_ATTR_QOS_DSCP_TO_FORWARDING_CLASS_MAP, + + /** + * @brief Enable EXP -> Forwarding Class MAP on switch + * + * MAP id = #SAI_NULL_OBJECT_ID to disable map on switch. + * Default no map. + * + * @type sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_QOS_MAP + * @allownull true + * @default SAI_NULL_OBJECT_ID + */ + SAI_SWITCH_ATTR_QOS_MPLS_EXP_TO_FORWARDING_CLASS_MAP, + /** * @brief End of attributes */ diff --git a/inc/saitypes.h b/inc/saitypes.h index 782a790b8..beba5e3b4 100644 --- a/inc/saitypes.h +++ b/inc/saitypes.h @@ -280,6 +280,7 @@ typedef enum _sai_object_type_t SAI_OBJECT_TYPE_SWITCH_TUNNEL = 95, SAI_OBJECT_TYPE_MY_SID_ENTRY = 96, SAI_OBJECT_TYPE_MY_MAC = 97, + SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP = 98, SAI_OBJECT_TYPE_MAX, /* Must remain in last position */ } sai_object_type_t; @@ -653,6 +654,7 @@ typedef enum _sai_packet_color_t * dot1p/DSCP/MPLS_EXP --> TC * dot1p/DSCP/MPLS_EXP --> Color * dot1p/DSCP/MPLS_EXP --> TC + Color + * DSCP/MPLS_EXP --> FC * TC --> dot1p/DSCP/MPLS_EXP. * TC + color --> dot1p/DSCP/MPLS_EXP. * TC --> Egress Queue. @@ -686,6 +688,9 @@ typedef struct _sai_qos_map_params_t /** MPLS exp value */ sai_uint8_t mpls_exp; + /** Forwarding class */ + sai_uint8_t fc; + } sai_qos_map_params_t; typedef struct _sai_qos_map_t diff --git a/meta/checkheaders.pl b/meta/checkheaders.pl index 16138d279..592f68733 100755 --- a/meta/checkheaders.pl +++ b/meta/checkheaders.pl @@ -190,6 +190,8 @@ sub CheckHash next if $key eq "SAI_ACL_TABLE_ATTR_FIELD_END"; next if $key eq "SAI_ACL_ENTRY_ATTR_FIELD_END"; next if $key eq "SAI_ACL_ENTRY_ATTR_ACTION_END"; + next if $key eq "SAI_OBJECT_TYPE_MAX"; + next if $key eq "SAI_API_MAX"; # NOTE: some other attributes/enum with END range could be added }