From: Pat Ruddy Date: Fri, 4 Dec 2020 12:14:26 +0000 (+0000) Subject: bgpd: add show commands for bgp labelpool X-Git-Tag: base_7.6~69^2~7 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=e3ea65039e8e17144e0cb91d9c93d4fc3f949e1d;p=mirror%2Ffrr.git bgpd: add show commands for bgp labelpool These commands allow the bgp labelpool lists and counts to be viewed for debug purposes. Signed-off-by: Pat Ruddy --- 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 [json] +.. clicmd:: show bgp labelpool [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