+// SPDX-License-Identifier: GPL-2.0-or-later
/* BGP routing information
* Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
* Copyright (C) 2016 Job Snijders <job@instituut.net>
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_mac.h"
#include "bgpd/bgp_network.h"
-#include "bgpd/bgp_orr.h"
#include "bgpd/bgp_trace.h"
#include "bgpd/bgp_rpki.h"
enum bgp_path_selection_reason *reason)
{
const struct prefix *new_p;
- struct prefix exist_p;
struct attr *newattr, *existattr;
enum bgp_peer_sort new_sort;
enum bgp_peer_sort exist_sort;
bool new_origin, exist_origin;
struct bgp_path_info *bpi_ultimate;
- struct bgp_orr_group *orr_group = NULL;
- struct listnode *node;
- struct bgp_orr_igp_metric *igp_metric = NULL;
- struct list *orr_group_igp_metric_info = NULL;
-
*paths_eq = 0;
/* 0. Null check. */
if (exist->extra)
existm = exist->extra->igpmetric;
- if (new->peer->orr_group_name[afi][safi]) {
- ret = str2prefix(new->peer->host, &exist_p);
- orr_group = bgp_orr_group_lookup_by_name(
- bgp, afi, safi, new->peer->orr_group_name[afi][safi]);
- if (orr_group) {
- orr_group_igp_metric_info = orr_group->igp_metric_info;
- if (orr_group_igp_metric_info) {
- for (ALL_LIST_ELEMENTS_RO(
- orr_group_igp_metric_info, node,
- igp_metric)) {
- if (ret &&
- prefix_cmp(&exist_p,
- &igp_metric->prefix) ==
- 0) {
- newm = igp_metric->igp_metric;
- break;
- }
- }
- }
- }
- }
- if (exist->peer->orr_group_name[afi][safi]) {
- ret = str2prefix(exist->peer->host, &exist_p);
- orr_group = bgp_orr_group_lookup_by_name(
- bgp, afi, safi, exist->peer->orr_group_name[afi][safi]);
- if (orr_group) {
- orr_group_igp_metric_info = orr_group->igp_metric_info;
- if (orr_group_igp_metric_info) {
- for (ALL_LIST_ELEMENTS_RO(
- orr_group_igp_metric_info, node,
- igp_metric)) {
- if (ret &&
- prefix_cmp(&exist_p,
- &igp_metric->prefix) ==
- 0) {
- existm = igp_metric->igp_metric;
- break;
- }
- }
- }
- }
- }
-
if (newm < existm) {
if (debug && peer_sort_ret < 0)
zlog_debug(
}
/* AS path loop check. */
- if (onlypeer && onlypeer->as_path_loop_detection
- && aspath_loop_check(piattr->aspath, onlypeer->as)) {
+ if (peer->as_path_loop_detection &&
+ aspath_loop_check(piattr->aspath, peer->as)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
"%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
- onlypeer, onlypeer->as);
+ peer, peer->as);
return false;
}
&& peer->shared_network
&& (from == bgp->peer_self
|| peer->sort == BGP_PEER_EBGP))) {
- attr->mp_nexthop_len =
- BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
+ if (safi == SAFI_MPLS_VPN)
+ attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL;
+ else
+ attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
}
/* Clear off link-local nexthop in source, whenever it is not
return false;
}
-int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
- struct attr *attr, afi_t afi, safi_t safi, int type,
- int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, int soft_reconfig,
- struct bgp_route_evpn *evpn)
+void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
+ struct attr *attr, afi_t afi, safi_t safi, int type,
+ int sub_type, struct prefix_rd *prd, mpls_label_t *label,
+ uint32_t num_labels, int soft_reconfig,
+ struct bgp_route_evpn *evpn)
{
int ret;
int aspath_loop_count = 0;
bgp_dest_unlock_node(dest);
bgp_attr_unintern(&attr_new);
- return 0;
+ return;
}
/* Withdraw/Announce before we fully processed the withdraw */
bgp_evpn_unimport_route(
bgp, afi, safi, p, pi);
else /* SAFI_MPLS_VPN */
- vpn_leak_to_vrf_withdraw(bgp,
- pi);
+ vpn_leak_to_vrf_withdraw(pi);
}
}
}
ret = bgp_damp_update(pi, dest, afi, safi);
if (ret == BGP_DAMP_SUPPRESSED) {
bgp_dest_unlock_node(dest);
- return 0;
+ return;
}
}
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
}
- return 0;
+ return;
} // End of implicit withdraw
/* Received Logging. */
bgp_path_info_delete(dest, new);
}
- return 0;
+ return;
/* This BGP update is filtered. Log the reason then update BGP
entry. */
if ((SAFI_MPLS_VPN == safi)
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
- vpn_leak_to_vrf_withdraw(bgp, pi);
+ vpn_leak_to_vrf_withdraw(pi);
}
bgp_rib_remove(dest, pi, peer, afi, safi);
}
#endif
- return 0;
+ return;
}
-int bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
- struct attr *attr, afi_t afi, safi_t safi, int type,
- int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, struct bgp_route_evpn *evpn)
+void bgp_withdraw(struct peer *peer, const struct prefix *p,
+ uint32_t addpath_id, struct attr *attr, afi_t afi,
+ safi_t safi, int type, int sub_type, struct prefix_rd *prd,
+ mpls_label_t *label, uint32_t num_labels,
+ struct bgp_route_evpn *evpn)
{
struct bgp *bgp;
char pfx_buf[BGP_PRD_PATH_STRLEN];
peer->host, pfx_buf);
}
bgp_dest_unlock_node(dest);
- return 0;
+ return;
}
/* Lookup withdrawn route. */
if ((SAFI_MPLS_VPN == safi)
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
- vpn_leak_to_vrf_withdraw(bgp, pi);
+ vpn_leak_to_vrf_withdraw(pi);
}
} else if (bgp_debug_update(peer, p, NULL, 1)) {
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
/* Unlock bgp_node_get() lock. */
bgp_dest_unlock_node(dest);
- return 0;
+ return;
}
void bgp_default_originate(struct peer *peer, afi_t afi, safi_t safi,
}
}
-static int bgp_soft_reconfig_table_update(struct peer *peer,
- struct bgp_dest *dest,
- struct bgp_adj_in *ain, afi_t afi,
- safi_t safi, struct prefix_rd *prd)
+static void bgp_soft_reconfig_table_update(struct peer *peer,
+ struct bgp_dest *dest,
+ struct bgp_adj_in *ain, afi_t afi,
+ safi_t safi, struct prefix_rd *prd)
{
struct bgp_path_info *pi;
uint32_t num_labels = 0;
else
memset(&evpn, 0, sizeof(evpn));
- return bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
- ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, prd, label_pnt, num_labels, 1,
- &evpn);
+ bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id,
+ ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd,
+ label_pnt, num_labels, 1, &evpn);
}
static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
struct bgp_table *table,
struct prefix_rd *prd)
{
- int ret;
struct bgp_dest *dest;
struct bgp_adj_in *ain;
if (ain->peer != peer)
continue;
- ret = bgp_soft_reconfig_table_update(peer, dest, ain,
- afi, safi, prd);
-
- if (ret < 0) {
- bgp_dest_unlock_node(dest);
- return;
- }
+ bgp_soft_reconfig_table_update(peer, dest, ain, afi,
+ safi, prd);
}
}
static void bgp_soft_reconfig_table_task(struct thread *thread)
{
uint32_t iter, max_iter;
- int ret;
struct bgp_dest *dest;
struct bgp_adj_in *ain;
struct peer *peer;
if (ain->peer != peer)
continue;
- ret = bgp_soft_reconfig_table_update(
+ bgp_soft_reconfig_table_update(
peer, dest, ain, table->afi,
table->safi, prd);
iter++;
-
- if (ret < 0) {
- bgp_dest_unlock_node(dest);
- listnode_delete(
- table->soft_reconfig_peers,
- peer);
- bgp_announce_route(peer, table->afi,
- table->safi, false);
- if (list_isempty(
- table->soft_reconfig_peers)) {
- list_delete(
- &table->soft_reconfig_peers);
- bgp_soft_reconfig_table_flag(
- table, false);
- return;
- }
- }
}
}
}
}
if (SAFI_MPLS_VPN == safi &&
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
- vpn_leak_to_vrf_withdraw(bgp, pi);
+ vpn_leak_to_vrf_withdraw(pi);
}
bgp_rib_remove(dest, pi, peer, afi, safi);
BGP_ROUTE_IMPORTED &&
peer->bgp->inst_type ==
BGP_INSTANCE_TYPE_DEFAULT)
- vpn_leak_to_vrf_withdraw(
- peer->bgp, pi);
+ vpn_leak_to_vrf_withdraw(pi);
bgp_rib_remove(rm, pi, peer, afi, safi);
break;
uint8_t *lim;
struct prefix p;
int psize;
- int ret;
afi_t afi;
safi_t safi;
bool addpath_capable;
/* Normal process. */
if (attr)
- ret = bgp_update(peer, &p, addpath_id, attr, afi, safi,
- ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
- NULL, NULL, 0, 0, NULL);
+ bgp_update(peer, &p, addpath_id, attr, afi, safi,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
+ NULL, 0, 0, NULL);
else
- ret = bgp_withdraw(peer, &p, addpath_id, attr, afi,
- safi, ZEBRA_ROUTE_BGP,
- BGP_ROUTE_NORMAL, NULL, NULL, 0,
- NULL);
+ bgp_withdraw(peer, &p, addpath_id, attr, afi, safi,
+ ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL,
+ NULL, 0, NULL);
/* Do not send BGP notification twice when maximum-prefix count
* overflow. */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
return BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW;
-
- /* Address family configuration mismatch. */
- if (ret < 0)
- return BGP_NLRI_PARSE_ERROR_ADDRESS_FAMILY;
}
/* Packet length consistency check. */
#endif
if (SAFI_MPLS_VPN == safi
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
- vpn_leak_to_vrf_withdraw(bgp, pi);
+ vpn_leak_to_vrf_withdraw(pi);
}
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
bgp_path_info_delete(dest, pi);
json_object_string_add(json_path, "path",
attr->aspath->str);
else
- aspath_print_vty(vty, "%s", attr->aspath, " ");
+ aspath_print_vty(vty, attr->aspath);
}
/* Print origin */
/* Print aspath */
if (attr->aspath)
- aspath_print_vty(vty, "%s", attr->aspath, " ");
+ aspath_print_vty(vty, attr->aspath);
/* Print origin */
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
if (!json_path) {
vty_out(vty, "?");
} else {
- json_object_string_add(json_nexthop, "Error",
- "Unsupported address-family");
json_object_string_add(json_nexthop, "error",
"Unsupported address-family");
}
use_json, NULL));
if (attr->aspath)
- aspath_print_vty(vty, "%s", attr->aspath, " ");
+ aspath_print_vty(vty, attr->aspath);
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
vty_out(vty, "%*s ", 8, " ");
if (attr->aspath)
- aspath_print_vty(vty, "%s", attr->aspath, " ");
+ aspath_print_vty(vty, attr->aspath);
vty_out(vty, "%s", bgp_origin_str[attr->origin]);
if (tag_buf[0] != '\0')
vty_out(vty, " VNI %s", tag_buf);
} else {
- if (tag_buf[0]) {
- json_object_string_add(json_path, "VNI",
- tag_buf);
+ if (tag_buf[0])
json_object_string_add(json_path, "vni",
tag_buf);
- }
}
}
}
attr->aspath->json);
} else {
if (attr->aspath->segments)
- aspath_print_vty(vty, " %s", attr->aspath, "");
+ vty_out(vty, " %s", attr->aspath->str);
else
vty_out(vty, " Local");
}
else
vty_out(vty, ",\"%pFX\": ", dest_p);
}
- vty_json(vty, json_paths);
+ /*
+ * We are using no_pretty here because under
+ * extremely high settings( say lots and lots of
+ * routes with lots and lots of ways to reach
+ * that route via different paths ) this can
+ * save several minutes of output when FRR
+ * is run on older cpu's or more underperforming
+ * routers out there
+ */
+ vty_json_no_pretty(vty, json_paths);
json_paths = NULL;
first = 0;
} else
case SAFI_ENCAP:
case SAFI_EVPN:
return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
- default:
+ case SAFI_UNSPEC:
+ case SAFI_UNICAST:
+ case SAFI_MULTICAST:
+ case SAFI_LABELED_UNICAST:
+ case SAFI_FLOWSPEC:
+ case SAFI_MAX:
return NULL;
}
+
+ assert(!"Reached end of function when we were not expecting it");
}
/* Display specified route of BGP table. */
|alias ALIAS_NAME\
|A.B.C.D/M longer-prefixes\
|X:X::X:X/M longer-prefixes\
- |optimal-route-reflection [WORD$orr_group_name]\
|detail-routes$detail_routes\
] [json$uj [detail$detail_json] | wide$wide]",
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
"Display route and more specific routes\n"
"IPv6 prefix\n"
"Display route and more specific routes\n"
- "Display Optimal Route Reflection RR Clients\n"
- "ORR Group name\n"
"Display detailed version of all routes\n"
JSON_STR
"Display detailed version of JSON output\n"
uint16_t show_flags = 0;
enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
struct prefix p;
- bool orr_group = false;
if (uj) {
argc--;
output_arg = &p;
}
- if (argv_find(argv, argc, "optimal-route-reflection", &idx))
- orr_group = true;
-
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 (orr_group)
- return bgp_show_orr(vty, bgp, afi, safi, orr_group_name,
- show_flags);
else
return bgp_show(vty, bgp, afi, safi, sh_type,
output_arg, show_flags,
vty, abgp, community,
exact_match, afi, safi,
show_flags);
- else if (orr_group)
- bgp_show_orr(vty, bgp, afi,
- safi,
- orr_group_name,
- show_flags);
else
bgp_show(vty, abgp, afi, safi,
sh_type, output_arg,
vty, abgp, community,
exact_match, afi, safi,
show_flags);
- else if (orr_group)
- bgp_show_orr(vty, bgp, afi,
- safi,
- orr_group_name,
- show_flags);
else
bgp_show(vty, abgp, afi, safi,
sh_type, output_arg,
case AFI_L2VPN:
space = EVPN_ROUTE_PREFIXLEN;
break;
- default:
+ case AFI_UNSPEC:
+ case AFI_MAX:
return;
}
case AFI_L2VPN:
bitlen = EVPN_ROUTE_PREFIXLEN;
break;
- default:
+ case AFI_UNSPEC:
+ case AFI_MAX:
break;
}
const char *rmap_name, json_object *json, json_object *json_ar,
json_object *json_scode, json_object *json_ocode,
uint16_t show_flags, int *header1, int *header2, char *rd_str,
- unsigned long *output_count, unsigned long *filtered_count)
+ const struct prefix *match, unsigned long *output_count,
+ unsigned long *filtered_count)
{
- struct bgp_adj_in *ain;
- struct bgp_adj_out *adj;
+ struct bgp_adj_in *ain = NULL;
+ struct bgp_adj_out *adj = NULL;
struct bgp_dest *dest;
struct bgp *bgp;
struct attr attr;
int ret;
struct update_subgroup *subgrp;
- struct peer_af *paf;
+ struct peer_af *paf = NULL;
bool route_filtered;
bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
bgp = peer->bgp;
+ /* If the user supplied a prefix, look for a matching route instead
+ * of walking the whole table.
+ */
+ if (match) {
+ dest = bgp_node_match(table, match);
+ if (!dest) {
+ if (!use_json)
+ vty_out(vty, "Network not in table\n");
+ return;
+ }
+
+ const struct prefix *rn_p = bgp_dest_get_prefix(dest);
+
+ if (rn_p->prefixlen != match->prefixlen) {
+ if (!use_json)
+ vty_out(vty, "Network not in table\n");
+ bgp_dest_unlock_node(dest);
+ return;
+ }
+
+ if (type == bgp_show_adj_route_received ||
+ type == bgp_show_adj_route_filtered) {
+ for (ain = dest->adj_in; ain; ain = ain->next) {
+ if (ain->peer == peer) {
+ attr = *ain->attr;
+ break;
+ }
+ }
+ /* bail out if if adj_out is empty, or
+ * if the prefix isn't in this peer's
+ * adj_in
+ */
+ if (!ain || ain->peer != peer) {
+ if (!use_json)
+ vty_out(vty, "Network not in table\n");
+ bgp_dest_unlock_node(dest);
+ return;
+ }
+ } else if (type == bgp_show_adj_route_advertised) {
+ bool peer_found = false;
+
+ RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
+ SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
+ if (paf->peer == peer && adj->attr) {
+ attr = *adj->attr;
+ peer_found = true;
+ break;
+ }
+ }
+ if (peer_found)
+ break;
+ }
+ /* bail out if if adj_out is empty, or
+ * if the prefix isn't in this peer's
+ * adj_out
+ */
+ if (!paf || !peer_found) {
+ if (!use_json)
+ vty_out(vty, "Network not in table\n");
+ bgp_dest_unlock_node(dest);
+ return;
+ }
+ }
+
+ ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
+ rmap_name);
+
+ if (ret != RMAP_DENY) {
+ show_adj_route_header(vty, peer, table, header1,
+ header2, json, json_scode,
+ json_ocode, wide, detail);
+
+ if (use_json)
+ json_net = json_object_new_object();
+
+ bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
+ afi, safi, json_net,
+ BGP_PATH_SHOW_ALL, &display,
+ RPKI_NOT_BEING_USED);
+ if (use_json)
+ json_object_object_addf(json_ar, json_net,
+ "%pFX", rn_p);
+ (*output_count)++;
+ } else
+ (*filtered_count)++;
+
+ bgp_attr_flush(&attr);
+ bgp_dest_unlock_node(dest);
+ return;
+ }
+
+
subgrp = peer_subgroup(peer, afi, safi);
if (type == bgp_show_adj_route_advertised && subgrp
header2, json, json_scode,
json_ocode, wide, detail);
+ const struct prefix *rn_p = bgp_dest_get_prefix(dest);
+
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
pi = pi->next) {
if (pi->peer != peer)
if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
continue;
- route_vty_out_tmp(vty, dest,
- bgp_dest_get_prefix(dest),
- pi->attr, safi, use_json,
- json_ar, wide);
+ if (detail) {
+ if (use_json)
+ json_net =
+ json_object_new_object();
+ bgp_show_path_info(
+ NULL /* prefix_rd */, dest, vty,
+ bgp, afi, safi, json_net,
+ BGP_PATH_SHOW_BESTPATH,
+ &display, RPKI_NOT_BEING_USED);
+ if (use_json)
+ json_object_object_addf(
+ json_ar, json_net,
+ "%pFX", rn_p);
+ } else
+ route_vty_out_tmp(
+ vty, dest, rn_p, pi->attr, safi,
+ use_json, json_ar, wide);
(*output_count)++;
}
}
static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
safi_t safi, enum bgp_show_adj_route_type type,
- const char *rmap_name, uint16_t show_flags)
+ const char *rmap_name, const struct prefix *match,
+ uint16_t show_flags)
{
struct bgp *bgp;
struct bgp_table *table;
prefix_rd2str(prd, rd_str, sizeof(rd_str));
- show_adj_route(vty, peer, table, afi, safi, type,
- rmap_name, json, json_routes, json_scode,
- json_ocode, show_flags, &header1,
- &header2, rd_str, &output_count_per_rd,
- &filtered_count_per_rd);
+ show_adj_route(
+ vty, peer, table, afi, safi, type, rmap_name,
+ json, json_routes, json_scode, json_ocode,
+ show_flags, &header1, &header2, rd_str, match,
+ &output_count_per_rd, &filtered_count_per_rd);
/* Don't include an empty RD in the output! */
if (json_routes && (output_count_per_rd > 0))
} else
show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
json, json_ar, json_scode, json_ocode,
- show_flags, &header1, &header2, rd_str,
+ show_flags, &header1, &header2, rd_str, match,
&output_count, &filtered_count);
if (use_json) {
vty_json(vty, json);
} else if (output_count > 0) {
- if (filtered_count > 0)
+ if (!match && filtered_count > 0)
vty_out(vty,
"\nTotal number of prefixes %ld (%ld filtered)\n",
output_count, filtered_count);
DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
show_ip_bgp_instance_neighbor_bestpath_route_cmd,
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [json$uj | wide$wide]",
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [detail$detail] [json$uj | wide$wide]",
SHOW_STR
IP_STR
BGP_STR
"Neighbor to display information about\n"
"Neighbor on BGP configured interface\n"
"Display the routes selected by best path\n"
+ "Display detailed version of routes\n"
JSON_STR
"Increase table width for longer prefixes\n")
{
int idx = 0;
uint16_t show_flags = 0;
+ if (detail)
+ SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
+
if (uj)
SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
if (!peer)
return CMD_WARNING;
- return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
+ return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
show_flags);
}
DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
show_ip_bgp_instance_neighbor_advertised_route_cmd,
- "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [detail$detail] [json$uj | wide$wide]",
+ "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [<A.B.C.D/M|X:X::X:X/M>$prefix | detail$detail] [json$uj | wide$wide]",
SHOW_STR
IP_STR
BGP_STR
"Display the filtered routes received from neighbor\n"
"Route-map to modify the attributes\n"
"Name of the route map\n"
+ "IPv4 prefix\n"
+ "IPv6 prefix\n"
"Display detailed version of routes\n"
JSON_STR
"Increase table width for longer prefixes\n")
struct listnode *node;
struct bgp *abgp;
- if (detail)
+ if (detail || prefix_str)
SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
if (uj) {
if (!all)
return peer_adj_routes(vty, peer, afi, safi, type, route_map,
- show_flags);
+ prefix_str ? prefix : NULL, show_flags);
if (uj)
vty_out(vty, "{\n");
false));
peer_adj_routes(vty, peer, afi, safi, type,
- route_map, show_flags);
+ route_map, prefix, show_flags);
}
}
} else {
false));
peer_adj_routes(vty, peer, afi, safi, type,
- route_map, show_flags);
+ route_map, prefix, show_flags);
}
}
}
struct bgp_distance *bdistance;
struct access_list *alist;
struct bgp_static *bgp_static;
+ struct bgp_path_info *bpi_ultimate;
if (!bgp)
return 0;
if (pinfo->attr->distance)
return pinfo->attr->distance;
+ /* get peer origin to calculate appropriate distance */
+ if (pinfo->sub_type == BGP_ROUTE_IMPORTED) {
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(pinfo);
+ peer = bpi_ultimate->peer;
+ }
+
/* Check source address.
* Note: for aggregate route, peer can have unspec af type.
*/