]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: add 'mpls label dynamic-block' command
authorPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 3 Oct 2023 08:22:05 +0000 (10:22 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 18 Oct 2023 07:41:02 +0000 (09:41 +0200)
Hardset label values (eg. ISIS Segment-routing label blocks,
hardset BGP L3VPN service label) may conflict with label chunks
dynamically allocated by zebra.

Add an optional 'mpls label dynamic-block' command to let the user
define a range that is not in conflict with the hardset values.
Restarting control planes is recommended when dynamic label
chunks are already allocated. Command is aborted when any hardset
label chunks conflict with the dynamic block.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
zebra/label_manager.c
zebra/label_manager.h
zebra/zebra_mpls_vty.c

index 32dc2cd250f649dbd35650a7e2871611081009c2..3fc1ee5bae8b08202d2f51debfe7b6bffbb282f4 100644 (file)
@@ -51,10 +51,14 @@ DEFINE_HOOK(lm_get_chunk,
 DEFINE_HOOK(lm_release_chunk,
             (struct zserv *client, uint32_t start, uint32_t end),
             (client, start, end));
+/* show running-config needs an API for dynamic-block */
+DEFINE_HOOK(lm_write_label_block_config,
+           (struct vty *vty, struct zebra_vrf *zvrf),
+           (vty, zvrf));
 DEFINE_HOOK(lm_cbs_inited, (), ());
 
-/* define wrappers to be called in zapi_msg.c (as hooks must be called in
- * source file where they were defined)
+/* define wrappers to be called in zapi_msg.c or zebra_mpls_vty.c (as hooks
+ * must be called in source file where they were defined)
  */
 void lm_client_connect_call(struct zserv *client, vrf_id_t vrf_id)
 {
@@ -71,6 +75,11 @@ void lm_release_chunk_call(struct zserv *client, uint32_t start, uint32_t end)
        hook_call(lm_release_chunk, client, start, end);
 }
 
+int lm_write_label_block_config_call(struct vty *vty, struct zebra_vrf *zvrf)
+{
+       return hook_call(lm_write_label_block_config, vty, zvrf);
+}
+
 /* forward declarations of the static functions to be used for some hooks */
 static int label_manager_connect(struct zserv *client, vrf_id_t vrf_id);
 static int label_manager_disconnect(struct zserv *client);
@@ -80,6 +89,8 @@ static int label_manager_get_chunk(struct label_manager_chunk **lmc,
                                   vrf_id_t vrf_id);
 static int label_manager_release_label_chunk(struct zserv *client,
                                             uint32_t start, uint32_t end);
+static int label_manager_write_label_block_config(struct vty *vty,
+                                                 struct zebra_vrf *zvrf);
 
 void delete_label_chunk(void *val)
 {
@@ -138,6 +149,8 @@ void lm_hooks_register(void)
        hook_register(lm_client_disconnect, label_manager_disconnect);
        hook_register(lm_get_chunk, label_manager_get_chunk);
        hook_register(lm_release_chunk, label_manager_release_label_chunk);
+       hook_register(lm_write_label_block_config,
+                     label_manager_write_label_block_config);
 }
 void lm_hooks_unregister(void)
 {
@@ -145,6 +158,8 @@ void lm_hooks_unregister(void)
        hook_unregister(lm_client_disconnect, label_manager_disconnect);
        hook_unregister(lm_get_chunk, label_manager_get_chunk);
        hook_unregister(lm_release_chunk, label_manager_release_label_chunk);
+       hook_unregister(lm_write_label_block_config,
+                       label_manager_write_label_block_config);
 }
 
 DEFPY(show_label_table, show_label_table_cmd, "show debugging label-table",
@@ -163,6 +178,73 @@ DEFPY(show_label_table, show_label_table_cmd, "show debugging label-table",
        return CMD_SUCCESS;
 }
 
+DEFPY(mpls_label_dynamic_block, mpls_label_dynamic_block_cmd,
+      "[no$no] mpls label dynamic-block [(16-1048575)$start (16-1048575)$end]",
+      NO_STR
+      MPLS_STR
+      "Label configuration\n"
+      "Configure dynamic label block\n"
+      "Start label\n"
+      "End label\n")
+{
+       struct listnode *node;
+       struct label_manager_chunk *lmc;
+
+       /* unset dynamic range */
+       if (no ||
+           (start == MPLS_LABEL_UNRESERVED_MIN && end == MPLS_LABEL_MAX)) {
+               lbl_mgr.dynamic_block_start = MPLS_LABEL_UNRESERVED_MIN;
+               lbl_mgr.dynamic_block_end = MPLS_LABEL_MAX;
+               return CMD_SUCCESS;
+       }
+       if (!start || !end) {
+               vty_out(vty,
+                       "%% label dynamic-block, range missing, aborting\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+       if (start > end) {
+               vty_out(vty,
+                       "%% label dynamic-block, wrong range (%ld > %ld), aborting\n",
+                       start, end);
+               return CMD_WARNING_CONFIG_FAILED;
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) {
+               if (lmc->proto == NO_PROTO)
+                       continue;
+               if (!lmc->is_dynamic && lmc->start >= (uint32_t)start &&
+                   lmc->end <= (uint32_t)end) {
+                       vty_out(vty,
+                               "%% Found a static label chunk [%u-%u] for %s in conflict with the dynamic label block\n",
+                               lmc->start, lmc->end,
+                               zebra_route_string(lmc->proto));
+                       return CMD_WARNING_CONFIG_FAILED;
+               } else if (lmc->is_dynamic && (lmc->end > (uint32_t)end ||
+                                              lmc->start < (uint32_t)start)) {
+                       vty_out(vty,
+                               "%% Found a dynamic label chunk [%u-%u] for %s outside the new dynamic label block, consider restart the service\n",
+                               lmc->start, lmc->end,
+                               zebra_route_string(lmc->proto));
+               }
+       }
+       lbl_mgr.dynamic_block_start = start;
+       lbl_mgr.dynamic_block_end = end;
+       return CMD_SUCCESS;
+}
+
+static int label_manager_write_label_block_config(struct vty *vty,
+                                                 struct zebra_vrf *zvrf)
+{
+       if (zvrf_id(zvrf) != VRF_DEFAULT)
+               return 0;
+       if (lbl_mgr.dynamic_block_start == MPLS_LABEL_UNRESERVED_MIN &&
+           lbl_mgr.dynamic_block_end == MPLS_LABEL_MAX)
+               return 0;
+       vty_out(vty, "mpls label dynamic-block %u %u\n",
+               lbl_mgr.dynamic_block_start, lbl_mgr.dynamic_block_end);
+       return 1;
+}
+
 /**
  * Init label manager (or proxy to an external one)
  */
@@ -170,6 +252,8 @@ void label_manager_init(void)
 {
        lbl_mgr.lc_list = list_new();
        lbl_mgr.lc_list->del = delete_label_chunk;
+       lbl_mgr.dynamic_block_start = MPLS_LABEL_UNRESERVED_MIN;
+       lbl_mgr.dynamic_block_end = MPLS_LABEL_MAX;
        hook_register(zserv_client_close, lm_client_disconnect_cb);
 
        /* register default hooks for the label manager actions */
@@ -179,6 +263,7 @@ void label_manager_init(void)
        hook_call(lm_cbs_inited);
 
        install_element(VIEW_NODE, &show_label_table_cmd);
+       install_element(CONFIG_NODE, &mpls_label_dynamic_block_cmd);
 }
 
 /* alloc and fill a label chunk */
index df9513281f070d9127b76e938b5842909ce93312..ab6ad7f639e2454527cecf81dd35f4dfeae04328 100644 (file)
@@ -62,11 +62,14 @@ DECLARE_HOOK(lm_get_chunk,
 DECLARE_HOOK(lm_release_chunk,
             (struct zserv *client, uint32_t start, uint32_t end),
             (client, start, end));
+DECLARE_HOOK(lm_write_label_block_config,
+            (struct vty *vty, struct zebra_vrf *zvrf),
+            (vty, zvrf));
 DECLARE_HOOK(lm_cbs_inited, (), ());
 
 
-/* declare wrappers to be called in zapi_msg.c (as hooks must be called in
- * source file where they were defined)
+/* declare wrappers to be called in zapi_msg.c or zebra_mpls_vty.c (as hooks
+ * must be called in source file where they were defined)
  */
 void lm_client_connect_call(struct zserv *client, vrf_id_t vrf_id);
 void lm_get_chunk_call(struct label_manager_chunk **lmc, struct zserv *client,
@@ -74,6 +77,7 @@ void lm_get_chunk_call(struct label_manager_chunk **lmc, struct zserv *client,
                       vrf_id_t vrf_id);
 void lm_release_chunk_call(struct zserv *client, uint32_t start,
                           uint32_t end);
+int lm_write_label_block_config_call(struct vty *vty, struct zebra_vrf *zvrf);
 
 /* API for an external LM to return responses for requests */
 int lm_client_connect_response(uint8_t proto, uint16_t instance,
@@ -96,6 +100,8 @@ void lm_hooks_unregister(void);
  */
 struct label_manager {
        struct list *lc_list;
+       uint32_t dynamic_block_start;
+       uint32_t dynamic_block_end;
 };
 
 void label_manager_init(void);
index e64e7009b4d2422692066af6c9207bb396d76dbe..fd09e6b444464f5c4a22c633a63b2d34714f4dd2 100644 (file)
@@ -22,6 +22,7 @@
 #include "zebra/zebra_rnh.h"
 #include "zebra/redistribute.h"
 #include "zebra/zebra_routemap.h"
+#include "zebra/label_manager.h"
 
 static int zebra_mpls_transit_lsp(struct vty *vty, int add_cmd,
                                  const char *inlabel_str, const char *gate_str,
@@ -270,6 +271,8 @@ static int zebra_mpls_config(struct vty *vty)
        write += zebra_mpls_write_lsp_config(vty, zvrf);
        write += zebra_mpls_write_fec_config(vty, zvrf);
        write += zebra_mpls_write_label_block_config(vty, zvrf);
+       write += lm_write_label_block_config_call(vty, zvrf);
+
        return write;
 }