mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-06-04 02:53:32 +00:00
Merge pull request #17226 from louis-6wind/fix-bmp-tests
tests: fix bmp tests random failure
This commit is contained in:
commit
574a71516a
34
tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step1.json
Normal file
34
tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step1.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"loc-rib": {
|
||||
"update": {
|
||||
"172.31.0.15/32": {
|
||||
"as_path": "65501 65502",
|
||||
"bgp_nexthop": "192.168.0.2",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"is_filtered": false,
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib"
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"is_filtered": false,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step2.json
Normal file
43
tests/topotests/bgp_bmp/bmp1/bmp-update-loc-rib-step2.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"loc-rib": {
|
||||
"update": {
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"is_filtered": false,
|
||||
"label": 105,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"nxhp_rd1": "0:0",
|
||||
"nxhp_rd2": "0:0",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib",
|
||||
"rd": "555:2",
|
||||
"safi": 128
|
||||
},
|
||||
"172.31.0.15/32": {
|
||||
"afi": 1,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"is_filtered": false,
|
||||
"label": 102,
|
||||
"nxhp_ip": "192.168.0.2",
|
||||
"nxhp_rd": "0:0",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib",
|
||||
"rd": "444:2",
|
||||
"safi": 128
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"post-policy": {
|
||||
"update": {
|
||||
"172.31.0.15/32": {
|
||||
"as_path": "65501 65502",
|
||||
"bgp_nexthop": "192.168.0.2",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy"
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"ipv6": true,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
{
|
||||
"post-policy": {
|
||||
"update": {
|
||||
"172.31.0.15/32": {
|
||||
"afi": 1,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"label": 102,
|
||||
"nxhp_ip": "192.168.0.2",
|
||||
"nxhp_rd": "0:0",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy",
|
||||
"rd": "444:2",
|
||||
"safi": 128
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"ipv6": true,
|
||||
"label": 105,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"nxhp_rd1": "0:0",
|
||||
"nxhp_rd2": "0:0",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy",
|
||||
"rd": "555:2",
|
||||
"safi": 128
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"pre-policy": {
|
||||
"update": {
|
||||
"172.31.0.15/32": {
|
||||
"as_path": "65501 65502",
|
||||
"bgp_nexthop": "192.168.0.2",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy"
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"ipv6": true,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
{
|
||||
"pre-policy": {
|
||||
"update": {
|
||||
"172.31.0.15/32": {
|
||||
"afi": 1,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"label": 102,
|
||||
"nxhp_ip": "192.168.0.2",
|
||||
"nxhp_rd": "0:0",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy",
|
||||
"rd": "444:2",
|
||||
"safi": 128
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"ipv6": true,
|
||||
"label": 105,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"nxhp_rd1": "0:0",
|
||||
"nxhp_rd2": "0:0",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy",
|
||||
"rd": "555:2",
|
||||
"safi": 128
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step1.json
Normal file
28
tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step1.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"loc-rib": {
|
||||
"withdraw": {
|
||||
"172.31.0.15/32": {
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"is_filtered": false,
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib"
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"is_filtered": false,
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step2.json
Normal file
34
tests/topotests/bgp_bmp/bmp1/bmp-withdraw-loc-rib-step2.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"loc-rib": {
|
||||
"withdraw": {
|
||||
"172.31.0.15/32": {
|
||||
"afi": 1,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"is_filtered": false,
|
||||
"label": 0,
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib",
|
||||
"rd": "444:2",
|
||||
"safi": 128
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"is_filtered": false,
|
||||
"label": 0,
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib",
|
||||
"rd": "555:2",
|
||||
"safi": 128
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
"post-policy": {
|
||||
"withdraw": {
|
||||
"172.31.0.15/32": {
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy"
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"ipv6": true,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"post-policy": {
|
||||
"withdraw": {
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"ipv6": true,
|
||||
"label": 0,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy",
|
||||
"rd": "555:2",
|
||||
"safi": 128
|
||||
},
|
||||
"172.31.0.15/32": {
|
||||
"afi": 1,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"label": 0,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy",
|
||||
"rd": "444:2",
|
||||
"safi": 128
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
"pre-policy": {
|
||||
"withdraw": {
|
||||
"172.31.0.15/32": {
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy"
|
||||
},
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"ipv6": true,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"pre-policy": {
|
||||
"withdraw": {
|
||||
"2001::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2001::1111/128",
|
||||
"ipv6": true,
|
||||
"label": 0,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy",
|
||||
"rd": "555:2",
|
||||
"safi": 128
|
||||
},
|
||||
"172.31.0.15/32": {
|
||||
"afi": 1,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"label": 0,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy",
|
||||
"rd": "444:2",
|
||||
"safi": 128
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,18 @@ router bgp 65501
|
||||
!
|
||||
bmp targets bmp1
|
||||
bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000
|
||||
bmp monitor ipv4 unicast pre-policy
|
||||
bmp monitor ipv6 unicast pre-policy
|
||||
bmp monitor ipv4 vpn pre-policy
|
||||
bmp monitor ipv6 vpn pre-policy
|
||||
bmp monitor ipv4 unicast post-policy
|
||||
bmp monitor ipv6 unicast post-policy
|
||||
bmp monitor ipv4 vpn post-policy
|
||||
bmp monitor ipv6 vpn post-policy
|
||||
bmp monitor ipv4 unicast loc-rib
|
||||
bmp monitor ipv6 unicast loc-rib
|
||||
bmp monitor ipv4 vpn loc-rib
|
||||
bmp monitor ipv6 vpn loc-rib
|
||||
exit
|
||||
!
|
||||
address-family ipv4 vpn
|
||||
@ -28,7 +40,7 @@ router bgp 65501
|
||||
neighbor 192:168::2 soft-reconfiguration inbound
|
||||
exit-address-family
|
||||
!
|
||||
router bgp 65502 vrf vrf1
|
||||
router bgp 65501 vrf vrf1
|
||||
bgp router_id 192.168.0.1
|
||||
bgp log-neighbor-changes
|
||||
address-family ipv4 unicast
|
||||
|
21
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step1.json
Normal file
21
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step1.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"routes": {
|
||||
"172.31.0.15/32": [
|
||||
{
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"path": "65502",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "192.168.0.2",
|
||||
"hostname": "r2",
|
||||
"afi": "ipv4",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
25
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step2.json
Normal file
25
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-update-step2.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"routes": {
|
||||
"routeDistinguishers": {
|
||||
"444:2": {
|
||||
"172.31.0.15/32": [
|
||||
{
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"path": "65502",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "192.168.0.2",
|
||||
"hostname": "r2",
|
||||
"afi": "ipv4",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"routes": {
|
||||
"2001::1111/128": null
|
||||
}
|
||||
}
|
||||
|
10
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-withdraw-step2.json
Normal file
10
tests/topotests/bgp_bmp/r1/show-bgp-ipv4-withdraw-step2.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"routes": {
|
||||
"routeDistinguishers": {
|
||||
"444:2": {
|
||||
"2001::1111/128": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step1.json
Normal file
27
tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step1.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"routes": {
|
||||
"2001::1111/128": [
|
||||
{
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"path": "65502",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "192:168::2",
|
||||
"hostname": "r2",
|
||||
"afi": "ipv6",
|
||||
"scope": "global"
|
||||
},
|
||||
{
|
||||
"hostname": "r2",
|
||||
"afi": "ipv6",
|
||||
"scope": "link-local",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
25
tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step2.json
Normal file
25
tests/topotests/bgp_bmp/r1/show-bgp-ipv6-update-step2.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"routes": {
|
||||
"routeDistinguishers": {
|
||||
"555:2": {
|
||||
"2001::1111/128": [
|
||||
{
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"path": "65502",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "192:168::2",
|
||||
"hostname": "r2",
|
||||
"afi": "ipv6",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"routes": {
|
||||
"2001::1111/128": null
|
||||
}
|
||||
}
|
||||
|
10
tests/topotests/bgp_bmp/r1/show-bgp-ipv6-withdraw-step2.json
Normal file
10
tests/topotests/bgp_bmp/r1/show-bgp-ipv6-withdraw-step2.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"routes": {
|
||||
"routeDistinguishers": {
|
||||
"555:2": {
|
||||
"2001::1111/128": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,9 @@ PRE_POLICY = "pre-policy"
|
||||
POST_POLICY = "post-policy"
|
||||
LOC_RIB = "loc-rib"
|
||||
|
||||
UPDATE_EXPECTED_JSON = False
|
||||
DEBUG_PCAP = False
|
||||
|
||||
|
||||
def build_topo(tgen):
|
||||
tgen.add_router("r1")
|
||||
@ -67,6 +70,12 @@ def setup_module(mod):
|
||||
tgen = Topogen(build_topo, mod.__name__)
|
||||
tgen.start_topology()
|
||||
|
||||
if DEBUG_PCAP:
|
||||
tgen.gears["r1"].run("rm /tmp/bmp.pcap")
|
||||
tgen.gears["r1"].run(
|
||||
"tcpdump -nni r1-eth0 -s 0 -w /tmp/bmp.pcap &", stdout=None
|
||||
)
|
||||
|
||||
for rname, router in tgen.routers().items():
|
||||
router.load_config(
|
||||
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||
@ -122,42 +131,181 @@ def get_bmp_messages():
|
||||
return messages
|
||||
|
||||
|
||||
def check_for_prefixes(expected_prefixes, bmp_log_type, policy, labels=None):
|
||||
def update_seq():
|
||||
global SEQ
|
||||
|
||||
messages = get_bmp_messages()
|
||||
|
||||
if len(messages):
|
||||
SEQ = messages[-1]["seq"]
|
||||
|
||||
|
||||
def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, step):
|
||||
tgen = get_topogen()
|
||||
|
||||
with open(f"/tmp/bmp-{bmp_log_type}-{policy}-step{step}.json", "w") as json_file:
|
||||
json.dump(bmp_actual, json_file, indent=4)
|
||||
|
||||
if step == 2: # vpn
|
||||
rd = "444:2"
|
||||
out = tgen.gears["r1"].vtysh_cmd("show bgp ipv4 vpn json", isjson=True)
|
||||
filtered_out = {
|
||||
"routes": {
|
||||
"routeDistinguishers": {
|
||||
rd: {
|
||||
prefix: route_info
|
||||
for prefix, route_info in out["routes"]
|
||||
.get("routeDistinguishers", {})
|
||||
.get(rd, {})
|
||||
.items()
|
||||
if prefix in expected_prefixes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if bmp_log_type == "withdraw":
|
||||
for pfx in expected_prefixes:
|
||||
if "::" in pfx:
|
||||
continue
|
||||
filtered_out["routes"]["routeDistinguishers"][rd][pfx] = None
|
||||
|
||||
# ls /tmp/show*json | while read file; do egrep -v 'prefix|network|metric|ocPrf|version|weight|peerId|vrf|Version|valid|Reason|fe80' $file >$(basename $file); echo >> $(basename $file); done
|
||||
with open(
|
||||
f"/tmp/show-bgp-ipv4-{bmp_log_type}-step{step}.json", "w"
|
||||
) as json_file:
|
||||
json.dump(filtered_out, json_file, indent=4)
|
||||
|
||||
rd = "555:2"
|
||||
out = tgen.gears["r1"].vtysh_cmd("show bgp ipv6 vpn json", isjson=True)
|
||||
filtered_out = {
|
||||
"routes": {
|
||||
"routeDistinguishers": {
|
||||
rd: {
|
||||
prefix: route_info
|
||||
for prefix, route_info in out["routes"]
|
||||
.get("routeDistinguishers", {})
|
||||
.get(rd, {})
|
||||
.items()
|
||||
if prefix in expected_prefixes
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if bmp_log_type == "withdraw":
|
||||
for pfx in expected_prefixes:
|
||||
if "::" not in pfx:
|
||||
continue
|
||||
filtered_out["routes"]["routeDistinguishers"][rd][pfx] = None
|
||||
with open(
|
||||
f"/tmp/show-bgp-ipv6-{bmp_log_type}-step{step}.json", "w"
|
||||
) as json_file:
|
||||
json.dump(filtered_out, json_file, indent=4)
|
||||
|
||||
return
|
||||
|
||||
out = tgen.gears["r1"].vtysh_cmd("show bgp ipv4 json", isjson=True)
|
||||
filtered_out = {
|
||||
"routes": {
|
||||
prefix: route_info
|
||||
for prefix, route_info in out["routes"].items()
|
||||
if prefix in expected_prefixes
|
||||
}
|
||||
}
|
||||
if bmp_log_type == "withdraw":
|
||||
for pfx in expected_prefixes:
|
||||
if "::" in pfx:
|
||||
continue
|
||||
filtered_out["routes"][pfx] = None
|
||||
|
||||
# ls /tmp/show*json | while read file; do egrep -v 'prefix|network|metric|ocPrf|version|weight|peerId|vrf|Version|valid|Reason|fe80' $file >$(basename $file); echo >> $(basename $file); done
|
||||
with open(f"/tmp/show-bgp-ipv4-{bmp_log_type}-step{step}.json", "w") as json_file:
|
||||
json.dump(filtered_out, json_file, indent=4)
|
||||
|
||||
out = tgen.gears["r1"].vtysh_cmd("show bgp ipv6 json", isjson=True)
|
||||
filtered_out = {
|
||||
"routes": {
|
||||
prefix: route_info
|
||||
for prefix, route_info in out["routes"].items()
|
||||
if prefix in expected_prefixes
|
||||
}
|
||||
}
|
||||
if bmp_log_type == "withdraw":
|
||||
for pfx in expected_prefixes:
|
||||
if "::" not in pfx:
|
||||
continue
|
||||
filtered_out["routes"][pfx] = None
|
||||
with open(f"/tmp/show-bgp-ipv6-{bmp_log_type}-step{step}.json", "w") as json_file:
|
||||
json.dump(filtered_out, json_file, indent=4)
|
||||
|
||||
|
||||
def check_for_prefixes(expected_prefixes, bmp_log_type, policy, step):
|
||||
"""
|
||||
Check for the presence of the given prefixes in the BMP server logs with
|
||||
the given message type and the set policy.
|
||||
|
||||
"""
|
||||
global SEQ
|
||||
|
||||
# we care only about the new messages
|
||||
messages = [
|
||||
m for m in sorted(get_bmp_messages(), key=lambda d: d["seq"]) if m["seq"] > SEQ
|
||||
]
|
||||
|
||||
# get the list of pairs (prefix, policy, seq) for the given message type
|
||||
prefixes = [
|
||||
m["ip_prefix"]
|
||||
for m in messages
|
||||
if "ip_prefix" in m.keys()
|
||||
and "bmp_log_type" in m.keys()
|
||||
and m["bmp_log_type"] == bmp_log_type
|
||||
and m["policy"] == policy
|
||||
and (
|
||||
labels is None
|
||||
or (
|
||||
m["ip_prefix"] in labels.keys() and m["label"] == labels[m["ip_prefix"]]
|
||||
)
|
||||
)
|
||||
]
|
||||
# create empty initial files
|
||||
# for step in $(seq 2); do
|
||||
# for i in "update" "withdraw"; do
|
||||
# for j in "pre-policy" "post-policy" "loc-rib"; do
|
||||
# echo '{"null": {}}'> bmp-$i-$j-step$step.json
|
||||
# done
|
||||
# done
|
||||
# done
|
||||
|
||||
# check for prefixes
|
||||
for ep in expected_prefixes:
|
||||
if ep not in prefixes:
|
||||
msg = "The prefix {} is not present in the {} log messages."
|
||||
logger.debug(msg.format(ep, bmp_log_type))
|
||||
return False
|
||||
ref_file = f"{CWD}/bmp1/bmp-{bmp_log_type}-{policy}-step{step}.json"
|
||||
expected = json.loads(open(ref_file).read())
|
||||
|
||||
SEQ = messages[-1]["seq"]
|
||||
return True
|
||||
# Build actual json from logs
|
||||
actual = {}
|
||||
for m in messages:
|
||||
if (
|
||||
"bmp_log_type" in m.keys()
|
||||
and "ip_prefix" in m.keys()
|
||||
and m["ip_prefix"] in expected_prefixes
|
||||
and m["bmp_log_type"] == bmp_log_type
|
||||
and m["policy"] == policy
|
||||
):
|
||||
policy_dict = actual.setdefault(m["policy"], {})
|
||||
bmp_log_type_dict = policy_dict.setdefault(m["bmp_log_type"], {})
|
||||
|
||||
# Add or update the ip_prefix dictionary with filtered key-value pairs
|
||||
bmp_log_type_dict[m["ip_prefix"]] = {
|
||||
k: v
|
||||
for k, v in sorted(m.items())
|
||||
# filter out variable keys
|
||||
if k not in ["timestamp", "seq", "nxhp_link-local"]
|
||||
and (
|
||||
# When policy is loc-rib, the peer-distinguisher is 0:0
|
||||
# for the default VRF or the RD if any or the 0:<vrf_id>.
|
||||
# 0:<vrf_id> is used to distinguished. RFC7854 says: "If the
|
||||
# peer is a "Local Instance Peer", it is set to a unique,
|
||||
# locally defined value." The value is not tested because it
|
||||
# is variable.
|
||||
k != "peer_distinguisher"
|
||||
or policy != LOC_RIB
|
||||
or v == "0:0"
|
||||
or not v.startswith("0:")
|
||||
)
|
||||
}
|
||||
|
||||
# build expected JSON files
|
||||
if (
|
||||
UPDATE_EXPECTED_JSON
|
||||
and actual
|
||||
and set(actual.get(policy, {}).get(bmp_log_type, {}).keys())
|
||||
== set(expected_prefixes)
|
||||
):
|
||||
update_expected_files(actual, expected_prefixes, bmp_log_type, policy, step)
|
||||
|
||||
return topotest.json_cmp(actual, expected, exact=True)
|
||||
|
||||
|
||||
def check_for_peer_message(expected_peers, bmp_log_type):
|
||||
@ -188,22 +336,6 @@ def check_for_peer_message(expected_peers, bmp_log_type):
|
||||
return True
|
||||
|
||||
|
||||
def set_bmp_policy(tgen, node, asn, target, safi, policy, vrf=None):
|
||||
"""
|
||||
Configure the bmp policy.
|
||||
"""
|
||||
vrf = " vrf {}" if vrf else ""
|
||||
cmd = [
|
||||
"con t\n",
|
||||
"router bgp {}{}\n".format(asn, vrf),
|
||||
"bmp targets {}\n".format(target),
|
||||
"bmp monitor ipv4 {} {}\n".format(safi, policy),
|
||||
"bmp monitor ipv6 {} {}\n".format(safi, policy),
|
||||
"end\n",
|
||||
]
|
||||
tgen.gears[node].vtysh_cmd("".join(cmd))
|
||||
|
||||
|
||||
def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True):
|
||||
"""
|
||||
Configure the bgp prefixes.
|
||||
@ -223,67 +355,49 @@ def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True):
|
||||
tgen.gears[node].vtysh_cmd("".join(cmd))
|
||||
|
||||
|
||||
def unicast_prefixes(policy):
|
||||
def _test_prefixes(policy, vrf=None, step=0):
|
||||
"""
|
||||
Setup the BMP monitor policy, Add and withdraw ipv4/v6 prefixes.
|
||||
Check if the previous actions are logged in the BMP server with the right
|
||||
message type and the right policy.
|
||||
"""
|
||||
tgen = get_topogen()
|
||||
set_bmp_policy(tgen, "r1", 65501, "bmp1", "unicast", policy)
|
||||
|
||||
prefixes = ["172.31.0.15/32", "2111::1111/128"]
|
||||
# add prefixes
|
||||
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes)
|
||||
safi = "vpn" if vrf else "unicast"
|
||||
|
||||
logger.info("checking for updated prefixes")
|
||||
# check
|
||||
test_func = partial(check_for_prefixes, prefixes, "update", policy)
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
assert success, "Checking the updated prefixes has been failed !."
|
||||
prefixes = ["172.31.0.15/32", "2001::1111/128"]
|
||||
|
||||
# withdraw prefixes
|
||||
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, update=False)
|
||||
logger.info("checking for withdrawed prefxies")
|
||||
# check
|
||||
test_func = partial(check_for_prefixes, prefixes, "withdraw", policy)
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
assert success, "Checking the withdrawed prefixes has been failed !."
|
||||
for type in ("update", "withdraw"):
|
||||
update_seq()
|
||||
|
||||
configure_prefixes(
|
||||
tgen, "r2", 65502, "unicast", prefixes, vrf=vrf, update=(type == "update")
|
||||
)
|
||||
|
||||
def vpn_prefixes(policy):
|
||||
"""
|
||||
Setup the BMP monitor policy, Add and withdraw ipv4/v6 prefixes.
|
||||
Check if the previous actions are logged in the BMP server with the right
|
||||
message type and the right policy.
|
||||
"""
|
||||
tgen = get_topogen()
|
||||
set_bmp_policy(tgen, "r1", 65501, "bmp1", "vpn", policy)
|
||||
logger.info(f"checking for prefixes {type}")
|
||||
|
||||
prefixes = ["172.31.10.1/32", "2001::2222/128"]
|
||||
for ipver in [4, 6]:
|
||||
if UPDATE_EXPECTED_JSON:
|
||||
continue
|
||||
ref_file = "{}/r1/show-bgp-ipv{}-{}-step{}.json".format(
|
||||
CWD, ipver, type, step
|
||||
)
|
||||
expected = json.loads(open(ref_file).read())
|
||||
|
||||
# "label vpn export" value in r2/bgpd.conf
|
||||
labels = {
|
||||
"172.31.10.1/32": 102,
|
||||
"2001::2222/128": 105,
|
||||
}
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
tgen.gears["r1"],
|
||||
f"show bgp ipv{ipver} {safi} json",
|
||||
expected,
|
||||
)
|
||||
_, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
|
||||
assertmsg = f"r1: BGP IPv{ipver} convergence failed"
|
||||
assert res is None, assertmsg
|
||||
|
||||
# add prefixes
|
||||
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, vrf="vrf1")
|
||||
|
||||
logger.info("checking for updated prefixes")
|
||||
# check
|
||||
test_func = partial(check_for_prefixes, prefixes, "update", policy, labels=labels)
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
assert success, "Checking the updated prefixes has been failed !."
|
||||
|
||||
# withdraw prefixes
|
||||
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, vrf="vrf1", update=False)
|
||||
logger.info("checking for withdrawed prefixes")
|
||||
# check
|
||||
test_func = partial(check_for_prefixes, prefixes, "withdraw", policy)
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
assert success, "Checking the withdrawed prefixes has been failed !."
|
||||
# check
|
||||
test_func = partial(check_for_prefixes, prefixes, type, policy, step)
|
||||
success, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
|
||||
assert success, "Checking the updated prefixes has failed ! %s" % res
|
||||
|
||||
|
||||
def test_bmp_server_logging():
|
||||
@ -300,7 +414,7 @@ def test_bmp_server_logging():
|
||||
return False
|
||||
return True
|
||||
|
||||
success, _ = topotest.run_and_expect(check_for_log_file, True, wait=0.5)
|
||||
success, _ = topotest.run_and_expect(check_for_log_file, True, count=30, wait=1)
|
||||
assert success, "The BMP server is not logging"
|
||||
|
||||
|
||||
@ -314,7 +428,7 @@ def test_peer_up():
|
||||
logger.info("checking for BMP peers up messages")
|
||||
|
||||
test_func = partial(check_for_peer_message, peers, "peer up")
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
success, _ = topotest.run_and_expect(test_func, True, count=30, wait=1)
|
||||
assert success, "Checking the updated prefixes has been failed !."
|
||||
|
||||
|
||||
@ -323,21 +437,21 @@ def test_bmp_bgp_unicast():
|
||||
Add/withdraw bgp unicast prefixes and check the bmp logs.
|
||||
"""
|
||||
logger.info("*** Unicast prefixes pre-policy logging ***")
|
||||
unicast_prefixes(PRE_POLICY)
|
||||
_test_prefixes(PRE_POLICY, step=1)
|
||||
logger.info("*** Unicast prefixes post-policy logging ***")
|
||||
unicast_prefixes(POST_POLICY)
|
||||
_test_prefixes(POST_POLICY, step=1)
|
||||
logger.info("*** Unicast prefixes loc-rib logging ***")
|
||||
unicast_prefixes(LOC_RIB)
|
||||
_test_prefixes(LOC_RIB, step=1)
|
||||
|
||||
|
||||
def test_bmp_bgp_vpn():
|
||||
# check for the prefixes in the BMP server logging file
|
||||
logger.info("***** VPN prefixes pre-policy logging *****")
|
||||
vpn_prefixes(PRE_POLICY)
|
||||
_test_prefixes(PRE_POLICY, vrf="vrf1", step=2)
|
||||
logger.info("***** VPN prefixes post-policy logging *****")
|
||||
vpn_prefixes(POST_POLICY)
|
||||
_test_prefixes(POST_POLICY, vrf="vrf1", step=2)
|
||||
logger.info("***** VPN prefixes loc-rib logging *****")
|
||||
vpn_prefixes(LOC_RIB)
|
||||
_test_prefixes(LOC_RIB, vrf="vrf1", step=2)
|
||||
|
||||
|
||||
def test_peer_down():
|
||||
@ -353,7 +467,7 @@ def test_peer_down():
|
||||
logger.info("checking for BMP peers down messages")
|
||||
|
||||
test_func = partial(check_for_peer_message, peers, "peer down")
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
success, _ = topotest.run_and_expect(test_func, True, count=30, wait=1)
|
||||
assert success, "Checking the updated prefixes has been failed !."
|
||||
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
{
|
||||
"loc-rib": {
|
||||
"update": {
|
||||
"172.31.0.15/32": {
|
||||
"as_path": "65501 65502",
|
||||
"bgp_nexthop": "192.168.0.2",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"is_filtered": false,
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib"
|
||||
},
|
||||
"2111::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2111::1111/128",
|
||||
"is_filtered": false,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"post-policy": {
|
||||
"update": {
|
||||
"172.31.0.15/32": {
|
||||
"as_path": "65501 65502",
|
||||
"bgp_nexthop": "192.168.0.2",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy"
|
||||
},
|
||||
"2111::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2111::1111/128",
|
||||
"ipv6": true,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"pre-policy": {
|
||||
"update": {
|
||||
"172.31.0.15/32": {
|
||||
"as_path": "65501 65502",
|
||||
"bgp_nexthop": "192.168.0.2",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy"
|
||||
},
|
||||
"2111::1111/128": {
|
||||
"afi": 2,
|
||||
"as_path": "65501 65502",
|
||||
"bmp_log_type": "update",
|
||||
"ip_prefix": "2111::1111/128",
|
||||
"ipv6": true,
|
||||
"nxhp_ip": "192:168::2",
|
||||
"origin": "IGP",
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
{
|
||||
"loc-rib": {
|
||||
"withdraw": {
|
||||
"172.31.0.15/32": {
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"is_filtered": false,
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib"
|
||||
},
|
||||
"2111::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2111::1111/128",
|
||||
"is_filtered": false,
|
||||
"peer_asn": 65501,
|
||||
"peer_bgp_id": "192.168.0.1",
|
||||
"peer_type": "loc-rib instance",
|
||||
"policy": "loc-rib",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
"post-policy": {
|
||||
"withdraw": {
|
||||
"172.31.0.15/32": {
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy"
|
||||
},
|
||||
"2111::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2111::1111/128",
|
||||
"ipv6": true,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "post-policy",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
"pre-policy": {
|
||||
"withdraw": {
|
||||
"172.31.0.15/32": {
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "172.31.0.15/32",
|
||||
"ipv6": false,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192.168.0.2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy"
|
||||
},
|
||||
"2111::1111/128": {
|
||||
"afi": 2,
|
||||
"bmp_log_type": "withdraw",
|
||||
"ip_prefix": "2111::1111/128",
|
||||
"ipv6": true,
|
||||
"peer_asn": 65502,
|
||||
"peer_bgp_id": "192.168.0.2",
|
||||
"peer_distinguisher": "0:0",
|
||||
"peer_ip": "192:168::2",
|
||||
"peer_type": "global instance",
|
||||
"policy": "pre-policy",
|
||||
"safi": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,12 @@ router bgp 65501 vrf vrf1
|
||||
!
|
||||
bmp targets bmp1
|
||||
bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000
|
||||
bmp monitor ipv4 unicast pre-policy
|
||||
bmp monitor ipv6 unicast pre-policy
|
||||
bmp monitor ipv4 unicast post-policy
|
||||
bmp monitor ipv6 unicast post-policy
|
||||
bmp monitor ipv4 unicast loc-rib
|
||||
bmp monitor ipv6 unicast loc-rib
|
||||
exit
|
||||
!
|
||||
|
||||
|
@ -0,0 +1,21 @@
|
||||
{
|
||||
"routes": {
|
||||
"172.31.0.15/32": [
|
||||
{
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"path": "65502",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "192.168.0.2",
|
||||
"hostname": "r2",
|
||||
"afi": "ipv4",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"routes": {
|
||||
"172.31.0.15/32": null
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
{
|
||||
"routes": {
|
||||
"2111::1111/128": [
|
||||
{
|
||||
"bestpath": true,
|
||||
"pathFrom": "external",
|
||||
"path": "65502",
|
||||
"origin": "IGP",
|
||||
"nexthops": [
|
||||
{
|
||||
"ip": "192:168::2",
|
||||
"hostname": "r2",
|
||||
"afi": "ipv6",
|
||||
"scope": "global"
|
||||
},
|
||||
{
|
||||
"hostname": "r2",
|
||||
"afi": "ipv6",
|
||||
"scope": "link-local",
|
||||
"used": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"routes": {
|
||||
"2111::1111/128": null
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,9 @@ PRE_POLICY = "pre-policy"
|
||||
POST_POLICY = "post-policy"
|
||||
LOC_RIB = "loc-rib"
|
||||
|
||||
UPDATE_EXPECTED_JSON = False
|
||||
DEBUG_PCAP = False
|
||||
|
||||
|
||||
def build_topo(tgen):
|
||||
tgen.add_router("r1")
|
||||
@ -76,6 +79,12 @@ ip link set r1-eth1 master vrf1
|
||||
"""
|
||||
)
|
||||
|
||||
if DEBUG_PCAP:
|
||||
tgen.gears["r1"].run("rm /tmp/bmp_vrf.pcap")
|
||||
tgen.gears["r1"].run(
|
||||
"tcpdump -nni r1-eth0 -s 0 -w /tmp/bmp_vrf.pcap &", stdout=None
|
||||
)
|
||||
|
||||
for rname, router in tgen.routers().items():
|
||||
router.load_config(
|
||||
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||
@ -131,42 +140,125 @@ def get_bmp_messages():
|
||||
return messages
|
||||
|
||||
|
||||
def check_for_prefixes(expected_prefixes, bmp_log_type, policy, labels=None):
|
||||
def update_seq():
|
||||
global SEQ
|
||||
|
||||
messages = get_bmp_messages()
|
||||
|
||||
if len(messages):
|
||||
SEQ = messages[-1]["seq"]
|
||||
|
||||
|
||||
def update_expected_files(bmp_actual, expected_prefixes, bmp_log_type, policy, step):
|
||||
tgen = get_topogen()
|
||||
|
||||
with open(f"/tmp/bmp-{bmp_log_type}-{policy}-step{step}.json", "w") as json_file:
|
||||
json.dump(bmp_actual, json_file, indent=4)
|
||||
|
||||
out = tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 ipv4 json", isjson=True)
|
||||
filtered_out = {
|
||||
"routes": {
|
||||
prefix: route_info
|
||||
for prefix, route_info in out["routes"].items()
|
||||
if prefix in expected_prefixes
|
||||
}
|
||||
}
|
||||
if bmp_log_type == "withdraw":
|
||||
for pfx in expected_prefixes:
|
||||
if "::" in pfx:
|
||||
continue
|
||||
filtered_out["routes"][pfx] = None
|
||||
|
||||
# ls /tmp/show*json | while read file; do egrep -v 'prefix|network|metric|ocPrf|version|weight|peerId|vrf|Version|valid|Reason|fe80' $file >$(basename $file); echo >> $(basename $file); done
|
||||
with open(f"/tmp/show-bgp-ipv4-{bmp_log_type}-step{step}.json", "w") as json_file:
|
||||
json.dump(filtered_out, json_file, indent=4)
|
||||
|
||||
out = tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 ipv6 json", isjson=True)
|
||||
filtered_out = {
|
||||
"routes": {
|
||||
prefix: route_info
|
||||
for prefix, route_info in out["routes"].items()
|
||||
if prefix in expected_prefixes
|
||||
}
|
||||
}
|
||||
if bmp_log_type == "withdraw":
|
||||
for pfx in expected_prefixes:
|
||||
if "::" not in pfx:
|
||||
continue
|
||||
filtered_out["routes"][pfx] = None
|
||||
|
||||
with open(f"/tmp/show-bgp-ipv6-{bmp_log_type}-step{step}.json", "w") as json_file:
|
||||
json.dump(filtered_out, json_file, indent=4)
|
||||
|
||||
|
||||
def check_for_prefixes(expected_prefixes, bmp_log_type, policy, step):
|
||||
"""
|
||||
Check for the presence of the given prefixes in the BMP server logs with
|
||||
the given message type and the set policy.
|
||||
|
||||
"""
|
||||
global SEQ
|
||||
|
||||
# we care only about the new messages
|
||||
messages = [
|
||||
m for m in sorted(get_bmp_messages(), key=lambda d: d["seq"]) if m["seq"] > SEQ
|
||||
]
|
||||
|
||||
# get the list of pairs (prefix, policy, seq) for the given message type
|
||||
prefixes = [
|
||||
m["ip_prefix"]
|
||||
for m in messages
|
||||
if "ip_prefix" in m.keys()
|
||||
and "bmp_log_type" in m.keys()
|
||||
and m["bmp_log_type"] == bmp_log_type
|
||||
and m["policy"] == policy
|
||||
and (
|
||||
labels is None
|
||||
or (
|
||||
m["ip_prefix"] in labels.keys() and m["label"] == labels[m["ip_prefix"]]
|
||||
)
|
||||
)
|
||||
]
|
||||
# create empty initial files
|
||||
# for step in $(seq 1); do
|
||||
# for i in "update" "withdraw"; do
|
||||
# for j in "pre-policy" "post-policy" "loc-rib"; do
|
||||
# echo '{"null": {}}'> bmp-$i-$j-step$step.json
|
||||
# done
|
||||
# done
|
||||
# done
|
||||
|
||||
# check for prefixes
|
||||
for ep in expected_prefixes:
|
||||
if ep not in prefixes:
|
||||
msg = "The prefix {} is not present in the {} log messages."
|
||||
logger.debug(msg.format(ep, bmp_log_type))
|
||||
return False
|
||||
ref_file = f"{CWD}/bmp1/bmp-{bmp_log_type}-{policy}-step{step}.json"
|
||||
expected = json.loads(open(ref_file).read())
|
||||
|
||||
SEQ = messages[-1]["seq"]
|
||||
return True
|
||||
# Build actual json from logs
|
||||
actual = {}
|
||||
for m in messages:
|
||||
if (
|
||||
"bmp_log_type" in m.keys()
|
||||
and "ip_prefix" in m.keys()
|
||||
and m["ip_prefix"] in expected_prefixes
|
||||
and m["bmp_log_type"] == bmp_log_type
|
||||
and m["policy"] == policy
|
||||
):
|
||||
policy_dict = actual.setdefault(m["policy"], {})
|
||||
bmp_log_type_dict = policy_dict.setdefault(m["bmp_log_type"], {})
|
||||
|
||||
# Add or update the ip_prefix dictionary with filtered key-value pairs
|
||||
bmp_log_type_dict[m["ip_prefix"]] = {
|
||||
k: v
|
||||
for k, v in sorted(m.items())
|
||||
# filter out variable keys
|
||||
if k not in ["timestamp", "seq", "nxhp_link-local"]
|
||||
and (
|
||||
# When policy is loc-rib, the peer-distinguisher is 0:0
|
||||
# for the default VRF or the RD if any or the 0:<vrf_id>.
|
||||
# 0:<vrf_id> is used to distinguished. RFC7854 says: "If the
|
||||
# peer is a "Local Instance Peer", it is set to a unique,
|
||||
# locally defined value." The value is not tested because it
|
||||
# is variable.
|
||||
k != "peer_distinguisher"
|
||||
or policy != LOC_RIB
|
||||
or v == "0:0"
|
||||
or not v.startswith("0:")
|
||||
)
|
||||
}
|
||||
|
||||
# build expected JSON files
|
||||
if (
|
||||
UPDATE_EXPECTED_JSON
|
||||
and actual
|
||||
and set(actual.get(policy, {}).get(bmp_log_type, {}).keys())
|
||||
== set(expected_prefixes)
|
||||
):
|
||||
update_expected_files(actual, expected_prefixes, bmp_log_type, policy, step)
|
||||
|
||||
return topotest.json_cmp(actual, expected, exact=True)
|
||||
|
||||
|
||||
def check_for_peer_message(expected_peers, bmp_log_type):
|
||||
@ -197,22 +289,6 @@ def check_for_peer_message(expected_peers, bmp_log_type):
|
||||
return True
|
||||
|
||||
|
||||
def set_bmp_policy(tgen, node, asn, target, safi, policy, vrf=None):
|
||||
"""
|
||||
Configure the bmp policy.
|
||||
"""
|
||||
vrf = " vrf {}".format(vrf) if vrf else ""
|
||||
cmd = [
|
||||
"con t\n",
|
||||
"router bgp {}{}\n".format(asn, vrf),
|
||||
"bmp targets {}\n".format(target),
|
||||
"bmp monitor ipv4 {} {}\n".format(safi, policy),
|
||||
"bmp monitor ipv6 {} {}\n".format(safi, policy),
|
||||
"end\n",
|
||||
]
|
||||
tgen.gears[node].vtysh_cmd("".join(cmd))
|
||||
|
||||
|
||||
def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True):
|
||||
"""
|
||||
Configure the bgp prefixes.
|
||||
@ -232,32 +308,48 @@ def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True):
|
||||
tgen.gears[node].vtysh_cmd("".join(cmd))
|
||||
|
||||
|
||||
def unicast_prefixes(policy):
|
||||
def _test_prefixes(policy, step=1):
|
||||
"""
|
||||
Setup the BMP monitor policy, Add and withdraw ipv4/v6 prefixes.
|
||||
Check if the previous actions are logged in the BMP server with the right
|
||||
message type and the right policy.
|
||||
"""
|
||||
tgen = get_topogen()
|
||||
set_bmp_policy(tgen, "r1", 65501, "bmp1", "unicast", policy, vrf="vrf1")
|
||||
|
||||
prefixes = ["172.31.0.15/32", "2111::1111/128"]
|
||||
# add prefixes
|
||||
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes)
|
||||
|
||||
logger.info("checking for updated prefixes")
|
||||
# check
|
||||
test_func = partial(check_for_prefixes, prefixes, "update", policy)
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
assert success, "Checking the updated prefixes has been failed !."
|
||||
for type in ("update", "withdraw"):
|
||||
update_seq()
|
||||
|
||||
# withdraw prefixes
|
||||
configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, update=False)
|
||||
logger.info("checking for withdrawed prefxies")
|
||||
# check
|
||||
test_func = partial(check_for_prefixes, prefixes, "withdraw", policy)
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
assert success, "Checking the withdrawed prefixes has been failed !."
|
||||
# add prefixes
|
||||
configure_prefixes(
|
||||
tgen, "r2", 65502, "unicast", prefixes, update=(type == "update")
|
||||
)
|
||||
|
||||
logger.info(f"checking for prefixes {type}")
|
||||
|
||||
for ipver in [4, 6]:
|
||||
if UPDATE_EXPECTED_JSON:
|
||||
continue
|
||||
ref_file = "{}/r1/show-bgp-ipv{}-{}-step{}.json".format(
|
||||
CWD, ipver, type, step
|
||||
)
|
||||
expected = json.loads(open(ref_file).read())
|
||||
|
||||
test_func = partial(
|
||||
topotest.router_json_cmp,
|
||||
tgen.gears["r1"],
|
||||
f"show bgp vrf vrf1 ipv{ipver} json",
|
||||
expected,
|
||||
)
|
||||
_, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
|
||||
assertmsg = f"r1: BGP IPv{ipver} convergence failed"
|
||||
assert res is None, assertmsg
|
||||
|
||||
# check
|
||||
test_func = partial(check_for_prefixes, prefixes, type, policy, step)
|
||||
success, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
|
||||
assert success, "Checking the updated prefixes has been failed ! %s" % res
|
||||
|
||||
|
||||
def test_bmp_server_logging():
|
||||
@ -274,7 +366,7 @@ def test_bmp_server_logging():
|
||||
return False
|
||||
return True
|
||||
|
||||
success, _ = topotest.run_and_expect(check_for_log_file, True, wait=0.5)
|
||||
success, _ = topotest.run_and_expect(check_for_log_file, True, count=30, wait=1)
|
||||
assert success, "The BMP server is not logging"
|
||||
|
||||
|
||||
@ -288,7 +380,7 @@ def test_peer_up():
|
||||
logger.info("checking for BMP peers up messages")
|
||||
|
||||
test_func = partial(check_for_peer_message, peers, "peer up")
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
success, _ = topotest.run_and_expect(test_func, True, count=30, wait=1)
|
||||
assert success, "Checking the updated prefixes has been failed !."
|
||||
|
||||
|
||||
@ -297,11 +389,11 @@ def test_bmp_bgp_unicast():
|
||||
Add/withdraw bgp unicast prefixes and check the bmp logs.
|
||||
"""
|
||||
logger.info("*** Unicast prefixes pre-policy logging ***")
|
||||
unicast_prefixes(PRE_POLICY)
|
||||
_test_prefixes(PRE_POLICY)
|
||||
logger.info("*** Unicast prefixes post-policy logging ***")
|
||||
unicast_prefixes(POST_POLICY)
|
||||
_test_prefixes(POST_POLICY)
|
||||
logger.info("*** Unicast prefixes loc-rib logging ***")
|
||||
unicast_prefixes(LOC_RIB)
|
||||
_test_prefixes(LOC_RIB)
|
||||
|
||||
|
||||
def test_peer_down():
|
||||
@ -317,7 +409,7 @@ def test_peer_down():
|
||||
logger.info("checking for BMP peers down messages")
|
||||
|
||||
test_func = partial(check_for_peer_message, peers, "peer down")
|
||||
success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
|
||||
success, _ = topotest.run_and_expect(test_func, True, count=30, wait=1)
|
||||
assert success, "Checking the updated prefixes has been failed !."
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user