diff options
| author | Carmine Scarpitta <carmine.scarpitta@uniroma2.it> | 2023-09-03 08:54:57 +0200 | 
|---|---|---|
| committer | Carmine Scarpitta <carmine.scarpitta@uniroma2.it> | 2023-09-11 22:11:51 +0200 | 
| commit | bfec26bc7a59698f82e66d1c7a6ae64909191a83 (patch) | |
| tree | fad612f17f878dc78f297cfaac56cad557372fa2 | |
| parent | dd8f09cc5505e6a255b2dd382f884ff02cb6f873 (diff) | |
isisd: Make SRv6 interface configurable
Add CLI command and functions to configure the interface used for
installing SRv6 SIDs into Linux data plane
Signed-off-by: Carmine Scarpitta <carmine.scarpitta@uniroma2.it>
| -rw-r--r-- | isisd/isis_circuit.c | 4 | ||||
| -rw-r--r-- | isisd/isis_cli.c | 28 | ||||
| -rw-r--r-- | isisd/isis_nb.c | 7 | ||||
| -rw-r--r-- | isisd/isis_nb.h | 4 | ||||
| -rw-r--r-- | isisd/isis_nb_config.c | 25 | ||||
| -rw-r--r-- | isisd/isis_srv6.c | 73 | ||||
| -rw-r--r-- | isisd/isis_srv6.h | 10 | ||||
| -rw-r--r-- | isisd/isis_zebra.c | 8 | 
8 files changed, 152 insertions, 7 deletions
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index feab451233..ffa6ad3e40 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -41,6 +41,7 @@  #include "isisd/isisd.h"  #include "isisd/isis_csm.h"  #include "isisd/isis_events.h" +#include "isisd/isis_srv6.h"  #include "isisd/isis_te.h"  #include "isisd/isis_mt.h"  #include "isisd/isis_errors.h" @@ -1631,6 +1632,9 @@ static int isis_ifp_up(struct interface *ifp)  		isis_csm_state_change(IF_UP_FROM_Z, circuit, ifp);  	} +	/* Notify SRv6 that the interface went up */ +	isis_srv6_ifp_up_notify(ifp); +  	return 0;  } diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 328f76b35b..9718a457ed 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -2239,6 +2239,33 @@ void cli_show_isis_srv6_node_msd(struct vty *vty, const struct lyd_node *dnode,  }  /* + * XPath: /frr-isisd:isis/instance/segment-routing-srv6/interface + */ +DEFPY (isis_srv6_interface, +       isis_srv6_interface_cmd, +       "[no] interface WORD$interface", +       NO_STR +       "Interface for Segment Routing over IPv6 (SRv6)\n" +       "Interface for Segment Routing over IPv6 (SRv6)\n") +{ +	if (no) { +		nb_cli_enqueue_change(vty, "./interface", +				      NB_OP_MODIFY, NULL); +	} else { +		nb_cli_enqueue_change(vty, "./interface", +				      NB_OP_MODIFY, interface); +	} + +	return nb_cli_apply_changes(vty, NULL); +} + +void cli_show_isis_srv6_interface(struct vty *vty, const struct lyd_node *dnode, +				bool show_defaults) +{ +	vty_out(vty, "  interface %s\n", yang_dnode_get_string(dnode, NULL)); +} + +/*   * XPath: /frr-isisd:isis/instance/fast-reroute/level-{1,2}/lfa/priority-limit   */  DEFPY_YANG (isis_frr_lfa_priority_limit, @@ -4011,6 +4038,7 @@ void isis_cli_init(void)  	install_element(ISIS_NODE, &no_isis_srv6_enable_cmd);  	install_element(ISIS_SRV6_NODE, &isis_srv6_locator_cmd);  	install_element(ISIS_SRV6_NODE, &isis_srv6_node_msd_cmd); +	install_element(ISIS_SRV6_NODE, &isis_srv6_interface_cmd);  	install_element(ISIS_SRV6_NODE_MSD_NODE,  			&isis_srv6_node_msd_max_segs_left_cmd);  	install_element(ISIS_SRV6_NODE_MSD_NODE, diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c index 528ba4a1ad..186ebfc729 100644 --- a/isisd/isis_nb.c +++ b/isisd/isis_nb.c @@ -910,6 +910,13 @@ const struct frr_yang_module_info frr_isisd_info = {  			},  		},  		{ +			.xpath = "/frr-isisd:isis/instance/segment-routing-srv6/interface", +			.cbs = { +				.modify = isis_instance_segment_routing_srv6_interface_modify, +				.cli_show = cli_show_isis_srv6_interface, +			}, +		}, +		{  			.xpath = "/frr-isisd:isis/instance/mpls/ldp-sync",  			.cbs = {  				.cli_show = cli_show_isis_mpls_ldp_sync, diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h index f200c52f06..be89fd2ac6 100644 --- a/isisd/isis_nb.h +++ b/isisd/isis_nb.h @@ -350,6 +350,10 @@ int isis_instance_segment_routing_srv6_msd_node_msd_max_end_d_destroy(  	struct nb_cb_destroy_args *args);  void cli_show_isis_srv6_node_msd(struct vty *vty, const struct lyd_node *dnode,  				 bool show_defaults); +int isis_instance_segment_routing_srv6_interface_modify( +	struct nb_cb_modify_args *args); +void cli_show_isis_srv6_interface(struct vty *vty, const struct lyd_node *dnode, +				bool show_defaults);  int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args);  int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args);  int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args); diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c index 08eb91448c..5d0089d6fb 100644 --- a/isisd/isis_nb_config.c +++ b/isisd/isis_nb_config.c @@ -3719,6 +3719,31 @@ int isis_instance_segment_routing_srv6_msd_node_msd_max_end_d_destroy(  }  /* + * XPath: /frr-isisd:isis/instance/segment-routing-srv6/interface + */ +int isis_instance_segment_routing_srv6_interface_modify( +	struct nb_cb_modify_args *args) +{ +	struct isis_area *area; +	const char *ifname; + +	if (args->event != NB_EV_APPLY) +		return NB_OK; + +	area = nb_running_get_entry(lyd_parent(lyd_parent(args->dnode)), NULL, +				    true); + +	ifname = yang_dnode_get_string(args->dnode, NULL); + +	sr_debug("Changing SRv6 interface for IS-IS area %s to %s", +		 area->area_tag, ifname); + +	isis_srv6_interface_set(area, ifname); + +	return NB_OK; +} + +/*   * XPath: /frr-isisd:isis/instance/mpls/ldp-sync   */  int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args) diff --git a/isisd/isis_srv6.c b/isisd/isis_srv6.c index f6c05b3afe..0eb8ac3fb7 100644 --- a/isisd/isis_srv6.c +++ b/isisd/isis_srv6.c @@ -158,6 +158,46 @@ bool isis_srv6_locator_unset(struct isis_area *area)  }  /** + * Set the interface used to install SRv6 SIDs into the data plane. + * + * @param area	IS-IS area + */ +void isis_srv6_interface_set(struct isis_area *area, const char *ifname) +{ +	struct listnode *node; +	struct isis_srv6_sid *sid; + +	if (!ifname) +		return; + +	if (!strncmp(ifname, area->srv6db.config.srv6_ifname, IF_NAMESIZE)) { +		/* The interface has not changed, nothing to do */ +		return; +	} + +	sr_debug("SRv6 interface for IS-IS area %s changed (old interface: %s, new interface: %s)", area->area_tag, area->srv6db.config.srv6_ifname, ifname); + +	/* Walk through all SIDs and uninstall them from the data plane */ +	for (ALL_LIST_ELEMENTS_RO(area->srv6db.srv6_sids, node, sid)) { +		sr_debug("Uninstalling SID %pI6 from the data plane", &sid->sid); +		isis_zebra_srv6_sid_uninstall(area, sid); +	} + +	strncpy(area->srv6db.config.srv6_ifname, ifname, IF_NAMESIZE - 1); + +	if (!if_lookup_by_name(area->srv6db.config.srv6_ifname, VRF_DEFAULT)) { +		sr_debug("Interface %s not yet exist in data plane, deferring SIDs installation until it's created", area->srv6db.config.srv6_ifname); +		return; +	} + +	/* Walk through all SIDs and re-install them into the data plane with the newly configured interface */ +	for (ALL_LIST_ELEMENTS_RO(area->srv6db.srv6_sids, node, sid)) { +		sr_debug("Installing SID %pI6 from the data plane", &sid->sid); +		isis_zebra_srv6_sid_install(area, sid); +	} +} + +/**   * Encode SID function in the SRv6 SID.   *   * @param sid @@ -683,6 +723,38 @@ DEFUN(show_srv6_node, show_srv6_node_cmd,  	return CMD_SUCCESS;  } +int isis_srv6_ifp_up_notify(struct interface *ifp) +{ +	struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT); +	struct listnode *node, *node2; +	struct isis_area *area; +	struct isis_srv6_sid *sid; + +	if (!isis) +		return 0; + +	/* Walk through all areas of the ISIS instance */ +	for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) { +		/* Skip area, if SRv6 is not enabled */ +		if (!area->srv6db.config.enabled) +			continue; + +		/* Skip area if the interface is not the one configured for SRv6 */ +		if (strncmp(area->srv6db.config.srv6_ifname, ifp->name, IF_NAMESIZE)) +			continue; + +		sr_debug("Interface %s went up. Installing SIDs for area %s in data plane", ifp->name, area->area_tag); + +		/* Walk through all SIDs and re-install them into the data plane with the newly configured interface */ +		for (ALL_LIST_ELEMENTS_RO(area->srv6db.srv6_sids, node2, sid)) { +			sr_debug("Installing SID %pI6 from the data plane", &sid->sid); +			isis_zebra_srv6_sid_install(area, sid); +		} +	} + +	return 0; +} +  /**   * IS-IS SRv6 initialization for given area.   * @@ -716,6 +788,7 @@ void isis_srv6_area_init(struct isis_area *area)  				       ISIS_SRV6);  	srv6db->config.max_end_d_msd =  		yang_get_default_uint8("%s/msd/node-msd/max-end-d", ISIS_SRV6); +	strncpy(srv6db->config.srv6_ifname, yang_get_default_string("%s/interface", ISIS_SRV6), IF_NAMESIZE - 1);  	/* Initialize SRv6 Locator chunks list */  	srv6db->srv6_locator_chunks = list_new(); diff --git a/isisd/isis_srv6.h b/isisd/isis_srv6.h index c0f4a477de..65c0978bc5 100644 --- a/isisd/isis_srv6.h +++ b/isisd/isis_srv6.h @@ -13,9 +13,6 @@  #include "lib/srv6.h"  #include "isisd/isis_tlvs.h" -/* Name of the interface used for installing SRv6 SIDs into the data plane */ -#define SRV6_IFNAME "sr0" -  /* SRv6 SID structure */  struct isis_srv6_sid_structure {  	uint8_t loc_block_len; @@ -135,11 +132,16 @@ struct isis_srv6_db {  		/* Maximum End D MSD supported by the router */  		uint8_t max_end_d_msd; + +		/* Interface used for installing SRv6 SIDs into the data plane */ +		char srv6_ifname[IF_NAMESIZE];  	} config;  };  bool isis_srv6_locator_unset(struct isis_area *area); +void isis_srv6_interface_set(struct isis_area *area, const char *ifname); +  struct isis_srv6_sid *  isis_srv6_sid_alloc(struct isis_area *area, struct srv6_locator_chunk *chunk,  		    enum srv6_endpoint_behavior_codepoint behavior, @@ -168,4 +170,6 @@ struct srv6_adjacency *isis_srv6_endx_sid_find(struct isis_adjacency *adj,  					       enum srv6_adj_type type);  void isis_area_delete_backup_srv6_endx_sids(struct isis_area *area, int level); +int isis_srv6_ifp_up_notify(struct interface *ifp); +  #endif /* _FRR_ISIS_SRV6_H */ diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 9df030345a..ada8f1ad29 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -942,11 +942,11 @@ void isis_zebra_srv6_sid_install(struct isis_area *area,  	}  	/* Attach the SID to the SRv6 interface */ -	ifp = if_lookup_by_name(SRV6_IFNAME, VRF_DEFAULT); +	ifp = if_lookup_by_name(area->srv6db.config.srv6_ifname, VRF_DEFAULT);  	if (!ifp) {  		zlog_warn(  			"Failed to install SRv6 SID %pI6: %s interface not found", -			&sid->sid, SRV6_IFNAME); +			&sid->sid, area->srv6db.config.srv6_ifname);  		return;  	} @@ -999,10 +999,10 @@ void isis_zebra_srv6_sid_uninstall(struct isis_area *area,  	}  	/* The SID is attached to the SRv6 interface */ -	ifp = if_lookup_by_name(SRV6_IFNAME, VRF_DEFAULT); +	ifp = if_lookup_by_name(area->srv6db.config.srv6_ifname, VRF_DEFAULT);  	if (!ifp) {  		zlog_warn("%s interface not found: nothing to uninstall", -			  SRV6_IFNAME); +			  area->srv6db.config.srv6_ifname);  		return;  	}  | 
