]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: add show commands for bgp labelpool
authorPat Ruddy <pat@voltanet.io>
Fri, 4 Dec 2020 12:14:26 +0000 (12:14 +0000)
committerPat Ruddy <pat@voltanet.io>
Mon, 4 Jan 2021 14:29:35 +0000 (14:29 +0000)
These commands allow the bgp labelpool lists and counts to be
viewed for debug purposes.

Signed-off-by: Pat Ruddy <pat@voltanet.io>
bgpd/bgp_labelpool.c
bgpd/bgp_labelpool.h
bgpd/bgpd.c
bgpd/subdir.am
doc/user/bgp.rst

index e8d8167c35f1f7477d42708b2023b3f068a8767c..c191165ef9209d86d41230a70e0808c200bc98ff 100644 (file)
@@ -538,6 +538,7 @@ void bgp_lp_event_zebra_up(void)
        struct lp_lcb *lcb;
        int lm_init_ok;
 
+       lp->reconnect_count++;
        /*
         * Get label chunk allocation request dispatched to zebra
         */
@@ -607,3 +608,370 @@ void bgp_lp_event_zebra_up(void)
                skiplist_delete_first(lp->inuse);
        }
 }
+
+DEFUN(show_bgp_labelpool_summary, show_bgp_labelpool_summary_cmd,
+      "show bgp labelpool summary [json]",
+      SHOW_STR BGP_STR
+      "BGP Labelpool information\n"
+      "BGP Labelpool summary\n" JSON_STR)
+{
+       bool uj = use_json(argc, argv);
+       json_object *json = NULL;
+
+       if (!lp) {
+               if (uj)
+                       vty_out(vty, "{}\n");
+               else
+                       vty_out(vty, "No existing BGP labelpool\n");
+               return (CMD_WARNING);
+       }
+
+       if (uj) {
+               json = json_object_new_object();
+               json_object_int_add(json, "Ledger", skiplist_count(lp->ledger));
+               json_object_int_add(json, "InUse", skiplist_count(lp->inuse));
+               json_object_int_add(json, "Requests",
+                                   lp_fifo_count(&lp->requests));
+               json_object_int_add(json, "LabelChunks", listcount(lp->chunks));
+               json_object_int_add(json, "Pending", lp->pending_count);
+               json_object_int_add(json, "Reconnects", lp->reconnect_count);
+               vty_out(vty, "%s\n",
+                       json_object_to_json_string_ext(
+                               json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       } else {
+               vty_out(vty, "Labelpool Summary\n");
+               vty_out(vty, "-----------------\n");
+               vty_out(vty, "%-13s %d\n",
+                       "Ledger:", skiplist_count(lp->ledger));
+               vty_out(vty, "%-13s %d\n", "InUse:", skiplist_count(lp->inuse));
+               vty_out(vty, "%-13s %zu\n",
+                       "Requests:", lp_fifo_count(&lp->requests));
+               vty_out(vty, "%-13s %d\n",
+                       "LabelChunks:", listcount(lp->chunks));
+               vty_out(vty, "%-13s %d\n", "Pending:", lp->pending_count);
+               vty_out(vty, "%-13s %d\n", "Reconnects:", lp->reconnect_count);
+       }
+       return CMD_SUCCESS;
+}
+
+DEFUN(show_bgp_labelpool_ledger, show_bgp_labelpool_ledger_cmd,
+      "show bgp labelpool ledger [json]",
+      SHOW_STR BGP_STR
+      "BGP Labelpool information\n"
+      "BGP Labelpool ledger\n" JSON_STR)
+{
+       bool uj = use_json(argc, argv);
+       json_object *json = NULL, *json_elem = NULL;
+       struct lp_lcb *lcb = NULL;
+       struct bgp_path_info *pi;
+       void *cursor = NULL;
+       const struct prefix *p;
+       int rc, count;
+
+       if (!lp) {
+               if (uj)
+                       vty_out(vty, "{}\n");
+               else
+                       vty_out(vty, "No existing BGP labelpool\n");
+               return (CMD_WARNING);
+       }
+
+       if (uj) {
+               count = skiplist_count(lp->ledger);
+               if (!count) {
+                       vty_out(vty, "{}\n");
+                       return CMD_SUCCESS;
+               }
+               json = json_object_new_array();
+       } else {
+               vty_out(vty, "Prefix                Label\n");
+               vty_out(vty, "---------------------------\n");
+       }
+
+       for (rc = skiplist_next(lp->ledger, (void **)&pi, (void **)&lcb,
+                               &cursor);
+            !rc; rc = skiplist_next(lp->ledger, (void **)&pi, (void **)&lcb,
+                                    &cursor)) {
+               if (uj) {
+                       json_elem = json_object_new_object();
+                       json_object_array_add(json, json_elem);
+               }
+               switch (lcb->type) {
+               case LP_TYPE_BGP_LU:
+                       if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
+                               if (uj) {
+                                       json_object_string_add(
+                                               json_elem, "prefix", "INVALID");
+                                       json_object_int_add(json_elem, "label",
+                                                           lcb->label);
+                               } else
+                                       vty_out(vty, "%-18s         %u\n",
+                                               "INVALID", lcb->label);
+                       else {
+                               char buf[PREFIX2STR_BUFFER];
+                               p = bgp_dest_get_prefix(pi->net);
+                               prefix2str(p, buf, sizeof(buf));
+                               if (uj) {
+                                       json_object_string_add(json_elem,
+                                                              "prefix", buf);
+                                       json_object_int_add(json_elem, "label",
+                                                           lcb->label);
+                               } else
+                                       vty_out(vty, "%-18s    %u\n", buf,
+                                               lcb->label);
+                       }
+                       break;
+               case LP_TYPE_VRF:
+                       if (uj) {
+                               json_object_string_add(json_elem, "prefix",
+                                                      "VRF");
+                               json_object_int_add(json_elem, "label",
+                                                   lcb->label);
+                       } else
+                               vty_out(vty, "%-18s         %u\n", "VRF",
+                                       lcb->label);
+
+                       break;
+               }
+       }
+       if (uj) {
+               vty_out(vty, "%s\n",
+                       json_object_to_json_string_ext(
+                               json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+       return CMD_SUCCESS;
+}
+
+DEFUN(show_bgp_labelpool_inuse, show_bgp_labelpool_inuse_cmd,
+      "show bgp labelpool inuse [json]",
+      SHOW_STR BGP_STR
+      "BGP Labelpool information\n"
+      "BGP Labelpool inuse\n" JSON_STR)
+{
+       bool uj = use_json(argc, argv);
+       json_object *json = NULL, *json_elem = NULL;
+       struct bgp_path_info *pi;
+       mpls_label_t label;
+       struct lp_lcb *lcb;
+       void *cursor = NULL;
+       const struct prefix *p;
+       int rc, count;
+
+       if (!lp) {
+               vty_out(vty, "No existing BGP labelpool\n");
+               return (CMD_WARNING);
+       }
+       if (!lp) {
+               if (uj)
+                       vty_out(vty, "{}\n");
+               else
+                       vty_out(vty, "No existing BGP labelpool\n");
+               return (CMD_WARNING);
+       }
+
+       if (uj) {
+               count = skiplist_count(lp->inuse);
+               if (!count) {
+                       vty_out(vty, "{}\n");
+                       return CMD_SUCCESS;
+               }
+               json = json_object_new_array();
+       } else {
+               vty_out(vty, "Prefix                Label\n");
+               vty_out(vty, "---------------------------\n");
+       }
+       for (rc = skiplist_next(lp->inuse, (void **)&label, (void **)&pi,
+                               &cursor);
+            !rc; rc = skiplist_next(lp->ledger, (void **)&label, (void **)&pi,
+                                    &cursor)) {
+               if (skiplist_search(lp->ledger, pi, (void **)&lcb))
+                       continue;
+
+               if (uj) {
+                       json_elem = json_object_new_object();
+                       json_object_array_add(json, json_elem);
+               }
+
+               switch (lcb->type) {
+               case LP_TYPE_BGP_LU:
+                       if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
+                               if (uj) {
+                                       json_object_string_add(
+                                               json_elem, "prefix", "INVALID");
+                                       json_object_int_add(json_elem, "label",
+                                                           label);
+                               } else
+                                       vty_out(vty, "INVALID         %u\n",
+                                               label);
+                       else {
+                               char buf[PREFIX2STR_BUFFER];
+                               p = bgp_dest_get_prefix(pi->net);
+                               prefix2str(p, buf, sizeof(buf));
+                               if (uj) {
+                                       json_object_string_add(json_elem,
+                                                              "prefix", buf);
+                                       json_object_int_add(json_elem, "label",
+                                                           label);
+                               } else
+                                       vty_out(vty, "%-18s    %u\n", buf,
+                                               label);
+                       }
+                       break;
+               case LP_TYPE_VRF:
+                       if (uj) {
+                               json_object_string_add(json_elem, "prefix",
+                                                      "VRF");
+                               json_object_int_add(json_elem, "label", label);
+                       } else
+                               vty_out(vty, "%-18s         %u\n", "VRF",
+                                       label);
+                       break;
+               }
+       }
+       if (uj) {
+               vty_out(vty, "%s\n",
+                       json_object_to_json_string_ext(
+                               json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+       return CMD_SUCCESS;
+}
+
+DEFUN(show_bgp_labelpool_requests, show_bgp_labelpool_requests_cmd,
+      "show bgp labelpool requests [json]",
+      SHOW_STR BGP_STR
+      "BGP Labelpool information\n"
+      "BGP Labelpool requests\n" JSON_STR)
+{
+       bool uj = use_json(argc, argv);
+       json_object *json = NULL, *json_elem = NULL;
+       struct bgp_path_info *pi;
+       const struct prefix *p;
+       char buf[PREFIX2STR_BUFFER];
+       struct lp_fifo *item, *next;
+       int count;
+
+       if (!lp) {
+               if (uj)
+                       vty_out(vty, "{}\n");
+               else
+                       vty_out(vty, "No existing BGP labelpool\n");
+               return (CMD_WARNING);
+       }
+
+       if (uj) {
+               count = lp_fifo_count(&lp->requests);
+               if (!count) {
+                       vty_out(vty, "{}\n");
+                       return CMD_SUCCESS;
+               }
+               json = json_object_new_array();
+       } else {
+               vty_out(vty, "Prefix         \n");
+               vty_out(vty, "----------------\n");
+       }
+
+       for (item = lp_fifo_first(&lp->requests); item; item = next) {
+               next = lp_fifo_next_safe(&lp->requests, item);
+               pi = item->lcb.labelid;
+               if (uj) {
+                       json_elem = json_object_new_object();
+                       json_object_array_add(json, json_elem);
+               }
+               switch (item->lcb.type) {
+               case LP_TYPE_BGP_LU:
+                       if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) {
+                               if (uj)
+                                       json_object_string_add(
+                                               json_elem, "prefix", "INVALID");
+                               else
+                                       vty_out(vty, "INVALID\n");
+                       } else {
+                               p = bgp_dest_get_prefix(pi->net);
+                               prefix2str(p, buf, sizeof(buf));
+                               if (uj)
+                                       json_object_string_add(json_elem,
+                                                              "prefix", buf);
+                               else
+                                       vty_out(vty, "%-18s\n", buf);
+                       }
+                       break;
+               case LP_TYPE_VRF:
+                       if (uj)
+                               json_object_string_add(json_elem, "prefix",
+                                                      "VRF");
+                       else
+                               vty_out(vty, "VRF\n");
+                       break;
+               }
+       }
+       if (uj) {
+               vty_out(vty, "%s\n",
+                       json_object_to_json_string_ext(
+                               json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+       return CMD_SUCCESS;
+}
+
+DEFUN(show_bgp_labelpool_chunks, show_bgp_labelpool_chunks_cmd,
+      "show bgp labelpool chunks [json]",
+      SHOW_STR BGP_STR
+      "BGP Labelpool information\n"
+      "BGP Labelpool chunks\n" JSON_STR)
+{
+       bool uj = use_json(argc, argv);
+       json_object *json = NULL, *json_elem;
+       struct listnode *node;
+       struct lp_chunk *chunk;
+       int count;
+
+       if (!lp) {
+               if (uj)
+                       vty_out(vty, "{}\n");
+               else
+                       vty_out(vty, "No existing BGP labelpool\n");
+               return (CMD_WARNING);
+       }
+
+       if (uj) {
+               count = listcount(lp->chunks);
+               if (!count) {
+                       vty_out(vty, "{}\n");
+                       return CMD_SUCCESS;
+               }
+               json = json_object_new_array();
+       } else {
+               vty_out(vty, "First    Last\n");
+               vty_out(vty, "--------------\n");
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(lp->chunks, node, chunk)) {
+               if (uj) {
+                       json_elem = json_object_new_object();
+                       json_object_array_add(json, json_elem);
+                       json_object_int_add(json_elem, "first", chunk->first);
+                       json_object_int_add(json_elem, "last", chunk->last);
+               } else
+                       vty_out(vty, "%-10u %-10u\n", chunk->first,
+                               chunk->last);
+       }
+       if (uj) {
+               vty_out(vty, "%s\n",
+                       json_object_to_json_string_ext(
+                               json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       }
+       return CMD_SUCCESS;
+}
+
+void bgp_lp_vty_init(void)
+{
+       install_element(VIEW_NODE, &show_bgp_labelpool_summary_cmd);
+       install_element(VIEW_NODE, &show_bgp_labelpool_ledger_cmd);
+       install_element(VIEW_NODE, &show_bgp_labelpool_inuse_cmd);
+       install_element(VIEW_NODE, &show_bgp_labelpool_requests_cmd);
+       install_element(VIEW_NODE, &show_bgp_labelpool_chunks_cmd);
+}
index eaa3fce20b107dc793d9f8980058f12cddc83b78..d9f64acfe40002f25d4e87492c151cf83f8c8ce0 100644 (file)
@@ -40,6 +40,7 @@ struct labelpool {
        struct lp_fifo_head     requests;       /* blocked on zebra */
        struct work_queue       *callback_q;
        uint32_t                pending_count;  /* requested from zebra */
+       uint32_t reconnect_count;               /* zebra reconnections */
 };
 
 extern void bgp_lp_init(struct thread_master *master, struct labelpool *pool);
@@ -50,5 +51,6 @@ extern void bgp_lp_release(int type, void *labelid, mpls_label_t label);
 extern void bgp_lp_event_chunk(uint8_t keep, uint32_t first, uint32_t last);
 extern void bgp_lp_event_zebra_down(void);
 extern void bgp_lp_event_zebra_up(void);
+extern void bgp_lp_vty_init(void);
 
 #endif /* _FRR_BGP_LABELPOOL_H */
index b6afa391f34528e8d6ecf0b60d9aba71e2cb4c32..fa40611c48e014fdb13a17fe85b76d14935cc543 100644 (file)
@@ -7613,6 +7613,8 @@ void bgp_init(unsigned short instance)
        /* BFD init */
        bgp_bfd_init();
 
+       bgp_lp_vty_init();
+
        cmd_variable_handler_register(bgp_viewvrf_var_handlers);
 }
 
index ea60b921d1b5c5888b078b3e98dabdf560172fd8..ac84f4b9e4880599c97e4dbbcccc14a871155ffe 100644 (file)
@@ -18,6 +18,7 @@ vtysh_scan += \
        bgpd/bgp_evpn_mh.c \
        bgpd/bgp_evpn_vty.c \
        bgpd/bgp_filter.c \
+       bgpd/bgp_labelpool.c \
        bgpd/bgp_mplsvpn.c \
        bgpd/bgp_nexthop.c \
        bgpd/bgp_route.c \
index e0e16aaeebd9e99cfed73a18e09741ff0f22fde7..ddd87c2017de76fed169763ad9ab2342812d9dc7 100644 (file)
@@ -3373,6 +3373,32 @@ attribute.
 
    If ``json`` option is specified, output is displayed in JSON format.
 
+.. index:: show bgp labelpool <chunks|inuse|ledger|requests|summary> [json] 
+.. clicmd:: show bgp labelpool <chunks|inuse|ledger|requests|summary> [json]
+
+   These commands display information about the BGP labelpool used for
+   the association of MPLS labels with routes for L3VPN and Labeled Unicast
+
+   If ``chunks`` option is specified, output shows the current list of label
+   chunks granted to BGP by Zebra, indicating the start and end label in
+   each chunk
+
+   If ``inuse`` option is specified, output shows the current inuse list of
+   label to prefix mappings
+
+   If ``ledger`` option is specified, output shows ledger list of all
+   label requests made per prefix
+
+   If ``requests`` option is specified, output shows current list of label
+   requests which have not yet been fulfilled by the labelpool
+
+   If ``summary`` option is specified, output is a summary of the counts for
+   the chunks, inuse, ledger and requests list along with the count of
+   outstanding chunk requests to Zebra and the nummber of zebra reconnects
+   that have happened
+
+   If ``json`` option is specified, output is displayed in JSON format.
+
 .. _bgp-display-routes-by-lcommunity:
 
 Displaying Routes by Large Community Attribute