#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_errors.h"
#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_rd.h"
#define BGP_LABELPOOL_ENABLE_TESTS 0
lcb->label);
break;
+ case LP_TYPE_NEXTHOP:
+ if (uj) {
+ json_object_string_add(json_elem, "prefix",
+ "nexthop");
+ json_object_int_add(json_elem, "label",
+ lcb->label);
+ } else
+ vty_out(vty, "%-18s %u\n", "nexthop",
+ lcb->label);
+ break;
}
}
if (uj)
vty_out(vty, "%-18s %u\n", "VRF",
label);
break;
+ case LP_TYPE_NEXTHOP:
+ if (uj) {
+ json_object_string_add(json_elem, "prefix",
+ "nexthop");
+ json_object_int_add(json_elem, "label", label);
+ } else
+ vty_out(vty, "%-18s %u\n", "nexthop",
+ label);
+ break;
}
}
if (uj)
else
vty_out(vty, "VRF\n");
break;
+ case LP_TYPE_NEXTHOP:
+ if (uj)
+ json_object_string_add(json_elem, "prefix",
+ "nexthop");
+ else
+ vty_out(vty, "Nexthop\n");
+ break;
}
}
if (uj)
return CMD_SUCCESS;
}
+static void show_bgp_nexthop_label_afi(struct vty *vty, afi_t afi,
+ struct bgp *bgp, bool detail)
+{
+ struct bgp_label_per_nexthop_cache_head *tree;
+ struct bgp_label_per_nexthop_cache *iter;
+ safi_t safi;
+ void *src;
+ char buf[PREFIX2STR_BUFFER];
+ char labelstr[MPLS_LABEL_STRLEN];
+ struct bgp_dest *dest;
+ struct bgp_path_info *path;
+ struct bgp *bgp_path;
+ struct bgp_table *table;
+ time_t tbuf;
+
+ vty_out(vty, "Current BGP label nexthop cache for %s, VRF %s\n",
+ afi2str(afi), bgp->name_pretty);
+
+ tree = &bgp->mpls_labels_per_nexthop[afi];
+ frr_each (bgp_label_per_nexthop_cache, tree, iter) {
+ if (afi2family(afi) == AF_INET)
+ src = (void *)&iter->nexthop.u.prefix4;
+ else
+ src = (void *)&iter->nexthop.u.prefix6;
+
+ vty_out(vty, " %s, label %s #paths %u\n",
+ inet_ntop(afi2family(afi), src, buf, sizeof(buf)),
+ mpls_label2str(1, &iter->label, labelstr,
+ sizeof(labelstr), 0, true),
+ iter->path_count);
+ if (iter->nh)
+ vty_out(vty, " if %s\n",
+ ifindex2ifname(iter->nh->ifindex,
+ iter->nh->vrf_id));
+ tbuf = time(NULL) - (monotime(NULL) - iter->last_update);
+ vty_out(vty, " Last update: %s", ctime(&tbuf));
+ if (!detail)
+ continue;
+ vty_out(vty, " Paths:\n");
+ LIST_FOREACH (path, &(iter->paths), label_nh_thread) {
+ dest = path->net;
+ table = bgp_dest_table(dest);
+ assert(dest && table);
+ afi = family2afi(bgp_dest_get_prefix(dest)->family);
+ safi = table->safi;
+ bgp_path = table->bgp;
+
+ if (dest->pdest) {
+ vty_out(vty, " %d/%d %pBD RD ", afi, safi,
+ dest);
+
+ vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation),
+ (struct prefix_rd *)bgp_dest_get_prefix(
+ dest->pdest));
+ vty_out(vty, " %s flags 0x%x\n",
+ bgp_path->name_pretty, path->flags);
+ } else
+ vty_out(vty, " %d/%d %pBD %s flags 0x%x\n",
+ afi, safi, dest, bgp_path->name_pretty,
+ path->flags);
+ }
+ }
+}
+
+DEFPY(show_bgp_nexthop_label, show_bgp_nexthop_label_cmd,
+ "show bgp [<view|vrf> VIEWVRFNAME] label-nexthop [detail]",
+ SHOW_STR BGP_STR BGP_INSTANCE_HELP_STR
+ "BGP label per-nexthop table\n"
+ "Show detailed information\n")
+{
+ int idx = 0;
+ char *vrf = NULL;
+ struct bgp *bgp;
+ bool detail = false;
+ int afi;
+
+ if (argv_find(argv, argc, "vrf", &idx)) {
+ vrf = argv[++idx]->arg;
+ bgp = bgp_lookup_by_name(vrf);
+ } else
+ bgp = bgp_get_default();
+
+ if (!bgp)
+ return CMD_SUCCESS;
+
+ if (argv_find(argv, argc, "detail", &idx))
+ detail = true;
+
+ for (afi = AFI_IP; afi <= AFI_IP6; afi++)
+ show_bgp_nexthop_label_afi(vty, afi, bgp, detail);
+ return CMD_SUCCESS;
+}
+
#if BGP_LABELPOOL_ENABLE_TESTS
/*------------------------------------------------------------------------
* Testing code start
install_element(ENABLE_NODE, &clear_labelpool_perf_test_cmd);
#endif /* BGP_LABELPOOL_ENABLE_TESTS */
}
+
+DEFINE_MTYPE_STATIC(BGPD, LABEL_PER_NEXTHOP_CACHE,
+ "BGP Label Per Nexthop entry");
+
+/* The nexthops values are compared to
+ * find in the tree the appropriate cache entry
+ */
+int bgp_label_per_nexthop_cache_cmp(const struct bgp_label_per_nexthop_cache *a,
+ const struct bgp_label_per_nexthop_cache *b)
+{
+ return prefix_cmp(&a->nexthop, &b->nexthop);
+}
+
+struct bgp_label_per_nexthop_cache *
+bgp_label_per_nexthop_new(struct bgp_label_per_nexthop_cache_head *tree,
+ struct prefix *nexthop)
+{
+ struct bgp_label_per_nexthop_cache *blnc;
+
+ blnc = XCALLOC(MTYPE_LABEL_PER_NEXTHOP_CACHE,
+ sizeof(struct bgp_label_per_nexthop_cache));
+ blnc->tree = tree;
+ blnc->label = MPLS_INVALID_LABEL;
+ prefix_copy(&blnc->nexthop, nexthop);
+ LIST_INIT(&(blnc->paths));
+ bgp_label_per_nexthop_cache_add(tree, blnc);
+
+ return blnc;
+}
+
+struct bgp_label_per_nexthop_cache *
+bgp_label_per_nexthop_find(struct bgp_label_per_nexthop_cache_head *tree,
+ struct prefix *nexthop)
+{
+ struct bgp_label_per_nexthop_cache blnc = {};
+
+ if (!tree)
+ return NULL;
+
+ memcpy(&blnc.nexthop, nexthop, sizeof(struct prefix));
+ return bgp_label_per_nexthop_cache_find(tree, &blnc);
+}
+
+void bgp_label_per_nexthop_free(struct bgp_label_per_nexthop_cache *blnc)
+{
+ if (blnc->label != MPLS_INVALID_LABEL) {
+ bgp_zebra_send_nexthop_label(ZEBRA_MPLS_LABELS_DELETE,
+ blnc->label, blnc->nh->ifindex,
+ blnc->nh->vrf_id, ZEBRA_LSP_BGP,
+ &blnc->nexthop);
+ bgp_lp_release(LP_TYPE_NEXTHOP, blnc, blnc->label);
+ }
+ bgp_label_per_nexthop_cache_del(blnc->tree, blnc);
+ if (blnc->nh)
+ nexthop_free(blnc->nh);
+ blnc->nh = NULL;
+ XFREE(MTYPE_LABEL_PER_NEXTHOP_CACHE, blnc);
+}
+
+void bgp_label_per_nexthop_init(void)
+{
+ install_element(VIEW_NODE, &show_bgp_nexthop_label_cmd);
+}