summaryrefslogtreecommitdiffstats
path: root/isisd
diff options
context:
space:
mode:
authorCarmine Scarpitta <carmine.scarpitta@uniroma2.it>2023-09-03 08:54:57 +0200
committerCarmine Scarpitta <carmine.scarpitta@uniroma2.it>2023-09-11 22:11:51 +0200
commitbfec26bc7a59698f82e66d1c7a6ae64909191a83 (patch)
treefad612f17f878dc78f297cfaac56cad557372fa2 /isisd
parentyang: Add SRv6 interface to IS-IS YANG model (diff)
downloadfrr-bfec26bc7a59698f82e66d1c7a6ae64909191a83.tar.xz
frr-bfec26bc7a59698f82e66d1c7a6ae64909191a83.zip
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>
Diffstat (limited to 'isisd')
-rw-r--r--isisd/isis_circuit.c4
-rw-r--r--isisd/isis_cli.c28
-rw-r--r--isisd/isis_nb.c7
-rw-r--r--isisd/isis_nb.h4
-rw-r--r--isisd/isis_nb_config.c25
-rw-r--r--isisd/isis_srv6.c73
-rw-r--r--isisd/isis_srv6.h10
-rw-r--r--isisd/isis_zebra.c8
8 files changed, 152 insertions, 7 deletions
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index feab45123..ffa6ad3e4 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 328f76b35..9718a457e 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 528ba4a1a..186ebfc72 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 f200c52f0..be89fd2ac 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 08eb91448..5d0089d6f 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 f6c05b3af..0eb8ac3fb 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 c0f4a477d..65c0978bc 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 9df030345..ada8f1ad2 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;
}