]> git.puffer.fish Git - mirror/frr.git/commitdiff
isisd: Make SRv6 interface configurable
authorCarmine Scarpitta <carmine.scarpitta@uniroma2.it>
Sun, 3 Sep 2023 06:54:57 +0000 (08:54 +0200)
committerCarmine Scarpitta <carmine.scarpitta@uniroma2.it>
Mon, 11 Sep 2023 20:11:51 +0000 (22:11 +0200)
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>
isisd/isis_circuit.c
isisd/isis_cli.c
isisd/isis_nb.c
isisd/isis_nb.h
isisd/isis_nb_config.c
isisd/isis_srv6.c
isisd/isis_srv6.h
isisd/isis_zebra.c

index feab45123383e3027376080b57b446bb43f042d0..ffa6ad3e402daa1852ac4c4cf87b7bf5d14406ea 100644 (file)
@@ -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;
 }
 
index 328f76b35b8e2eb0fe35286ddb7b8635ff24d776..9718a457ede57a9fc5c71f5cfb4fe443a5faf12d 100644 (file)
@@ -2238,6 +2238,33 @@ void cli_show_isis_srv6_node_msd(struct vty *vty, const struct lyd_node *dnode,
                        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
  */
@@ -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,
index 528ba4a1ad0bbf199baaa4cb360ffa650e96f746..186ebfc729daea11a978764f120a2f85ab78ba40 100644 (file)
@@ -909,6 +909,13 @@ const struct frr_yang_module_info frr_isisd_info = {
                                .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 = {
index f200c52f06be645bb47b301380b02d59620f4786..be89fd2ac68acefbc08f19bd21d73b1d1bb7d4d9 100644 (file)
@@ -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);
index 08eb91448cf5d17e5abc1d88ac9f1818d3926885..5d0089d6fb3772bf18eea12b609de88bc96d27e8 100644 (file)
@@ -3718,6 +3718,31 @@ int isis_instance_segment_routing_srv6_msd_node_msd_max_end_d_destroy(
        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
  */
index f6c05b3afe0556cde3ed32bd696986ffac2e8a10..0eb8ac3fb75fedce3d4f5a93fddc88d84d9a997e 100644 (file)
@@ -157,6 +157,46 @@ bool isis_srv6_locator_unset(struct isis_area *area)
        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.
  *
@@ -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();
index c0f4a477de2447ff7e33d39b55c64cecfc6409f5..65c0978bc55aa5c799ac9b7e9a64d4a95cc8687b 100644 (file)
@@ -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 */
index 9df030345a592e6183051bb73b56d582cc4cad8f..ada8f1ad297bc911f9e5d1568c154556aedd7b2a 100644 (file)
@@ -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;
        }