]>
Commit | Line | Data |
---|---|---|
7ea16cb0 | 1 | #!/usr/bin/env python |
acddc0ed | 2 | # SPDX-License-Identifier: ISC |
7ea16cb0 DA |
3 | |
4 | # | |
5 | # test_bgp_reject_as_sets.py | |
6 | # Part of NetDEF Topology Tests | |
7 | # | |
8 | # Copyright (c) 2019 by | |
9 | # Donatas Abraitis <donatas.abraitis@gmail.com> | |
10 | # | |
7ea16cb0 DA |
11 | |
12 | """ | |
13 | Test if an aggregated route with AS_SET is not sent to peers. | |
14 | Addressing draft-ietf-idr-deprecate-as-set-confed-set recommendations. | |
15 | ||
16 | BGP speakers conforming to this document (i.e., conformant BGP | |
17 | speakers) MUST NOT locally generate BGP UPDATE messages containing | |
18 | AS_SET or AS_CONFED_SET. Conformant BGP speakers SHOULD NOT send BGP | |
19 | UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of | |
20 | such messages, conformant BGP speakers SHOULD use the "Treat-as- | |
21 | withdraw" error handling behavior as per [RFC7606]. | |
22 | """ | |
23 | ||
24 | import os | |
25 | import sys | |
26 | import json | |
7ea16cb0 DA |
27 | import pytest |
28 | import functools | |
29 | ||
30 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
787e7624 | 31 | sys.path.append(os.path.join(CWD, "../")) |
7ea16cb0 DA |
32 | |
33 | # pylint: disable=C0413 | |
34 | from lib import topotest | |
35 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
7ea16cb0 | 36 | |
bf3a0a9a DS |
37 | pytestmark = [pytest.mark.bgpd] |
38 | ||
787e7624 | 39 | |
e82b531d CH |
40 | def build_topo(tgen): |
41 | for routern in range(1, 4): | |
42 | tgen.add_router("r{}".format(routern)) | |
7ea16cb0 | 43 | |
e82b531d CH |
44 | switch = tgen.add_switch("s1") |
45 | switch.add_link(tgen.gears["r1"]) | |
46 | switch.add_link(tgen.gears["r2"]) | |
787e7624 | 47 | |
e82b531d CH |
48 | switch = tgen.add_switch("s2") |
49 | switch.add_link(tgen.gears["r2"]) | |
50 | switch.add_link(tgen.gears["r3"]) | |
7ea16cb0 | 51 | |
7ea16cb0 DA |
52 | |
53 | def setup_module(mod): | |
e82b531d | 54 | tgen = Topogen(build_topo, mod.__name__) |
7ea16cb0 DA |
55 | tgen.start_topology() |
56 | ||
57 | router_list = tgen.routers() | |
58 | ||
e5f0ed14 | 59 | for i, (rname, router) in enumerate(router_list.items(), 1): |
7ea16cb0 | 60 | router.load_config( |
787e7624 | 61 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) |
7ea16cb0 DA |
62 | ) |
63 | router.load_config( | |
787e7624 | 64 | TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) |
7ea16cb0 DA |
65 | ) |
66 | ||
67 | tgen.start_router() | |
68 | ||
787e7624 | 69 | |
7ea16cb0 DA |
70 | def teardown_module(mod): |
71 | tgen = get_topogen() | |
72 | tgen.stop_topology() | |
73 | ||
787e7624 | 74 | |
7ea16cb0 DA |
75 | def test_bgp_reject_as_sets(): |
76 | tgen = get_topogen() | |
77 | ||
78 | if tgen.routers_have_failure(): | |
79 | pytest.skip(tgen.errors) | |
80 | ||
787e7624 | 81 | router = tgen.gears["r2"] |
7ea16cb0 DA |
82 | |
83 | def _bgp_converge(router): | |
84 | output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json")) | |
85 | expected = { | |
787e7624 | 86 | "192.168.255.2": { |
87 | "bgpState": "Established", | |
88 | "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}}, | |
7ea16cb0 DA |
89 | } |
90 | } | |
91 | return topotest.json_cmp(output, expected) | |
92 | ||
93 | def _bgp_has_aggregated_route_with_stripped_as_set(router): | |
94 | output = json.loads(router.vtysh_cmd("show ip bgp 172.16.0.0/16 json")) | |
95 | expected = { | |
787e7624 | 96 | "paths": [{"aspath": {"string": "Local", "segments": [], "length": 0}}] |
7ea16cb0 DA |
97 | } |
98 | return topotest.json_cmp(output, expected) | |
99 | ||
100 | def _bgp_announce_route_without_as_sets(router): | |
787e7624 | 101 | output = json.loads( |
102 | router.vtysh_cmd( | |
103 | "show ip bgp neighbor 192.168.254.2 advertised-routes json" | |
104 | ) | |
105 | ) | |
7ea16cb0 | 106 | expected = { |
787e7624 | 107 | "advertisedRoutes": { |
108 | "172.16.0.0/16": {"path": ""}, | |
109 | "192.168.254.0/30": {"path": "65003"}, | |
110 | "192.168.255.0/30": {"path": "65001"}, | |
7ea16cb0 | 111 | }, |
787e7624 | 112 | "totalPrefixCounter": 3, |
7ea16cb0 DA |
113 | } |
114 | return topotest.json_cmp(output, expected) | |
115 | ||
116 | test_func = functools.partial(_bgp_converge, router) | |
117 | success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) | |
118 | ||
119 | assert result is None, 'Failed bgp convergence in "{}"'.format(router) | |
120 | ||
787e7624 | 121 | test_func = functools.partial( |
122 | _bgp_has_aggregated_route_with_stripped_as_set, router | |
123 | ) | |
7ea16cb0 DA |
124 | success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) |
125 | ||
126 | assert result is None, 'Failed to see an aggregated route in "{}"'.format(router) | |
127 | ||
128 | test_func = functools.partial(_bgp_announce_route_without_as_sets, router) | |
129 | success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) | |
130 | ||
787e7624 | 131 | assert ( |
132 | result is None | |
133 | ), 'Route 172.16.0.0/16 should be sent without AS_SET to r3 "{}"'.format(router) | |
134 | ||
7ea16cb0 | 135 | |
787e7624 | 136 | if __name__ == "__main__": |
7ea16cb0 DA |
137 | args = ["-s"] + sys.argv[1:] |
138 | sys.exit(pytest.main(args)) |