mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-11 15:18:06 +00:00
Merge pull request #8701 from ton31337/feature/show_ip_bgp_alias
bgpd: Show BGP prefixes by community alias
This commit is contained in:
commit
2db528e384
@ -451,9 +451,11 @@ static void set_community_string(struct community *com, bool make_json)
|
|||||||
val = comval & 0xFFFF;
|
val = comval & 0xFFFF;
|
||||||
char buf[32];
|
char buf[32];
|
||||||
snprintf(buf, sizeof(buf), "%u:%d", as, val);
|
snprintf(buf, sizeof(buf), "%u:%d", as, val);
|
||||||
strlcat(str, bgp_community2alias(buf), len);
|
const char *com2alias = bgp_community2alias(buf);
|
||||||
|
|
||||||
|
strlcat(str, com2alias, len);
|
||||||
if (make_json) {
|
if (make_json) {
|
||||||
json_string = json_object_new_string(buf);
|
json_string = json_object_new_string(com2alias);
|
||||||
json_object_array_add(json_community_list,
|
json_object_array_add(json_community_list,
|
||||||
json_string);
|
json_string);
|
||||||
}
|
}
|
||||||
|
@ -232,11 +232,13 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
|
|||||||
snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1,
|
snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1,
|
||||||
local2);
|
local2);
|
||||||
|
|
||||||
len = strlcat(str_buf, bgp_community2alias(lcsb), str_buf_sz);
|
const char *com2alias = bgp_community2alias(lcsb);
|
||||||
|
|
||||||
|
len = strlcat(str_buf, com2alias, str_buf_sz);
|
||||||
assert((unsigned int)len < str_buf_sz);
|
assert((unsigned int)len < str_buf_sz);
|
||||||
|
|
||||||
if (make_json) {
|
if (make_json) {
|
||||||
json_string = json_object_new_string(lcsb);
|
json_string = json_object_new_string(com2alias);
|
||||||
json_object_array_add(json_lcommunity_list,
|
json_object_array_add(json_lcommunity_list,
|
||||||
json_string);
|
json_string);
|
||||||
}
|
}
|
||||||
|
138
bgpd/bgp_route.c
138
bgpd/bgp_route.c
@ -23,6 +23,7 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "printfrr.h"
|
#include "printfrr.h"
|
||||||
|
#include "frrstr.h"
|
||||||
#include "prefix.h"
|
#include "prefix.h"
|
||||||
#include "linklist.h"
|
#include "linklist.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
@ -10570,7 +10571,6 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp,
|
|||||||
const char *comstr, int exact, afi_t afi,
|
const char *comstr, int exact, afi_t afi,
|
||||||
safi_t safi, uint8_t show_flags);
|
safi_t safi, uint8_t show_flags);
|
||||||
|
|
||||||
|
|
||||||
static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
|
static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
|
||||||
struct bgp_table *table, enum bgp_show_type type,
|
struct bgp_table *table, enum bgp_show_type type,
|
||||||
void *output_arg, char *rd, int is_last,
|
void *output_arg, char *rd, int is_last,
|
||||||
@ -10647,6 +10647,48 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == bgp_show_type_community_alias) {
|
||||||
|
char *alias = output_arg;
|
||||||
|
char **communities;
|
||||||
|
int num;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
if (pi->attr->community) {
|
||||||
|
frrstr_split(pi->attr->community->str,
|
||||||
|
" ", &communities, &num);
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
const char *com2alias =
|
||||||
|
bgp_community2alias(
|
||||||
|
communities[i]);
|
||||||
|
if (strncmp(alias, com2alias,
|
||||||
|
strlen(com2alias))
|
||||||
|
== 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found && pi->attr->lcommunity) {
|
||||||
|
frrstr_split(pi->attr->lcommunity->str,
|
||||||
|
" ", &communities, &num);
|
||||||
|
for (int i = 0; i < num; i++) {
|
||||||
|
const char *com2alias =
|
||||||
|
bgp_community2alias(
|
||||||
|
communities[i]);
|
||||||
|
if (strncmp(alias, com2alias,
|
||||||
|
strlen(com2alias))
|
||||||
|
== 0) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (type == bgp_show_type_rpki) {
|
if (type == bgp_show_type_rpki) {
|
||||||
if (dest_p->family == AF_INET
|
if (dest_p->family == AF_INET
|
||||||
|| dest_p->family == AF_INET6)
|
|| dest_p->family == AF_INET6)
|
||||||
@ -11920,9 +11962,10 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* BGP route print out function with JSON */
|
/* BGP route print out function with JSON */
|
||||||
DEFPY (show_ip_bgp_json,
|
DEFPY(show_ip_bgp_json, show_ip_bgp_json_cmd,
|
||||||
show_ip_bgp_json_cmd,
|
"show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR
|
||||||
"show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\
|
" [" BGP_SAFI_WITH_LABEL_CMD_STR
|
||||||
|
"]]\
|
||||||
[all$all]\
|
[all$all]\
|
||||||
[cidr-only\
|
[cidr-only\
|
||||||
|dampening <flap-statistics|dampened-paths>\
|
|dampening <flap-statistics|dampened-paths>\
|
||||||
@ -11933,44 +11976,41 @@ DEFPY (show_ip_bgp_json,
|
|||||||
|route-filter-translated-v4] [exact-match]\
|
|route-filter-translated-v4] [exact-match]\
|
||||||
|rpki <invalid|valid|notfound>\
|
|rpki <invalid|valid|notfound>\
|
||||||
|version (1-4294967295)\
|
|version (1-4294967295)\
|
||||||
|
|alias WORD\
|
||||||
] [json$uj [detail$detail] | wide$wide]",
|
] [json$uj [detail$detail] | wide$wide]",
|
||||||
SHOW_STR
|
SHOW_STR IP_STR BGP_STR BGP_INSTANCE_HELP_STR BGP_AFI_HELP_STR
|
||||||
IP_STR
|
BGP_SAFI_WITH_LABEL_HELP_STR
|
||||||
BGP_STR
|
"Display the entries for all address families\n"
|
||||||
BGP_INSTANCE_HELP_STR
|
"Display only routes with non-natural netmasks\n"
|
||||||
BGP_AFI_HELP_STR
|
"Display detailed information about dampening\n"
|
||||||
BGP_SAFI_WITH_LABEL_HELP_STR
|
"Display flap statistics of routes\n"
|
||||||
"Display the entries for all address families\n"
|
"Display paths suppressed due to dampening\n"
|
||||||
"Display only routes with non-natural netmasks\n"
|
"Display routes matching the communities\n" COMMUNITY_AANN_STR
|
||||||
"Display detailed information about dampening\n"
|
"Do not send outside local AS (well-known community)\n"
|
||||||
"Display flap statistics of routes\n"
|
"Do not advertise to any peer (well-known community)\n"
|
||||||
"Display paths suppressed due to dampening\n"
|
"Do not export to next AS (well-known community)\n"
|
||||||
"Display routes matching the communities\n"
|
"Graceful shutdown (well-known community)\n"
|
||||||
COMMUNITY_AANN_STR
|
"Do not export to any peer (well-known community)\n"
|
||||||
"Do not send outside local AS (well-known community)\n"
|
"Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
|
||||||
"Do not advertise to any peer (well-known community)\n"
|
"Staled Long-lived Graceful Restart VPN route (well-known community)\n"
|
||||||
"Do not export to next AS (well-known community)\n"
|
"Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
|
||||||
"Graceful shutdown (well-known community)\n"
|
"Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
|
||||||
"Do not export to any peer (well-known community)\n"
|
"Should accept VPN route with local nexthop (well-known community)\n"
|
||||||
"Inform EBGP peers to blackhole traffic to prefix (well-known community)\n"
|
"RT VPNv6 route filtering (well-known community)\n"
|
||||||
"Staled Long-lived Graceful Restart VPN route (well-known community)\n"
|
"RT VPNv4 route filtering (well-known community)\n"
|
||||||
"Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n"
|
"RT translated VPNv6 route filtering (well-known community)\n"
|
||||||
"Should accept local VPN route if exported and imported into different VRF (well-known community)\n"
|
"RT translated VPNv4 route filtering (well-known community)\n"
|
||||||
"Should accept VPN route with local nexthop (well-known community)\n"
|
"Exact match of the communities\n"
|
||||||
"RT VPNv6 route filtering (well-known community)\n"
|
"RPKI route types\n"
|
||||||
"RT VPNv4 route filtering (well-known community)\n"
|
"A valid path as determined by rpki\n"
|
||||||
"RT translated VPNv6 route filtering (well-known community)\n"
|
"A invalid path as determined by rpki\n"
|
||||||
"RT translated VPNv4 route filtering (well-known community)\n"
|
"A path that has no rpki data\n"
|
||||||
"Exact match of the communities\n"
|
"Display prefixes with matching version numbers\n"
|
||||||
"RPKI route types\n"
|
"Version number and above\n"
|
||||||
"A valid path as determined by rpki\n"
|
"Display prefixes with matching BGP community alias\n"
|
||||||
"A invalid path as determined by rpki\n"
|
"BGP community alias\n" JSON_STR
|
||||||
"A path that has no rpki data\n"
|
"Display detailed version of JSON output\n"
|
||||||
"Display prefixes with matching version numbers\n"
|
"Increase table width for longer prefixes\n")
|
||||||
"Version number and above\n"
|
|
||||||
JSON_STR
|
|
||||||
"Display detailed version of JSON output\n"
|
|
||||||
"Increase table width for longer prefixes\n")
|
|
||||||
{
|
{
|
||||||
afi_t afi = AFI_IP6;
|
afi_t afi = AFI_IP6;
|
||||||
safi_t safi = SAFI_UNICAST;
|
safi_t safi = SAFI_UNICAST;
|
||||||
@ -11980,6 +12020,7 @@ DEFPY (show_ip_bgp_json,
|
|||||||
int exact_match = 0;
|
int exact_match = 0;
|
||||||
char *community = NULL;
|
char *community = NULL;
|
||||||
char *prefix_version = NULL;
|
char *prefix_version = NULL;
|
||||||
|
char *bgp_community_alias = NULL;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
uint8_t show_flags = 0;
|
uint8_t show_flags = 0;
|
||||||
enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
|
enum rpki_states rpki_target_state = RPKI_NOT_BEING_USED;
|
||||||
@ -12056,6 +12097,12 @@ DEFPY (show_ip_bgp_json,
|
|||||||
prefix_version = argv[idx + 1]->arg;
|
prefix_version = argv[idx + 1]->arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Display prefixes with matching BGP community alias */
|
||||||
|
if (argv_find(argv, argc, "alias", &idx)) {
|
||||||
|
sh_type = bgp_show_type_community_alias;
|
||||||
|
bgp_community_alias = argv[idx + 1]->arg;
|
||||||
|
}
|
||||||
|
|
||||||
if (!all) {
|
if (!all) {
|
||||||
/* show bgp: AFI_IP6, show ip bgp: AFI_IP */
|
/* show bgp: AFI_IP6, show ip bgp: AFI_IP */
|
||||||
if (community)
|
if (community)
|
||||||
@ -12066,6 +12113,10 @@ DEFPY (show_ip_bgp_json,
|
|||||||
return bgp_show(vty, bgp, afi, safi, sh_type,
|
return bgp_show(vty, bgp, afi, safi, sh_type,
|
||||||
prefix_version, show_flags,
|
prefix_version, show_flags,
|
||||||
rpki_target_state);
|
rpki_target_state);
|
||||||
|
else if (bgp_community_alias)
|
||||||
|
return bgp_show(vty, bgp, afi, safi, sh_type,
|
||||||
|
bgp_community_alias, show_flags,
|
||||||
|
rpki_target_state);
|
||||||
else
|
else
|
||||||
return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
|
return bgp_show(vty, bgp, afi, safi, sh_type, NULL,
|
||||||
show_flags, rpki_target_state);
|
show_flags, rpki_target_state);
|
||||||
@ -12108,6 +12159,11 @@ DEFPY (show_ip_bgp_json,
|
|||||||
sh_type, prefix_version,
|
sh_type, prefix_version,
|
||||||
show_flags,
|
show_flags,
|
||||||
rpki_target_state);
|
rpki_target_state);
|
||||||
|
else if (bgp_community_alias)
|
||||||
|
return bgp_show(
|
||||||
|
vty, bgp, afi, safi, sh_type,
|
||||||
|
bgp_community_alias, show_flags,
|
||||||
|
rpki_target_state);
|
||||||
else
|
else
|
||||||
bgp_show(vty, bgp, afi, safi, sh_type,
|
bgp_show(vty, bgp, afi, safi, sh_type,
|
||||||
NULL, show_flags,
|
NULL, show_flags,
|
||||||
|
@ -42,6 +42,7 @@ enum bgp_show_type {
|
|||||||
bgp_show_type_neighbor,
|
bgp_show_type_neighbor,
|
||||||
bgp_show_type_cidr_only,
|
bgp_show_type_cidr_only,
|
||||||
bgp_show_type_prefix_longer,
|
bgp_show_type_prefix_longer,
|
||||||
|
bgp_show_type_community_alias,
|
||||||
bgp_show_type_community_all,
|
bgp_show_type_community_all,
|
||||||
bgp_show_type_community,
|
bgp_show_type_community,
|
||||||
bgp_show_type_community_exact,
|
bgp_show_type_community_exact,
|
||||||
|
@ -2111,6 +2111,10 @@ things on the wire.
|
|||||||
Large Community: lcommunity-1 65001:123:2
|
Large Community: lcommunity-1 65001:123:2
|
||||||
Last update: Fri Apr 16 12:51:27 2021
|
Last update: Fri Apr 16 12:51:27 2021
|
||||||
|
|
||||||
|
.. clicmd:: show bgp [afi] [safi] [all] alias WORD [wide|json]
|
||||||
|
|
||||||
|
Display prefixes with matching BGP community alias.
|
||||||
|
|
||||||
.. _bgp-using-communities-in-route-map:
|
.. _bgp-using-communities-in-route-map:
|
||||||
|
|
||||||
Using Communities in Route Maps
|
Using Communities in Route Maps
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
!
|
!
|
||||||
bgp community alias 65002:1 community-r2-1
|
bgp community alias 65001:1 community-r2-1
|
||||||
bgp community alias 65002:2 community-r2-2
|
bgp community alias 65002:2 community-r2-2
|
||||||
bgp community alias 65002:1:1 large-community-r2-1
|
bgp community alias 65001:1:1 large-community-r2-1
|
||||||
!
|
!
|
||||||
router bgp 65001
|
router bgp 65001
|
||||||
no bgp ebgp-requires-policy
|
no bgp ebgp-requires-policy
|
||||||
|
@ -6,7 +6,14 @@ router bgp 65002
|
|||||||
neighbor 192.168.1.1 route-map r1 out
|
neighbor 192.168.1.1 route-map r1 out
|
||||||
exit-address-family
|
exit-address-family
|
||||||
!
|
!
|
||||||
route-map r1 permit 10
|
ip prefix-list p1 permit 172.16.16.1/32
|
||||||
set community 65002:1 65002:2
|
ip prefix-list p2 permit 172.16.16.2/32
|
||||||
set large-community 65002:1:1 65002:2:1
|
!
|
||||||
|
route-map r1 permit 10
|
||||||
|
match ip address prefix-list p1
|
||||||
|
set community 65001:1 65001:2
|
||||||
|
set large-community 65001:1:1 65001:1:2
|
||||||
|
route-map r1 permit 20
|
||||||
|
match ip address prefix-list p2
|
||||||
|
set community 65002:1 65002:2
|
||||||
!
|
!
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
!
|
!
|
||||||
|
int lo
|
||||||
|
ip address 172.16.16.1/32
|
||||||
|
ip address 172.16.16.2/32
|
||||||
|
!
|
||||||
int r2-eth0
|
int r2-eth0
|
||||||
ip address 192.168.1.2/24
|
ip address 192.168.1.2/24
|
||||||
!
|
!
|
||||||
|
@ -84,12 +84,14 @@ def test_bgp_community_alias():
|
|||||||
router = tgen.gears["r1"]
|
router = tgen.gears["r1"]
|
||||||
|
|
||||||
def _bgp_converge(router):
|
def _bgp_converge(router):
|
||||||
output = json.loads(router.vtysh_cmd("show ip bgp 192.168.1.0/24 json"))
|
output = json.loads(
|
||||||
|
router.vtysh_cmd("show bgp ipv4 unicast 172.16.16.1/32 json")
|
||||||
|
)
|
||||||
expected = {
|
expected = {
|
||||||
"paths": [
|
"paths": [
|
||||||
{
|
{
|
||||||
"community": {"string": "community-r2-1 community-r2-2"},
|
"community": {"string": "community-r2-1 65001:2"},
|
||||||
"largeCommunity": {"string": "large-community-r2-1 65002:2:1"},
|
"largeCommunity": {"string": "large-community-r2-1 65001:1:2"},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -97,9 +99,25 @@ def test_bgp_community_alias():
|
|||||||
|
|
||||||
test_func = functools.partial(_bgp_converge, router)
|
test_func = functools.partial(_bgp_converge, router)
|
||||||
success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
|
||||||
assert result is None, 'Cannot see BGP community aliases "{}"'.format(router)
|
assert result is None, 'Cannot see BGP community aliases "{}"'.format(router)
|
||||||
|
|
||||||
|
def _bgp_show_prefixes_by_alias(router):
|
||||||
|
output = json.loads(
|
||||||
|
router.vtysh_cmd("show bgp ipv4 unicast alias community-r2-2 json detail")
|
||||||
|
)
|
||||||
|
expected = {
|
||||||
|
"routes": {
|
||||||
|
"172.16.16.2/32": [{"community": {"string": "65002:1 community-r2-2"}}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return topotest.json_cmp(output, expected)
|
||||||
|
|
||||||
|
test_func = functools.partial(_bgp_show_prefixes_by_alias, router)
|
||||||
|
success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||||
|
assert result is None, 'Cannot see BGP prefixes by community alias "{}"'.format(
|
||||||
|
router
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
args = ["-s"] + sys.argv[1:]
|
args = ["-s"] + sys.argv[1:]
|
||||||
|
Loading…
Reference in New Issue
Block a user