topotests: add bgp_asdot_regex test

This test ensures that the regex used to filter as paths has to
be expressed in the asnotation of the BGP instance where prefixes
are received. 2 aspaths have been forged, both for AS 65540, but
only the former is expressed in asdot. If the local BGP instance
is expressed in asdot format, then only the former ASPATH will
match properly the incoming update. Reversely, when the local BGP
instance is expressed in plain format, then only the latter ASPATH
will match properly the incoming update.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2022-11-28 10:13:07 +01:00
parent 6ccfd1030b
commit 8650fef03e
8 changed files with 347 additions and 0 deletions

View file

@ -0,0 +1,27 @@
router bgp 1.1
no bgp ebgp-requires-policy
no bgp network import-check
neighbor 192.168.255.2 remote-as 1.2
address-family ipv4 unicast
network 172.31.1.0/24 route-map rmapout
network 172.31.2.0/24 route-map rmapout
neighbor 192.168.255.2 route-map rmapin in
neighbor 192.168.255.2 activate
exit-address-family
exit
bgp as-path access-list only1_4 permit _1.4_
bgp as-path access-list only65540 permit _65540_
access-list 172313 permit 172.31.3.0/24
access-list 172314 permit 172.31.4.0/24
route-map rmapout permit 1
set as-path prepend 1.4
exit
route-map rmapin permit 1
match ip address 172313
match as-path only1_4
exit
route-map rmapin permit 2
match ip address 172314
match as-path only65540
exit

View file

@ -0,0 +1,80 @@
{
"vrfId": 0,
"vrfName": "default",
"tableVersion": 3,
"routerId": "192.168.255.1",
"defaultLocPrf": 100,
"localAS": "1.1",
"routes": { "172.31.1.0/24": [
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"172.31.1.0",
"prefixLen":24,
"network":"172.31.1.0/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"1.4",
"origin":"IGP",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
,"172.31.2.0/24": [
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"172.31.2.0",
"prefixLen":24,
"network":"172.31.2.0/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"1.4",
"origin":"IGP",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
,"172.31.3.0/24": [
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"172.31.3.0",
"prefixLen":24,
"network":"172.31.3.0/24",
"metric":0,
"weight":0,
"peerId":"192.168.255.2",
"path":"1.2 1.4",
"origin":"IGP",
"nexthops":[
{
"ip":"192.168.255.2",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
} }

View file

@ -0,0 +1,6 @@
!
interface r1-eth0
ip address 192.168.255.1/24
!
ip forwarding
!

View file

@ -0,0 +1,26 @@
router bgp 65538
no bgp ebgp-requires-policy
no bgp network import-check
neighbor 192.168.255.1 remote-as 65537
address-family ipv4 unicast
network 172.31.3.0/24 route-map rmapout
network 172.31.4.0/24 route-map rmapout
neighbor 192.168.255.1 route-map rmapin in
neighbor 192.168.255.1 activate
exit-address-family
exit
bgp as-path access-list only65540 permit _65540_
bgp as-path access-list only1_4 permit _1.4_
access-list 172311 permit 172.31.1.0/24
access-list 172312 permit 172.31.2.0/24
route-map rmapout permit 1
set as-path prepend 65540
exit
route-map rmapin permit 1
match ip address 172311
match as-path only65540
exit
route-map rmapin permit 2
match ip address 172312
match as-path only1_4
exit

View file

@ -0,0 +1,80 @@
{
"vrfId": 0,
"vrfName": "default",
"tableVersion": 3,
"routerId": "192.168.255.2",
"defaultLocPrf": 100,
"localAS": 65538,
"routes": { "172.31.1.0/24": [
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"172.31.1.0",
"prefixLen":24,
"network":"172.31.1.0/24",
"metric":0,
"weight":0,
"peerId":"192.168.255.1",
"path":"65537 65540",
"origin":"IGP",
"nexthops":[
{
"ip":"192.168.255.1",
"hostname":"r1",
"afi":"ipv4",
"used":true
}
]
}
]
,"172.31.3.0/24": [
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"172.31.3.0",
"prefixLen":24,
"network":"172.31.3.0/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"65540",
"origin":"IGP",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
,"172.31.4.0/24": [
{
"valid":true,
"bestpath":true,
"selectionReason":"First path received",
"pathFrom":"external",
"prefix":"172.31.4.0",
"prefixLen":24,
"network":"172.31.4.0/24",
"metric":0,
"weight":32768,
"peerId":"(unspec)",
"path":"65540",
"origin":"IGP",
"nexthops":[
{
"ip":"0.0.0.0",
"hostname":"r2",
"afi":"ipv4",
"used":true
}
]
}
]
} }

View file

@ -0,0 +1,6 @@
!
interface r2-eth0
ip address 192.168.255.2/24
!
ip forwarding
!

View file

@ -0,0 +1,122 @@
#!/usr/bin/env python
#
# test_bgp_asdot_regex.py
# Part of Topotests
#
# Copyright 2022 6WIND S.A.
#
# Permission to use, copy, modify, and/or distribute this software
# for any purpose with or without fee is hereby granted, provided
# that the above copyright notice and this permission notice appear
# in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
# OF THIS SOFTWARE.
#
"""
test_bgp_asdot_regex.py:
Test how regex applies when asnotation to forge bgp config is based on dot or not.
"""
import os
import sys
import json
import pytest
from functools import partial
# add after imports, before defining classes or functions:
pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
for routern in range(1, 3):
tgen.add_router("r{}".format(routern))
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
switch.add_link(tgen.gears["r2"])
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
for i, (rname, router) in enumerate(router_list.items(), 1):
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
router.load_config(
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
)
tgen.start_router()
def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()
def test_bgp_asdot_regex():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
router1 = tgen.gears["r1"]
router2 = tgen.gears["r2"]
def _bgp_converge(router):
output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json"))
expected = {
"192.168.255.2": {
"bgpState": "Established",
"addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 1}},
}
}
return topotest.json_cmp(output, expected)
logger.info("Check if neighbor sessions are up in {}".format(router1.name))
test_func = partial(_bgp_converge, router1)
success, result = topotest.run_and_expect(test_func, None, count=15, wait=0.5)
assert result is None, 'Failed to see BGP convergence in "{}"'.format(router1.name)
logger.info("BGP neighbor session is up in {}".format(router1.name))
logger.info("waiting for bgp peers exchanging UPDATES")
for router in tgen.routers().values():
ref_file = "{}/{}/show_bgp_ipv4.json".format(CWD, router.name)
expected = json.loads(open(ref_file).read())
test_func = partial(
topotest.router_json_cmp, router, "show bgp ipv4 unicast json", expected
)
_, res = topotest.run_and_expect(test_func, None, count=40, wait=2.5)
assertmsg = "{}: BGP UPDATE exchange failure".format(router.name)
assert res is None, assertmsg
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))