diff --git a/doc/ECMP/Class-Based-Forwarding.md b/doc/ECMP/Class-Based-Forwarding.md new file mode 100644 index 000000000..3aff85403 --- /dev/null +++ b/doc/ECMP/Class-Based-Forwarding.md @@ -0,0 +1,204 @@ +# 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 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. + +*Resource monitoring considerations:* + +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 may be a limited 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, a simple 1:1 mapping is configured. + ******************************************************/ + const int num_forwarding_classes = 8; + + sai_object_id_t nh_group_map; + + sai_map_t fc_map[num_forwarding_classes]; + for (int i = 0; i < num_forwarding_classes; ++i) { + fc_map[i].key = i; + fc_map[i].value = i; + } + + sai_map_list_t fc_map_list; + fc_map_list.key.count = num_forwarding_classes; + fc_map_list.key.list = fc_map; + + attr.type = 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_forwarding_classes; + 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 (i = 0; i < size; ++i) { + 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[i]; // Next-hop or ECMP group + attrs.push_back(attr); + + attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX; + attr.value.u32 = i; + attrs.push_back(attr); + + sai_next_hop_group_api->create_next_hop_group_member( + &members[i], + g_switch_id, + attrs.size(), + attrs.data()); + } + ``` diff --git a/inc/saiacl.h b/inc/saiacl.h index 9c3a37fa7..a6553bb87 100644 --- a/inc/saiacl.h +++ b/inc/saiacl.h @@ -271,6 +271,12 @@ typedef enum _sai_acl_action_type_t /** Set custom ECMP hash object ID */ SAI_ACL_ACTION_TYPE_SET_ECMP_HASH_ID, + /** Associate with virtual router */ + SAI_ACL_ACTION_TYPE_SET_VRF, + + /** Set Forwarding class */ + SAI_ACL_ACTION_TYPE_SET_FORWARDING_CLASS, + } sai_acl_action_type_t; /** @@ -2909,10 +2915,29 @@ typedef enum _sai_acl_entry_attr_t */ SAI_ACL_ENTRY_ATTR_ACTION_SET_ECMP_HASH_ID, + /** + * @brief Set virtual router + * + * @type sai_acl_action_data_t sai_object_id_t + * @flags CREATE_AND_SET + * @objects SAI_OBJECT_TYPE_VIRTUAL_ROUTER + * @default disabled + */ + SAI_ACL_ENTRY_ATTR_ACTION_SET_VRF, + + /** + * @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, + /** * @brief End of Rule Actions */ - SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_SET_ECMP_HASH_ID, + SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_SET_FORWARDING_CLASS, /** * @brief End of ACL Entry attributes diff --git a/inc/saihostif.h b/inc/saihostif.h index 99e95714f..f8eeed703 100644 --- a/inc/saihostif.h +++ b/inc/saihostif.h @@ -322,6 +322,9 @@ typedef enum _sai_hostif_trap_type_t /** Default packet action is forward */ SAI_HOSTIF_TRAP_TYPE_IPV6_NEIGHBOR_ADVERTISEMENT = 0x00002013, + /** Default packet action is forward */ + SAI_HOSTIF_TRAP_TYPE_ISIS = 0x00002014, + /** Router traps custom range start */ SAI_HOSTIF_TRAP_TYPE_ROUTER_CUSTOM_RANGE_BASE = 0x00003000, diff --git a/inc/saimpls.h b/inc/saimpls.h index f103fd1ea..eb17c4057 100644 --- a/inc/saimpls.h +++ b/inc/saimpls.h @@ -281,6 +281,98 @@ typedef sai_status_t (*sai_get_inseg_entry_attribute_fn)( _In_ uint32_t attr_count, _Inout_ sai_attribute_t *attr_list); +/** + * @brief Bulk create In Segment entry + * + * @param[in] object_count Number of objects to create + * @param[in] inseg_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_inseg_entry_fn)( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_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 In Segment entry + * + * @param[in] object_count Number of objects to remove + * @param[in] inseg_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_inseg_entry_fn)( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_entry, + _In_ sai_bulk_op_error_mode_t mode, + _Out_ sai_status_t *object_statuses); + +/** + * @brief Bulk set attribute on In Segment entry + * + * @param[in] object_count Number of objects to set attribute + * @param[in] inseg_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_inseg_entry_attribute_fn)( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_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 In Segment entry + * + * @param[in] object_count Number of objects to set attribute + * @param[in] inseg_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_inseg_entry_attribute_fn)( + _In_ uint32_t object_count, + _In_ const sai_inseg_entry_t *inseg_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 MPLS methods table retrieved with sai_api_query() */ @@ -291,6 +383,11 @@ typedef struct _sai_mpls_api_t sai_set_inseg_entry_attribute_fn set_inseg_entry_attribute; sai_get_inseg_entry_attribute_fn get_inseg_entry_attribute; + sai_bulk_create_inseg_entry_fn create_inseg_entries; + sai_bulk_remove_inseg_entry_fn remove_inseg_entries; + sai_bulk_set_inseg_entry_attribute_fn set_inseg_entries_attribute; + sai_bulk_get_inseg_entry_attribute_fn get_inseg_entries_attribute; + } sai_mpls_api_t; /** diff --git a/inc/sainexthopgroup.h b/inc/sainexthopgroup.h index 9bd0aca51..ca77d7b2a 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; @@ -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 854b1f107..446167530 100644 --- a/inc/saiport.h +++ b/inc/saiport.h @@ -1707,6 +1707,34 @@ typedef enum _sai_port_attr_t */ SAI_PORT_ATTR_SYSTEM_PORT, + /** + * @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/sairouterinterface.h b/inc/sairouterinterface.h index 0b4cd918e..1d71d488e 100644 --- a/inc/sairouterinterface.h +++ b/inc/sairouterinterface.h @@ -285,6 +285,15 @@ typedef enum _sai_router_interface_attr_t */ SAI_ROUTER_INTERFACE_ATTR_DISABLE_DECREMENT_TTL, + /** + * @brief Admin MPLS state + * + * @type bool + * @flags CREATE_AND_SET + * @default false + */ + SAI_ROUTER_INTERFACE_ATTR_ADMIN_MPLS_STATE, + /** * @brief End of attributes */ diff --git a/inc/saiswitch.h b/inc/saiswitch.h index 0a358d081..2df490b60 100644 --- a/inc/saiswitch.h +++ b/inc/saiswitch.h @@ -1350,7 +1350,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 @@ -2265,6 +2265,42 @@ typedef enum _sai_switch_attr_t */ SAI_SWITCH_ATTR_TUNNEL_LOOPBACK_PACKET_ACTION, + /** + * @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 24d7f1d10..8ae67484b 100644 --- a/inc/saitypes.h +++ b/inc/saitypes.h @@ -277,6 +277,7 @@ typedef enum _sai_object_type_t SAI_OBJECT_TYPE_MACSEC_SA = 92, SAI_OBJECT_TYPE_SYSTEM_PORT = 93, SAI_OBJECT_TYPE_FINE_GRAINED_HASH_FIELD = 94, + SAI_OBJECT_TYPE_NEXT_HOP_GROUP_MAP = 95, SAI_OBJECT_TYPE_MAX, /* Must remain in last position */ } sai_object_type_t; @@ -624,6 +625,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. @@ -657,6 +659,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/saiserializetest.c b/meta/saiserializetest.c index f3fe246df..ddec80d1a 100644 --- a/meta/saiserializetest.c +++ b/meta/saiserializetest.c @@ -464,9 +464,9 @@ void test_serialize_enum() ASSERT_STR_EQ(buf, "-1", res); - res = sai_serialize_enum(buf, &sai_metadata_enum_sai_object_type_t, 100); + res = sai_serialize_enum(buf, &sai_metadata_enum_sai_object_type_t, 200); - ASSERT_STR_EQ(buf, "100", res); + ASSERT_STR_EQ(buf, "200", res); /* test all enums */ @@ -510,9 +510,9 @@ void test_deserialize_enum() ASSERT_TRUE(res == strlen("-1"), "expected true"); ASSERT_TRUE(value == -1, "expected true, value = %d", value); - res = sai_deserialize_enum("100", &sai_metadata_enum_sai_object_type_t, &value); - ASSERT_TRUE(res == strlen("100"), "expected true"); - ASSERT_TRUE(value == 100, "expected true"); + res = sai_deserialize_enum("200", &sai_metadata_enum_sai_object_type_t, &value); + ASSERT_TRUE(res == strlen("200"), "expected true"); + ASSERT_TRUE(value == 200, "expected true"); /* test all enums */ diff --git a/test/saithrift/Makefile b/test/saithrift/Makefile index 2af7288bd..516d8b165 100644 --- a/test/saithrift/Makefile +++ b/test/saithrift/Makefile @@ -32,7 +32,12 @@ CTYPESGEN = /usr/local/bin/ctypesgen else CTYPESGEN = /usr/local/bin/ctypesgen.py endif -LIBS = -lthrift -lpthread -lsai +LIBS = -lthrift -lpthread +ifeq ($(platform),vs) +LIBS += -lsaivs -lsaimeta -lsaimetadata +else +LIBS += -lsai +endif SAI_LIBRARY_DIR ?= $(SAI_PREFIX)/lib LDFLAGS = -L$(SAI_LIBRARY_DIR) -Wl,-rpath=$(SAI_LIBRARY_DIR) CPP_SOURCES = \