summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_labelpool.c368
-rw-r--r--bgpd/bgp_labelpool.h2
-rw-r--r--bgpd/bgpd.c2
-rw-r--r--bgpd/subdir.am1
-rw-r--r--doc/user/bgp.rst26
5 files changed, 399 insertions, 0 deletions
diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c
index e8d8167c35..c191165ef9 100644
--- a/bgpd/bgp_labelpool.c
+++ b/bgpd/bgp_labelpool.c
@@ -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);
+}
diff --git a/bgpd/bgp_labelpool.h b/bgpd/bgp_labelpool.h
index eaa3fce20b..d9f64acfe4 100644
--- a/bgpd/bgp_labelpool.h
+++ b/bgpd/bgp_labelpool.h
@@ -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 */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index b6afa391f3..fa40611c48 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -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);
}
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index ea60b921d1..ac84f4b9e4 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -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 \
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index e0e16aaeeb..ddd87c2017 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -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