Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class-Based Forwarding #1193

Merged
merged 20 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions doc/ECMP/Class-Based-Forwarding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
# 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 proposed:

```
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 directly chooses next-hop group member index.

This is accomplished by mapping each forwarding-class to the group member index.

```
/**
* @brief Forwarding-class to index map
*
* @type sai_map_list_t
* @flags CREATE_AND_SET
* @default empty
* @validonly SAI_NEXT_HOP_GROUP_ATTR_TYPE == SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED
*/
SAI_NEXT_HOP_GROUP_ATTR_FORWARDING_CLASS_TO_INDEX_MAP,
```
j-bos marked this conversation as resolved.
Show resolved Hide resolved

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:

<pre><code> /**
* @brief Next hop id
*
* @type sai_object_id_t
* @flags MANDATORY_ON_CREATE | CREATE_AND_SET
* @objects SAI_OBJECT_TYPE_NEXT_HOP, <b>SAI_OBJECT_TYPE_NEXT_HOP_GROUP</b>
*/
SAI_NEXT_HOP_GROUP_MEMBER_ATTR_NEXT_HOP_ID,
</code></pre>

*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;
```

j-bos marked this conversation as resolved.
Show resolved Hide resolved
In the event a packet is not assigned a forwarding-class, for example, a qos-map or ACL is not configured, then the forwarding-class of the packet shall be 0.

*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_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;

/*****************************************************
* Create a class-based forwarding group
*****************************************************/
sai_object_id_t nh_group;

attr.id = SAI_NEXT_HOP_GROUP_ATTR_TYPE;
attr.value.oid = SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED;
attrs.push_back(attr);

attr.id = SAI_NEXT_HOP_GROUP_ATTR_CONFIGURED_SIZE;
attr.value.oid = num_forwarding_classes;
attrs.push_back(attr);

attr.id = SAI_NEXT_HOP_GROUP_ATTR_FORWARDING_CLASS_TO_INDEX_MAP;
attr.value.maplist = fc_map_list;
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 object allowed
attrs.push_back(attr);

attr.id = SAI_NEXT_HOP_GROUP_MEMBER_ATTR_INDEX;
attr.value.oid = i;
attrs.push_back(attr);

sai_next_hop_group_api->create_next_hop_group_member(
&members[i],
g_switch_id,
attrs.size(),
attrs.data());
}
```
Binary file added doc/behavioral model/pipeline_v9.vsdx
Binary file not shown.
16 changes: 14 additions & 2 deletions inc/saiacl.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,10 @@ typedef enum _sai_acl_action_type_t
SAI_ACL_ACTION_TYPE_SET_ECMP_HASH_ID,

/** Associate with virtual router */
SAI_ACL_ACTION_TYPE_SET_VRF
SAI_ACL_ACTION_TYPE_SET_VRF,

/** Set Forwarding class */
SAI_ACL_ACTION_TYPE_SET_FORWARDING_CLASS,

} sai_acl_action_type_t;

Expand Down Expand Up @@ -2922,10 +2925,19 @@ typedef enum _sai_acl_entry_attr_t
*/
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_VRF,
SAI_ACL_ENTRY_ATTR_ACTION_END = SAI_ACL_ENTRY_ATTR_ACTION_SET_FORWARDING_CLASS,

/**
* @brief End of ACL Entry attributes
Expand Down
124 changes: 120 additions & 4 deletions inc/sainexthopgroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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,

Expand Down Expand Up @@ -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
j-bos marked this conversation as resolved.
Show resolved Hide resolved
* or SAI_NEXT_HOP_GROUP_TYPE_CLASS_BASED.
*
* @type sai_uint32_t
* @flags CREATE_ONLY
Expand Down Expand Up @@ -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
*/
j-bos marked this conversation as resolved.
Show resolved Hide resolved
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
*
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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()
*/
Expand All @@ -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;

/**
Expand Down
Loading