@@ -109,15 +109,19 @@ struct bpf_lwt_prog {
109109#define next_csid_chk_lcnode_fn_bits (flen ) \
110110 next_csid_chk_lcblock_bits(flen)
111111
112+ /* flag indicating that flavors are set up for a given End* behavior */
113+ #define SEG6_F_LOCAL_FLAVORS SEG6_F_ATTR(SEG6_LOCAL_FLAVORS)
114+
112115#define SEG6_F_LOCAL_FLV_OP (flvname ) BIT(SEG6_LOCAL_FLV_OP_##flvname)
116+ #define SEG6_F_LOCAL_FLV_NEXT_CSID SEG6_F_LOCAL_FLV_OP(NEXT_CSID)
113117#define SEG6_F_LOCAL_FLV_PSP SEG6_F_LOCAL_FLV_OP(PSP)
114118
115119/* Supported RFC8986 Flavor operations are reported in this bitmask */
116120#define SEG6_LOCAL_FLV8986_SUPP_OPS SEG6_F_LOCAL_FLV_PSP
117121
118- /* Supported Flavor operations are reported in this bitmask */
119- #define SEG6_LOCAL_FLV_SUPP_OPS (SEG6_F_LOCAL_FLV_OP(NEXT_CSID) | \
122+ #define SEG6_LOCAL_END_FLV_SUPP_OPS (SEG6_F_LOCAL_FLV_NEXT_CSID | \
120123 SEG6_LOCAL_FLV8986_SUPP_OPS)
124+ #define SEG6_LOCAL_END_X_FLV_SUPP_OPS SEG6_F_LOCAL_FLV_NEXT_CSID
121125
122126struct seg6_flavors_info {
123127 /* Flavor operations */
@@ -411,9 +415,72 @@ static int end_next_csid_core(struct sk_buff *skb, struct seg6_local_lwt *slwt)
411415 return input_action_end_finish (skb , slwt );
412416}
413417
418+ static int input_action_end_x_finish (struct sk_buff * skb ,
419+ struct seg6_local_lwt * slwt )
420+ {
421+ seg6_lookup_nexthop (skb , & slwt -> nh6 , 0 );
422+
423+ return dst_input (skb );
424+ }
425+
426+ static int input_action_end_x_core (struct sk_buff * skb ,
427+ struct seg6_local_lwt * slwt )
428+ {
429+ struct ipv6_sr_hdr * srh ;
430+
431+ srh = get_and_validate_srh (skb );
432+ if (!srh )
433+ goto drop ;
434+
435+ advance_nextseg (srh , & ipv6_hdr (skb )-> daddr );
436+
437+ return input_action_end_x_finish (skb , slwt );
438+
439+ drop :
440+ kfree_skb (skb );
441+ return - EINVAL ;
442+ }
443+
444+ static int end_x_next_csid_core (struct sk_buff * skb ,
445+ struct seg6_local_lwt * slwt )
446+ {
447+ const struct seg6_flavors_info * finfo = & slwt -> flv_info ;
448+ struct in6_addr * daddr = & ipv6_hdr (skb )-> daddr ;
449+
450+ if (seg6_next_csid_is_arg_zero (daddr , finfo ))
451+ return input_action_end_x_core (skb , slwt );
452+
453+ /* update DA */
454+ seg6_next_csid_advance_arg (daddr , finfo );
455+
456+ return input_action_end_x_finish (skb , slwt );
457+ }
458+
414459static bool seg6_next_csid_enabled (__u32 fops )
415460{
416- return fops & BIT (SEG6_LOCAL_FLV_OP_NEXT_CSID );
461+ return fops & SEG6_F_LOCAL_FLV_NEXT_CSID ;
462+ }
463+
464+ /* Processing of SRv6 End, End.X, and End.T behaviors can be extended through
465+ * the flavors framework. These behaviors must report the subset of (flavor)
466+ * operations they currently implement. In this way, if a user specifies a
467+ * flavor combination that is not supported by a given End* behavior, the
468+ * kernel refuses to instantiate the tunnel reporting the error.
469+ */
470+ static int seg6_flv_supp_ops_by_action (int action , __u32 * fops )
471+ {
472+ switch (action ) {
473+ case SEG6_LOCAL_ACTION_END :
474+ * fops = SEG6_LOCAL_END_FLV_SUPP_OPS ;
475+ break ;
476+ case SEG6_LOCAL_ACTION_END_X :
477+ * fops = SEG6_LOCAL_END_X_FLV_SUPP_OPS ;
478+ break ;
479+ default :
480+ return - EOPNOTSUPP ;
481+ }
482+
483+ return 0 ;
417484}
418485
419486/* 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)
746813/* regular endpoint, and forward to specified nexthop */
747814static int input_action_end_x (struct sk_buff * skb , struct seg6_local_lwt * slwt )
748815{
749- struct ipv6_sr_hdr * srh ;
750-
751- srh = get_and_validate_srh (skb );
752- if (!srh )
753- goto drop ;
754-
755- advance_nextseg (srh , & ipv6_hdr (skb )-> daddr );
756-
757- seg6_lookup_nexthop (skb , & slwt -> nh6 , 0 );
816+ const struct seg6_flavors_info * finfo = & slwt -> flv_info ;
817+ __u32 fops = finfo -> flv_ops ;
758818
759- return dst_input (skb );
819+ /* check for the presence of NEXT-C-SID since it applies first */
820+ if (seg6_next_csid_enabled (fops ))
821+ return end_x_next_csid_core (skb , slwt );
760822
761- drop :
762- kfree_skb (skb );
763- return - EINVAL ;
823+ return input_action_end_x_core (skb , slwt );
764824}
765825
766826static 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[] = {
14041464 .action = SEG6_LOCAL_ACTION_END ,
14051465 .attrs = 0 ,
14061466 .optattrs = SEG6_F_LOCAL_COUNTERS |
1407- SEG6_F_ATTR ( SEG6_LOCAL_FLAVORS ) ,
1467+ SEG6_F_LOCAL_FLAVORS ,
14081468 .input = input_action_end ,
14091469 },
14101470 {
14111471 .action = SEG6_LOCAL_ACTION_END_X ,
14121472 .attrs = SEG6_F_ATTR (SEG6_LOCAL_NH6 ),
1413- .optattrs = SEG6_F_LOCAL_COUNTERS ,
1473+ .optattrs = SEG6_F_LOCAL_COUNTERS |
1474+ SEG6_F_LOCAL_FLAVORS ,
14141475 .input = input_action_end_x ,
14151476 },
14161477 {
@@ -2070,7 +2131,8 @@ static int parse_nla_flavors(struct nlattr **attrs, struct seg6_local_lwt *slwt,
20702131{
20712132 struct seg6_flavors_info * finfo = & slwt -> flv_info ;
20722133 struct nlattr * tb [SEG6_LOCAL_FLV_MAX + 1 ];
2073- unsigned long fops ;
2134+ int action = slwt -> action ;
2135+ __u32 fops , supp_fops ;
20742136 int rc ;
20752137
20762138 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,
20862148 return - EINVAL ;
20872149
20882150 fops = nla_get_u32 (tb [SEG6_LOCAL_FLV_OPERATION ]);
2089- if (fops & ~SEG6_LOCAL_FLV_SUPP_OPS ) {
2151+ rc = seg6_flv_supp_ops_by_action (action , & supp_fops );
2152+ if (rc < 0 || (fops & ~supp_fops )) {
20902153 NL_SET_ERR_MSG (extack , "Unsupported Flavor operation(s)" );
20912154 return - EOPNOTSUPP ;
20922155 }
@@ -2618,6 +2681,11 @@ int __init seg6_local_init(void)
26182681 */
26192682 BUILD_BUG_ON (SEG6_LOCAL_MAX + 1 > BITS_PER_TYPE (unsigned long ));
26202683
2684+ /* Check whether the number of defined flavors exceeds the maximum
2685+ * allowed value.
2686+ */
2687+ BUILD_BUG_ON (SEG6_LOCAL_FLV_OP_MAX + 1 > BITS_PER_TYPE (__u32 ));
2688+
26212689 /* If the default NEXT-C-SID Locator-Block/Node Function lengths (in
26222690 * bits) have been changed with invalid values, kernel build stops
26232691 * here.
0 commit comments