"1:10": {
"192.168.1.0/24": [
{
- "selectionReason": "First path received",
+ "multipath": true,
"pathFrom": "external",
"prefix": "192.168.1.0",
"prefixLen": 24,
],
"192.168.3.0/24": [
{
- "selectionReason": "First path received",
+ "multipath": true,
"pathFrom": "external",
"prefix": "192.168.3.0",
"prefixLen": 24,
"1:20": {
"192.168.5.0/24": [
{
- "selectionReason": "First path received",
+ "multipath": true,
"pathFrom": "external",
"prefix": "192.168.5.0",
"prefixLen": 24,
]
}
]
+ },
+ "2:10": {
+ "192.168.2.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "192.168.2.0",
+ "prefixLen": 24,
+ "network": "192.168.2.0/24",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::2",
+ "path": "2",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::2",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "2:20": {
+ "192.168.4.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "192.168.4.0",
+ "prefixLen": 24,
+ "network": "192.168.4.0/24",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::2",
+ "path": "2",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::2",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.6.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "192.168.6.0",
+ "prefixLen": 24,
+ "network": "192.168.6.0/24",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "2001::2",
+ "path": "2",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "2001::2",
+ "hostname": "r2",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
}
}
}
"localAS": 1,
"routes": {
"routeDistinguishers": {
+ "1:10": {
+ "192.168.1.0/24": [
+ {
+ "multipath": true,
+ "pathFrom": "external",
+ "prefix": "192.168.1.0",
+ "prefixLen": 24,
+ "network": "192.168.1.0/24",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "2001::1",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.3.0/24": [
+ {
+ "multipath": true,
+ "pathFrom": "external",
+ "prefix": "192.168.3.0",
+ "prefixLen": 24,
+ "network": "192.168.3.0/24",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "2001::1",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
"1:20": {
"192.168.5.0/24": [
{
"1:10": {
"2001:1::/64": [
{
+ "multipath": true,
"pathFrom": "external",
"prefix": "2001:1::",
"prefixLen": 64,
],
"2001:3::/64": [
{
+ "multipath": true,
"pathFrom": "external",
"prefix": "2001:3::",
"prefixLen": 64,
"1:20": {
"2001:5::/64": [
{
+ "multipath": true,
"pathFrom": "external",
"prefix": "2001:5::",
"prefixLen": 64,
}
],
"2001:6::/64": [
- {
+ {
"valid": true,
"bestpath": true,
"selectionReason": "First path received",
"localAS": 1,
"routes": {
"routeDistinguishers": {
+ "1:10": {
+ "2001:1::/64": [
+ {
+ "multipath": true,
+ "pathFrom": "external",
+ "prefix": "2001:1::",
+ "prefixLen": 64,
+ "network": "2001:1::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "multipath": true,
+ "pathFrom": "external",
+ "prefix": "2001:3::",
+ "prefixLen": 64,
+ "network": "2001:3::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
"1:20": {
"2001:5::/64": [
{
]
}
}
- },
- "totalRoutes": 3,
- "totalPaths": 3
+ }
}
]
}
}
- },
- "totalRoutes": 3,
- "totalPaths": 3
+ }
}
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib import topotest
+from lib.bgp import bgp_vpn_router_json_cmp_exact_filter
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.common_config import required_linux_kernel_version
assert False, "Could not read file {}".format(filename)
-def check_rib(name, cmd, expected_file, count=30, wait=0.5):
- def _check(name, dest_addr, match):
+def check_rib(name, cmd, expected_file, count=10, wait=0.5):
+ def _check(router, cmd, expected):
logger.info("polling")
tgen = get_topogen()
- router = tgen.gears[name]
output = json.loads(router.vtysh_cmd(cmd))
- expected = open_json_file("{}/{}".format(CWD, expected_file))
return topotest.json_cmp(output, expected)
logger.info('[+] check {} "{}" {}'.format(name, cmd, expected_file))
tgen = get_topogen()
- func = functools.partial(_check, name, cmd, expected_file)
+ router = tgen.gears[name]
+ expected = open_json_file("{}/{}".format(CWD, expected_file))
+ if "show bgp" in cmd and "vpn" in cmd:
+ func = functools.partial(
+ bgp_vpn_router_json_cmp_exact_filter, tgen.gears[name], cmd, expected
+ )
+ else:
+ func = functools.partial(_check, router, cmd, expected)
_, result = topotest.run_and_expect(func, None, count, wait)
assert result is None, "Failed"
def test_rib():
- check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib.json", 120, 1)
+ check_rib("r1", "show bgp ipv4 vpn json", "r1/vpnv4_rib.json", 10, 1)
check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib.json")
check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10v4_rib.json")
check_rib("r1", "show ip route vrf vrf20 json", "r1/vrf20v4_rib.json")
# ("NetDEF") in this file.
#
+import json
import ipaddress
import sys
import traceback
]
logger.debug(f"setting prefix: ipv{ip.version} {safi} {ip}")
router.vtysh_cmd("".join(cmd))
+
+
+# compare exact fields of 'show bgp ipv4 vpn' and related commands
+# after having removed some attributes that are not relevant.
+def bgp_vpn_router_json_cmp_exact_filter(router, cmd, expected):
+ output = router.vtysh_cmd(cmd)
+ logger.info("{}: {}\n{}".format(router.name, cmd, output))
+
+ json_output = json.loads(output)
+
+ # filter out tableVersion, version and nhVrfID
+ json_output.pop("tableVersion")
+ if "totalRoutes" in json_output:
+ json_output.pop("totalRoutes")
+ if "totalPaths" in json_output:
+ json_output.pop("totalPaths")
+ for rd, data in json_output["routes"]["routeDistinguishers"].items():
+ for _, attrs in data.items():
+ for attr in attrs:
+ if "nhVrfId" in attr:
+ attr.pop("nhVrfId")
+ if "version" in attr:
+ attr.pop("version")
+
+ # filter out RD with no data (e.g. "444:3": {})
+ json_tmp = deepcopy(json_output)
+ for rd, data in json_tmp["routes"]["routeDistinguishers"].items():
+ if len(data.keys()) == 0:
+ json_output["routes"]["routeDistinguishers"].pop(rd)
+
+ return topotest.json_cmp(json_output, expected, exact=True)