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 /isisd | |
parent | yang: Add SRv6 interface to IS-IS YANG model (diff) | |
download | frr-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.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 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; } |