Skip to content

Commit

Permalink
Merge pull request #17306 from pguibert6WIND/bmp_test_factorise_plus_fix
Browse files Browse the repository at this point in the history
BMP test rework
  • Loading branch information
riw777 authored Dec 3, 2024
2 parents ee5a345 + d1301f1 commit 6e1eeed
Show file tree
Hide file tree
Showing 28 changed files with 885 additions and 936 deletions.
233 changes: 233 additions & 0 deletions tests/topotests/bgp_bmp/bgpbmp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
#!/usr/bin/env python
# SPDX-License-Identifier: GPL-2.0-or-later

# Copyright 2023, 6wind
import json
import os

from lib import topotest
from lib.topogen import get_topogen
from lib.topolog import logger

# remember the last sequence number of the logging messages
SEQ = 0


def bmp_reset_seq():
global SEQ
SEQ = 0


def get_bmp_messages(bmp_collector, bmp_log_file):
"""
Read the BMP logging messages.
"""
messages = []
text_output = bmp_collector.run(f"cat {bmp_log_file}")

for m in text_output.splitlines():
# some output in the bash can break the message decoding
try:
messages.append(json.loads(m))
except Exception as e:
logger.warning(str(e) + " message: {}".format(str(m)))
continue

if not messages:
logger.error("Bad BMP log format, check your BMP server")

return messages


def bmp_update_seq(bmp_collector, bmp_log_file):
global SEQ

messages = get_bmp_messages(bmp_collector, bmp_log_file)

if len(messages):
SEQ = messages[-1]["seq"]


def bmp_update_expected_files(
bmp_actual,
expected_prefixes,
bmp_log_type,
policy,
step,
bmp_client,
bmp_log_folder,
):
tgen = get_topogen()

with open(
f"{bmp_log_folder}/tmp/bmp-{bmp_log_type}-{policy}-step{step}.json", "w"
) as json_file:
json.dump(bmp_actual, json_file, indent=4)

out = bmp_client.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 {bmp_log_folder}/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"{bmp_log_folder}/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"{bmp_log_folder}/tmp/show-bgp-ipv6-{bmp_log_type}-step{step}.json", "w"
) as json_file:
json.dump(filtered_out, json_file, indent=4)


def bmp_check_for_prefixes(
expected_prefixes,
bmp_log_type,
policy,
step,
bmp_collector,
bmp_log_folder,
bmp_client,
expected_json_path,
update_expected_json,
loc_rib,
):
"""
Check for the presence of the given prefixes in the BMP server logs with
the given message type and the set policy.
"""
global SEQ

bmp_log_file = f"{bmp_log_folder}/bmp.log"
# we care only about the new messages
messages = [
m
for m in sorted(
get_bmp_messages(bmp_collector, bmp_log_file), key=lambda d: d["seq"]
)
if m["seq"] > SEQ
]

# 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

ref_file = f"{expected_json_path}/bmp-{bmp_log_type}-{policy}-step{step}.json"
expected = json.loads(open(ref_file).read())

# 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)
):
bmp_update_expected_files(
actual,
expected_prefixes,
bmp_log_type,
policy,
step,
bmp_client,
bmp_log_folder,
)

return topotest.json_cmp(actual, expected, exact=True)


def bmp_check_for_peer_message(
expected_peers, bmp_log_type, bmp_collector, bmp_log_file
):
"""
Check for the presence of a peer up message for the peer
"""
global SEQ

# we care only about the new messages
messages = [
m
for m in sorted(
get_bmp_messages(bmp_collector, bmp_log_file), key=lambda d: d["seq"]
)
if m["seq"] > SEQ
]

# get the list of pairs (prefix, policy, seq) for the given message type
peers = [
m["peer_ip"]
for m in messages
if "peer_ip" in m.keys() and m["bmp_log_type"] == bmp_log_type
]

# check for prefixes
for ep in expected_peers:
if ep not in peers:
msg = "The peer {} is not present in the {} log messages."
logger.debug(msg.format(ep, bmp_log_type))
return False

SEQ = messages[-1]["seq"]
return True
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
interface r1-eth0
ip address 192.0.2.1/24
!
interface r1-eth1
ip address 192.168.0.1/24
ipv6 address 192:168::1/64
!
router bgp 65501
bgp router-id 192.168.0.1
bgp log-neighbor-changes
Expand Down Expand Up @@ -41,7 +48,7 @@ router bgp 65501
exit-address-family
!
router bgp 65501 vrf vrf1
bgp router_id 192.168.0.1
bgp router-id 192.168.0.1
bgp log-neighbor-changes
address-family ipv4 unicast
label vpn export 101
Expand Down
7 changes: 0 additions & 7 deletions tests/topotests/bgp_bmp/r1/zebra.conf

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
interface r1vrf-eth0
ip address 192.0.2.1/24
!
interface r1vrf-eth1
ip address 192.168.0.1/24
ipv6 address 192:168::1/64
!
router bgp 65501 vrf vrf1
bgp router-id 192.168.0.1
bgp log-neighbor-changes
Expand All @@ -15,7 +22,6 @@ router bgp 65501 vrf vrf1
bmp monitor ipv6 unicast loc-rib
exit
!

address-family ipv4 unicast
neighbor 192.168.0.2 activate
neighbor 192.168.0.2 soft-reconfiguration inbound
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"nexthops": [
{
"ip": "192.168.0.2",
"hostname": "r2",
"afi": "ipv4",
"used": true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@
"nexthops": [
{
"ip": "192:168::2",
"hostname": "r2",
"afi": "ipv6",
"scope": "global"
},
{
"hostname": "r2",
"afi": "ipv6",
"scope": "link-local",
"used": true
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
interface r2-eth0
ip address 192.168.0.2/24
ipv6 address 192:168::2/64
!
interface r2-eth1
ip address 172.31.0.2/24
ipv6 address 172:31::2/64
!
router bgp 65502
bgp router-id 192.168.0.2
bgp log-neighbor-changes
Expand Down
8 changes: 0 additions & 8 deletions tests/topotests/bgp_bmp/r2/zebra.conf

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
interface r2vrf-eth0
ip address 192.168.0.2/24
ipv6 address 192:168::2/64
!
interface r2vrf-eth1
ip address 172.31.0.2/24
ipv6 address 172:31::2/64
!
router bgp 65502
bgp router-id 192.168.0.2
bgp log-neighbor-changes
Expand Down
Loading

0 comments on commit 6e1eeed

Please sign in to comment.