summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/topotests/bgp_bmp/r1/bgpd.conf28
-rw-r--r--tests/topotests/bgp_bmp/r1/zebra.conf2
-rw-r--r--tests/topotests/bgp_bmp/r2/bgpd.conf27
-rw-r--r--tests/topotests/bgp_bmp/test_bgp_bmp.py73
-rw-r--r--tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgp.evpn.route.prefix.after.json1
-rw-r--r--tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgp.evpn.route.prefix.before.json1
-rw-r--r--tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgpd.conf13
-rw-r--r--tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/zebra.conf6
-rwxr-xr-xtests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py72
-rwxr-xr-xtests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py1
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/fpm_counters.json8
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/fpm_stub.conf0
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/routes_summ.json27
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json20
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/sharpd.conf0
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/zebra.conf5
-rw-r--r--tests/topotests/fpm_testing_topo1/test_fpm_topo1.py134
-rw-r--r--tests/topotests/lib/bmp_collector/bmp.py173
-rwxr-xr-xtests/topotests/lib/bmp_collector/bmpserver4
-rw-r--r--tests/topotests/lib/topogen.py25
-rw-r--r--tests/topotests/lib/topotest.py28
-rw-r--r--tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json3
-rw-r--r--tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json3
-rw-r--r--tests/topotests/pytest.ini1
24 files changed, 547 insertions, 108 deletions
diff --git a/tests/topotests/bgp_bmp/r1/bgpd.conf b/tests/topotests/bgp_bmp/r1/bgpd.conf
index 69acf6e750..24505de4a8 100644
--- a/tests/topotests/bgp_bmp/r1/bgpd.conf
+++ b/tests/topotests/bgp_bmp/r1/bgpd.conf
@@ -6,9 +6,17 @@ router bgp 65501
neighbor 192:168::2 remote-as 65502
!
bmp targets bmp1
- bmp connect 192.0.178.10 port 1789 min-retry 100 max-retry 10000
+ bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000
exit
!
+ address-family ipv4 vpn
+ neighbor 192.168.0.2 activate
+ neighbor 192.168.0.2 soft-reconfiguration inbound
+ exit-address-family
+ address-family ipv6 vpn
+ neighbor 192:168::2 activate
+ neighbor 192:168::2 soft-reconfiguration inbound
+ exit-address-family
address-family ipv4 unicast
neighbor 192.168.0.2 activate
neighbor 192.168.0.2 soft-reconfiguration inbound
@@ -20,3 +28,21 @@ router bgp 65501
neighbor 192:168::2 soft-reconfiguration inbound
exit-address-family
!
+router bgp 65502 vrf vrf1
+ bgp router_id 192.168.0.1
+ bgp log-neighbor-changes
+ address-family ipv4 unicast
+ label vpn export 101
+ rd vpn export 444:1
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+ address-family ipv6 unicast
+ label vpn export 103
+ rd vpn export 555:1
+ rt vpn both 54:200
+ export vpn
+ import vpn
+ exit-address-family
+exit
diff --git a/tests/topotests/bgp_bmp/r1/zebra.conf b/tests/topotests/bgp_bmp/r1/zebra.conf
index 6a25a6f4c2..0b523c9e18 100644
--- a/tests/topotests/bgp_bmp/r1/zebra.conf
+++ b/tests/topotests/bgp_bmp/r1/zebra.conf
@@ -1,5 +1,5 @@
interface r1-eth0
- ip address 192.0.178.1/24
+ ip address 192.0.2.1/24
!
interface r1-eth1
ip address 192.168.0.1/24
diff --git a/tests/topotests/bgp_bmp/r2/bgpd.conf b/tests/topotests/bgp_bmp/r2/bgpd.conf
index 7c8255a175..40e2cd5bbc 100644
--- a/tests/topotests/bgp_bmp/r2/bgpd.conf
+++ b/tests/topotests/bgp_bmp/r2/bgpd.conf
@@ -12,8 +12,35 @@ router bgp 65502
redistribute connected
exit-address-family
!
+ address-family ipv4 vpn
+ neighbor 192.168.0.1 activate
+ exit-address-family
+!
+ address-family ipv6 vpn
+ neighbor 192:168::1 activate
+ exit-address-family
+!
address-family ipv6 unicast
neighbor 192:168::1 activate
redistribute connected
exit-address-family
!
+router bgp 65502 vrf vrf1
+ bgp router-id 192.168.0.2
+ bgp log-neighbor-changes
+ no bgp network import-check
+ address-family ipv4 unicast
+ label vpn export 102
+ rd vpn export 444:2
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+ address-family ipv6 unicast
+ label vpn export 105
+ rd vpn export 555:2
+ rt vpn both 54:200
+ export vpn
+ import vpn
+ exit-address-family
+exit
diff --git a/tests/topotests/bgp_bmp/test_bgp_bmp.py b/tests/topotests/bgp_bmp/test_bgp_bmp.py
index 250f1cb90d..02de805068 100644
--- a/tests/topotests/bgp_bmp/test_bgp_bmp.py
+++ b/tests/topotests/bgp_bmp/test_bgp_bmp.py
@@ -55,7 +55,7 @@ LOC_RIB = "loc-rib"
def build_topo(tgen):
tgen.add_router("r1")
tgen.add_router("r2")
- tgen.add_bmp_server("bmp1", ip="192.0.178.10", defaultRoute="via 192.0.178.1")
+ tgen.add_bmp_server("bmp1", ip="192.0.2.10", defaultRoute="via 192.0.2.1")
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
@@ -81,8 +81,8 @@ def setup_module(mod):
tgen.start_router()
logger.info("starting BMP servers")
- for _, server in tgen.get_bmp_servers().items():
- server.start()
+ for bmp_name, server in tgen.get_bmp_servers().items():
+ server.start(log_file=os.path.join(tgen.logdir, bmp_name, "bmp.log"))
def teardown_module(_mod):
@@ -105,7 +105,9 @@ def get_bmp_messages():
"""
messages = []
tgen = get_topogen()
- text_output = tgen.gears["bmp1"].run("cat /var/log/bmp.log")
+ text_output = tgen.gears["bmp1"].run(
+ "cat {}".format(os.path.join(tgen.logdir, "bmp1", "bmp.log"))
+ )
for m in text_output.splitlines():
# some output in the bash can break the message decoding
@@ -121,7 +123,7 @@ def get_bmp_messages():
return messages
-def check_for_prefixes(expected_prefixes, bmp_log_type, policy):
+def check_for_prefixes(expected_prefixes, bmp_log_type, policy, labels=None):
"""
Check for the presence of the given prefixes in the BMP server logs with
the given message type and the set policy.
@@ -140,6 +142,12 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy):
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"]]
+ )
+ )
]
# check for prefixes
@@ -174,7 +182,7 @@ def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True):
Configure the bgp prefixes.
"""
withdraw = "no " if not update else ""
- vrf = " vrf {}" if vrf else ""
+ vrf = " vrf {}".format(vrf) if vrf else ""
for p in prefixes:
ip = ip_network(p)
cmd = [
@@ -216,6 +224,45 @@ def unicast_prefixes(policy):
assert success, "Checking the withdrawed prefixes has been failed !."
+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)
+
+ prefixes = ["172.31.10.1/32", "2001::2222/128"]
+
+ if policy == PRE_POLICY:
+ # labels are not yet supported in adj-RIB-in. Do not test for the moment
+ labels = None
+ else:
+ # "label vpn export" value in r2/bgpd.conf
+ labels = {
+ "172.31.10.1/32": 102,
+ "2001::2222/128": 105,
+ }
+
+ # 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 !."
+
+
def test_bmp_server_logging():
"""
Assert the logging of the bmp server.
@@ -223,7 +270,9 @@ def test_bmp_server_logging():
def check_for_log_file():
tgen = get_topogen()
- output = tgen.gears["bmp1"].run("ls /var/log/")
+ output = tgen.gears["bmp1"].run(
+ "ls {}".format(os.path.join(tgen.logdir, "bmp1"))
+ )
if "bmp.log" not in output:
return False
return True
@@ -244,6 +293,16 @@ def test_bmp_bgp_unicast():
unicast_prefixes(LOC_RIB)
+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)
+ logger.info("***** VPN prefixes post-policy logging *****")
+ vpn_prefixes(POST_POLICY)
+ logger.info("***** VPN prefixes loc-rib logging *****")
+ vpn_prefixes(LOC_RIB)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgp.evpn.route.prefix.after.json b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgp.evpn.route.prefix.after.json
new file mode 100644
index 0000000000..0b5b1a1e2b
--- /dev/null
+++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgp.evpn.route.prefix.after.json
@@ -0,0 +1 @@
+{"27.3.0.85:3":{"rd":"27.3.0.85:3","[5]:[0]:[16]:[10.27.0.0]":{"prefix":"[5]:[0]:[16]:[10.27.0.0]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"external","routeType":5,"ethTag":0,"ipLen":16,"ip":"10.27.0.0","metric":0,"weight":32768,"peerId":"(unspec)","path":"","origin":"incomplete","extendedCommunity":{"string":"ET:8 RT:65000:4000 Rmac:44:00:00:ff:ff:01"},"nexthops":[{"ip":"10.10.10.10","hostname":"PE1","afi":"ipv4","used":true}]}]]}},"30.0.0.3:2":{"rd":"30.0.0.3:2","[5]:[0]:[32]:[4.4.4.1]":{"prefix":"[5]:[0]:[32]:[4.4.4.1]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"internal","routeType":5,"ethTag":0,"ipLen":32,"ip":"4.4.4.1","metric":0,"locPrf":100,"weight":0,"peerId":"10.30.30.30","path":"","origin":"incomplete","extendedCommunity":{"string":"RT:65000:300 ET:8 Rmac:44:20:00:ff:ff:01"},"nexthops":[{"ip":"10.30.30.30","hostname":"PE2","afi":"ipv4","used":true}]}]]}},"numPrefix":2,"numPaths":2}
diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgp.evpn.route.prefix.before.json b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgp.evpn.route.prefix.before.json
new file mode 100644
index 0000000000..67417b5986
--- /dev/null
+++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgp.evpn.route.prefix.before.json
@@ -0,0 +1 @@
+{"27.3.0.85:3":{"rd":"27.3.0.85:3","[5]:[0]:[24]:[10.27.7.0]":{"prefix":"[5]:[0]:[24]:[10.27.7.0]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"external","routeType":5,"ethTag":0,"ipLen":24,"ip":"10.27.7.0","metric":0,"weight":32768,"peerId":"(unspec)","path":"","origin":"incomplete","extendedCommunity":{"string":"ET:8 RT:65000:4000 Rmac:44:00:00:ff:ff:01"},"nexthops":[{"ip":"10.10.10.10","hostname":"PE1","afi":"ipv4","used":true}]}]]},"[5]:[0]:[30]:[10.27.7.8]":{"prefix":"[5]:[0]:[30]:[10.27.7.8]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"external","routeType":5,"ethTag":0,"ipLen":30,"ip":"10.27.7.8","metric":0,"weight":32768,"peerId":"(unspec)","path":"","origin":"incomplete","extendedCommunity":{"string":"ET:8 RT:65000:4000 Rmac:44:00:00:ff:ff:01"},"nexthops":[{"ip":"10.10.10.10","hostname":"PE1","afi":"ipv4","used":true}]}]]},"[5]:[0]:[32]:[10.27.7.22]":{"prefix":"[5]:[0]:[32]:[10.27.7.22]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"external","routeType":5,"ethTag":0,"ipLen":32,"ip":"10.27.7.22","metric":0,"weight":32768,"peerId":"(unspec)","path":"","origin":"incomplete","extendedCommunity":{"string":"ET:8 RT:65000:4000 Rmac:44:00:00:ff:ff:01"},"nexthops":[{"ip":"10.10.10.10","hostname":"PE1","afi":"ipv4","used":true}]}]]}},"30.0.0.3:2":{"rd":"30.0.0.3:2","[5]:[0]:[32]:[4.4.4.1]":{"prefix":"[5]:[0]:[32]:[4.4.4.1]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"internal","routeType":5,"ethTag":0,"ipLen":32,"ip":"4.4.4.1","metric":0,"locPrf":100,"weight":0,"peerId":"10.30.30.30","path":"","origin":"incomplete","extendedCommunity":{"string":"RT:65000:300 ET:8 Rmac:44:20:00:ff:ff:01"},"nexthops":[{"ip":"10.30.30.30","hostname":"PE2","afi":"ipv4","used":true}]}]]}},"numPrefix":4,"numPaths":4}
diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgpd.conf b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgpd.conf
index 9fb2bd6835..b58219ad8e 100644
--- a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgpd.conf
+++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/bgpd.conf
@@ -11,9 +11,22 @@ router bgp 65000
advertise-svi-ip
!
router bgp 65000 vrf vrf-red
+ address-family ipv4 unicast
+ redistribute static
+ exit-address-family
!
address-family l2vpn evpn
route-target import *:300
route-target import auto
exit-address-family
!
+router bgp 65000 vrf vrf-purple
+ address-family ipv4 unicast
+ redistribute static
+ exit-address-family
+ !
+ address-family l2vpn evpn
+ advertise ipv4 unicast
+ exit-address-family
+
+!
diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/zebra.conf b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/zebra.conf
index 8c6cf3e6d4..cea60a8b1e 100644
--- a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/zebra.conf
+++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/zebra.conf
@@ -5,6 +5,12 @@ vrf vrf-red
vni 100
exit-vrf
!
+vrf vrf-purple
+ vni 4000
+ ip route 10.27.7.0/24 blackhole
+ ip route 10.27.7.22/32 blackhole
+ ip route 10.27.7.10/30 blackhole
+exit-vrf
!
interface lo
ip address 10.10.10.10/32
diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py b/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py
index 65c0c3532a..fd75c34ebf 100755
--- a/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py
+++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/test_bgp_evpn_vxlan_svd.py
@@ -91,6 +91,10 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
pe.run("ip link add name bridge type bridge stp_state 0")
pe.run("ip link set dev bridge type bridge vlan_filtering 1")
pe.run("bridge vlan add vid 1 dev bridge self")
+ if pe_name == "PE1":
+ pe.run("ip link set dev bridge address 44:00:00:ff:ff:01")
+ if pe_name == "PE2":
+ pe.run("ip link set dev bridge address 44:20:00:ff:ff:01")
pe.run("ip link set dev bridge up")
# setup svi
@@ -113,6 +117,18 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
pe.run("bridge vlan add dev vxlan0 vid 1 tunnel_info id 101")
pe.run("ip link set up dev vxlan0")
+ # VRF creation
+ pe.run("ip link add vrf-purple type vrf table 1003")
+ pe.run("ip link set dev vrf-purple up")
+ if pe_name == "PE1":
+ pe.run("ip link add vrf-blue type vrf table 1002")
+ pe.run("ip link set dev vrf-blue up")
+ pe.run("ip addr add 27.2.0.85/32 dev vrf-blue")
+ pe.run("ip addr add 27.3.0.85/32 dev vrf-purple")
+ if pe_name == "PE2":
+ pe.run("ip link add vrf-blue type vrf table 2400")
+ pe.run("ip link set dev vrf-blue up")
+
# setup PE interface
pe.run("ip link set dev {0}-{1} master bridge".format(pe_name, intf))
pe.run("bridge vlan del vid 1 dev {0}-{1}".format(pe_name, intf))
@@ -120,7 +136,7 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
pe.run("bridge vlan add vid 1 dev {0}-{1}".format(pe_name, intf))
pe.run("bridge vlan add vid 1 pvid untagged dev {0}-{1}".format(pe_name, intf))
- # l3vni 100
+ # L3VNI 100
pe.run("ip link add vrf-red type vrf table 1400")
pe.run("ip link add link bridge name vlan100 type vlan id 100 protocol 802.1q")
pe.run("ip link set dev vlan100 master vrf-blue")
@@ -129,9 +145,16 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
pe.run("bridge vlan add dev vxlan0 vid 100")
pe.run("bridge vlan add dev vxlan0 vid 100 tunnel_info id 100")
+ # L3VNI 4000
+ pe.run("ip link add link bridge name vlan400 type vlan id 400 protocol 802.1q")
+ pe.run("ip link set dev vlan400 master vrf-purple")
+ pe.run("ip link set dev vlan400 up")
+ pe.run("bridge vlan add vid 400 dev bridge self")
+ pe.run("bridge vlan add dev vxlan0 vid 400")
+ pe.run("bridge vlan add dev vxlan0 vid 400 tunnel_info id 4000")
+
# add a vrf for testing DVNI
if pe_name == "PE2":
- pe.run("ip link add vrf-blue type vrf table 2400")
pe.run("ip link add link bridge name vlan300 type vlan id 300 protocol 802.1q")
pe.run("ip link set dev vlan300 master vrf-blue")
pe.run("ip link set dev vlan300 up")
@@ -199,6 +222,14 @@ def show_vni_json_elide_ifindex(pe, vni, expected):
return topotest.json_cmp(output_json, expected)
+def show_bgp_l2vpn_evpn_route_type_prefix_json(pe, expected):
+ output_json = pe.vtysh_cmd(
+ "show bgp l2vpn evpn route type prefix json", isjson=True
+ )
+
+ return topotest.json_cmp(output_json, expected)
+
+
def check_vni_macs_present(tgen, router, vni, maclist):
result = router.vtysh_cmd("show evpn mac vni {} json".format(vni), isjson=True)
for rname, ifname in maclist:
@@ -331,6 +362,7 @@ def mac_test_local_remote(local, remote):
remote_output_json = json.loads(remote_output)
local_output_vni_json = json.loads(local_output_vni)
+ # breakpoint()
for vni in local_output_json:
if vni not in remote_output_json:
continue
@@ -542,6 +574,42 @@ def test_dvni():
# tgen.mininet_cli()
+def test_pe_advertise_aggr_evpn_route():
+ "BGP advertise aggregated Type-5 prefix route"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Checking BGP EVPN route contains non-aggregate prefixes")
+ pe1 = tgen.gears["PE1"]
+ json_file = "{}/{}/bgp.evpn.route.prefix.before.json".format(CWD, pe1.name)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(show_bgp_l2vpn_evpn_route_type_prefix_json, pe1, expected)
+ _, result = topotest.run_and_expect(test_func, None, count=45, wait=1)
+ assertmsg = '"{}" JSON output mismatches'.format(pe1.name)
+ assert result is None, assertmsg
+
+ logger.info("Configure BGP aggregate-address summary-only under ipv4-unicast")
+ pe1.cmd(
+ 'vtysh -c "config t" -c "router bgp 65000 vrf vrf-purple" '
+ + ' -c "address-family ipv4 unicast" '
+ + ' -c "aggregate-address 10.27.0.0/16 summary-only" '
+ )
+
+ logger.info("Checking BGP EVPN route contains aggregated prefix")
+ pe1 = tgen.gears["PE1"]
+ json_file = "{}/{}/bgp.evpn.route.prefix.after.json".format(CWD, pe1.name)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(show_bgp_l2vpn_evpn_route_type_prefix_json, pe1, expected)
+ _, result = topotest.run_and_expect(test_func, None, count=45, wait=1)
+ assertmsg = '"{}" JSON output mismatches'.format(pe1.name)
+ assert result is None, assertmsg
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py b/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py
index 9239be9221..340df71a19 100755
--- a/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py
@@ -103,7 +103,6 @@ def setup_module(mod):
# For all registered routers, load the zebra configuration file
for rname, router in tgen.routers().items():
- router.run("/bin/bash {}/setup_vrfs".format(CWD))
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
diff --git a/tests/topotests/fpm_testing_topo1/r1/fpm_counters.json b/tests/topotests/fpm_testing_topo1/r1/fpm_counters.json
new file mode 100644
index 0000000000..05a6731e13
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/fpm_counters.json
@@ -0,0 +1,8 @@
+{
+ "connected":true,
+ "useNHG":true,
+ "useRouteReplace":true,
+ "disabled":false,
+ "address":"127.0.0.1",
+ "port":2620
+}
diff --git a/tests/topotests/fpm_testing_topo1/r1/fpm_stub.conf b/tests/topotests/fpm_testing_topo1/r1/fpm_stub.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/fpm_stub.conf
diff --git a/tests/topotests/fpm_testing_topo1/r1/routes_summ.json b/tests/topotests/fpm_testing_topo1/r1/routes_summ.json
new file mode 100644
index 0000000000..e9157bc664
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/routes_summ.json
@@ -0,0 +1,27 @@
+{
+ "routes":[
+ {
+ "fib":1,
+ "rib":1,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"connected"
+ },
+ {
+ "fib":1,
+ "rib":1,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"local"
+ },
+ {
+ "fib":10000,
+ "rib":10000,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"sharp"
+ }
+ ],
+ "routesTotal":10002,
+ "routesTotalFib":10002
+}
diff --git a/tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json b/tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json
new file mode 100644
index 0000000000..8585b2bb6b
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json
@@ -0,0 +1,20 @@
+{
+ "routes":[
+ {
+ "fib":1,
+ "rib":1,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"connected"
+ },
+ {
+ "fib":1,
+ "rib":1,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"local"
+ }
+ ],
+ "routesTotal":2,
+ "routesTotalFib":2
+}
diff --git a/tests/topotests/fpm_testing_topo1/r1/sharpd.conf b/tests/topotests/fpm_testing_topo1/r1/sharpd.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/sharpd.conf
diff --git a/tests/topotests/fpm_testing_topo1/r1/zebra.conf b/tests/topotests/fpm_testing_topo1/r1/zebra.conf
new file mode 100644
index 0000000000..c7b1646dda
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/zebra.conf
@@ -0,0 +1,5 @@
+fpm address 127.0.0.1
+
+interface r1-eth0
+ ip address 192.168.44.1/24
+!
diff --git a/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py b/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py
new file mode 100644
index 0000000000..bb4d02d342
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# test_route_scale1.py
+#
+# Copyright (c) 2024 by
+# Nvidia, Inc.
+# Donald Sharp
+#
+
+"""
+test_fpm_topo1.py: Testing FPM module
+
+"""
+import os
+import re
+import sys
+import pytest
+import json
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+
+pytestmark = [pytest.mark.fpm, pytest.mark.sharpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Populate routers
+ tgen.add_router("r1")
+
+ switch = tgen.add_switch("sw1")
+ switch.add_link(tgen.gears["r1"])
+
+
+def setup_module(module):
+ "Setup topology"
+
+ # fpm_stub = os.system("which fpm-stub")
+ # if fpm-stub:
+ # pytest.skip("")
+
+ tgen = Topogen(build_topo, module.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, "{}/zebra.conf".format(rname)),
+ "-M dplane_fpm_nl",
+ )
+ router.load_config(
+ TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_FPM_LISTENER, os.path.join(CWD, "{}/fpm_stub.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def test_fpm_connection_made():
+ "Test that the fpm starts up and a connection is made"
+
+ tgen = get_topogen()
+ router = tgen.gears["r1"]
+
+ fpm_counters = "{}/r1/fpm_counters.json".format(CWD)
+ expected = json.loads(open(fpm_counters).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show fpm status json", expected
+ )
+
+ success, result = topotest.run_and_expect(test_func, None, 30, 1)
+ assert success, "Unable to connect to the fpm:\n{}".format(result)
+
+
+def test_fpm_install_routes():
+ "Test that simple routes installed appears to work"
+
+ tgen = get_topogen()
+ router = tgen.gears["r1"]
+
+ # Let's install 10000 routes
+ router.vtysh_cmd("sharp install routes 10.0.0.0 nexthop 192.168.44.33 10000")
+ routes_file = "{}/r1/routes_summ.json".format(CWD)
+ expected = json.loads(open(routes_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route summ json", expected
+ )
+
+ success, result = topotest.run_and_expect(test_func, None, 60, 1)
+ assert success, "Unable to successfully install 10000 routes: {}".format(result)
+
+ # Let's remove 10000 routes
+ router.vtysh_cmd("sharp remove routes 10.0.0.0 10000")
+
+ routes_file_removed = "{}/r1/routes_summ_removed.json".format(CWD)
+ expected = json.loads(open(routes_file_removed).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route summ json", expected
+ )
+
+ success, result = topotest.run_and_expect(test_func, None, 60, 1)
+ assert success, "Unable to remove 10000 routes: {}".format(result)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/lib/bmp_collector/bmp.py b/tests/topotests/lib/bmp_collector/bmp.py
index 57f642aa0e..237decdd5e 100644
--- a/tests/topotests/lib/bmp_collector/bmp.py
+++ b/tests/topotests/lib/bmp_collector/bmp.py
@@ -33,30 +33,33 @@ IS_FILTERED = 1 << 7
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
+
def bin2str_ipaddress(ip_bytes, is_ipv6=False):
if is_ipv6:
return str(ipaddress.IPv6Address(ip_bytes))
return str(ipaddress.IPv4Address(ip_bytes[-4:]))
-def log2file(logs):
+
+def log2file(logs, log_file):
"""
XXX: extract the useful information and save it in a flat dictionnary
"""
- with open(LOG_FILE, 'a') as f:
+ with open(log_file, "a") as f:
f.write(json.dumps(logs) + "\n")
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPCodes:
"""
XXX: complete the list, provide RFCs.
"""
+
VERSION = 0x3
BMP_MSG_TYPE_ROUTE_MONITORING = 0x00
BMP_MSG_TYPE_STATISTICS_REPORT = 0x01
- BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION = 0x02
- BMP_MSG_TYPE_PEER_UP_NOTIFICATION = 0x03
+ BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION = 0x02
+ BMP_MSG_TYPE_PEER_UP_NOTIFICATION = 0x03
BMP_MSG_TYPE_INITIATION = 0x04
BMP_MSG_TYPE_TERMINATION = 0x05
BMP_MSG_TYPE_ROUTE_MIRRORING = 0x06
@@ -107,15 +110,15 @@ class BMPCodes:
# peer down reason code
BMP_PEER_DOWN_LOCAL_NOTIFY = 0x01
- BMP_PEER_DOWN_LOCAL_NO_NOTIFY = 0X02
- BMP_PEER_DOWN_REMOTE_NOTIFY = 0X03
- BMP_PEER_DOWN_REMOTE_NO_NOTIFY = 0X04
+ BMP_PEER_DOWN_LOCAL_NO_NOTIFY = 0x02
+ BMP_PEER_DOWN_REMOTE_NOTIFY = 0x03
+ BMP_PEER_DOWN_REMOTE_NO_NOTIFY = 0x04
BMP_PEER_DOWN_INFO_NO_LONGER = 0x05
- BMP_PEER_DOWN_SYSTEM_CLOSED = 0X06
+ BMP_PEER_DOWN_SYSTEM_CLOSED = 0x06
# termincation message types
BMP_TERM_TYPE_STRING = 0x00
- BMP_TERM_TYPE_REASON = 0X01
+ BMP_TERM_TYPE_REASON = 0x01
# termination reason code
BMP_TERM_REASON_ADMIN_CLOSE = 0x00
@@ -126,31 +129,32 @@ class BMPCodes:
# policy route tlv
BMP_ROUTE_POLICY_TLV_VRF = 0x00
- BMP_ROUTE_POLICY_TLV_POLICY= 0x01
+ BMP_ROUTE_POLICY_TLV_POLICY = 0x01
BMP_ROUTE_POLICY_TLV_PRE_POLICY = 0x02
BMP_ROUTE_POLICY_TLV_POST_POLICY = 0x03
BMP_ROUTE_POLICY_TLV_STRING = 0x04
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPMsg:
"""
XXX: should we move register_msg_type and look_msg_type
to generic Type class.
"""
+
TYPES = {}
UNKNOWN_TYPE = None
- HDR_STR = '!BIB'
+ HDR_STR = "!BIB"
MIN_LEN = struct.calcsize(HDR_STR)
TYPES_STR = {
- BMPCodes.BMP_MSG_TYPE_INITIATION: 'initiation',
- BMPCodes.BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION: 'peer down notification',
- BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION: 'peer up notification',
- BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING: 'route monitoring',
- BMPCodes.BMP_MSG_TYPE_STATISTICS_REPORT: 'statistics report',
- BMPCodes.BMP_MSG_TYPE_TERMINATION: 'termination',
- BMPCodes.BMP_MSG_TYPE_ROUTE_MIRRORING: 'route mirroring',
- BMPCodes.BMP_MSG_TYPE_ROUTE_POLICY: 'route policy',
+ BMPCodes.BMP_MSG_TYPE_INITIATION: "initiation",
+ BMPCodes.BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION: "peer down notification",
+ BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION: "peer up notification",
+ BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING: "route monitoring",
+ BMPCodes.BMP_MSG_TYPE_STATISTICS_REPORT: "statistics report",
+ BMPCodes.BMP_MSG_TYPE_TERMINATION: "termination",
+ BMPCodes.BMP_MSG_TYPE_ROUTE_MIRRORING: "route mirroring",
+ BMPCodes.BMP_MSG_TYPE_ROUTE_POLICY: "route policy",
}
@classmethod
@@ -158,6 +162,7 @@ class BMPMsg:
def _register_type(subcls):
cls.TYPES[msgtype] = subcls
return subcls
+
return _register_type
@classmethod
@@ -179,15 +184,15 @@ class BMPMsg:
if len(data) < cls.MIN_LEN:
pass
else:
- _version, _len, _type = struct.unpack(cls.HDR_STR, data[0:cls.MIN_LEN])
+ _version, _len, _type = struct.unpack(cls.HDR_STR, data[0 : cls.MIN_LEN])
return _version, _len, _type
@classmethod
- def dissect(cls, data):
+ def dissect(cls, data, log_file=None):
global SEQ
version, msglen, msgtype = cls.dissect_header(data)
- msg_data = data[cls.MIN_LEN:msglen]
+ msg_data = data[cls.MIN_LEN : msglen]
data = data[msglen:]
if version != BMPCodes.VERSION:
@@ -202,13 +207,13 @@ class BMPMsg:
msg_cls.MSG_LEN = msglen - cls.MIN_LEN
logs = msg_cls.dissect(msg_data)
logs["seq"] = SEQ
- log2file(logs)
+ log2file(logs, log_file if log_file else LOG_FILE)
SEQ += 1
return data
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPPerPeerMessage:
"""
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
@@ -229,30 +234,33 @@ class BMPPerPeerMessage:
| Timestamp (microseconds) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
- PEER_UNPACK_STR = '!BB8s16sI4sII'
+
+ PEER_UNPACK_STR = "!BB8s16sI4sII"
PEER_TYPE_STR = {
- BMPCodes.BMP_PEER_GLOBAL_INSTANCE: 'global instance',
- BMPCodes.BMP_PEER_RD_INSTANCE: 'route distinguisher instance',
- BMPCodes.BMP_PEER_LOCAL_INSTANCE: 'local instance',
- BMPCodes.BMP_PEER_LOC_RIB_INSTANCE: 'loc-rib instance',
+ BMPCodes.BMP_PEER_GLOBAL_INSTANCE: "global instance",
+ BMPCodes.BMP_PEER_RD_INSTANCE: "route distinguisher instance",
+ BMPCodes.BMP_PEER_LOCAL_INSTANCE: "local instance",
+ BMPCodes.BMP_PEER_LOC_RIB_INSTANCE: "loc-rib instance",
}
@classmethod
def dissect(cls, data):
- (peer_type,
- peer_flags,
- peer_distinguisher,
- peer_address,
- peer_asn,
- peer_bgp_id,
- timestamp_secs,
- timestamp_microsecs) = struct.unpack_from(cls.PEER_UNPACK_STR, data)
-
- msg = {'peer_type': cls.PEER_TYPE_STR[peer_type]}
+ (
+ peer_type,
+ peer_flags,
+ peer_distinguisher,
+ peer_address,
+ peer_asn,
+ peer_bgp_id,
+ timestamp_secs,
+ timestamp_microsecs,
+ ) = struct.unpack_from(cls.PEER_UNPACK_STR, data)
+
+ msg = {"peer_type": cls.PEER_TYPE_STR[peer_type]}
if peer_type == 0x03:
- msg['is_filtered'] = bool(peer_flags & IS_FILTERED)
- msg['policy'] = 'loc-rib'
+ msg["is_filtered"] = bool(peer_flags & IS_FILTERED)
+ msg["policy"] = "loc-rib"
else:
# peer_flags = 0x0000 0000
# ipv6, post-policy, as-path, adj-rib-out, reserverdx4
@@ -260,29 +268,29 @@ class BMPPerPeerMessage:
is_as_path = bool(peer_flags & IS_AS_PATH)
is_post_policy = bool(peer_flags & IS_POST_POLICY)
is_ipv6 = bool(peer_flags & IS_IPV6)
- msg['policy'] = 'post-policy' if is_post_policy else 'pre-policy'
- msg['ipv6'] = is_ipv6
- msg['peer_ip'] = bin2str_ipaddress(peer_address, is_ipv6)
-
+ msg["policy"] = "post-policy" if is_post_policy else "pre-policy"
+ msg["ipv6"] = is_ipv6
+ msg["peer_ip"] = bin2str_ipaddress(peer_address, is_ipv6)
peer_bgp_id = bin2str_ipaddress(peer_bgp_id)
- timestamp = float(timestamp_secs) + timestamp_microsecs * (10 ** -6)
-
- data = data[struct.calcsize(cls.PEER_UNPACK_STR):]
- msg.update({
- 'peer_distinguisher': str(RouteDistinguisher(peer_distinguisher)),
- 'peer_asn': peer_asn,
- 'peer_bgp_id': peer_bgp_id,
- 'timestamp': str(datetime.datetime.fromtimestamp(timestamp)),
- })
+ timestamp = float(timestamp_secs) + timestamp_microsecs * (10**-6)
+
+ data = data[struct.calcsize(cls.PEER_UNPACK_STR) :]
+ msg.update(
+ {
+ "peer_distinguisher": str(RouteDistinguisher(peer_distinguisher)),
+ "peer_asn": peer_asn,
+ "peer_bgp_id": peer_bgp_id,
+ "timestamp": str(datetime.datetime.fromtimestamp(timestamp)),
+ }
+ )
return data, msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING)
class BMPRouteMonitoring(BMPPerPeerMessage):
-
@classmethod
def dissect(cls, data):
data, peer_msg = super().dissect(data)
@@ -290,7 +298,7 @@ class BMPRouteMonitoring(BMPPerPeerMessage):
return {**peer_msg, **update_msg}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPStatisticsReport:
"""
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
@@ -303,10 +311,11 @@ class BMPStatisticsReport:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
+
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPPeerDownNotification:
"""
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
@@ -316,10 +325,11 @@ class BMPPeerDownNotification:
| Data (present if Reason = 1, 2 or 3) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
+
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION)
class BMPPeerUpNotification(BMPPerPeerMessage):
"""
@@ -336,7 +346,8 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
- UNPACK_STR = '!16sHH'
+
+ UNPACK_STR = "!16sHH"
MIN_LEN = struct.calcsize(UNPACK_STR)
MSG_LEN = None
@@ -344,16 +355,14 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
def dissect(cls, data):
data, peer_msg = super().dissect(data)
- (local_addr,
- local_port,
- remote_port) = struct.unpack_from(cls.UNPACK_STR, data)
+ (local_addr, local_port, remote_port) = struct.unpack_from(cls.UNPACK_STR, data)
msg = {
**peer_msg,
**{
- 'local_ip': bin2str_ipaddress(local_addr, peer_msg.get('ipv6')),
- 'local_port': int(local_port),
- 'remote_port': int(remote_port),
+ "local_ip": bin2str_ipaddress(local_addr, peer_msg.get("ipv6")),
+ "local_port": int(local_port),
+ "remote_port": int(remote_port),
},
}
@@ -362,7 +371,7 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
return msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_INITIATION)
class BMPInitiation:
"""
@@ -374,30 +383,31 @@ class BMPInitiation:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
- TLV_STR = '!HH'
+
+ TLV_STR = "!HH"
MIN_LEN = struct.calcsize(TLV_STR)
FIELD_TO_STR = {
- BMPCodes.BMP_INIT_INFO_STRING: 'information',
- BMPCodes.BMP_INIT_ADMIN_LABEL: 'admin_label',
- BMPCodes.BMP_INIT_SYSTEM_DESCRIPTION: 'system_description',
- BMPCodes.BMP_INIT_SYSTEM_NAME: 'system_name',
- BMPCodes.BMP_INIT_VRF_TABLE_NAME: 'vrf_table_name',
+ BMPCodes.BMP_INIT_INFO_STRING: "information",
+ BMPCodes.BMP_INIT_ADMIN_LABEL: "admin_label",
+ BMPCodes.BMP_INIT_SYSTEM_DESCRIPTION: "system_description",
+ BMPCodes.BMP_INIT_SYSTEM_NAME: "system_name",
+ BMPCodes.BMP_INIT_VRF_TABLE_NAME: "vrf_table_name",
}
@classmethod
def dissect(cls, data):
msg = {}
while len(data) > cls.MIN_LEN:
- _type, _len = struct.unpack_from(cls.TLV_STR, data[0:cls.MIN_LEN])
- _value = data[cls.MIN_LEN: cls.MIN_LEN + _len].decode()
+ _type, _len = struct.unpack_from(cls.TLV_STR, data[0 : cls.MIN_LEN])
+ _value = data[cls.MIN_LEN : cls.MIN_LEN + _len].decode()
msg[cls.FIELD_TO_STR[_type]] = _value
- data = data[cls.MIN_LEN + _len:]
+ data = data[cls.MIN_LEN + _len :]
return msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPTermination:
"""
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
@@ -408,14 +418,15 @@ class BMPTermination:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
+
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPRouteMirroring:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPRoutePolicy:
pass
diff --git a/tests/topotests/lib/bmp_collector/bmpserver b/tests/topotests/lib/bmp_collector/bmpserver
index 25b4a52c5e..5257df7530 100755
--- a/tests/topotests/lib/bmp_collector/bmpserver
+++ b/tests/topotests/lib/bmp_collector/bmpserver
@@ -16,10 +16,12 @@ BGP_MAX_SIZE = 4096
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--address", type=str, default="0.0.0.0")
parser.add_argument("-p", "--port", type=int, default=1789)
+parser.add_argument("-l", "--logfile", type=str, default="/var/log/bmp.log")
def main():
args = parser.parse_args()
ADDRESS, PORT = args.address, args.port
+ LOG_FILE = args.logfile
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -31,7 +33,7 @@ def main():
while True:
data = connection.recv(BGP_MAX_SIZE)
while len(data) > BMPMsg.MIN_LEN:
- data = BMPMsg.dissect(data)
+ data = BMPMsg.dissect(data, log_file=LOG_FILE)
except Exception as e:
# XXX: do something
pass
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index 155d2d0986..f49e30ea5f 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -94,7 +94,9 @@ def get_exabgp_cmd(commander=None):
return False
version = m.group(1)
if topotest.version_cmp(version, "4.2.11") < 0:
- logging.debug("found exabgp version < 4.2.11 in %s will keep looking", exacmd)
+ logging.debug(
+ "found exabgp version < 4.2.11 in %s will keep looking", exacmd
+ )
return False
logger.info("Using ExaBGP version %s in %s", version, exacmd)
return True
@@ -746,6 +748,7 @@ class TopoRouter(TopoGear):
RD_PIM6 = 19
RD_MGMTD = 20
RD_TRAP = 21
+ RD_FPM_LISTENER = 22
RD = {
RD_FRR: "frr",
RD_ZEBRA: "zebra",
@@ -769,6 +772,7 @@ class TopoRouter(TopoGear):
RD_SNMP: "snmpd",
RD_MGMTD: "mgmtd",
RD_TRAP: "snmptrapd",
+ RD_FPM_LISTENER: "fpm_listener",
}
def __init__(self, tgen, cls, name, **params):
@@ -845,7 +849,8 @@ class TopoRouter(TopoGear):
TopoRouter.RD_RIPNG, TopoRouter.RD_OSPF, TopoRouter.RD_OSPF6,
TopoRouter.RD_ISIS, TopoRouter.RD_BGP, TopoRouter.RD_LDP,
TopoRouter.RD_PIM, TopoRouter.RD_PIM6, TopoRouter.RD_PBR,
- TopoRouter.RD_SNMP, TopoRouter.RD_MGMTD, TopoRouter.RD_TRAP.
+ TopoRouter.RD_SNMP, TopoRouter.RD_MGMTD, TopoRouter.RD_TRAP,
+ TopoRouter.RD_FPM_LISTENER.
Possible `source` values are `None` for an empty config file, a path name which is
used directly, or a file name with no path components which is first looked for
@@ -883,7 +888,12 @@ class TopoRouter(TopoGear):
# Enable all daemon command logging, logging files
# and set them to the start dir.
for daemon, enabled in nrouter.daemons.items():
- if enabled and daemon != "snmpd" and daemon != "snmptrapd":
+ if (
+ enabled
+ and daemon != "snmpd"
+ and daemon != "snmptrapd"
+ and daemon != "fpm_listener"
+ ):
self.vtysh_cmd(
"\n".join(
[
@@ -933,7 +943,7 @@ class TopoRouter(TopoGear):
# and set them to the start dir.
for daemon in daemons:
enabled = nrouter.daemons[daemon]
- if enabled and daemon != "snmpd":
+ if enabled and daemon != "snmpd" and daemon != "fpm_listener":
self.vtysh_cmd(
"\n".join(
[
@@ -1253,9 +1263,12 @@ class TopoBMPCollector(TopoHost):
gear += " TopoBMPCollector<>".format()
return gear
- def start(self):
+ def start(self, log_file=None):
+ log_arg = "-l {}".format(log_file) if log_file else ""
self.run(
- "{}/bmp_collector/bmpserver -a {} -p {}&".format(CWD, self.ip, self.port),
+ "{}/bmp_collector/bmpserver -a {} -p {} {}&".format(
+ CWD, self.ip, self.port, log_arg
+ ),
stdout=None,
)
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 2bb892355e..0a5be970b8 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -1262,8 +1262,8 @@ def rlimit_atleast(rname, min_value, raises=False):
def fix_netns_limits(ns):
# Maximum read and write socket buffer sizes
- sysctl_atleast(ns, "net.ipv4.tcp_rmem", [10 * 1024, 87380, 16 * 2**20])
- sysctl_atleast(ns, "net.ipv4.tcp_wmem", [10 * 1024, 87380, 16 * 2**20])
+ sysctl_atleast(ns, "net.ipv4.tcp_rmem", [10 * 1024, 87380, 16 * 2 ** 20])
+ sysctl_atleast(ns, "net.ipv4.tcp_wmem", [10 * 1024, 87380, 16 * 2 ** 20])
sysctl_assure(ns, "net.ipv4.conf.all.rp_filter", 0)
sysctl_assure(ns, "net.ipv4.conf.default.rp_filter", 0)
@@ -1322,8 +1322,8 @@ def fix_host_limits():
sysctl_atleast(None, "net.core.netdev_max_backlog", 4 * 1024)
# Maximum read and write socket buffer sizes
- sysctl_atleast(None, "net.core.rmem_max", 16 * 2**20)
- sysctl_atleast(None, "net.core.wmem_max", 16 * 2**20)
+ sysctl_atleast(None, "net.core.rmem_max", 16 * 2 ** 20)
+ sysctl_atleast(None, "net.core.wmem_max", 16 * 2 ** 20)
# Garbage Collection Settings for ARP and Neighbors
sysctl_atleast(None, "net.ipv4.neigh.default.gc_thresh2", 4 * 1024)
@@ -1426,6 +1426,7 @@ class Router(Node):
"snmpd": 0,
"mgmtd": 0,
"snmptrapd": 0,
+ "fpm_listener": 0,
}
self.daemons_options = {"zebra": ""}
self.reportCores = True
@@ -1896,7 +1897,11 @@ class Router(Node):
)
rediropt = " > {0}.out 2> {0}.err".format(daemon)
- if daemon == "snmpd":
+ if daemon == "fpm_listener":
+ binary = "/usr/lib/frr/fpm_listener"
+ cmdenv = ""
+ cmdopt = "-d {}".format(daemon_opts)
+ elif daemon == "snmpd":
binary = "/usr/sbin/snmpd"
cmdenv = ""
cmdopt = "{} -C -c /etc/frr/snmpd.conf -p ".format(
@@ -2162,7 +2167,11 @@ class Router(Node):
"%s: %s %s started with rr", self, self.routertype, daemon
)
else:
- if daemon != "snmpd" and daemon != "snmptrapd":
+ if (
+ daemon != "snmpd"
+ and daemon != "snmptrapd"
+ and daemon != "fpm_listener"
+ ):
cmdopt += " -d "
cmdopt += rediropt
@@ -2212,6 +2221,11 @@ class Router(Node):
while "snmpd" in daemons_list:
daemons_list.remove("snmpd")
+ if "fpm_listener" in daemons_list:
+ start_daemon("fpm_listener")
+ while "fpm_listener" in daemons_list:
+ daemons_list.remove("fpm_listener")
+
# Now start all the other daemons
for daemon in daemons_list:
if self.daemons[daemon] == 0:
@@ -2407,6 +2421,8 @@ class Router(Node):
continue
if daemon == "snmptrapd":
continue
+ if daemon == "fpm_listener":
+ continue
if (self.daemons[daemon] == 1) and not (daemon in daemonsRunning):
sys.stderr.write("%s: Daemon %s not running\n" % (self.name, daemon))
if daemon == "staticd":
diff --git a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json
index f04e3a55e1..04591b6e29 100644
--- a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json
+++ b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json
@@ -14,7 +14,8 @@
"frr-zebra:zebra": {
"state": {
"up-count": 0,
- "down-count": 0
+ "down-count": 0,
+ "zif-type": "zif-veth"
}
}
}
diff --git a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json
index 84ad82c058..c770db49b1 100644
--- a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json
+++ b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json
@@ -25,7 +25,8 @@
},
"state": {
"up-count": 0,
- "down-count": 0
+ "down-count": 0,
+ "zif-type": "zif-veth"
}
}
}
diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini
index 98fcfbc848..db806fed39 100644
--- a/tests/topotests/pytest.ini
+++ b/tests/topotests/pytest.ini
@@ -43,6 +43,7 @@ markers =
bfdd: Tests that run against BFDD
bgpd: Tests that run against BGPD
eigrpd: Tests that run against EIGRPD
+ fpm: Tests that run against the FPM
isisd: Tests that run against ISISD
ldpd: Tests that run against LDPD
mgmtd: Tests that run against MGMTD