mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 22:10:19 +00:00
Merge pull request #4850 from lkrishnamoor/show_cli
bgpd: Adding new bgp evpn cli's for ip-prefix lookup
This commit is contained in:
commit
12bea6d575
109
bgpd/bgp_evpn.c
109
bgpd/bgp_evpn.c
@ -4697,59 +4697,60 @@ void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json)
|
|||||||
{
|
{
|
||||||
char buf1[ETHER_ADDR_STRLEN];
|
char buf1[ETHER_ADDR_STRLEN];
|
||||||
char buf2[PREFIX2STR_BUFFER];
|
char buf2[PREFIX2STR_BUFFER];
|
||||||
|
uint8_t family;
|
||||||
|
uint8_t prefixlen;
|
||||||
|
|
||||||
if (!json)
|
if (!json)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
|
json_object_int_add(json, "routeType", p->prefix.route_type);
|
||||||
json_object_int_add(json, "routeType", p->prefix.route_type);
|
|
||||||
|
switch (p->prefix.route_type) {
|
||||||
|
case BGP_EVPN_MAC_IP_ROUTE:
|
||||||
json_object_int_add(json, "ethTag",
|
json_object_int_add(json, "ethTag",
|
||||||
p->prefix.imet_addr.eth_tag);
|
p->prefix.macip_addr.eth_tag);
|
||||||
json_object_int_add(json, "ipLen",
|
json_object_int_add(json, "macLen", 8 * ETH_ALEN);
|
||||||
is_evpn_prefix_ipaddr_v4(p)
|
json_object_string_add(json, "mac",
|
||||||
? IPV4_MAX_BITLEN
|
prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
|
||||||
: IPV6_MAX_BITLEN);
|
sizeof(buf1)));
|
||||||
json_object_string_add(json, "ip",
|
|
||||||
inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
|
|
||||||
} else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
|
|
||||||
if (is_evpn_prefix_ipaddr_none(p)) {
|
|
||||||
json_object_int_add(json, "routeType",
|
|
||||||
p->prefix.route_type);
|
|
||||||
json_object_int_add(json, "ethTag",
|
|
||||||
p->prefix.macip_addr.eth_tag);
|
|
||||||
json_object_int_add(json, "macLen", 8 * ETH_ALEN);
|
|
||||||
json_object_string_add(json, "mac",
|
|
||||||
prefix_mac2str(&p->prefix.macip_addr.mac,
|
|
||||||
buf1,
|
|
||||||
sizeof(buf1)));
|
|
||||||
} else {
|
|
||||||
uint8_t family;
|
|
||||||
|
|
||||||
family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
|
if (!is_evpn_prefix_ipaddr_none(p)) {
|
||||||
: AF_INET6;
|
family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET :
|
||||||
|
AF_INET6;
|
||||||
json_object_int_add(json, "routeType",
|
prefixlen = (family == AF_INET) ?
|
||||||
p->prefix.route_type);
|
IPV4_MAX_BITLEN : IPV6_MAX_BITLEN;
|
||||||
json_object_int_add(json, "ethTag",
|
inet_ntop(family, &p->prefix.macip_addr.ip.ip.addr,
|
||||||
p->prefix.macip_addr.eth_tag);
|
buf2, PREFIX2STR_BUFFER);
|
||||||
json_object_int_add(json, "macLen", 8 * ETH_ALEN);
|
json_object_int_add(json, "ipLen", prefixlen);
|
||||||
json_object_string_add(json, "mac",
|
json_object_string_add(json, "ip", buf2);
|
||||||
prefix_mac2str(&p->prefix.macip_addr.mac,
|
|
||||||
buf1,
|
|
||||||
sizeof(buf1)));
|
|
||||||
json_object_int_add(json, "ipLen",
|
|
||||||
is_evpn_prefix_ipaddr_v4(p)
|
|
||||||
? IPV4_MAX_BITLEN
|
|
||||||
: IPV6_MAX_BITLEN);
|
|
||||||
json_object_string_add(
|
|
||||||
json, "ip",
|
|
||||||
inet_ntop(family,
|
|
||||||
&p->prefix.macip_addr.ip.ip.addr,
|
|
||||||
buf2,
|
|
||||||
PREFIX2STR_BUFFER));
|
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
/* Currently, this is to cater to other AF_ETHERNET code. */
|
|
||||||
|
case BGP_EVPN_IMET_ROUTE:
|
||||||
|
json_object_int_add(json, "ethTag",
|
||||||
|
p->prefix.imet_addr.eth_tag);
|
||||||
|
family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET : AF_INET6;
|
||||||
|
prefixlen = (family == AF_INET) ? IPV4_MAX_BITLEN :
|
||||||
|
IPV6_MAX_BITLEN;
|
||||||
|
inet_ntop(family, &p->prefix.imet_addr.ip.ip.addr, buf2,
|
||||||
|
PREFIX2STR_BUFFER);
|
||||||
|
json_object_int_add(json, "ipLen", prefixlen);
|
||||||
|
json_object_string_add(json, "ip", buf2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BGP_EVPN_IP_PREFIX_ROUTE:
|
||||||
|
json_object_int_add(json, "ethTag",
|
||||||
|
p->prefix.prefix_addr.eth_tag);
|
||||||
|
family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET : AF_INET6;
|
||||||
|
inet_ntop(family, &p->prefix.prefix_addr.ip.ip.addr,
|
||||||
|
buf2, sizeof(buf2));
|
||||||
|
json_object_int_add(json, "ipLen",
|
||||||
|
p->prefix.prefix_addr.ip_prefix_length);
|
||||||
|
json_object_string_add(json, "ip", buf2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6008,3 +6009,19 @@ void bgp_evpn_vrf_delete(struct bgp *bgp_vrf)
|
|||||||
{
|
{
|
||||||
bgp_evpn_unmap_vrf_from_its_rts(bgp_vrf);
|
bgp_evpn_unmap_vrf_from_its_rts(bgp_vrf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the prefixlen of the ip prefix carried within the type5 evpn route.
|
||||||
|
*/
|
||||||
|
int bgp_evpn_get_type5_prefixlen(struct prefix *pfx)
|
||||||
|
{
|
||||||
|
struct prefix_evpn *evp = (struct prefix_evpn *)pfx;
|
||||||
|
|
||||||
|
if (!pfx || pfx->family != AF_EVPN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return evp->prefix.prefix_addr.ip_prefix_length;
|
||||||
|
}
|
||||||
|
@ -190,5 +190,6 @@ extern void bgp_evpn_flood_control_change(struct bgp *bgp);
|
|||||||
extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp);
|
extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp);
|
||||||
extern void bgp_evpn_cleanup(struct bgp *bgp);
|
extern void bgp_evpn_cleanup(struct bgp *bgp);
|
||||||
extern void bgp_evpn_init(struct bgp *bgp);
|
extern void bgp_evpn_init(struct bgp *bgp);
|
||||||
|
extern int bgp_evpn_get_type5_prefixlen(struct prefix *pfx);
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_EVPN_H */
|
#endif /* _QUAGGA_BGP_EVPN_H */
|
||||||
|
277
bgpd/bgp_route.c
277
bgpd/bgp_route.c
@ -8227,7 +8227,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
|
|||||||
json_nexthop_global = json_object_new_object();
|
json_nexthop_global = json_object_new_object();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!json_paths && path->extra) {
|
if (path->extra) {
|
||||||
char tag_buf[30];
|
char tag_buf[30];
|
||||||
|
|
||||||
buf2[0] = '\0';
|
buf2[0] = '\0';
|
||||||
@ -8238,15 +8238,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
|
|||||||
sizeof(tag_buf));
|
sizeof(tag_buf));
|
||||||
}
|
}
|
||||||
if (safi == SAFI_EVPN) {
|
if (safi == SAFI_EVPN) {
|
||||||
bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
|
if (!json_paths) {
|
||||||
buf2, sizeof(buf2));
|
bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
|
||||||
vty_out(vty, " Route %s", buf2);
|
buf2, sizeof(buf2));
|
||||||
if (tag_buf[0] != '\0')
|
vty_out(vty, " Route %s", buf2);
|
||||||
vty_out(vty, " VNI %s", tag_buf);
|
if (tag_buf[0] != '\0')
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, " VNI %s", tag_buf);
|
||||||
|
vty_out(vty, "\n");
|
||||||
|
} else {
|
||||||
|
if (tag_buf[0])
|
||||||
|
json_object_string_add(json_path, "VNI",
|
||||||
|
tag_buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path->extra && path->extra->parent) {
|
if (path->extra && path->extra->parent && !json_paths) {
|
||||||
struct bgp_path_info *parent_ri;
|
struct bgp_path_info *parent_ri;
|
||||||
struct bgp_node *rn, *prn;
|
struct bgp_node *rn, *prn;
|
||||||
|
|
||||||
@ -9541,37 +9547,47 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
|||||||
if (has_valid_label)
|
if (has_valid_label)
|
||||||
label = label_pton(&rn->local_label);
|
label = label_pton(&rn->local_label);
|
||||||
|
|
||||||
if (json) {
|
if (safi == SAFI_EVPN) {
|
||||||
if (has_valid_label)
|
|
||||||
json_object_int_add(json, "localLabel", label);
|
|
||||||
|
|
||||||
json_object_string_add(
|
if (!json) {
|
||||||
json, "prefix",
|
|
||||||
prefix2str(p, prefix_str, sizeof(prefix_str)));
|
|
||||||
} else {
|
|
||||||
if (safi == SAFI_EVPN)
|
|
||||||
vty_out(vty, "BGP routing table entry for %s%s%s\n",
|
vty_out(vty, "BGP routing table entry for %s%s%s\n",
|
||||||
prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
|
prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
|
||||||
: "",
|
: "", prd ? ":" : "",
|
||||||
prd ? ":" : "",
|
|
||||||
bgp_evpn_route2str((struct prefix_evpn *)p,
|
bgp_evpn_route2str((struct prefix_evpn *)p,
|
||||||
buf3, sizeof(buf3)));
|
buf3, sizeof(buf3)));
|
||||||
else
|
} else {
|
||||||
|
json_object_string_add(json, "rd",
|
||||||
|
prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
|
||||||
|
"");
|
||||||
|
bgp_evpn_route2json((struct prefix_evpn *)p, json);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!json) {
|
||||||
vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
|
vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
|
||||||
((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
|
((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
|
||||||
? prefix_rd2str(prd, buf1,
|
? prefix_rd2str(prd, buf1,
|
||||||
sizeof(buf1))
|
sizeof(buf1))
|
||||||
: ""),
|
: ""),
|
||||||
safi == SAFI_MPLS_VPN ? ":" : "",
|
safi == SAFI_MPLS_VPN ? ":" : "",
|
||||||
inet_ntop(p->family, &p->u.prefix, buf2,
|
inet_ntop(p->family, &p->u.prefix, buf2,
|
||||||
INET6_ADDRSTRLEN),
|
INET6_ADDRSTRLEN),
|
||||||
p->prefixlen);
|
p->prefixlen);
|
||||||
|
|
||||||
if (has_valid_label)
|
} else
|
||||||
|
json_object_string_add(json, "prefix",
|
||||||
|
prefix2str(p, prefix_str, sizeof(prefix_str)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_valid_label) {
|
||||||
|
if (json)
|
||||||
|
json_object_int_add(json, "localLabel", label);
|
||||||
|
else
|
||||||
vty_out(vty, "Local label: %d\n", label);
|
vty_out(vty, "Local label: %d\n", label);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json)
|
||||||
if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
|
if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
|
||||||
vty_out(vty, "not allocated\n");
|
vty_out(vty, "not allocated\n");
|
||||||
}
|
|
||||||
|
|
||||||
for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
|
for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
|
||||||
count++;
|
count++;
|
||||||
@ -9703,6 +9719,58 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bgp_show_path_info(struct prefix_rd *pfx_rd,
|
||||||
|
struct bgp_node *bgp_node, struct vty *vty,
|
||||||
|
struct bgp *bgp, afi_t afi,
|
||||||
|
safi_t safi, json_object *json,
|
||||||
|
enum bgp_path_type pathtype, int *display)
|
||||||
|
{
|
||||||
|
struct bgp_path_info *pi;
|
||||||
|
int header = 1;
|
||||||
|
char rdbuf[RD_ADDRSTRLEN];
|
||||||
|
json_object *json_header = NULL;
|
||||||
|
json_object *json_paths = NULL;
|
||||||
|
|
||||||
|
for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
|
||||||
|
pi = pi->next) {
|
||||||
|
|
||||||
|
if (json && !json_paths) {
|
||||||
|
/* Instantiate json_paths only if path is valid */
|
||||||
|
json_paths = json_object_new_array();
|
||||||
|
if (pfx_rd) {
|
||||||
|
prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
|
||||||
|
json_header = json_object_new_object();
|
||||||
|
} else
|
||||||
|
json_header = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header) {
|
||||||
|
route_vty_out_detail_header(
|
||||||
|
vty, bgp, bgp_node, pfx_rd,
|
||||||
|
AFI_IP, safi, json_header);
|
||||||
|
header = 0;
|
||||||
|
}
|
||||||
|
(*display)++;
|
||||||
|
|
||||||
|
if (pathtype == BGP_PATH_SHOW_ALL
|
||||||
|
|| (pathtype == BGP_PATH_SHOW_BESTPATH
|
||||||
|
&& CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
|
||||||
|
|| (pathtype == BGP_PATH_SHOW_MULTIPATH
|
||||||
|
&& (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
|
||||||
|
|| CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
|
||||||
|
route_vty_out_detail(vty, bgp, bgp_node,
|
||||||
|
pi, AFI_IP, safi,
|
||||||
|
json_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json && json_paths) {
|
||||||
|
json_object_object_add(json_header, "paths", json_paths);
|
||||||
|
|
||||||
|
if (pfx_rd)
|
||||||
|
json_object_object_add(json, rdbuf, json_header);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Display specified route of BGP table. */
|
/* Display specified route of BGP table. */
|
||||||
static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
||||||
struct bgp_table *rib, const char *ip_str,
|
struct bgp_table *rib, const char *ip_str,
|
||||||
@ -9711,12 +9779,10 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
|||||||
enum bgp_path_type pathtype, bool use_json)
|
enum bgp_path_type pathtype, bool use_json)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int header;
|
|
||||||
int display = 0;
|
int display = 0;
|
||||||
struct prefix match;
|
struct prefix match;
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
struct bgp_node *rm;
|
struct bgp_node *rm;
|
||||||
struct bgp_path_info *pi;
|
|
||||||
struct bgp_table *table;
|
struct bgp_table *table;
|
||||||
json_object *json = NULL;
|
json_object *json = NULL;
|
||||||
json_object *json_paths = NULL;
|
json_object *json_paths = NULL;
|
||||||
@ -9730,12 +9796,10 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
|||||||
|
|
||||||
match.family = afi2family(afi);
|
match.family = afi2family(afi);
|
||||||
|
|
||||||
if (use_json) {
|
if (use_json)
|
||||||
json = json_object_new_object();
|
json = json_object_new_object();
|
||||||
json_paths = json_object_new_array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
|
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
|
||||||
for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
|
for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
|
||||||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||||
continue;
|
continue;
|
||||||
@ -9743,8 +9807,6 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
|||||||
if (!table)
|
if (!table)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
header = 1;
|
|
||||||
|
|
||||||
if ((rm = bgp_node_match(table, &match)) == NULL)
|
if ((rm = bgp_node_match(table, &match)) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -9754,73 +9816,83 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pi = bgp_node_get_bgp_path_info(rm); pi;
|
bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
|
||||||
pi = pi->next) {
|
vty, bgp, afi, safi, json,
|
||||||
if (header) {
|
pathtype, &display);
|
||||||
route_vty_out_detail_header(
|
|
||||||
vty, bgp, rm,
|
|
||||||
(struct prefix_rd *)&rn->p,
|
|
||||||
AFI_IP, safi, json);
|
|
||||||
header = 0;
|
|
||||||
}
|
|
||||||
display++;
|
|
||||||
|
|
||||||
if (pathtype == BGP_PATH_SHOW_ALL
|
bgp_unlock_node(rm);
|
||||||
|| (pathtype == BGP_PATH_SHOW_BESTPATH
|
}
|
||||||
&& CHECK_FLAG(pi->flags,
|
} else if (safi == SAFI_EVPN) {
|
||||||
BGP_PATH_SELECTED))
|
struct bgp_node *longest_pfx;
|
||||||
|| (pathtype == BGP_PATH_SHOW_MULTIPATH
|
bool is_exact_pfxlen_match = FALSE;
|
||||||
&& (CHECK_FLAG(pi->flags,
|
|
||||||
BGP_PATH_MULTIPATH)
|
for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
|
||||||
|| CHECK_FLAG(pi->flags,
|
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||||
BGP_PATH_SELECTED))))
|
continue;
|
||||||
route_vty_out_detail(vty, bgp, rm,
|
table = bgp_node_get_bgp_table_info(rn);
|
||||||
pi, AFI_IP, safi,
|
if (!table)
|
||||||
json_paths);
|
continue;
|
||||||
|
|
||||||
|
longest_pfx = NULL;
|
||||||
|
is_exact_pfxlen_match = FALSE;
|
||||||
|
/*
|
||||||
|
* Search through all the prefixes for a match. The
|
||||||
|
* pfx's are enumerated in ascending order of pfxlens.
|
||||||
|
* So, the last pfx match is the longest match. Set
|
||||||
|
* is_exact_pfxlen_match when we get exact pfxlen match
|
||||||
|
*/
|
||||||
|
for (rm = bgp_table_top(table); rm;
|
||||||
|
rm = bgp_route_next(rm)) {
|
||||||
|
/*
|
||||||
|
* Get prefixlen of the ip-prefix within type5
|
||||||
|
* evpn route
|
||||||
|
*/
|
||||||
|
if (evpn_type5_prefix_match(&rm->p,
|
||||||
|
&match) && rm->info) {
|
||||||
|
longest_pfx = rm;
|
||||||
|
int type5_pfxlen =
|
||||||
|
bgp_evpn_get_type5_prefixlen(&rm->p);
|
||||||
|
if (type5_pfxlen == match.prefixlen) {
|
||||||
|
is_exact_pfxlen_match = TRUE;
|
||||||
|
bgp_unlock_node(rm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!longest_pfx)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (prefix_check && !is_exact_pfxlen_match)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rm = longest_pfx;
|
||||||
|
bgp_lock_node(rm);
|
||||||
|
|
||||||
|
bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
|
||||||
|
vty, bgp, afi, safi, json,
|
||||||
|
pathtype, &display);
|
||||||
|
|
||||||
bgp_unlock_node(rm);
|
bgp_unlock_node(rm);
|
||||||
}
|
}
|
||||||
} else if (safi == SAFI_FLOWSPEC) {
|
} else if (safi == SAFI_FLOWSPEC) {
|
||||||
|
if (use_json)
|
||||||
|
json_paths = json_object_new_array();
|
||||||
|
|
||||||
display = bgp_flowspec_display_match_per_ip(afi, rib,
|
display = bgp_flowspec_display_match_per_ip(afi, rib,
|
||||||
&match, prefix_check,
|
&match, prefix_check,
|
||||||
vty,
|
vty,
|
||||||
use_json,
|
use_json,
|
||||||
json_paths);
|
json_paths);
|
||||||
|
if (use_json && display)
|
||||||
|
json_object_object_add(json, "paths", json_paths);
|
||||||
} else {
|
} else {
|
||||||
header = 1;
|
|
||||||
|
|
||||||
if ((rn = bgp_node_match(rib, &match)) != NULL) {
|
if ((rn = bgp_node_match(rib, &match)) != NULL) {
|
||||||
if (!prefix_check
|
if (!prefix_check
|
||||||
|| rn->p.prefixlen == match.prefixlen) {
|
|| rn->p.prefixlen == match.prefixlen) {
|
||||||
for (pi = bgp_node_get_bgp_path_info(rn); pi;
|
bgp_show_path_info(NULL, rn, vty, bgp, afi,
|
||||||
pi = pi->next) {
|
safi, json,
|
||||||
if (header) {
|
pathtype, &display);
|
||||||
route_vty_out_detail_header(
|
|
||||||
vty, bgp, rn, NULL, afi,
|
|
||||||
safi, json);
|
|
||||||
header = 0;
|
|
||||||
}
|
|
||||||
display++;
|
|
||||||
|
|
||||||
if (pathtype == BGP_PATH_SHOW_ALL
|
|
||||||
|| (pathtype
|
|
||||||
== BGP_PATH_SHOW_BESTPATH
|
|
||||||
&& CHECK_FLAG(
|
|
||||||
pi->flags,
|
|
||||||
BGP_PATH_SELECTED))
|
|
||||||
|| (pathtype
|
|
||||||
== BGP_PATH_SHOW_MULTIPATH
|
|
||||||
&& (CHECK_FLAG(
|
|
||||||
pi->flags,
|
|
||||||
BGP_PATH_MULTIPATH)
|
|
||||||
|| CHECK_FLAG(
|
|
||||||
pi->flags,
|
|
||||||
BGP_PATH_SELECTED))))
|
|
||||||
route_vty_out_detail(
|
|
||||||
vty, bgp, rn, pi,
|
|
||||||
afi, safi, json_paths);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bgp_unlock_node(rn);
|
bgp_unlock_node(rn);
|
||||||
@ -9828,11 +9900,9 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (use_json) {
|
if (use_json) {
|
||||||
if (display)
|
|
||||||
json_object_object_add(json, "paths", json_paths);
|
|
||||||
|
|
||||||
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
vty_out(vty, "%s\n", json_object_to_json_string_ext(
|
||||||
json, JSON_C_TO_STRING_PRETTY));
|
json, JSON_C_TO_STRING_PRETTY |
|
||||||
|
JSON_C_TO_STRING_NOSLASHESCAPE));
|
||||||
json_object_free(json);
|
json_object_free(json);
|
||||||
} else {
|
} else {
|
||||||
if (!display) {
|
if (!display) {
|
||||||
@ -11025,32 +11095,37 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix,
|
|||||||
}
|
}
|
||||||
#endif /* KEEP_OLD_VPN_COMMANDS */
|
#endif /* KEEP_OLD_VPN_COMMANDS */
|
||||||
|
|
||||||
DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
|
DEFUN (show_bgp_l2vpn_evpn_route_prefix,
|
||||||
show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
|
show_bgp_l2vpn_evpn_route_prefix_cmd,
|
||||||
"show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
|
"show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
|
||||||
SHOW_STR
|
SHOW_STR
|
||||||
IP_STR
|
|
||||||
BGP_STR
|
BGP_STR
|
||||||
L2VPN_HELP_STR
|
L2VPN_HELP_STR
|
||||||
EVPN_HELP_STR
|
EVPN_HELP_STR
|
||||||
"Display information about all EVPN NLRIs\n"
|
"Network in the BGP routing table to display\n"
|
||||||
|
"Network in the BGP routing table to display\n"
|
||||||
"Network in the BGP routing table to display\n"
|
"Network in the BGP routing table to display\n"
|
||||||
"Network in the BGP routing table to display\n"
|
"Network in the BGP routing table to display\n"
|
||||||
JSON_STR)
|
JSON_STR)
|
||||||
{
|
{
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
char *network = NULL;
|
char *network = NULL;
|
||||||
|
int prefix_check = 0;
|
||||||
|
|
||||||
if (argv_find(argv, argc, "A.B.C.D", &idx))
|
if (argv_find(argv, argc, "A.B.C.D", &idx) ||
|
||||||
|
argv_find(argv, argc, "X:X::X:X", &idx))
|
||||||
network = argv[idx]->arg;
|
network = argv[idx]->arg;
|
||||||
else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
|
else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
|
||||||
|
argv_find(argv, argc, "A.B.C.D/M", &idx)) {
|
||||||
network = argv[idx]->arg;
|
network = argv[idx]->arg;
|
||||||
else {
|
prefix_check = 1;
|
||||||
|
} else {
|
||||||
vty_out(vty, "Unable to figure out Network\n");
|
vty_out(vty, "Unable to figure out Network\n");
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
|
return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
|
||||||
BGP_PATH_SHOW_ALL, use_json(argc, argv));
|
prefix_check, BGP_PATH_SHOW_ALL,
|
||||||
|
use_json(argc, argv));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
|
static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
|
||||||
@ -12547,7 +12622,7 @@ void bgp_route_init(void)
|
|||||||
#endif /* KEEP_OLD_VPN_COMMANDS */
|
#endif /* KEEP_OLD_VPN_COMMANDS */
|
||||||
install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
|
install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
|
||||||
install_element(VIEW_NODE,
|
install_element(VIEW_NODE,
|
||||||
&show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
|
&show_bgp_l2vpn_evpn_route_prefix_cmd);
|
||||||
|
|
||||||
/* BGP dampening clear commands */
|
/* BGP dampening clear commands */
|
||||||
install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
|
install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
|
||||||
|
47
lib/prefix.c
47
lib/prefix.c
@ -601,6 +601,53 @@ int prefix_match(const struct prefix *n, const struct prefix *p)
|
|||||||
if (np[offset] != pp[offset])
|
if (np[offset] != pp[offset])
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* n is a type5 evpn prefix. This function tries to see if there is an
|
||||||
|
* ip-prefix within n which matches prefix p
|
||||||
|
* If n includes p prefix then return 1 else return 0.
|
||||||
|
*/
|
||||||
|
int evpn_type5_prefix_match(const struct prefix *n, const struct prefix *p)
|
||||||
|
{
|
||||||
|
int offset;
|
||||||
|
int shift;
|
||||||
|
int prefixlen;
|
||||||
|
const uint8_t *np, *pp;
|
||||||
|
struct prefix_evpn *evp;
|
||||||
|
|
||||||
|
if (n->family != AF_EVPN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
evp = (struct prefix_evpn *)n;
|
||||||
|
pp = p->u.val;
|
||||||
|
|
||||||
|
if ((evp->prefix.route_type != 5) ||
|
||||||
|
(p->family == AF_INET6 && !is_evpn_prefix_ipaddr_v6(evp)) ||
|
||||||
|
(p->family == AF_INET && !is_evpn_prefix_ipaddr_v4(evp)) ||
|
||||||
|
(is_evpn_prefix_ipaddr_none(evp)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
|
||||||
|
np = &evp->prefix.prefix_addr.ip.ip.addr;
|
||||||
|
|
||||||
|
/* If n's prefix is longer than p's one return 0. */
|
||||||
|
if (prefixlen > p->prefixlen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
offset = prefixlen / PNBBY;
|
||||||
|
shift = prefixlen % PNBBY;
|
||||||
|
|
||||||
|
if (shift)
|
||||||
|
if (maskbit[shift] & (np[offset] ^ pp[offset]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (offset--)
|
||||||
|
if (np[offset] != pp[offset])
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If n includes p then return 1 else return 0. Prefix mask is not considered */
|
/* If n includes p then return 1 else return 0. Prefix mask is not considered */
|
||||||
|
@ -407,6 +407,8 @@ extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
|
|||||||
char *buf, int buf_size);
|
char *buf, int buf_size);
|
||||||
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
|
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
|
||||||
extern const char *prefix2str(union prefixconstptr, char *, int);
|
extern const char *prefix2str(union prefixconstptr, char *, int);
|
||||||
|
extern int evpn_type5_prefix_match(const struct prefix *evpn_pfx,
|
||||||
|
const struct prefix *match_pfx);
|
||||||
extern int prefix_match(const struct prefix *, const struct prefix *);
|
extern int prefix_match(const struct prefix *, const struct prefix *);
|
||||||
extern int prefix_match_network_statement(const struct prefix *,
|
extern int prefix_match_network_statement(const struct prefix *,
|
||||||
const struct prefix *);
|
const struct prefix *);
|
||||||
|
Loading…
Reference in New Issue
Block a user