Mailing List Archive

[PATCH 56/57] bgpd: adj-in-rib table per VRF
When enabling adj-rib-in for global RIB table, it automatically
stores adj-rib-entries for VRF RIB tables. This commit introduces
a new vty command to dump the adj-rib-in entries per vrf:

show ip bgp vrf <RD> neighbor <IPneigh> received-routes

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
---
bgpd/bgp_route.c | 197 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
bgpd/bgp_route.h | 3 +
bgpd/bgpd.c | 20 +++++-
3 files changed, 216 insertions(+), 4 deletions(-)

diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index c6c5ddf26e19..789e219a1178 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -4142,6 +4142,25 @@ bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi)
}

void
+bgp_vrf_clear_adj_in (struct peer *peer, struct bgp_vrf *vrf, afi_t afi)
+{
+ struct bgp_table *table;
+ struct bgp_node *rn;
+ struct bgp_adj_in *ain;
+
+ table = vrf->rib[afi];
+
+ for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+ for (ain = rn->adj_in; ain ; ain = ain->next)
+ if (ain->peer == peer)
+ {
+ bgp_adj_in_remove (rn, ain);
+ bgp_unlock_node (rn);
+ break;
+ }
+}
+
+void
bgp_clear_stale_route (struct peer *peer, afi_t afi, safi_t safi)
{
struct bgp_node *rn;
@@ -8034,6 +8053,121 @@ bgp_show_table (struct vty *vty, struct bgp_table *table, struct in_addr *router
return CMD_SUCCESS;
}

+#define BGP_SHOW_SCODE_HEADER "Status codes: s suppressed, d damped, "\
+ "h history, * valid, > best, = multipath,%s"\
+ " i internal, r RIB-failure, S Stale, R Removed%s"
+#define BGP_SHOW_OCODE_HEADER "Origin codes: i - IGP, e - EGP, ? - incomplete%s%s"
+#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path%s"
+int
+show_adj_route_vrf (struct vty *vty, struct peer *peer, struct bgp_vrf *vrf, int in)
+{
+ struct bgp_table *table;
+ struct bgp *bgp;
+ char buf[RD_ADDRSTRLEN];
+ char *ptr;
+ struct bgp_node *rn;
+ unsigned long output_count;
+ safi_t safi;
+ int rd_header = 1;
+ int header1 = 1;
+ int header2 = 1;
+ struct bgp_adj_in *ain;
+ struct bgp_adj_out *adj;
+
+ /* This is first entry point, so reset total line. */
+ output_count = 0;
+
+ bgp = bgp_get_default ();
+ if (bgp == NULL)
+ {
+ vty_out (vty, "No BGP process is configured%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ table = vrf->rib[AFI_IP];
+
+ safi = table->type == BGP_TABLE_VRF ? SAFI_INTERNAL_EVPN : SAFI_UNICAST;
+ /* Start processing of routes. */
+ for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
+ if (rn->info != NULL)
+ {
+ if (in)
+ {
+ for (ain = rn->adj_in; ain; ain = ain->next)
+ if (ain->peer == peer)
+ {
+ if (header1)
+ {
+ vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+ vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+ header1 = 0;
+ }
+ if (header2)
+ {
+ vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
+ header2 = 0;
+ }
+ if (rd_header)
+ {
+ ptr = prefix_rd2str (&(vrf->outbound_rd), buf, RD_ADDRSTRLEN);
+ vty_out (vty, "Route Distinguisher: ");
+ if(ptr)
+ vty_out (vty, "%s", buf);
+ else
+ vty_out (vty, "<unknown>");
+ vty_out (vty, "%s", VTY_NEWLINE);
+ rd_header = 0;
+ }
+ if (ain->attr)
+ {
+ route_vty_out_tmp (vty, &rn->p, ain->attr, safi);
+ output_count++;
+ }
+ }
+ }
+ else
+ {
+ for (adj = rn->adj_out; adj; adj = adj->next)
+ if (adj->peer == peer)
+ {
+ if (header1)
+ {
+ vty_out (vty, "BGP table version is 0, local router ID is %s%s", inet_ntoa (bgp->router_id), VTY_NEWLINE);
+ vty_out (vty, BGP_SHOW_SCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+ vty_out (vty, BGP_SHOW_OCODE_HEADER, VTY_NEWLINE, VTY_NEWLINE);
+ header1 = 0;
+ }
+ if (rd_header)
+ {
+ ptr = prefix_rd2str ((struct prefix_rd *)rn->p.u.val, buf, RD_ADDRSTRLEN);
+ vty_out (vty, "Route Distinguisher: ");
+ if(ptr)
+ vty_out (vty, "%s", buf);
+ else
+ vty_out (vty, "<unknown>");
+ vty_out (vty, "%s", VTY_NEWLINE);
+ rd_header = 0;
+ }
+ if (header2)
+ {
+ vty_out (vty, BGP_SHOW_HEADER, VTY_NEWLINE);
+ header2 = 0;
+ }
+ if (adj->attr)
+ {
+ route_vty_out_tmp (vty, &rn->p, adj->attr, safi);
+ output_count++;
+ }
+ }
+ }
+ }
+ if (output_count != 0)
+ vty_out (vty, "%sTotal number of prefixes %ld%s",
+ VTY_NEWLINE, output_count, VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
static int
bgp_show (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
enum bgp_show_type type, void *output_arg)
@@ -8057,6 +8191,51 @@ bgp_show (struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
}

static int
+bgp_show_vrf_neigh (struct vty *vty, const char *vrf_name, afi_t afi,
+ const char *peername, int type)
+{
+ struct bgp *bgp = bgp_get_default();
+ struct bgp_vrf *vrf;
+ struct prefix_rd prd;
+ struct peer *peer;
+ union sockunion su;
+ int ret;
+
+ if (! bgp)
+ {
+ vty_out (vty, "%% No default BGP instance%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ if (! str2prefix_rd (vrf_name, &prd))
+ {
+ vty_out (vty, "%% Invalid RD '%s'%s", vrf_name, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ vrf = bgp_vrf_lookup (bgp, &prd);
+ if (! vrf)
+ {
+ vty_out (vty, "%% No VRF with RD '%s'%s", vrf_name, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ ret = str2sockunion (peername, &su);
+ if (ret < 0)
+ {
+ vty_out (vty, "%% Malformed address: %s%s", peername, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ peer = peer_lookup (NULL, &su);
+ if (! peer)
+ {
+ vty_out (vty, "%% No such neighbor or address family%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ return show_adj_route_vrf (vty, peer, vrf, 1);
+}
+
+static int
bgp_show_vrf (struct vty *vty, const char *vrf_name, afi_t afi,
enum bgp_show_type type, void *output_arg)
{
@@ -8069,7 +8248,7 @@ bgp_show_vrf (struct vty *vty, const char *vrf_name, afi_t afi,
vty_out (vty, "%% No default BGP instance%s", VTY_NEWLINE);
return CMD_WARNING;
}
- if (! prefix_str2rd (vrf_name, &prd))
+ if (! str2prefix_rd (vrf_name, &prd))
{
vty_out (vty, "%% Invalid RD '%s'%s", vrf_name, VTY_NEWLINE);
return CMD_WARNING;
@@ -8370,6 +8549,21 @@ DEFUN (show_ip_bgp_vrf,
return bgp_show_vrf (vty, argv[0], AFI_IP, bgp_show_type_normal, NULL);
}

+DEFUN (show_ip_bgp_vrf_neighbor_received,
+ show_ip_bgp_vrf_neighbor_received_cmd,
+ "show ip bgp vrf WORD neighbor A.B.C.D received-routes",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ "VRF\n"
+ "Route Distinguisher\n"
+ "Detailed information on TCP and BGP neighbor connections\n"
+ "Neighbor to display information about\n"
+ "Display the routes received from a BGP neighbor\n")
+{
+ return bgp_show_vrf_neigh (vty, argv[0], AFI_IP, argv[1], 1);
+}
+
DEFUN (show_ipv6_bgp_vrf,
show_ipv6_bgp_vrf_cmd,
"show ipv6 bgp vrf WORD",
@@ -18266,6 +18460,7 @@ bgp_route_init (void)
/* old style commands */
install_element (VIEW_NODE, &show_ip_bgp_cmd);
install_element (VIEW_NODE, &show_ip_bgp_vrf_cmd);
+ install_element (VIEW_NODE, &show_ip_bgp_vrf_neighbor_received_cmd);
install_element (VIEW_NODE, &show_ipv6_bgp_vrf_cmd);
install_element (VIEW_NODE, &show_ip_bgp_ipv4_cmd);
install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 74b974eb9f1a..f4b671af283f 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -303,5 +303,8 @@ extern void bgp_vrf_apply_new_imports (struct bgp_vrf *vrf, afi_t afi);
extern void
bgp_vrf_update (struct bgp_vrf *vrf, afi_t afi, struct bgp_node *rn,
struct bgp_info *selected, uint8_t announce);
+extern int
+show_adj_route_vrf (struct vty *vty, struct peer *peer, struct bgp_vrf *vrf, int in);
+extern void bgp_vrf_clear_adj_in (struct peer *, struct bgp_vrf *, afi_t);

#endif /* _QUAGGA_BGP_ROUTE_H */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 82d077c03876..4b246c80b880 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -2985,7 +2985,14 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
&& peer->status == Established)
{
if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
- bgp_clear_adj_in (peer, afi, safi);
+ {
+ struct listnode *node;
+ struct bgp_vrf *vrf;
+
+ bgp_clear_adj_in (peer, afi, safi);
+ for (ALL_LIST_ELEMENTS_RO(peer->bgp->vrfs, node, vrf))
+ bgp_vrf_clear_adj_in (peer, vrf, AF_INET);
+ }
else
{
if (flag == PEER_FLAG_REFLECTOR_CLIENT)
@@ -3026,8 +3033,15 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
if (peer->status == Established)
{
if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
- bgp_clear_adj_in (peer, afi, safi);
- else
+ {
+ struct listnode *node;
+ struct bgp_vrf *vrf;
+
+ bgp_clear_adj_in (peer, afi, safi);
+ for (ALL_LIST_ELEMENTS_RO(peer->bgp->vrfs, node, vrf))
+ bgp_vrf_clear_adj_in (peer, vrf, AF_INET);
+ }
+ else
{
if (flag == PEER_FLAG_REFLECTOR_CLIENT)
peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
--
2.1.4


_______________________________________________
Quagga-dev mailing list
Quagga-dev@lists.quagga.net
https://lists.quagga.net/mailman/listinfo/quagga-dev