Skip to content

Commit

Permalink
SRv6 VPN enhancements (#1744)
Browse files Browse the repository at this point in the history
* SAI enhancements for SRV6 VPN.

Below are the list of enhancements added through this PR.

1. Disaggregation of VPN SID from underlay SID List by use of tunnel map.
2. Selection of underlay nexthop to use for a given SID list
3. L3VPN only solution, without the need to use SID List.
4. Allow prefix based derivation of VPN SID.
5. Ability for multiple prefixes to same destination but different VPN SID to share same NH/NHG using Prefix aggregation id.
6. Statistics collection on SID List
* Added missing SID list underlay specification.
* Update the VPN diagram to display segment list numbers.
---------

Signed-off-by: Ramesh Santhanakrishnan <rameshms@cisco.com>
  • Loading branch information
rameshms-work committed Mar 14, 2023
1 parent 9e01a14 commit 440f3c7
Show file tree
Hide file tree
Showing 13 changed files with 986 additions and 1 deletion.
674 changes: 674 additions & 0 deletions doc/SAI-IPv6-Segment-Routing-VPN.md

Large diffs are not rendered by default.

Binary file added doc/behavioral model/pipeline_v10.vsdx
Binary file not shown.
Binary file added doc/figures/SRv6_l3vpn_topology.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/figures/SRv6_topology.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
188 changes: 188 additions & 0 deletions doc/figures/sai_srv6_encap_model.gv
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
// SAI SRv6 Encap model Graphviz file
// To generate the diagram use below command:
// dot -Tpng sai_srv6_encap_model.gv -o sai_srv6_encap_model.png

digraph g {
fontname="Helvetica,Arial,sans-serif"
node [fontname="Helvetica,Arial,sans-serif"]
edge [fontname="Helvetica,Arial,sans-serif"]
graph [
rankdir = "LR"
];
node [
fontsize = "16"
];
edge [
];

subgraph cluster_vrf {
"VRF_a_route_table_label" [ label = <VRF-A Route table>
style = "filled,setlinewidth(5)"
fillcolor = "#91b5c9"
shape = box
width = 2.2
]

"Route_10_0_0_0" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD colspan="2" BGCOLOR="palegreen" PORT="title">SAI Route</TD></TR>
<tr><td>Prefix</td><td>10.0.0.0/8</td></tr>
<tr><td>VRF</td><td>VRF-A</td></tr>
<tr><td BGCOLOR="tomato">Prefix Agg ID</td><td BGCOLOR="tomato">10</td></tr>
<tr><td>Prefix</td><td port="nexthop">Overlay NHG1</td></tr>
</TABLE>
>
shape = plaintext
]
"Route_12_0_0_0" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD colspan="2" BGCOLOR="palegreen" PORT="title">SAI Route</TD></TR>
<tr><td>Prefix</td><td>12.0.0.0/8</td></tr>
<tr><td>VRF</td><td>VRF-A</td></tr>
<tr><td BGCOLOR="tomato">Prefix Agg ID</td><td BGCOLOR="tomato">20</td></tr>
<tr><td>Prefix</td><td port="nexthop">SRv6 NH1</td></tr>
</TABLE>
>
shape = plaintext
]
}

"Route_10_0_0_0":nexthop -> "l1_nhg1":ecmp_group
"Route_12_0_0_0":nexthop -> "srv6_nh1":nexthop

subgraph cluster_l1_ecmp {
// rank = same
label = <Overlay Next hop group>
"l1_nhg1" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD PORT="ecmp_group" BGCOLOR="palegreen">L1 ECMP Group</TD></TR>
<tr><td BGCOLOR="black"></td></tr>
<TR><TD BGCOLOR="skyblue" PORT="nh_mbr_id">NHG member list</TD></TR>
<tr><td port="nh2">SRv6 NH2</td></tr>
<tr><td port="nh1">SRv6 NH1</td></tr>
</TABLE>
>
shape = plaintext
]
}

subgraph cluster_srv6_nh {
rank = same
"srv6_nh1" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD PORT="nexthop" BGCOLOR="palegreen">SRv6 NH1</TD></TR>
<TR><TD>Nexthop OID</TD></TR>
<TR><TD PORT="tunnel">NODE_21 Tunnel OID</TD></TR>
<TR><TD PORT="sidlist">SIDList OID1</TD></TR>
</TABLE>
>
shape = plaintext
]

"srv6_nh2" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD PORT="nexthop" BGCOLOR="palegreen">SRv6 NH2</TD></TR>
<TR><TD>Nexthop OID</TD></TR>
<TR><TD PORT="tunnel">NODE_22 Tunnel OID</TD></TR>
<TR><TD PORT="sidlist">SIDList OID2</TD></TR>
</TABLE>
>
shape = plaintext
]
}

"l1_nhg1":nh1 -> "srv6_nh1":nexthop
"l1_nhg1":nh2 -> "srv6_nh2":nexthop
"srv6_nh1":tunnel -> "node21-tunnel":tunnel
"srv6_nh2":tunnel -> "node22-tunnel":tunnel

subgraph cluster_tunnel {
rank = same
"node21-tunnel" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD PORT="tunnel" BGCOLOR="palegreen">SAI Tunnel<br/>NODE_21 Endpoint</TD></TR>
<TR><TD>Tunnel OID</TD></TR>
<TR><TD PORT="mapper">Encap mapper</TD></TR>
<TR><TD>Encap SRC IP</TD></TR>
<TR><TD>Type = P2P</TD></TR>
<TR><TD>Encap DST IP</TD></TR>
</TABLE>
>
shape = plaintext
]
"node21-encap_mapper" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD colspan="2" PORT="mapper" BGCOLOR="palegreen">Encap Mapper</TD></TR>
<TR><TD colspan="2">Encap Mapper OID 1</TD></TR>
<tr><td colspan="2" BGCOLOR="black"></td></tr>
<TR><TD BGCOLOR="skyblue" colspan="3">PrefixID to VPNSID</TD></TR>
<TR><TD BGCOLOR="tomato">10</TD><TD PORT="sidlist1" BGCOLOR="tomato">VPN SID1</TD></TR>
<TR><TD BGCOLOR="tomato">20</TD><TD PORT="sidlist2" BGCOLOR="tomato">VPN SID2</TD></TR>
</TABLE>
>
shape = plaintext
]
"node21-tunnel":mapper -> "node21-encap_mapper":mapper

"node22-tunnel" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD PORT="tunnel" BGCOLOR="palegreen">SAI Tunnel<br/>NODE_22 Endpoint</TD></TR>
<TR><TD>Tunnel OID</TD></TR>
<TR><TD PORT="mapper">Encap mapper</TD></TR>
<TR><TD>Encap SRC IP</TD></TR>
<TR><TD>Encap DST IP</TD></TR>
</TABLE>
>
shape = plaintext
]
"node22-encap_mapper" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD colspan="2" PORT="mapper" BGCOLOR="palegreen">Encap Mapper</TD></TR>
<TR><TD colspan="2">Encap Mapper OID 2</TD></TR>
<tr><td colspan="2" BGCOLOR="black"></td></tr>
<TR><TD BGCOLOR="skyblue" colspan="3">PrefixID to VPNSID</TD></TR>
<TR><TD BGCOLOR="tomato">10</TD><TD PORT="sidlist1" BGCOLOR="tomato">VPN SID3</TD></TR>
</TABLE>
>
shape = plaintext
]
"node22-tunnel":mapper -> "node22-encap_mapper":mapper
}

subgraph sidlist_block {
label = <SID Lists>
rank = same

"SID_List1" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD colspan="2" BGCOLOR="palegreen" PORT="title">SAI SIDList 1</TD></TR>
<TR><TD>SID</TD><TD>IPv6 address list</TD></TR>
<TR><TD BGCOLOR="tomato">Underlay NH</TD><TD BGCOLOR="tomato">IP NH_OID</TD></TR>
</TABLE>
>
shape = plaintext
]
"SID_List2" [
label = <
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD colspan="2" BGCOLOR="palegreen" PORT="title">SAI SIDList 2</TD></TR>
<TR><TD>SID</TD><TD>IPv6 address list</TD></TR>
<TR><TD BGCOLOR="tomato">Underlay NH</TD><TD BGCOLOR="tomato">Unspecified</TD></TR>
</TABLE>
>
shape = plaintext
]
}
"srv6_nh1":sidlist -> "SID_List1":title
"srv6_nh2":sidlist -> "SID_List2":title
}
Binary file added doc/figures/sai_srv6_encap_model.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/figures/srv6_vpn_pipeline.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions inc/sainexthop.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ typedef enum _sai_next_hop_attr_t
* @type sai_object_id_t
* @flags MANDATORY_ON_CREATE | CREATE_ONLY
* @objects SAI_OBJECT_TYPE_SRV6_SIDLIST
* @allownull true
* @condition SAI_NEXT_HOP_ATTR_TYPE == SAI_NEXT_HOP_TYPE_SRV6_SIDLIST
*/
SAI_NEXT_HOP_ATTR_SRV6_SIDLIST_ID,
Expand Down
14 changes: 14 additions & 0 deletions inc/sairoute.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ typedef enum _sai_route_entry_attr_t
*/
SAI_ROUTE_ENTRY_ATTR_COUNTER_ID,

/**
* @brief Route Prefix Aggregation ID
*
* Prefix aggregation ID is used for SRV6 VPN cases. When multiple prefixes
* use the same set of remote SRV6 Endpoint(s) but with different VPN SID
* values, prefix aggregation id allows SAI to derive different VPN SID while
* keeping using single destination (NH or Next hop group)
*
* @type sai_uint32_t
* @flags CREATE_AND_SET
* @default 0
*/
SAI_ROUTE_ENTRY_ATTR_PREFIX_AGG_ID,

/**
* @brief End of attributes
*/
Expand Down
75 changes: 75 additions & 0 deletions inc/saisrv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,17 @@ typedef enum _sai_srv6_sidlist_attr_t
*/
SAI_SRV6_SIDLIST_ATTR_SEGMENT_LIST,

/**
* @brief Underlay Next hop to use
*
* @type sai_object_id_t
* @flags CREATE_AND_SET
* @objects SAI_OBJECT_TYPE_NEXT_HOP
* @allownull true
* @default SAI_NULL_OBJECT_ID
*/
SAI_SRV6_SIDLIST_ATTR_NEXT_HOP_ID,

/**
* @brief End of attributes
*/
Expand All @@ -189,6 +200,18 @@ typedef enum _sai_srv6_sidlist_attr_t
SAI_SRV6_SIDLIST_ATTR_CUSTOM_RANGE_END
} sai_srv6_sidlist_attr_t;

/**
* @brief SRV6 SID List counter IDs
*/
typedef enum _sai_srv6_sidlist_stat_t
{
/** Egress packet stat count */
SAI_SRV6_SIDLIST_STAT_OUT_PACKETS,

/** Egress byte stat count */
SAI_SRV6_SIDLIST_STAT_OUT_OCTETS,
} sai_srv6_sidlist_stat_t;

/**
* @brief Create Segment ID List
*
Expand Down Expand Up @@ -241,6 +264,54 @@ typedef sai_status_t (*sai_get_srv6_sidlist_attribute_fn)(
_In_ uint32_t attr_count,
_Inout_ sai_attribute_t *attr_list);

/**
* @brief Get SRV6 SID List statistics counters. Deprecated for backward compatibility.
*
* @param[in] srv6_sidlist_id SRV6 SID List id
* @param[in] number_of_counters Number of counters in the array
* @param[in] counter_ids Specifies the array of counter ids
* @param[out] counters Array of resulting counter values.
*
* @return #SAI_STATUS_SUCCESS on success, failure status code on error
*/
typedef sai_status_t (*sai_get_srv6_sidlist_stats_fn)(
_In_ sai_object_id_t srv6_sidlist_id,
_In_ uint32_t number_of_counters,
_In_ const sai_stat_id_t *counter_ids,
_Out_ uint64_t *counters);

/**
* @brief Get SRV6 SID List statistics counters extended.
*
* @param[in] srv6_sidlist_id SRV6 SID List id
* @param[in] number_of_counters Number of counters in the array
* @param[in] counter_ids Specifies the array of counter ids
* @param[in] mode Statistics mode
* @param[out] counters Array of resulting counter values.
*
* @return #SAI_STATUS_SUCCESS on success, failure status code on error
*/
typedef sai_status_t (*sai_get_srv6_sidlist_stats_ext_fn)(
_In_ sai_object_id_t srv6_sidlist_id,
_In_ uint32_t number_of_counters,
_In_ const sai_stat_id_t *counter_ids,
_In_ sai_stats_mode_t mode,
_Out_ uint64_t *counters);

/**
* @brief Clear SRV6 SID List statistics counters.
*
* @param[in] srv6_sidlist_id SRV6 SID List id
* @param[in] number_of_counters Number of counters in the array
* @param[in] counter_ids Specifies the array of counter ids
*
* @return #SAI_STATUS_SUCCESS on success, failure status code on error
*/
typedef sai_status_t (*sai_clear_srv6_sidlist_stats_fn)(
_In_ sai_object_id_t srv6_sidlist_id,
_In_ uint32_t number_of_counters,
_In_ const sai_stat_id_t *counter_ids);

/**
* @brief Attribute list for My SID
*/
Expand Down Expand Up @@ -549,6 +620,10 @@ typedef struct _sai_srv6_api_t
sai_bulk_object_create_fn create_srv6_sidlists;
sai_bulk_object_remove_fn remove_srv6_sidlists;

sai_get_srv6_sidlist_stats_fn get_srv6_sidlist_stats;
sai_get_srv6_sidlist_stats_ext_fn get_srv6_sidlist_stats_ext;
sai_clear_srv6_sidlist_stats_fn clear_srv6_sidlist_stats;

sai_create_my_sid_entry_fn create_my_sid_entry;
sai_remove_my_sid_entry_fn remove_my_sid_entry;
sai_set_my_sid_entry_attribute_fn set_my_sid_entry_attribute;
Expand Down
26 changes: 25 additions & 1 deletion inc/saitunnel.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ typedef enum _sai_tunnel_map_type_t
/** TUNNEL Map Bridge IF to VSID */
SAI_TUNNEL_MAP_TYPE_BRIDGE_IF_TO_VSID = 0x0000000b,

/** TUNNEL Map Virtual Router ID to SRV6 VPN SID */
SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VPN_SID = 0x0000000c,

/** TUNNEL Map Prefix Aggregation ID to SRV6 VPN SID */
SAI_TUNNEL_MAP_TYPE_PREFIX_AGG_ID_TO_SRV6_VPN_SID = 0x0000000d,

/** Custom range base value */
SAI_TUNNEL_MAP_TYPE_CUSTOM_RANGE_BASE = 0x10000000

Expand Down Expand Up @@ -203,7 +209,7 @@ typedef enum _sai_tunnel_map_entry_attr_t
* @type sai_object_id_t
* @flags MANDATORY_ON_CREATE | CREATE_ONLY
* @objects SAI_OBJECT_TYPE_VIRTUAL_ROUTER
* @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VNI
* @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VNI or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VPN_SID
*/
SAI_TUNNEL_MAP_ENTRY_ATTR_VIRTUAL_ROUTER_ID_KEY = 0x0000000c,

Expand Down Expand Up @@ -235,6 +241,24 @@ typedef enum _sai_tunnel_map_entry_attr_t
*/
SAI_TUNNEL_MAP_ENTRY_ATTR_VSID_ID_VALUE = 0x0000000f,

/**
* @brief Prefix Aggregation ID key
*
* @type sai_uint32_t
* @flags MANDATORY_ON_CREATE | CREATE_ONLY
* @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_PREFIX_AGG_ID_TO_SRV6_VPN_SID
*/
SAI_TUNNEL_MAP_ENTRY_ATTR_PREFIX_AGG_ID_KEY = 0x00000010,

/**
* @brief SRV6 VPN SID
*
* @type sai_ip6_t
* @flags MANDATORY_ON_CREATE | CREATE_ONLY
* @condition SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_PREFIX_AGG_ID_TO_SRV6_VPN_SID or SAI_TUNNEL_MAP_ENTRY_ATTR_TUNNEL_MAP_TYPE == SAI_TUNNEL_MAP_TYPE_VIRTUAL_ROUTER_ID_TO_VPN_SID
*/
SAI_TUNNEL_MAP_ENTRY_ATTR_SRV6_VPN_SID_VALUE = 0x00000011,

/**
* @brief End of attributes
*/
Expand Down
1 change: 1 addition & 0 deletions meta/acronyms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ USXGMII - Universal Serial 10 Gigabit Media Independent Interface
VNI - Virtual Network Interface
VNID - Virtual Network Identifier
VOQ - Virtual Output Queue
VPN - Virtual Private Network
VR - Virtual Router
VRF - Virtual Route Forwarding
VRRP - Virtual Router Redundancy Protocol
Expand Down
8 changes: 8 additions & 0 deletions meta/saisanitycheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -3840,6 +3840,14 @@ void check_objects_for_loops_recursive(

/* skip known loops */

if (m->objecttype == SAI_OBJECT_TYPE_SRV6_SIDLIST)
{
if (m->attrid == SAI_SRV6_SIDLIST_ATTR_NEXT_HOP_ID)
{
continue;
}
}

if (m->objecttype == SAI_OBJECT_TYPE_PORT)
{
if (m->attrid == SAI_PORT_ATTR_EGRESS_MIRROR_SESSION ||
Expand Down

0 comments on commit 440f3c7

Please sign in to comment.