#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"
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;
}
yang_dnode_get_uint8(dnode, "./max-end-d"));
}
+/*
+ * 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
*/
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,
.cli_show = cli_show_isis_srv6_node_msd,
},
},
+ {
+ .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 = {
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);
return NB_OK;
}
+/*
+ * 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
*/
return true;
}
+/**
+ * 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.
*
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.
*
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();
#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;
/* 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,
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 */
}
/* 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;
}
}
/* 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;
}