mbox series

[net-next,v2,0/2] seg6: add NEXT-C-SID support for SRv6 End.X behavior

Message ID 20230812180926.16689-1-andrea.mayer@uniroma2.it
Headers show
Series seg6: add NEXT-C-SID support for SRv6 End.X behavior | expand

Message

Andrea Mayer Aug. 12, 2023, 6:09 p.m. UTC
In the Segment Routing (SR) architecture a list of instructions, called
segments, can be added to the packet headers to influence the forwarding and
processing of the packets in an SR enabled network.

Considering the Segment Routing over IPv6 data plane (SRv6) [1], the segment
identifiers (SIDs) are IPv6 addresses (128 bits) and the segment list (SID
List) is carried in the Segment Routing Header (SRH). A segment may correspond
to a "behavior" that is executed by a node when the packet is received.
The Linux kernel currently supports a large subset of the behaviors described
in [2] (e.g., End, End.X, End.T and so on).

In some SRv6 scenarios, the number of segments carried by the SID List may
increase dramatically, reducing the MTU (Maximum Transfer Unit) size and/or
limiting the processing power of legacy hardware devices (due to longer IPv6
headers).

The NEXT-C-SID mechanism [3] extends the SRv6 architecture by providing several
ways to efficiently represent the SID List.
By leveraging the NEXT-C-SID, it is possible to encode several SRv6 segments
within a single 128 bit SID address (also referenced as Compressed SID
Container). In this way, the length of the SID List can be drastically reduced.

The NEXT-C-SID mechanism is built upon the "flavors" framework defined in [2].
This framework is already supported by the Linux SRv6 subsystem and is used to
modify and/or extend a subset of existing behaviors.

In this patchset, we extend the SRv6 End.X behavior in order to support the
NEXT-C-SID mechanism.

In details, the patchset is made of:
 - patch 1/2: add NEXT-C-SID support for SRv6 End.X behavior;
 - patch 2/2: add selftest for NEXT-C-SID in SRv6 End.X behavior.

Comments

Hangbin Liu Aug. 14, 2023, 7:49 a.m. UTC | #1
On Sat, Aug 12, 2023 at 08:09:25PM +0200, Andrea Mayer wrote:
> The NEXT-C-SID mechanism described in [1] offers the possibility of
> encoding several SRv6 segments within a single 128 bit SID address. Such
> a SID address is called a Compressed SID (C-SID) container. In this way,
> the length of the SID List can be drastically reduced.
> 
> A SID instantiated with the NEXT-C-SID flavor considers an IPv6 address
> logically structured in three main blocks: i) Locator-Block; ii)
> Locator-Node Function; iii) Argument.
> 
>                         C-SID container
> +------------------------------------------------------------------+
> |     Locator-Block      |Loc-Node|            Argument            |
> |                        |Function|                                |
> +------------------------------------------------------------------+
> <--------- B -----------> <- NF -> <------------- A --------------->
> 
>    (i) The Locator-Block can be any IPv6 prefix available to the provider;
> 
>   (ii) The Locator-Node Function represents the node and the function to
>        be triggered when a packet is received on the node;
> 
>  (iii) The Argument carries the remaining C-SIDs in the current C-SID
>        container.
> 
> This patch leverages the NEXT-C-SID mechanism previously introduced in the
> Linux SRv6 subsystem [2] to support SID compression capabilities in the
> SRv6 End.X behavior [3].
> An SRv6 End.X behavior with NEXT-C-SID flavor works as an End.X behavior
> but it is capable of processing the compressed SID List encoded in C-SID
> containers.
> 
> An SRv6 End.X behavior with NEXT-C-SID flavor can be configured to support
> user-provided Locator-Block and Locator-Node Function lengths. In this
> implementation, such lengths must be evenly divisible by 8 (i.e. must be
> byte-aligned), otherwise the kernel informs the user about invalid
> values with a meaningful error code and message through netlink_ext_ack.
> 
> If Locator-Block and/or Locator-Node Function lengths are not provided
> by the user during configuration of an SRv6 End.X behavior instance with
> NEXT-C-SID flavor, the kernel will choose their default values i.e.,
> 32-bit Locator-Block and 16-bit Locator-Node Function.
> 
> [1] - https://datatracker.ietf.org/doc/html/draft-ietf-spring-srv6-srh-compression
> [2] - https://lore.kernel.org/all/20220912171619.16943-1-andrea.mayer@uniroma2.it/
> [3] - https://datatracker.ietf.org/doc/html/rfc8986#name-endx-l3-cross-connect
> 
> Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
> ---
>  net/ipv6/seg6_local.c | 108 ++++++++++++++++++++++++++++++++++--------
>  1 file changed, 88 insertions(+), 20 deletions(-)
> 
> diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
> index dd433cc265c8..24e2b4b494cb 100644
> --- a/net/ipv6/seg6_local.c
> +++ b/net/ipv6/seg6_local.c
> @@ -109,15 +109,19 @@ struct bpf_lwt_prog {
>  #define next_csid_chk_lcnode_fn_bits(flen)		\
>  	next_csid_chk_lcblock_bits(flen)
>  
> +/* flag indicating that flavors are set up for a given End* behavior */
> +#define SEG6_F_LOCAL_FLAVORS		SEG6_F_ATTR(SEG6_LOCAL_FLAVORS)
> +
>  #define SEG6_F_LOCAL_FLV_OP(flvname)	BIT(SEG6_LOCAL_FLV_OP_##flvname)
> +#define SEG6_F_LOCAL_FLV_NEXT_CSID	SEG6_F_LOCAL_FLV_OP(NEXT_CSID)
>  #define SEG6_F_LOCAL_FLV_PSP		SEG6_F_LOCAL_FLV_OP(PSP)
>  
>  /* Supported RFC8986 Flavor operations are reported in this bitmask */
>  #define SEG6_LOCAL_FLV8986_SUPP_OPS	SEG6_F_LOCAL_FLV_PSP
>  
> -/* Supported Flavor operations are reported in this bitmask */
> -#define SEG6_LOCAL_FLV_SUPP_OPS		(SEG6_F_LOCAL_FLV_OP(NEXT_CSID) | \
> +#define SEG6_LOCAL_END_FLV_SUPP_OPS	(SEG6_F_LOCAL_FLV_NEXT_CSID | \
>  					 SEG6_LOCAL_FLV8986_SUPP_OPS)
> +#define SEG6_LOCAL_END_X_FLV_SUPP_OPS	SEG6_F_LOCAL_FLV_NEXT_CSID
>  
>  struct seg6_flavors_info {
>  	/* Flavor operations */
> @@ -411,9 +415,72 @@ static int end_next_csid_core(struct sk_buff *skb, struct seg6_local_lwt *slwt)
>  	return input_action_end_finish(skb, slwt);
>  }
>  
> +static int input_action_end_x_finish(struct sk_buff *skb,
> +				     struct seg6_local_lwt *slwt)
> +{
> +	seg6_lookup_nexthop(skb, &slwt->nh6, 0);
> +
> +	return dst_input(skb);
> +}
> +
> +static int input_action_end_x_core(struct sk_buff *skb,
> +				   struct seg6_local_lwt *slwt)
> +{
> +	struct ipv6_sr_hdr *srh;
> +
> +	srh = get_and_validate_srh(skb);
> +	if (!srh)
> +		goto drop;
> +
> +	advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
> +
> +	return input_action_end_x_finish(skb, slwt);
> +
> +drop:
> +	kfree_skb(skb);
> +	return -EINVAL;
> +}
> +
> +static int end_x_next_csid_core(struct sk_buff *skb,
> +				struct seg6_local_lwt *slwt)
> +{
> +	const struct seg6_flavors_info *finfo = &slwt->flv_info;
> +	struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
> +
> +	if (seg6_next_csid_is_arg_zero(daddr, finfo))
> +		return input_action_end_x_core(skb, slwt);
> +
> +	/* update DA */
> +	seg6_next_csid_advance_arg(daddr, finfo);
> +
> +	return input_action_end_x_finish(skb, slwt);
> +}
> +
>  static bool seg6_next_csid_enabled(__u32 fops)
>  {
> -	return fops & BIT(SEG6_LOCAL_FLV_OP_NEXT_CSID);
> +	return fops & SEG6_F_LOCAL_FLV_NEXT_CSID;
> +}
> +
> +/* Processing of SRv6 End, End.X, and End.T behaviors can be extended through
> + * the flavors framework. These behaviors must report the subset of (flavor)
> + * operations they currently implement. In this way, if a user specifies a
> + * flavor combination that is not supported by a given End* behavior, the
> + * kernel refuses to instantiate the tunnel reporting the error.
> + */
> +static int seg6_flv_supp_ops_by_action(int action, __u32 *fops)
> +{
> +	switch (action) {
> +	case SEG6_LOCAL_ACTION_END:
> +		*fops = SEG6_LOCAL_END_FLV_SUPP_OPS;
> +		break;
> +	case SEG6_LOCAL_ACTION_END_X:
> +		*fops = SEG6_LOCAL_END_X_FLV_SUPP_OPS;
> +		break;
> +	default:
> +		return -EOPNOTSUPP;
> +	}
> +
> +	return 0;
>  }
>  
>  /* We describe the packet state in relation to the absence/presence of the SRH
> @@ -746,21 +813,14 @@ static int input_action_end(struct sk_buff *skb, struct seg6_local_lwt *slwt)
>  /* regular endpoint, and forward to specified nexthop */
>  static int input_action_end_x(struct sk_buff *skb, struct seg6_local_lwt *slwt)
>  {
> -	struct ipv6_sr_hdr *srh;
> -
> -	srh = get_and_validate_srh(skb);
> -	if (!srh)
> -		goto drop;
> -
> -	advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
> -
> -	seg6_lookup_nexthop(skb, &slwt->nh6, 0);
> +	const struct seg6_flavors_info *finfo = &slwt->flv_info;
> +	__u32 fops = finfo->flv_ops;
>  
> -	return dst_input(skb);
> +	/* check for the presence of NEXT-C-SID since it applies first */
> +	if (seg6_next_csid_enabled(fops))
> +		return end_x_next_csid_core(skb, slwt);
>  
> -drop:
> -	kfree_skb(skb);
> -	return -EINVAL;
> +	return input_action_end_x_core(skb, slwt);
>  }
>  
>  static int input_action_end_t(struct sk_buff *skb, struct seg6_local_lwt *slwt)
> @@ -1404,13 +1464,14 @@ static struct seg6_action_desc seg6_action_table[] = {
>  		.action		= SEG6_LOCAL_ACTION_END,
>  		.attrs		= 0,
>  		.optattrs	= SEG6_F_LOCAL_COUNTERS |
> -				  SEG6_F_ATTR(SEG6_LOCAL_FLAVORS),
> +				  SEG6_F_LOCAL_FLAVORS,
>  		.input		= input_action_end,
>  	},
>  	{
>  		.action		= SEG6_LOCAL_ACTION_END_X,
>  		.attrs		= SEG6_F_ATTR(SEG6_LOCAL_NH6),
> -		.optattrs	= SEG6_F_LOCAL_COUNTERS,
> +		.optattrs	= SEG6_F_LOCAL_COUNTERS |
> +				  SEG6_F_LOCAL_FLAVORS,
>  		.input		= input_action_end_x,
>  	},
>  	{
> @@ -2070,7 +2131,8 @@ static int parse_nla_flavors(struct nlattr **attrs, struct seg6_local_lwt *slwt,
>  {
>  	struct seg6_flavors_info *finfo = &slwt->flv_info;
>  	struct nlattr *tb[SEG6_LOCAL_FLV_MAX + 1];
> -	unsigned long fops;
> +	int action = slwt->action;
> +	__u32 fops, supp_fops;
>  	int rc;
>  
>  	rc = nla_parse_nested_deprecated(tb, SEG6_LOCAL_FLV_MAX,
> @@ -2086,7 +2148,8 @@ static int parse_nla_flavors(struct nlattr **attrs, struct seg6_local_lwt *slwt,
>  		return -EINVAL;
>  
>  	fops = nla_get_u32(tb[SEG6_LOCAL_FLV_OPERATION]);
> -	if (fops & ~SEG6_LOCAL_FLV_SUPP_OPS) {
> +	rc = seg6_flv_supp_ops_by_action(action, &supp_fops);
> +	if (rc < 0 || (fops & ~supp_fops)) {
>  		NL_SET_ERR_MSG(extack, "Unsupported Flavor operation(s)");
>  		return -EOPNOTSUPP;
>  	}
> @@ -2618,6 +2681,11 @@ int __init seg6_local_init(void)
>  	 */
>  	BUILD_BUG_ON(SEG6_LOCAL_MAX + 1 > BITS_PER_TYPE(unsigned long));
>  
> +	/* Check whether the number of defined flavors exceeds the maximum
> +	 * allowed value.
> +	 */
> +	BUILD_BUG_ON(SEG6_LOCAL_FLV_OP_MAX + 1 > BITS_PER_TYPE(__u32));
> +
>  	/* If the default NEXT-C-SID Locator-Block/Node Function lengths (in
>  	 * bits) have been changed with invalid values, kernel build stops
>  	 * here.
> -- 
> 2.20.1
> 

Reviewed-by: Hangbin Liu <liuhangbin@gmail.com>
David Ahern Aug. 14, 2023, 4:16 p.m. UTC | #2
On 8/12/23 12:09 PM, Andrea Mayer wrote:
> The NEXT-C-SID mechanism described in [1] offers the possibility of
> encoding several SRv6 segments within a single 128 bit SID address. Such
> a SID address is called a Compressed SID (C-SID) container. In this way,
> the length of the SID List can be drastically reduced.
> 
> A SID instantiated with the NEXT-C-SID flavor considers an IPv6 address
> logically structured in three main blocks: i) Locator-Block; ii)
> Locator-Node Function; iii) Argument.
> 
>                         C-SID container
> +------------------------------------------------------------------+
> |     Locator-Block      |Loc-Node|            Argument            |
> |                        |Function|                                |
> +------------------------------------------------------------------+
> <--------- B -----------> <- NF -> <------------- A --------------->
> 
>    (i) The Locator-Block can be any IPv6 prefix available to the provider;
> 
>   (ii) The Locator-Node Function represents the node and the function to
>        be triggered when a packet is received on the node;
> 
>  (iii) The Argument carries the remaining C-SIDs in the current C-SID
>        container.
> 
> This patch leverages the NEXT-C-SID mechanism previously introduced in the
> Linux SRv6 subsystem [2] to support SID compression capabilities in the
> SRv6 End.X behavior [3].
> An SRv6 End.X behavior with NEXT-C-SID flavor works as an End.X behavior
> but it is capable of processing the compressed SID List encoded in C-SID
> containers.
> 
> An SRv6 End.X behavior with NEXT-C-SID flavor can be configured to support
> user-provided Locator-Block and Locator-Node Function lengths. In this
> implementation, such lengths must be evenly divisible by 8 (i.e. must be
> byte-aligned), otherwise the kernel informs the user about invalid
> values with a meaningful error code and message through netlink_ext_ack.
> 
> If Locator-Block and/or Locator-Node Function lengths are not provided
> by the user during configuration of an SRv6 End.X behavior instance with
> NEXT-C-SID flavor, the kernel will choose their default values i.e.,
> 32-bit Locator-Block and 16-bit Locator-Node Function.
> 
> [1] - https://datatracker.ietf.org/doc/html/draft-ietf-spring-srv6-srh-compression
> [2] - https://lore.kernel.org/all/20220912171619.16943-1-andrea.mayer@uniroma2.it/
> [3] - https://datatracker.ietf.org/doc/html/rfc8986#name-endx-l3-cross-connect
> 
> Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
> ---
>  net/ipv6/seg6_local.c | 108 ++++++++++++++++++++++++++++++++++--------
>  1 file changed, 88 insertions(+), 20 deletions(-)
> 

Reviewed-by: David Ahern <dsahern@kernel.org>