mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 05:18:47 +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
103
bgpd/bgp_evpn.c
103
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 buf2[PREFIX2STR_BUFFER];
|
||||
uint8_t family;
|
||||
uint8_t prefixlen;
|
||||
|
||||
if (!json)
|
||||
return;
|
||||
|
||||
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
|
||||
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",
|
||||
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)));
|
||||
|
||||
if (!is_evpn_prefix_ipaddr_none(p)) {
|
||||
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.macip_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_IMET_ROUTE:
|
||||
json_object_int_add(json, "ethTag",
|
||||
p->prefix.imet_addr.eth_tag);
|
||||
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_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 : 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;
|
||||
|
||||
family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
|
||||
: AF_INET6;
|
||||
|
||||
json_object_int_add(json, "routeType",
|
||||
p->prefix.route_type);
|
||||
case BGP_EVPN_IP_PREFIX_ROUTE:
|
||||
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)));
|
||||
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",
|
||||
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 {
|
||||
/* Currently, this is to cater to other AF_ETHERNET code. */
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(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 */
|
||||
|
255
bgpd/bgp_route.c
255
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();
|
||||
}
|
||||
|
||||
if (!json_paths && path->extra) {
|
||||
if (path->extra) {
|
||||
char tag_buf[30];
|
||||
|
||||
buf2[0] = '\0';
|
||||
@ -8238,15 +8238,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
|
||||
sizeof(tag_buf));
|
||||
}
|
||||
if (safi == SAFI_EVPN) {
|
||||
if (!json_paths) {
|
||||
bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
|
||||
buf2, sizeof(buf2));
|
||||
vty_out(vty, " Route %s", buf2);
|
||||
if (tag_buf[0] != '\0')
|
||||
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_node *rn, *prn;
|
||||
|
||||
@ -9541,22 +9547,22 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
||||
if (has_valid_label)
|
||||
label = label_pton(&rn->local_label);
|
||||
|
||||
if (json) {
|
||||
if (has_valid_label)
|
||||
json_object_int_add(json, "localLabel", label);
|
||||
if (safi == SAFI_EVPN) {
|
||||
|
||||
json_object_string_add(
|
||||
json, "prefix",
|
||||
prefix2str(p, prefix_str, sizeof(prefix_str)));
|
||||
} else {
|
||||
if (safi == SAFI_EVPN)
|
||||
if (!json) {
|
||||
vty_out(vty, "BGP routing table entry for %s%s%s\n",
|
||||
prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
|
||||
: "",
|
||||
prd ? ":" : "",
|
||||
: "", prd ? ":" : "",
|
||||
bgp_evpn_route2str((struct prefix_evpn *)p,
|
||||
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",
|
||||
((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
|
||||
? prefix_rd2str(prd, buf1,
|
||||
@ -9567,11 +9573,21 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
|
||||
INET6_ADDRSTRLEN),
|
||||
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);
|
||||
}
|
||||
|
||||
if (!json)
|
||||
if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
|
||||
vty_out(vty, "not allocated\n");
|
||||
}
|
||||
|
||||
for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
|
||||
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. */
|
||||
static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
int header;
|
||||
int display = 0;
|
||||
struct prefix match;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_node *rm;
|
||||
struct bgp_path_info *pi;
|
||||
struct bgp_table *table;
|
||||
json_object *json = 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);
|
||||
|
||||
if (use_json) {
|
||||
if (use_json)
|
||||
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)) {
|
||||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||
continue;
|
||||
@ -9743,8 +9807,6 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
||||
if (!table)
|
||||
continue;
|
||||
|
||||
header = 1;
|
||||
|
||||
if ((rm = bgp_node_match(table, &match)) == NULL)
|
||||
continue;
|
||||
|
||||
@ -9754,73 +9816,83 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
|
||||
continue;
|
||||
}
|
||||
|
||||
for (pi = bgp_node_get_bgp_path_info(rm); pi;
|
||||
pi = pi->next) {
|
||||
if (header) {
|
||||
route_vty_out_detail_header(
|
||||
vty, bgp, rm,
|
||||
(struct prefix_rd *)&rn->p,
|
||||
AFI_IP, safi, json);
|
||||
header = 0;
|
||||
}
|
||||
display++;
|
||||
bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
|
||||
vty, bgp, afi, safi, json,
|
||||
pathtype, &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, rm,
|
||||
pi, AFI_IP, safi,
|
||||
json_paths);
|
||||
bgp_unlock_node(rm);
|
||||
}
|
||||
} else if (safi == SAFI_EVPN) {
|
||||
struct bgp_node *longest_pfx;
|
||||
bool is_exact_pfxlen_match = FALSE;
|
||||
|
||||
for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
|
||||
if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
|
||||
continue;
|
||||
table = bgp_node_get_bgp_table_info(rn);
|
||||
if (!table)
|
||||
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);
|
||||
}
|
||||
} else if (safi == SAFI_FLOWSPEC) {
|
||||
if (use_json)
|
||||
json_paths = json_object_new_array();
|
||||
|
||||
display = bgp_flowspec_display_match_per_ip(afi, rib,
|
||||
&match, prefix_check,
|
||||
vty,
|
||||
use_json,
|
||||
json_paths);
|
||||
if (use_json && display)
|
||||
json_object_object_add(json, "paths", json_paths);
|
||||
} else {
|
||||
header = 1;
|
||||
|
||||
if ((rn = bgp_node_match(rib, &match)) != NULL) {
|
||||
if (!prefix_check
|
||||
|| rn->p.prefixlen == match.prefixlen) {
|
||||
for (pi = bgp_node_get_bgp_path_info(rn); pi;
|
||||
pi = pi->next) {
|
||||
if (header) {
|
||||
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_show_path_info(NULL, rn, vty, bgp, afi,
|
||||
safi, json,
|
||||
pathtype, &display);
|
||||
}
|
||||
|
||||
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 (display)
|
||||
json_object_object_add(json, "paths", json_paths);
|
||||
|
||||
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);
|
||||
} else {
|
||||
if (!display) {
|
||||
@ -11025,32 +11095,37 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix,
|
||||
}
|
||||
#endif /* KEEP_OLD_VPN_COMMANDS */
|
||||
|
||||
DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
|
||||
show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
|
||||
"show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
|
||||
DEFUN (show_bgp_l2vpn_evpn_route_prefix,
|
||||
show_bgp_l2vpn_evpn_route_prefix_cmd,
|
||||
"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
|
||||
IP_STR
|
||||
BGP_STR
|
||||
L2VPN_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"
|
||||
JSON_STR)
|
||||
{
|
||||
int idx = 0;
|
||||
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;
|
||||
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;
|
||||
else {
|
||||
prefix_check = 1;
|
||||
} else {
|
||||
vty_out(vty, "Unable to figure out Network\n");
|
||||
return CMD_WARNING;
|
||||
}
|
||||
return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
|
||||
BGP_PATH_SHOW_ALL, use_json(argc, argv));
|
||||
return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
|
||||
prefix_check, BGP_PATH_SHOW_ALL,
|
||||
use_json(argc, argv));
|
||||
}
|
||||
|
||||
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 */
|
||||
install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
|
||||
install_element(VIEW_NODE,
|
||||
&show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
|
||||
&show_bgp_l2vpn_evpn_route_prefix_cmd);
|
||||
|
||||
/* BGP dampening clear commands */
|
||||
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])
|
||||
return 0;
|
||||
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 */
|
||||
|
@ -407,6 +407,8 @@ extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
|
||||
char *buf, int buf_size);
|
||||
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
|
||||
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_network_statement(const struct prefix *,
|
||||
const struct prefix *);
|
||||
|
Loading…
Reference in New Issue
Block a user