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

Update CBF code to fit new SAI API #1

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
204 changes: 204 additions & 0 deletions doc/ECMP/Class-Based-Forwarding.md
Original file line number Diff line number Diff line change
@@ -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, <b>SAI_OBJECT_TYPE_NEXT_HOP_GROUP</b>
*/
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());
}
```
27 changes: 26 additions & 1 deletion inc/saiacl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions inc/saihostif.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
97 changes: 97 additions & 0 deletions inc/saimpls.h
Original file line number Diff line number Diff line change
Expand Up @@ -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()
*/
Expand All @@ -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;

/**
Expand Down
Loading