summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDonatas Abraitis <donatas.abraitis@gmail.com>2021-04-09 08:33:41 +0200
committerDonatas Abraitis <donatas.abraitis@gmail.com>2021-04-12 09:43:53 +0200
commit7d3cae70b22ee6124a403b179db7b4fbab70dff6 (patch)
tree47deed1aec0f1871a20841543f89eb4b1a461e92
parentbgpd: Show BGP table version which was used for a particular prefix (diff)
downloadfrr-7d3cae70b22ee6124a403b179db7b4fbab70dff6.tar.xz
frr-7d3cae70b22ee6124a403b179db7b4fbab70dff6.zip
bgpd: Filter BGP routes by prefix version
The idea is to find out prefixes including specific BGP table version and above. Let's say I have a converged network and suddently I noticed a couple of prefixes seems hijacked. I want to look what new prefixes arrived with a specific BGP table version. ``` exit1-debian-9# show ip bgp version 8 BGP table version is 9, local router ID is 192.168.100.1, vrf id 0 Default local pref 100, local AS 65534 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path * 192.168.2.0/24 192.168.0.2 0 0 65030 ? *> 192.168.0.2 0 0 65030 ? * 192.168.3.0/24 192.168.0.2 0 0 65030 ? *> 192.168.0.2 0 0 65030 ? Displayed 2 routes and 18 total paths exit1-debian-9# ``` ``` exit1-debian-9# show ip bgp version 8 json { "vrfId": 0, "vrfName": "default", "tableVersion": 9, "routerId": "192.168.100.1", "defaultLocPrf": 100, "localAS": 65534, "routes": { "192.168.2.0/24": [ { "valid":true, "pathFrom":"external", "prefix":"192.168.2.0", "prefixLen":24, "network":"192.168.2.0\/24", "version":8, "metric":0, "weight":0, "peerId":"2a02:bbd::2", "path":"65030", "origin":"incomplete", "nexthops":[ { "ip":"192.168.0.2", "hostname":"home-spine1.donatas.net", "afi":"ipv4", "used":true } ] }, { "valid":true, "bestpath":true, "selectionReason":"Neighbor IP", "pathFrom":"external", "prefix":"192.168.2.0", "prefixLen":24, "network":"192.168.2.0\/24", "version":8, "metric":0, "weight":0, "peerId":"192.168.0.2", "path":"65030", "origin":"incomplete", "nexthops":[ { "ip":"192.168.0.2", "hostname":"home-spine1.donatas.net", "afi":"ipv4", "used":true } ] } ],"192.168.3.0/24": [ { "valid":true, "pathFrom":"external", "prefix":"192.168.3.0", "prefixLen":24, "network":"192.168.3.0\/24", "version":9, "metric":0, "weight":0, "peerId":"2a02:bbd::2", "path":"65030", "origin":"incomplete", "nexthops":[ { "ip":"192.168.0.2", "hostname":"home-spine1.donatas.net", "afi":"ipv4", "used":true } ] }, { "valid":true, "bestpath":true, "selectionReason":"Neighbor IP", "pathFrom":"external", "prefix":"192.168.3.0", "prefixLen":24, "network":"192.168.3.0\/24", "version":9, "metric":0, "weight":0, "peerId":"192.168.0.2", "path":"65030", "origin":"incomplete", "nexthops":[ { "ip":"192.168.0.2", "hostname":"home-spine1.donatas.net", "afi":"ipv4", "used":true } ] } ] } } ``` Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
-rw-r--r--bgpd/bgp_route.c68
-rw-r--r--bgpd/bgp_route.h8
-rw-r--r--bgpd/bgp_updgrp_adv.c4
-rw-r--r--bgpd/bgp_vpn.c5
4 files changed, 62 insertions, 23 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0f0d0590b..1c2ad7fc7 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -8223,8 +8223,8 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
}
/* Static function to display route. */
-static void route_vty_out_route(const struct prefix *p, struct vty *vty,
- json_object *json, bool wide)
+static void route_vty_out_route(struct bgp_dest *dest, const struct prefix *p,
+ struct vty *vty, json_object *json, bool wide)
{
int len = 0;
char buf[BUFSIZ];
@@ -8241,6 +8241,7 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty,
json_object_int_add(json, "prefixLen", p->prefixlen);
prefix2str(p, buf2, PREFIX_STRLEN);
json_object_string_add(json, "network", buf2);
+ json_object_int_add(json, "version", dest->version);
}
} else if (p->family == AF_ETHERNET) {
len = vty_out(vty, "%pFX", p);
@@ -8265,6 +8266,7 @@ static void route_vty_out_route(const struct prefix *p, struct vty *vty,
json_object_int_add(json, "prefixLen", p->prefixlen);
prefix2str(p, buf2, PREFIX_STRLEN);
json_object_string_add(json, "network", buf2);
+ json_object_int_add(json, "version", dest->version);
}
}
@@ -8460,11 +8462,11 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
if (!json_paths) {
/* print prefix and mask */
if (!display)
- route_vty_out_route(p, vty, json_path, wide);
+ route_vty_out_route(path->net, p, vty, json_path, wide);
else
vty_out(vty, "%*s", (wide ? 45 : 17), " ");
} else {
- route_vty_out_route(p, vty, json_path, wide);
+ route_vty_out_route(path->net, p, vty, json_path, wide);
}
/*
@@ -8924,9 +8926,9 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
}
/* called from terminal list command */
-void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
- struct attr *attr, safi_t safi, bool use_json,
- json_object *json_ar, bool wide)
+void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
+ const struct prefix *p, struct attr *attr, safi_t safi,
+ bool use_json, json_object *json_ar, bool wide)
{
json_object *json_status = NULL;
json_object *json_net = NULL;
@@ -8958,7 +8960,7 @@ void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
json_object_string_add(json_net, "network", buff);
}
} else
- route_vty_out_route(p, vty, NULL, wide);
+ route_vty_out_route(dest, p, vty, NULL, wide);
/* Print attribute */
if (attr) {
@@ -9106,7 +9108,7 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
/* print prefix and mask */
if (json == NULL) {
if (!display)
- route_vty_out_route(p, vty, NULL, false);
+ route_vty_out_route(path->net, p, vty, NULL, false);
else
vty_out(vty, "%*s", 17, " ");
}
@@ -9208,7 +9210,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
/* print prefix and mask */
if (!display)
- route_vty_out_route(p, vty, json_path, false);
+ route_vty_out_route(path->net, p, vty, json_path, false);
else
vty_out(vty, "%*s", 17, " ");
@@ -9313,7 +9315,7 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
/* print prefix and mask */
if (!use_json) {
if (!display)
- route_vty_out_route(p, vty, NULL, false);
+ route_vty_out_route(path->net, p, vty, NULL, false);
else
vty_out(vty, "%*s", 17, " ");
}
@@ -9384,7 +9386,7 @@ static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
/* print prefix and mask */
if (!use_json) {
if (!display)
- route_vty_out_route(p, vty, NULL, false);
+ route_vty_out_route(path->net, p, vty, NULL, false);
else
vty_out(vty, "%*s", 17, " ");
}
@@ -10121,6 +10123,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, ", valid");
}
+ if (json_paths)
+ json_object_int_add(json_path, "version", bn->version);
+
if (path->peer != bgp->peer_self) {
if (path->peer->as == path->peer->local_as) {
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
@@ -10616,6 +10621,13 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
for (; pi; pi = pi->next) {
total_count++;
+ if (type == bgp_show_type_prefix_version) {
+ uint32_t version =
+ strtoul(output_arg, NULL, 10);
+ if (dest->version < version)
+ continue;
+ }
+
if (type == bgp_show_type_rpki) {
if (dest_p->family == AF_INET
|| dest_p->family == AF_INET6)
@@ -11892,6 +11904,7 @@ DEFPY (show_ip_bgp_json,
|route-filter-v4|route-filter-translated-v6\
|route-filter-translated-v4] [exact-match]\
|rpki <invalid|valid|notfound>\
+ |version (1-4294967295)\
] [json$uj | wide$wide]",
SHOW_STR
IP_STR
@@ -11925,6 +11938,8 @@ DEFPY (show_ip_bgp_json,
"A valid path as determined by rpki\n"
"A invalid path as determined by rpki\n"
"A path that has no rpki data\n"
+ "Display prefixes with matching version numbers\n"
+ "Version number and above\n"
JSON_STR
"Increase table width for longer prefixes\n")
{
@@ -11935,6 +11950,7 @@ DEFPY (show_ip_bgp_json,
int idx = 0;
int exact_match = 0;
char *community = NULL;
+ char *prefix_version = NULL;
bool first = true;
uint8_t show_flags = 0;
enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
@@ -12002,12 +12018,22 @@ DEFPY (show_ip_bgp_json,
rpki_target_state = RPKI_INVALID;
}
+ /* Display prefixes with matching version numbers */
+ if (argv_find(argv, argc, "version", &idx)) {
+ sh_type = bgp_show_type_prefix_version;
+ prefix_version = argv[idx + 1]->arg;
+ }
+
if (!all) {
/* show bgp: AFI_IP6, show ip bgp: AFI_IP */
if (community)
return bgp_show_community(vty, bgp, community,
exact_match, afi, safi,
show_flags);
+ else if (prefix_version)
+ return bgp_show(vty, bgp, afi, safi, sh_type,
+ prefix_version, show_flags,
+ rpki_target_state);
else
return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
show_flags, rpki_target_state);
@@ -12045,6 +12071,11 @@ DEFPY (show_ip_bgp_json,
bgp_show_community(vty, bgp, community,
exact_match, afi,
safi, show_flags);
+ else if (prefix_version)
+ return bgp_show(vty, bgp, afi, safi,
+ sh_type, prefix_version,
+ show_flags,
+ rpki_target_state);
else
bgp_show(vty, bgp, afi, safi, sh_type,
NULL, show_flags,
@@ -12077,6 +12108,11 @@ DEFPY (show_ip_bgp_json,
bgp_show_community(vty, bgp, community,
exact_match, afi,
safi, show_flags);
+ else if (prefix_version)
+ return bgp_show(vty, bgp, afi, safi,
+ sh_type, prefix_version,
+ show_flags,
+ rpki_target_state);
else
bgp_show(vty, bgp, afi, safi, sh_type,
NULL, show_flags,
@@ -13289,7 +13325,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
&& (route_filtered || ret == RMAP_DENY))
(*filtered_count)++;
- route_vty_out_tmp(vty, rn_p, &attr, safi,
+ route_vty_out_tmp(vty, dest, rn_p, &attr, safi,
use_json, json_ar, wide);
bgp_attr_undup(&attr, ain->attr);
(*output_count)++;
@@ -13331,8 +13367,8 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
}
}
route_vty_out_tmp(
- vty, rn_p, &attr, safi,
- use_json, json_ar,
+ vty, dest, rn_p, &attr,
+ safi, use_json, json_ar,
wide);
(*output_count)++;
} else {
@@ -13356,7 +13392,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
continue;
- route_vty_out_tmp(vty,
+ route_vty_out_tmp(vty, dest,
bgp_dest_get_prefix(dest),
pi->attr, safi, use_json,
json_ar, wide);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 0a4fd026e..1bf5dcf18 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -58,6 +58,7 @@ enum bgp_show_type {
bgp_show_type_damp_neighbor,
bgp_show_type_detail,
bgp_show_type_rpki,
+ bgp_show_type_prefix_version,
};
enum bgp_show_adj_route_type {
@@ -714,9 +715,10 @@ extern void route_vty_out(struct vty *vty, const struct prefix *p,
extern void route_vty_out_tag(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
safi_t safi, json_object *json);
-extern void route_vty_out_tmp(struct vty *vty, const struct prefix *p,
- struct attr *attr, safi_t safi, bool use_json,
- json_object *json_ar, bool wide);
+extern void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
+ const struct prefix *p, struct attr *attr,
+ safi_t safi, bool use_json, json_object *json_ar,
+ bool wide);
extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
json_object *json);
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index fb64f010f..bb0c95e32 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -267,7 +267,7 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
}
if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv
&& adj->adv->baa) {
- route_vty_out_tmp(vty, dest_p,
+ route_vty_out_tmp(vty, dest, dest_p,
adj->adv->baa->attr,
SUBGRP_SAFI(subgrp),
0, NULL, false);
@@ -275,7 +275,7 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
}
if ((flags & UPDWALK_FLAGS_ADVERTISED)
&& adj->attr) {
- route_vty_out_tmp(vty, dest_p,
+ route_vty_out_tmp(vty, dest, dest_p,
adj->attr,
SUBGRP_SAFI(subgrp),
0, NULL, false);
diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c
index cb459ae13..8d2cffbb4 100644
--- a/bgpd/bgp_vpn.c
+++ b/bgpd/bgp_vpn.c
@@ -229,8 +229,9 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
}
rd_header = 0;
}
- route_vty_out_tmp(vty, bgp_dest_get_prefix(rm), attr,
- safi, use_json, json_routes, false);
+ route_vty_out_tmp(vty, rm, bgp_dest_get_prefix(rm),
+ attr, safi, use_json, json_routes,
+ false);
output_count++;
}