summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvivek <vivek@cumulusnetworks.com>2020-05-25 13:48:37 -0700
committervivek <vivek@cumulusnetworks.com>2020-05-25 13:57:53 -0700
commit5d76a53dfc54e00bb9f8395e15c02b490a2df3ad (patch)
tree08782e763f360927d9b34abba573f994cc3e69f7
parent812507ec5c07504b1c84e1c365954dd49188ce15 (diff)
bgpd: Enhance BGP NHT show commands
Display next hop resolution information, whether the "detail" option is specified or not as it is quite fundamental and only minimally increases the output. Introduce option to look at a specific NHT entry, which will also show the paths associated with that entry. Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
-rw-r--r--bgpd/bgp_nexthop.c168
1 files changed, 118 insertions, 50 deletions
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index bfce61c2af..ff238d71b1 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -44,6 +44,7 @@
#include "bgpd/bgp_damp.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_rd.h"
DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String");
@@ -695,13 +696,44 @@ bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
return false;
}
+static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,
+ struct bgp_nexthop_cache *bnc)
+{
+ struct bgp_node *rn;
+ struct bgp_path_info *path;
+ int afi;
+ safi_t safi;
+ struct bgp_table *table;
+ struct bgp *bgp_path;
+ char buf1[BUFSIZ];
+
+ vty_out(vty, " Paths:\n");
+ LIST_FOREACH (path, &(bnc->paths), nh_thread) {
+ rn = path->net;
+ assert(rn && bgp_node_table(rn));
+ afi = family2afi(rn->p.family);
+ table = bgp_node_table(rn);
+ safi = table->safi;
+ bgp_path = table->bgp;
+
+ if (rn->prn) {
+ prefix_rd2str((struct prefix_rd *)&rn->prn->p,
+ buf1, sizeof(buf1));
+ vty_out(vty, " %d/%d %pRN RD %s %s flags 0x%x\n",
+ afi, safi, rn, buf1, bgp_path->name_pretty, path->flags);
+ } else
+ vty_out(vty, " %d/%d %pRN %s flags 0x%x\n",
+ afi, safi, rn, bgp_path->name_pretty, path->flags);
+ }
+}
+
static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
struct bgp_nexthop_cache *bnc)
{
char buf[PREFIX2STR_BUFFER];
struct nexthop *nexthop;
- for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
+ for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV6:
vty_out(vty, " gate %s\n",
@@ -736,15 +768,55 @@ static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp,
vty_out(vty, " invalid nexthop type %u\n",
nexthop->type);
}
+ }
}
-static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
- bool import_table)
+static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
+ struct bgp_node *rn,
+ struct bgp_nexthop_cache *bnc,
+ bool specific)
{
- struct bgp_node *rn;
- struct bgp_nexthop_cache *bnc;
char buf[PREFIX2STR_BUFFER];
time_t tbuf;
+ struct peer *peer;
+ const struct prefix *p = bgp_node_get_prefix(rn);
+
+ peer = (struct peer *)bnc->nht_info;
+
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
+ vty_out(vty, " %s valid [IGP metric %d], #paths %d",
+ inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf)),
+ bnc->metric, bnc->path_count);
+ if (peer)
+ vty_out(vty, ", peer %s", peer->host);
+ vty_out(vty, "\n");
+ bgp_show_nexthops_detail(vty, bgp, bnc);
+ } else {
+ vty_out(vty, " %s invalid, #paths %d",
+ inet_ntop(p->family, &p->u.prefix, buf, sizeof(buf)),
+ bnc->path_count);
+ if (peer)
+ vty_out(vty, ", peer %s", peer->host);
+ vty_out(vty, "\n");
+ if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
+ vty_out(vty, " Must be Connected\n");
+ if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
+ vty_out(vty, " Is not Registered\n");
+ }
+ tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
+ vty_out(vty, " Last update: %s", ctime(&tbuf));
+ vty_out(vty, "\n");
+
+ /* show paths dependent on nexthop, if needed. */
+ if (specific)
+ bgp_show_nexthop_paths(vty, bgp, bnc);
+}
+
+static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp,
+ bool import_table)
+{
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
afi_t afi;
struct bgp_table **table;
@@ -761,52 +833,17 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
continue;
for (rn = bgp_table_top(table[afi]); rn;
rn = bgp_route_next(rn)) {
- struct peer *peer;
- const struct prefix *p = bgp_node_get_prefix(rn);
-
bnc = bgp_node_get_bgp_nexthop_info(rn);
if (!bnc)
continue;
- peer = (struct peer *)bnc->nht_info;
-
- if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
- vty_out(vty,
- " %s valid [IGP metric %d], #paths %d",
- inet_ntop(p->family, &p->u.prefix, buf,
- sizeof(buf)),
- bnc->metric, bnc->path_count);
- if (peer)
- vty_out(vty, ", peer %s", peer->host);
- vty_out(vty, "\n");
-
- if (!detail)
- continue;
-
- bgp_show_nexthops_detail(vty, bgp, bnc);
-
- } else {
- vty_out(vty, " %s invalid",
- inet_ntop(p->family, &p->u.prefix, buf,
- sizeof(buf)));
- if (peer)
- vty_out(vty, ", peer %s", peer->host);
- vty_out(vty, "\n");
- if (CHECK_FLAG(bnc->flags,
- BGP_NEXTHOP_CONNECTED))
- vty_out(vty, " Must be Connected\n");
- if (!CHECK_FLAG(bnc->flags,
- BGP_NEXTHOP_REGISTERED))
- vty_out(vty, " Is not Registered\n");
- }
- tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
- vty_out(vty, " Last update: %s", ctime(&tbuf));
- vty_out(vty, "\n");
+ bgp_show_nexthop(vty, bgp, rn, bnc, false);
}
}
}
static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
- int detail, bool import_table)
+ const char *nhopip_str,
+ bool import_table)
{
struct bgp *bgp;
@@ -819,7 +856,31 @@ static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
return CMD_WARNING;
}
- bgp_show_nexthops(vty, bgp, detail, import_table);
+ if (nhopip_str) {
+ struct prefix nhop;
+ struct bgp_table **table;
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+
+ if (!str2prefix(nhopip_str, &nhop)) {
+ vty_out(vty, "nexthop address is malformed\n");
+ return CMD_WARNING;
+ }
+ table = import_table ? \
+ bgp->import_check_table : bgp->nexthop_cache_table;
+ rn = bgp_node_lookup(table[family2afi(nhop.family)], &nhop);
+ if (!rn) {
+ vty_out(vty, "specified nexthop is not found\n");
+ return CMD_SUCCESS;
+ }
+ bnc = bgp_node_get_bgp_nexthop_info(rn);
+ if (!bnc) {
+ vty_out(vty, "specified nexthop does not have entry\n");
+ return CMD_SUCCESS;
+ }
+ bgp_show_nexthop(vty, bgp, rn, bnc, true);
+ } else
+ bgp_show_nexthops(vty, bgp, import_table);
return CMD_SUCCESS;
}
@@ -834,29 +895,36 @@ static void bgp_show_all_instances_nexthops_vty(struct vty *vty)
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
? VRF_DEFAULT_NAME
: bgp->name);
- bgp_show_nexthops(vty, bgp, 0, false);
+ bgp_show_nexthops(vty, bgp, false);
}
}
DEFUN (show_ip_bgp_nexthop,
show_ip_bgp_nexthop_cmd,
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [detail]",
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] nexthop [<A.B.C.D|X:X::X:X>] [detail]",
SHOW_STR
IP_STR
BGP_STR
BGP_INSTANCE_HELP_STR
"BGP nexthop table\n"
+ "IPv4 nexthop address\n"
+ "IPv6 nexthop address\n"
"Show detailed information\n")
{
int idx = 0;
+ int nh_idx = 0;
char *vrf = NULL;
+ char *nhop_ip = NULL;
if (argv_find(argv, argc, "view", &idx)
|| argv_find(argv, argc, "vrf", &idx))
vrf = argv[++idx]->arg;
- int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
- return show_ip_bgp_nexthop_table(vty, vrf, detail, false);
+ if (argv_find(argv, argc, "A.B.C.D", &nh_idx)
+ || argv_find(argv, argc, "X:X::X:X", &nh_idx))
+ nhop_ip = argv[nh_idx]->arg;
+
+ return show_ip_bgp_nexthop_table(vty, vrf, nhop_ip, false);
}
DEFUN (show_ip_bgp_import_check,
@@ -875,8 +943,8 @@ DEFUN (show_ip_bgp_import_check,
if (argv_find(argv, argc, "view", &idx)
|| argv_find(argv, argc, "vrf", &idx))
vrf = argv[++idx]->arg;
- int detail = argv_find(argv, argc, "detail", &idx) ? 1 : 0;
- return show_ip_bgp_nexthop_table(vty, vrf, detail, true);
+
+ return show_ip_bgp_nexthop_table(vty, vrf, NULL, true);
}
DEFUN (show_ip_bgp_instance_all_nexthop,