2023-02-08 13:17:09 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2017-01-09 18:26:24 +01:00
|
|
|
/* VPN Related functions
|
2017-05-13 10:25:29 +02:00
|
|
|
* Copyright (C) 2017 6WIND
|
|
|
|
*
|
|
|
|
* This file is part of FRRouting
|
|
|
|
*/
|
2017-01-09 18:26:24 +01:00
|
|
|
|
|
|
|
#include <zebra.h>
|
|
|
|
#include "command.h"
|
|
|
|
#include "prefix.h"
|
|
|
|
#include "lib/json.h"
|
2020-10-15 21:33:09 +02:00
|
|
|
#include "lib/printfrr.h"
|
2017-01-09 18:26:24 +01:00
|
|
|
|
|
|
|
#include "bgpd/bgpd.h"
|
|
|
|
#include "bgpd/bgp_route.h"
|
|
|
|
#include "bgpd/bgp_table.h"
|
|
|
|
#include "bgpd/bgp_attr.h"
|
|
|
|
#include "bgpd/bgp_mplsvpn.h"
|
|
|
|
#include "bgpd/bgp_vpn.h"
|
2019-09-27 20:45:38 +02:00
|
|
|
#include "bgpd/bgp_updgrp.h"
|
2017-01-09 18:26:24 +01:00
|
|
|
|
|
|
|
int show_adj_route_vpn(struct vty *vty, struct peer *peer,
|
|
|
|
struct prefix_rd *prd, afi_t afi, safi_t safi,
|
2018-08-29 14:19:54 +02:00
|
|
|
bool use_json)
|
2017-01-09 18:26:24 +01:00
|
|
|
{
|
|
|
|
struct bgp *bgp;
|
|
|
|
struct bgp_table *table;
|
2020-03-27 00:11:58 +01:00
|
|
|
struct bgp_dest *dest;
|
|
|
|
struct bgp_dest *rm;
|
2017-01-09 18:26:24 +01:00
|
|
|
int rd_header;
|
|
|
|
int header = 1;
|
|
|
|
json_object *json = NULL;
|
2019-09-27 20:45:38 +02:00
|
|
|
json_object *json_adv = NULL;
|
2017-01-09 18:26:24 +01:00
|
|
|
json_object *json_routes = NULL;
|
2019-09-27 20:45:38 +02:00
|
|
|
char rd_str[BUFSIZ];
|
|
|
|
unsigned long output_count = 0;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-01-09 18:26:24 +01:00
|
|
|
bgp = bgp_get_default();
|
|
|
|
if (bgp == NULL) {
|
|
|
|
if (!use_json)
|
2017-07-13 17:49:13 +02:00
|
|
|
vty_out(vty, "No BGP process is configured\n");
|
2017-07-26 17:27:37 +02:00
|
|
|
else
|
|
|
|
vty_out(vty, "{}\n");
|
2017-01-09 18:26:24 +01:00
|
|
|
return CMD_WARNING;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2017-01-09 18:26:24 +01:00
|
|
|
if (use_json) {
|
|
|
|
json = json_object_new_object();
|
2019-09-27 20:45:38 +02:00
|
|
|
json_adv = json_object_new_object();
|
2017-01-09 18:26:24 +01:00
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
|
|
|
|
dest = bgp_route_next(dest)) {
|
|
|
|
const struct prefix *dest_p = bgp_dest_get_prefix(dest);
|
2020-03-22 05:02:18 +01:00
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
if (prd && memcmp(dest_p->u.val, prd->val, 8) != 0)
|
2017-01-09 18:26:24 +01:00
|
|
|
continue;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
table = bgp_dest_get_bgp_table_info(dest);
|
2018-10-13 17:17:12 +02:00
|
|
|
if (table == NULL)
|
|
|
|
continue;
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2019-11-22 00:30:00 +01:00
|
|
|
/*
|
|
|
|
* Initialize variables for each RD
|
|
|
|
* All prefixes under an RD is aggregated within "json_routes"
|
|
|
|
*/
|
2018-10-13 17:17:12 +02:00
|
|
|
rd_header = 1;
|
2019-09-27 20:45:38 +02:00
|
|
|
memset(rd_str, 0, sizeof(rd_str));
|
2019-11-22 00:30:00 +01:00
|
|
|
json_routes = NULL;
|
2018-10-13 17:17:12 +02:00
|
|
|
|
|
|
|
for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
|
2019-09-27 20:45:38 +02:00
|
|
|
struct bgp_adj_out *adj = NULL;
|
|
|
|
struct attr *attr = NULL;
|
|
|
|
struct peer_af *paf = NULL;
|
|
|
|
|
|
|
|
RB_FOREACH (adj, bgp_adj_out_rb, &rm->adj_out)
|
|
|
|
SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
|
|
|
|
if (paf->peer != peer || !adj->attr)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
attr = adj->attr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
if (bgp_dest_get_bgp_path_info(rm) == NULL)
|
2018-10-13 17:17:12 +02:00
|
|
|
continue;
|
|
|
|
|
2019-11-12 23:02:05 +01:00
|
|
|
if (!attr)
|
|
|
|
continue;
|
|
|
|
|
2018-10-13 17:17:12 +02:00
|
|
|
if (header) {
|
|
|
|
if (use_json) {
|
|
|
|
json_object_int_add(
|
|
|
|
json, "bgpTableVersion", 0);
|
2021-11-18 09:55:47 +01:00
|
|
|
json_object_string_addf(
|
2018-10-13 17:17:12 +02:00
|
|
|
json, "bgpLocalRouterId",
|
2021-11-18 09:55:47 +01:00
|
|
|
"%pI4", &bgp->router_id);
|
2019-09-27 20:45:38 +02:00
|
|
|
json_object_int_add(
|
|
|
|
json,
|
|
|
|
"defaultLocPrf",
|
|
|
|
bgp->default_local_pref);
|
|
|
|
json_object_int_add(
|
|
|
|
json, "localAS",
|
|
|
|
bgp->as);
|
2018-10-13 17:17:12 +02:00
|
|
|
} else {
|
|
|
|
vty_out(vty,
|
2020-10-15 21:33:09 +02:00
|
|
|
"BGP table version is 0, local router ID is %pI4\n",
|
|
|
|
&bgp->router_id);
|
2019-09-27 20:45:38 +02:00
|
|
|
vty_out(vty, "Default local pref %u, ",
|
|
|
|
bgp->default_local_pref);
|
|
|
|
vty_out(vty, "local AS %u\n", bgp->as);
|
2018-10-13 17:17:12 +02:00
|
|
|
vty_out(vty,
|
|
|
|
"Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
|
|
|
|
vty_out(vty,
|
|
|
|
"Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
|
|
|
|
vty_out(vty, V4_HEADER);
|
|
|
|
}
|
|
|
|
header = 0;
|
|
|
|
}
|
2017-07-17 14:03:14 +02:00
|
|
|
|
2018-10-13 17:17:12 +02:00
|
|
|
if (rd_header) {
|
|
|
|
uint16_t type;
|
|
|
|
struct rd_as rd_as = {0};
|
|
|
|
struct rd_ip rd_ip = {0};
|
2020-04-01 21:05:26 +02:00
|
|
|
#ifdef ENABLE_BGP_VNC
|
2018-10-13 17:17:12 +02:00
|
|
|
struct rd_vnc_eth rd_vnc_eth = {0};
|
2017-01-09 18:26:24 +01:00
|
|
|
#endif
|
2020-03-22 05:02:18 +01:00
|
|
|
const uint8_t *pnt;
|
2018-10-13 17:17:12 +02:00
|
|
|
|
2020-03-27 00:11:58 +01:00
|
|
|
pnt = dest_p->u.val;
|
2018-10-13 17:17:12 +02:00
|
|
|
|
|
|
|
/* Decode RD type. */
|
|
|
|
type = decode_rd_type(pnt);
|
|
|
|
/* Decode RD value. */
|
|
|
|
if (type == RD_TYPE_AS)
|
|
|
|
decode_rd_as(pnt + 2, &rd_as);
|
|
|
|
else if (type == RD_TYPE_AS4)
|
|
|
|
decode_rd_as4(pnt + 2, &rd_as);
|
|
|
|
else if (type == RD_TYPE_IP)
|
|
|
|
decode_rd_ip(pnt + 2, &rd_ip);
|
2020-04-01 21:05:26 +02:00
|
|
|
#ifdef ENABLE_BGP_VNC
|
2018-10-13 17:17:12 +02:00
|
|
|
else if (type == RD_TYPE_VNC_ETH)
|
|
|
|
decode_rd_vnc_eth(pnt, &rd_vnc_eth);
|
2017-01-09 18:26:24 +01:00
|
|
|
#endif
|
2018-10-13 17:17:12 +02:00
|
|
|
if (use_json) {
|
2019-09-27 20:45:38 +02:00
|
|
|
json_routes = json_object_new_object();
|
|
|
|
|
2018-10-13 17:17:12 +02:00
|
|
|
if (type == RD_TYPE_AS
|
|
|
|
|| type == RD_TYPE_AS4)
|
2020-04-20 20:12:38 +02:00
|
|
|
snprintf(rd_str, sizeof(rd_str),
|
|
|
|
"%u:%d", rd_as.as,
|
|
|
|
rd_as.val);
|
2018-10-13 17:17:12 +02:00
|
|
|
else if (type == RD_TYPE_IP)
|
2020-10-15 21:33:09 +02:00
|
|
|
snprintfrr(rd_str,
|
|
|
|
sizeof(rd_str),
|
|
|
|
"%pI4:%d", &rd_ip.ip,
|
|
|
|
rd_ip.val);
|
2018-10-13 17:17:12 +02:00
|
|
|
json_object_string_add(
|
|
|
|
json_routes,
|
2019-09-27 20:45:38 +02:00
|
|
|
"rd", rd_str);
|
2018-10-13 17:17:12 +02:00
|
|
|
} else {
|
|
|
|
vty_out(vty, "Route Distinguisher: ");
|
|
|
|
|
|
|
|
if (type == RD_TYPE_AS
|
|
|
|
|| type == RD_TYPE_AS4)
|
|
|
|
vty_out(vty, "%u:%d", rd_as.as,
|
|
|
|
rd_as.val);
|
|
|
|
else if (type == RD_TYPE_IP)
|
2020-10-15 21:33:09 +02:00
|
|
|
vty_out(vty, "%pI4:%d",
|
|
|
|
&rd_ip.ip, rd_ip.val);
|
2020-04-01 21:05:26 +02:00
|
|
|
#ifdef ENABLE_BGP_VNC
|
2018-10-13 17:17:12 +02:00
|
|
|
else if (type == RD_TYPE_VNC_ETH)
|
|
|
|
vty_out(vty,
|
|
|
|
"%u:%02x:%02x:%02x:%02x:%02x:%02x",
|
|
|
|
rd_vnc_eth.local_nve_id,
|
|
|
|
rd_vnc_eth.macaddr
|
|
|
|
.octet[0],
|
|
|
|
rd_vnc_eth.macaddr
|
|
|
|
.octet[1],
|
|
|
|
rd_vnc_eth.macaddr
|
|
|
|
.octet[2],
|
|
|
|
rd_vnc_eth.macaddr
|
|
|
|
.octet[3],
|
|
|
|
rd_vnc_eth.macaddr
|
|
|
|
.octet[4],
|
|
|
|
rd_vnc_eth.macaddr
|
|
|
|
.octet[5]);
|
2017-01-09 18:26:24 +01:00
|
|
|
#endif
|
|
|
|
|
2018-10-13 17:17:12 +02:00
|
|
|
vty_out(vty, "\n");
|
2017-01-09 18:26:24 +01:00
|
|
|
}
|
2018-10-13 17:17:12 +02:00
|
|
|
rd_header = 0;
|
|
|
|
}
|
2024-04-11 16:46:46 +02:00
|
|
|
route_vty_out_tmp(vty, bgp, rm, bgp_dest_get_prefix(rm),
|
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>
2021-04-09 08:33:41 +02:00
|
|
|
attr, safi, use_json, json_routes,
|
|
|
|
false);
|
2019-09-27 20:45:38 +02:00
|
|
|
output_count++;
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2019-09-27 20:45:38 +02:00
|
|
|
|
2019-11-22 00:30:00 +01:00
|
|
|
if (use_json && json_routes)
|
2019-09-27 20:45:38 +02:00
|
|
|
json_object_object_add(json_adv, rd_str, json_routes);
|
2017-07-17 14:03:14 +02:00
|
|
|
}
|
2019-09-27 20:45:38 +02:00
|
|
|
|
2017-01-09 18:26:24 +01:00
|
|
|
if (use_json) {
|
2019-09-27 20:45:38 +02:00
|
|
|
json_object_object_add(json, "advertisedRoutes", json_adv);
|
|
|
|
json_object_int_add(json,
|
|
|
|
"totalPrefixCounter", output_count);
|
2021-11-25 16:51:12 +01:00
|
|
|
vty_json(vty, json);
|
2019-09-27 20:45:38 +02:00
|
|
|
} else
|
|
|
|
vty_out(vty, "\nTotal number of prefixes %ld\n", output_count);
|
|
|
|
|
2017-01-09 18:26:24 +01:00
|
|
|
return CMD_SUCCESS;
|
|
|
|
}
|