diff options
| author | Russ White <russ@riw.us> | 2023-09-20 23:09:35 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-20 23:09:35 -0400 | 
| commit | 90d19d1489c7237acaad7dfa79af2080301ad60d (patch) | |
| tree | 59d903742e50c7d36edf22cfcd98cff736fbf063 /staticd | |
| parent | 0c9aabe76040dff04c76b127f92087236a623451 (diff) | |
| parent | 9f3ceabd490a4ab90dd8e8b74b4d16117edd8c10 (diff) | |
Merge pull request #14089 from dmytroshytyi-6WIND/srv6_multiple_segs_sids
 bgpd,doc,lib,sharpd,staticd,yang,zebra: SRv6 multiple segs SIDs
Diffstat (limited to 'staticd')
| -rw-r--r-- | staticd/static_nb.c | 29 | ||||
| -rw-r--r-- | staticd/static_nb.h | 20 | ||||
| -rw-r--r-- | staticd/static_nb_config.c | 200 | ||||
| -rw-r--r-- | staticd/static_routes.h | 10 | ||||
| -rw-r--r-- | staticd/static_vty.c | 280 | ||||
| -rw-r--r-- | staticd/static_zebra.c | 15 | 
6 files changed, 443 insertions, 111 deletions
diff --git a/staticd/static_nb.c b/staticd/static_nb.c index d8b5b167cf..1c69a58035 100644 --- a/staticd/static_nb.c +++ b/staticd/static_nb.c @@ -75,6 +75,21 @@ const struct frr_yang_module_info frr_staticd_info = {  			}  		},  		{ +			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry", +			.cbs = { +				.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_create, +				.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_destroy, + +			} +		}, +		{ +			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry/seg", +			.cbs = { +				.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_modify, +				.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_destroy, +			} +		}, +		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry",  			.cbs = {  				.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create, @@ -183,6 +198,20 @@ const struct frr_yang_module_info frr_staticd_info = {  			}  		},  		{ +			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry", +			.cbs = { +				.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_create, +				.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_destroy, +			} +		}, +		{ +			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry/seg", +			.cbs = { +				.modify = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_modify, +				.destroy = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_destroy, +			} +		}, +		{  			.xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry",  			.cbs = {  				.create = routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create, diff --git a/staticd/static_nb.h b/staticd/static_nb.h index ce3644076c..9f80653b76 100644 --- a/staticd/static_nb.h +++ b/staticd/static_nb.h @@ -35,6 +35,14 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa  	struct nb_cb_modify_args *args);  int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_color_destroy(  	struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_create( +	struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_destroy( +	struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_modify( +	struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_destroy( +	struct nb_cb_destroy_args *args);  int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(  	struct nb_cb_create_args *args);  int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy( @@ -80,6 +88,14 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_sr  	struct nb_cb_modify_args *args);  int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_color_destroy(  	struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_create( +	struct nb_cb_create_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_destroy( +	struct nb_cb_destroy_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_modify( +	struct nb_cb_modify_args *args); +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_destroy( +	struct nb_cb_destroy_args *args);  int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create(  	struct nb_cb_create_args *args);  int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_destroy( @@ -147,6 +163,10 @@ int routing_control_plane_protocols_name_validate(  #define FRR_STATIC_ROUTE_NHLB_KEY_XPATH "/entry[id='%u']/label" +#define FRR_STATIC_ROUTE_NH_SRV6_SEGS_XPATH "/srv6-segs-stack" + +#define FRR_STATIC_ROUTE_NH_SRV6_KEY_SEG_XPATH "/entry[id='%u']/seg" +  /* route-list/srclist */  #define FRR_S_ROUTE_SRC_INFO_KEY_XPATH                                         \  	"/frr-routing:routing/control-plane-protocols/"                        \ diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c index 520a3ee2c1..ede2e38754 100644 --- a/staticd/static_nb_config.c +++ b/staticd/static_nb_config.c @@ -209,6 +209,98 @@ static bool static_nexthop_destroy(struct nb_cb_destroy_args *args)  	return NB_OK;  } +static int nexthop_srv6_segs_stack_entry_create(struct nb_cb_create_args *args) +{ +	struct static_nexthop *nh; +	uint32_t pos; +	uint8_t index; + +	switch (args->event) { +	case NB_EV_VALIDATE: +	case NB_EV_PREPARE: +	case NB_EV_ABORT: +		break; +	case NB_EV_APPLY: +		nh = nb_running_get_entry(args->dnode, NULL, true); +		pos = yang_get_list_pos(args->dnode); +		if (!pos) { +			flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, +				  "libyang returns invalid seg position"); +			return NB_ERR; +		} +		/* Mapping to array = list-index -1 */ +		index = pos - 1; +		memset(&nh->snh_seg.seg[index], 0, sizeof(struct in6_addr)); +		nh->snh_seg.num_segs++; +		break; +	} + +	return NB_OK; +} + +static int nexthop_srv6_segs_stack_entry_destroy(struct nb_cb_destroy_args *args) +{ +	struct static_nexthop *nh; +	uint32_t pos; +	uint8_t index; +	int old_num_segs; + +	switch (args->event) { +	case NB_EV_VALIDATE: +	case NB_EV_PREPARE: +	case NB_EV_ABORT: +		break; +	case NB_EV_APPLY: +		nh = nb_running_get_entry(args->dnode, NULL, true); +		pos = yang_get_list_pos(args->dnode); +		if (!pos) { +			flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, +				  "libyang returns invalid seg position"); +			return NB_ERR; +		} +		index = pos - 1; +		old_num_segs = nh->snh_seg.num_segs; +		memset(&nh->snh_seg.seg[index], 0, sizeof(struct in6_addr)); +		nh->snh_seg.num_segs--; + +		if (old_num_segs != nh->snh_seg.num_segs) +			nh->state = STATIC_START; +		break; +	} + +	return NB_OK; +} + +static int static_nexthop_srv6_segs_modify(struct nb_cb_modify_args *args) +{ +	struct static_nexthop *nh; +	uint32_t pos; +	uint8_t index; +	struct in6_addr old_seg; +	struct in6_addr cli_seg; + +	nh = nb_running_get_entry(args->dnode, NULL, true); +	pos = yang_get_list_pos(lyd_parent(args->dnode)); +	if (!pos) { +		flog_warn(EC_LIB_NB_CB_CONFIG_APPLY, +			  "libyang returns invalid seg position"); +		return NB_ERR; +	} +	/* Mapping to array = list-index -1 */ +	index = pos - 1; + +	old_seg = nh->snh_seg.seg[index]; +	yang_dnode_get_ipv6(&cli_seg, args->dnode, NULL); + +	memcpy(&nh->snh_seg.seg[index], &cli_seg, sizeof(struct in6_addr)); + +	if (memcmp(&old_seg, &nh->snh_seg.seg[index], +		   sizeof(struct in6_addr)) != 0) +		nh->state = STATIC_START; + +	return NB_OK; +} +  static int nexthop_mpls_label_stack_entry_create(struct nb_cb_create_args *args)  {  	struct static_nexthop *nh; @@ -643,6 +735,60 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_pa  /*   * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_create( +	struct nb_cb_create_args *args) +{ +	return nexthop_srv6_segs_stack_entry_create(args); +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_destroy( +	struct nb_cb_destroy_args *args) +{ +	return nexthop_srv6_segs_stack_entry_destroy(args); +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry/seg + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_modify( +	struct nb_cb_modify_args *args) +{ +	switch (args->event) { +	case NB_EV_VALIDATE: +	case NB_EV_PREPARE: +	case NB_EV_ABORT: +		break; +	case NB_EV_APPLY: +		if (static_nexthop_srv6_segs_modify(args) != NB_OK) +			return NB_ERR; +		break; +	} +	return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_destroy( +	struct nb_cb_destroy_args *args) +{ +	/* +	 * No operation is required in this call back. +	 * nexthop_srv6_segs_stack_entry_destroy() will take care +	 * to reset the seg vaue. +	 */ +	switch (args->event) { +	case NB_EV_VALIDATE: +	case NB_EV_PREPARE: +	case NB_EV_ABORT: +	case NB_EV_APPLY: +		break; +	} +	return NB_OK; +} + +/* + * XPath:   * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry   */  int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create( @@ -1021,6 +1167,60 @@ int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_sr  /*   * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_create( +	struct nb_cb_create_args *args) +{ +	return nexthop_srv6_segs_stack_entry_create(args); +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_destroy( +	struct nb_cb_destroy_args *args) +{ +	return nexthop_srv6_segs_stack_entry_destroy(args); +} + +/* + * XPath: + * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/srv6-segs-stack/entry/seg + */ +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_modify( +	struct nb_cb_modify_args *args) +{ +	switch (args->event) { +	case NB_EV_VALIDATE: +	case NB_EV_PREPARE: +	case NB_EV_ABORT: +		break; +	case NB_EV_APPLY: +		if (static_nexthop_srv6_segs_modify(args) != NB_OK) +			return NB_ERR; +		break; +	} +	return NB_OK; +} + +int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_srv6_segs_stack_entry_seg_destroy( +	struct nb_cb_destroy_args *args) +{ +	/* +	 * No operation is required in this call back. +	 * nexthop_mpls_seg_stack_entry_destroy() will take care +	 * to reset the seg vaue. +	 */ +	switch (args->event) { +	case NB_EV_VALIDATE: +	case NB_EV_PREPARE: +	case NB_EV_ABORT: +	case NB_EV_APPLY: +		break; +	} +	return NB_OK; +} + +/* + * XPath:   * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-staticd:staticd/route-list/src-list/path-list/frr-nexthops/nexthop/mpls-label-stack/entry   */  int routing_control_plane_protocols_control_plane_protocol_staticd_route_list_src_list_path_list_frr_nexthops_nexthop_mpls_label_stack_entry_create( diff --git a/staticd/static_routes.h b/staticd/static_routes.h index 3be6fd6b14..548148b187 100644 --- a/staticd/static_routes.h +++ b/staticd/static_routes.h @@ -9,6 +9,7 @@  #include "lib/bfd.h"  #include "lib/mpls.h" +#include "lib/srv6.h"  #include "table.h"  #include "memory.h" @@ -27,6 +28,12 @@ struct static_nh_label {  	mpls_label_t label[MPLS_MAX_LABELS];  }; +/* Static route seg information */ +struct static_nh_seg { +	int num_segs; +	struct in6_addr seg[SRV6_MAX_SIDS]; +}; +  enum static_blackhole_type {  	STATIC_BLACKHOLE_DROP = 0,  	STATIC_BLACKHOLE_NULL, @@ -129,6 +136,9 @@ struct static_nexthop {  	/* Label information */  	struct static_nh_label snh_label; +	/* SRv6 Seg information */ +	struct static_nh_seg snh_seg; +  	/*  	 * Whether to pretend the nexthop is directly attached to the specified  	 * link. Only meaningful when both a gateway address and interface name diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 16e4cb7d83..b07878f063 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -47,6 +47,7 @@ struct static_route_args {  	const char *source;  	const char *gateway;  	const char *interface_name; +	const char *segs;  	const char *flag;  	const char *tag;  	const char *distance; @@ -73,12 +74,16 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)  	char xpath_nexthop[XPATH_MAXLEN];  	char xpath_mpls[XPATH_MAXLEN];  	char xpath_label[XPATH_MAXLEN]; +	char xpath_segs[XPATH_MAXLEN]; +	char xpath_seg[XPATH_MAXLEN];  	char ab_xpath[XPATH_MAXLEN];  	char buf_prefix[PREFIX_STRLEN];  	char buf_src_prefix[PREFIX_STRLEN] = {};  	char buf_nh_type[PREFIX_STRLEN] = {};  	char buf_tag[PREFIX_STRLEN];  	uint8_t label_stack_id = 0; +	uint8_t segs_stack_id = 0; +  	const char *buf_gate_str;  	uint8_t distance = ZEBRA_STATIC_DISTANCE_DEFAULT;  	route_tag_t tag = 0; @@ -345,7 +350,39 @@ static int static_route_nb_run(struct vty *vty, struct static_route_args *args)  			nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,  					      NULL);  		} +		if (args->segs) { +			/* copy of seg string (start) */ +			char *ostr; +			/* pointer to next segment */ +			char *nump; +			strlcpy(xpath_segs, xpath_nexthop, sizeof(xpath_segs)); +			strlcat(xpath_segs, FRR_STATIC_ROUTE_NH_SRV6_SEGS_XPATH, +				sizeof(xpath_segs)); + +			nb_cli_enqueue_change(vty, xpath_segs, NB_OP_DESTROY, +					      NULL); + +			ostr = XSTRDUP(MTYPE_TMP, args->segs); +			while ((nump = strsep(&ostr, "/")) != NULL) { +				snprintf(ab_xpath, sizeof(ab_xpath), +					 FRR_STATIC_ROUTE_NH_SRV6_KEY_SEG_XPATH, +					 segs_stack_id); +				strlcpy(xpath_seg, xpath_segs, +					sizeof(xpath_seg)); +				strlcat(xpath_seg, ab_xpath, sizeof(xpath_seg)); +				nb_cli_enqueue_change(vty, xpath_seg, +						      NB_OP_MODIFY, nump); +				segs_stack_id++; +			} +			XFREE(MTYPE_TMP, ostr); +		} else { +			strlcpy(xpath_segs, xpath_nexthop, sizeof(xpath_segs)); +			strlcat(xpath_segs, FRR_STATIC_ROUTE_NH_SRV6_SEGS_XPATH, +				sizeof(xpath_segs)); +			nb_cli_enqueue_change(vty, xpath_segs, NB_OP_DESTROY, +					      NULL); +		}  		if (args->bfd) {  			char xpath_bfd[XPATH_MAXLEN]; @@ -951,9 +988,8 @@ DEFPY_YANG(ipv6_route_blackhole_vrf,  	return static_route_nb_run(vty, &args);  } -DEFPY_YANG(ipv6_route_address_interface, -      ipv6_route_address_interface_cmd, -      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ +DEFPY_YANG(ipv6_route_address_interface, ipv6_route_address_interface_cmd, +	   "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \            X:X::X:X$gate                                    \            <INTERFACE|Null0>$ifname                         \            [{                                               \ @@ -966,33 +1002,28 @@ DEFPY_YANG(ipv6_route_address_interface,  	    |onlink$onlink                                 \  	    |color (1-4294967295)                          \  	    |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \ +		|segments WORD 								   \            }]", -      NO_STR -      IPV6_STR -      "Establish static routes\n" -      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" -      "IPv6 source-dest route\n" -      "IPv6 source prefix\n" -      "IPv6 gateway address\n" -      "IPv6 gateway interface name\n" -      "Null interface\n" -      "Set tag for this route\n" -      "Tag value\n" -      "Distance value for this prefix\n" -      VRF_CMD_HELP_STR -      MPLS_LABEL_HELPSTR -      "Table to configure\n" -      "The table number to configure\n" -      VRF_CMD_HELP_STR -      "Treat the nexthop as directly attached to the interface\n" -      "SR-TE color\n" -      "The SR-TE color to configure\n" -      BFD_INTEGRATION_STR -      BFD_INTEGRATION_MULTI_HOP_STR -      BFD_INTEGRATION_SOURCE_STR -      BFD_INTEGRATION_SOURCEV4_STR -      BFD_PROFILE_STR -      BFD_PROFILE_NAME_STR) +	   NO_STR IPV6_STR +	   "Establish static routes\n" +	   "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" +	   "IPv6 source-dest route\n" +	   "IPv6 source prefix\n" +	   "IPv6 gateway address\n" +	   "IPv6 gateway interface name\n" +	   "Null interface\n" +	   "Set tag for this route\n" +	   "Tag value\n" +	   "Distance value for this prefix\n" VRF_CMD_HELP_STR MPLS_LABEL_HELPSTR +	   "Table to configure\n" +	   "The table number to configure\n" VRF_CMD_HELP_STR +	   "Treat the nexthop as directly attached to the interface\n" +	   "SR-TE color\n" +	   "The SR-TE color to configure\n" BFD_INTEGRATION_STR +		   BFD_INTEGRATION_MULTI_HOP_STR BFD_INTEGRATION_SOURCE_STR +			   BFD_INTEGRATION_SOURCEV4_STR BFD_PROFILE_STR +				   BFD_PROFILE_NAME_STR "Value of segs\n" +	   "Segs (SIDs)\n")  {  	struct static_route_args args = {  		.delete = !!no, @@ -1014,14 +1045,15 @@ DEFPY_YANG(ipv6_route_address_interface,  		.bfd_multi_hop = !!bfd_multi_hop,  		.bfd_source = bfd_source_str,  		.bfd_profile = bfd_profile, +		.segs = segments,  	};  	return static_route_nb_run(vty, &args);  }  DEFPY_YANG(ipv6_route_address_interface_vrf, -      ipv6_route_address_interface_vrf_cmd, -      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ +	   ipv6_route_address_interface_vrf_cmd, +	   "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \            X:X::X:X$gate                                    \            <INTERFACE|Null0>$ifname                         \            [{                                               \ @@ -1033,32 +1065,28 @@ DEFPY_YANG(ipv6_route_address_interface_vrf,  	    |onlink$onlink                                 \  	    |color (1-4294967295)                          \  	    |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \ +		|segments WORD 								   \            }]", -      NO_STR -      IPV6_STR -      "Establish static routes\n" -      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" -      "IPv6 source-dest route\n" -      "IPv6 source prefix\n" -      "IPv6 gateway address\n" -      "IPv6 gateway interface name\n" -      "Null interface\n" -      "Set tag for this route\n" -      "Tag value\n" -      "Distance value for this prefix\n" -      MPLS_LABEL_HELPSTR -      "Table to configure\n" -      "The table number to configure\n" -      VRF_CMD_HELP_STR -      "Treat the nexthop as directly attached to the interface\n" -      "SR-TE color\n" -      "The SR-TE color to configure\n" -      BFD_INTEGRATION_STR -      BFD_INTEGRATION_MULTI_HOP_STR -      BFD_INTEGRATION_SOURCE_STR -      BFD_INTEGRATION_SOURCEV4_STR -      BFD_PROFILE_STR -      BFD_PROFILE_NAME_STR) +	   NO_STR IPV6_STR +	   "Establish static routes\n" +	   "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" +	   "IPv6 source-dest route\n" +	   "IPv6 source prefix\n" +	   "IPv6 gateway address\n" +	   "IPv6 gateway interface name\n" +	   "Null interface\n" +	   "Set tag for this route\n" +	   "Tag value\n" +	   "Distance value for this prefix\n" MPLS_LABEL_HELPSTR +	   "Table to configure\n" +	   "The table number to configure\n" VRF_CMD_HELP_STR +	   "Treat the nexthop as directly attached to the interface\n" +	   "SR-TE color\n" +	   "The SR-TE color to configure\n" BFD_INTEGRATION_STR +		   BFD_INTEGRATION_MULTI_HOP_STR BFD_INTEGRATION_SOURCE_STR +			   BFD_INTEGRATION_SOURCEV4_STR BFD_PROFILE_STR +				   BFD_PROFILE_NAME_STR "Value of segs\n" +	   "Segs (SIDs)\n")  {  	struct static_route_args args = {  		.delete = !!no, @@ -1080,14 +1108,14 @@ DEFPY_YANG(ipv6_route_address_interface_vrf,  		.bfd_multi_hop = !!bfd_multi_hop,  		.bfd_source = bfd_source_str,  		.bfd_profile = bfd_profile, +		.segs = segments,  	};  	return static_route_nb_run(vty, &args);  } -DEFPY_YANG(ipv6_route, -      ipv6_route_cmd, -      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ +DEFPY_YANG(ipv6_route, ipv6_route_cmd, +	   "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \            <X:X::X:X$gate|<INTERFACE|Null0>$ifname>         \            [{                                               \              tag (1-4294967295)                             \ @@ -1098,32 +1126,26 @@ DEFPY_YANG(ipv6_route,              |nexthop-vrf NAME                              \              |color (1-4294967295)                          \  	    |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \ +			|segments WORD 								   \            }]", -      NO_STR -      IPV6_STR -      "Establish static routes\n" -      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" -      "IPv6 source-dest route\n" -      "IPv6 source prefix\n" -      "IPv6 gateway address\n" -      "IPv6 gateway interface name\n" -      "Null interface\n" -      "Set tag for this route\n" -      "Tag value\n" -      "Distance value for this prefix\n" -      VRF_CMD_HELP_STR -      MPLS_LABEL_HELPSTR -      "Table to configure\n" -      "The table number to configure\n" -      VRF_CMD_HELP_STR -      "SR-TE color\n" -      "The SR-TE color to configure\n" -      BFD_INTEGRATION_STR -      BFD_INTEGRATION_MULTI_HOP_STR -      BFD_INTEGRATION_SOURCE_STR -      BFD_INTEGRATION_SOURCEV4_STR -      BFD_PROFILE_STR -      BFD_PROFILE_NAME_STR) +	   NO_STR IPV6_STR +	   "Establish static routes\n" +	   "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" +	   "IPv6 source-dest route\n" +	   "IPv6 source prefix\n" +	   "IPv6 gateway address\n" +	   "IPv6 gateway interface name\n" +	   "Null interface\n" +	   "Set tag for this route\n" +	   "Tag value\n" +	   "Distance value for this prefix\n" VRF_CMD_HELP_STR MPLS_LABEL_HELPSTR +	   "Table to configure\n" +	   "The table number to configure\n" VRF_CMD_HELP_STR "SR-TE color\n" +	   "The SR-TE color to configure\n" BFD_INTEGRATION_STR +		   BFD_INTEGRATION_MULTI_HOP_STR BFD_INTEGRATION_SOURCE_STR +			   BFD_INTEGRATION_SOURCEV4_STR BFD_PROFILE_STR +				   BFD_PROFILE_NAME_STR "Value of segs\n" +	   "Segs (SIDs)\n")  {  	struct static_route_args args = {  		.delete = !!no, @@ -1144,14 +1166,15 @@ DEFPY_YANG(ipv6_route,  		.bfd_multi_hop = !!bfd_multi_hop,  		.bfd_source = bfd_source_str,  		.bfd_profile = bfd_profile, +		.segs = segments, +  	};  	return static_route_nb_run(vty, &args);  } -DEFPY_YANG(ipv6_route_vrf, -      ipv6_route_vrf_cmd, -      "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \ +DEFPY_YANG(ipv6_route_vrf, ipv6_route_vrf_cmd, +	   "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \            <X:X::X:X$gate|<INTERFACE|Null0>$ifname>                 \            [{                                               \              tag (1-4294967295)                             \ @@ -1161,31 +1184,26 @@ DEFPY_YANG(ipv6_route_vrf,              |nexthop-vrf NAME                              \  	    |color (1-4294967295)                          \  	    |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \ +		|segments WORD 								   \            }]", -      NO_STR -      IPV6_STR -      "Establish static routes\n" -      "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" -      "IPv6 source-dest route\n" -      "IPv6 source prefix\n" -      "IPv6 gateway address\n" -      "IPv6 gateway interface name\n" -      "Null interface\n" -      "Set tag for this route\n" -      "Tag value\n" -      "Distance value for this prefix\n" -      MPLS_LABEL_HELPSTR -      "Table to configure\n" -      "The table number to configure\n" -      VRF_CMD_HELP_STR -      "SR-TE color\n" -      "The SR-TE color to configure\n" -      BFD_INTEGRATION_STR -      BFD_INTEGRATION_MULTI_HOP_STR -      BFD_INTEGRATION_SOURCE_STR -      BFD_INTEGRATION_SOURCEV4_STR -      BFD_PROFILE_STR -      BFD_PROFILE_NAME_STR) +	   NO_STR IPV6_STR +	   "Establish static routes\n" +	   "IPv6 destination prefix (e.g. 3ffe:506::/32)\n" +	   "IPv6 source-dest route\n" +	   "IPv6 source prefix\n" +	   "IPv6 gateway address\n" +	   "IPv6 gateway interface name\n" +	   "Null interface\n" +	   "Set tag for this route\n" +	   "Tag value\n" +	   "Distance value for this prefix\n" MPLS_LABEL_HELPSTR +	   "Table to configure\n" +	   "The table number to configure\n" VRF_CMD_HELP_STR "SR-TE color\n" +	   "The SR-TE color to configure\n" BFD_INTEGRATION_STR +		   BFD_INTEGRATION_MULTI_HOP_STR BFD_INTEGRATION_SOURCE_STR +			   BFD_INTEGRATION_SOURCEV4_STR BFD_PROFILE_STR +				   BFD_PROFILE_NAME_STR "Value of segs\n" +	   "Segs (SIDs)\n")  {  	struct static_route_args args = {  		.delete = !!no, @@ -1206,6 +1224,7 @@ DEFPY_YANG(ipv6_route_vrf,  		.bfd_multi_hop = !!bfd_multi_hop,  		.bfd_source = bfd_source_str,  		.bfd_profile = bfd_profile, +		.segs = segments,  	};  	return static_route_nb_run(vty, &args); @@ -1252,6 +1271,39 @@ static int mpls_label_iter_cb(const struct lyd_node *dnode, void *arg)  	return YANG_ITER_CONTINUE;  } +struct srv6_seg_iter { +	struct vty *vty; +	bool first; +}; + +static int srv6_seg_iter_cb(const struct lyd_node *dnode, void *arg) +{ +	struct srv6_seg_iter *iter = arg; +	char buffer[INET6_ADDRSTRLEN]; +	struct in6_addr cli_seg; + +	if (yang_dnode_exists(dnode, "./seg")) { +		if (iter->first) { +			yang_dnode_get_ipv6(&cli_seg, dnode, "./seg"); +			if (inet_ntop(AF_INET6, &cli_seg, buffer, +				      INET6_ADDRSTRLEN) == NULL) { +				return 1; +			} +			vty_out(iter->vty, " segments %s", buffer); +		} else { +			yang_dnode_get_ipv6(&cli_seg, dnode, "./seg"); +			if (inet_ntop(AF_INET6, &cli_seg, buffer, +				      INET6_ADDRSTRLEN) == NULL) { +				return 1; +			} +			vty_out(iter->vty, "/%s", buffer); +		} +		iter->first = false; +	} + +	return YANG_ITER_CONTINUE; +} +  static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,  			     const struct lyd_node *src,  			     const struct lyd_node *path, @@ -1266,6 +1318,7 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,  	uint32_t tag;  	uint8_t distance;  	struct mpls_label_iter iter; +	struct srv6_seg_iter seg_iter;  	const char *nexthop_vrf;  	uint32_t table_id;  	bool onlink; @@ -1342,6 +1395,11 @@ static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,  	yang_dnode_iterate(mpls_label_iter_cb, &iter, nexthop,  			   "./mpls-label-stack/entry"); +	seg_iter.vty = vty; +	seg_iter.first = true; +	yang_dnode_iterate(srv6_seg_iter_cb, &seg_iter, nexthop, +			   "./srv6-segs-stack/entry"); +  	nexthop_vrf = yang_dnode_get_string(nexthop, "./vrf");  	if (strcmp(vrf, nexthop_vrf))  		vty_out(vty, " nexthop-vrf %s", nexthop_vrf); diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 4f3ccde53d..6abbdadc08 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -499,6 +499,21 @@ extern void static_zebra_route_add(struct static_path *pn, bool install)  			for (i = 0; i < api_nh->label_num; i++)  				api_nh->labels[i] = nh->snh_label.label[i];  		} +		if (nh->snh_seg.num_segs) { +			int i; + +			api_nh->seg6local_action = +				ZEBRA_SEG6_LOCAL_ACTION_UNSPEC; +			SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6); +			SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION); +			api.safi = SAFI_UNICAST; + +			api_nh->seg_num = nh->snh_seg.num_segs; +			for (i = 0; i < api_nh->seg_num; i++) +				memcpy(&api_nh->seg6_segs[i], +				       &nh->snh_seg.seg[i], +				       sizeof(struct in6_addr)); +		}  		nh_num++;  	}  | 
