]>
Commit | Line | Data |
---|---|---|
2c61dd73 | 1 | #!/usr/bin/env python |
acddc0ed | 2 | # SPDX-License-Identifier: ISC |
2c61dd73 DA |
3 | |
4 | # | |
5 | # Copyright (c) 2022 by | |
6 | # Donatas Abraitis <donatas@opensourcerouting.org> | |
7 | # | |
2c61dd73 DA |
8 | |
9 | """ | |
10 | Test if BGP SoO per neighbor works correctly. Routes having SoO | |
11 | extended community MUST be rejected if the neighbor is configured | |
12 | with soo (neighbor soo). | |
13 | """ | |
14 | ||
15 | import os | |
16 | import sys | |
17 | import json | |
18 | import pytest | |
19 | import functools | |
20 | ||
21 | CWD = os.path.dirname(os.path.realpath(__file__)) | |
22 | sys.path.append(os.path.join(CWD, "../")) | |
23 | ||
24 | # pylint: disable=C0413 | |
25 | from lib import topotest | |
26 | from lib.topogen import Topogen, TopoRouter, get_topogen | |
27 | from lib.common_config import step | |
28 | ||
29 | pytestmark = [pytest.mark.bgpd] | |
30 | ||
31 | ||
32 | def build_topo(tgen): | |
33 | tgen.add_router("cpe1") | |
34 | tgen.add_router("cpe2") | |
35 | tgen.add_router("pe1") | |
36 | tgen.add_router("pe2") | |
37 | ||
38 | switch = tgen.add_switch("s1") | |
39 | switch.add_link(tgen.gears["cpe1"]) | |
40 | switch.add_link(tgen.gears["pe1"]) | |
41 | ||
42 | switch = tgen.add_switch("s2") | |
43 | switch.add_link(tgen.gears["pe1"]) | |
44 | switch.add_link(tgen.gears["pe2"]) | |
45 | ||
46 | switch = tgen.add_switch("s3") | |
47 | switch.add_link(tgen.gears["pe2"]) | |
48 | switch.add_link(tgen.gears["cpe2"]) | |
49 | ||
50 | switch = tgen.add_switch("s4") | |
51 | switch.add_link(tgen.gears["cpe2"]) | |
52 | switch.add_link(tgen.gears["cpe1"]) | |
53 | ||
54 | ||
55 | def setup_module(mod): | |
56 | tgen = Topogen(build_topo, mod.__name__) | |
57 | tgen.start_topology() | |
58 | ||
59 | pe1 = tgen.gears["pe1"] | |
60 | pe2 = tgen.gears["pe2"] | |
61 | ||
62 | pe1.run("ip link add RED type vrf table 1001") | |
63 | pe1.run("ip link set up dev RED") | |
64 | pe2.run("ip link add RED type vrf table 1001") | |
65 | pe2.run("ip link set up dev RED") | |
66 | pe1.run("ip link set pe1-eth0 master RED") | |
67 | pe2.run("ip link set pe2-eth1 master RED") | |
68 | ||
69 | pe1.run("sysctl -w net.ipv4.ip_forward=1") | |
70 | pe2.run("sysctl -w net.ipv4.ip_forward=1") | |
71 | pe1.run("sysctl -w net.mpls.conf.pe1-eth0.input=1") | |
72 | pe2.run("sysctl -w net.mpls.conf.pe2-eth1.input=1") | |
73 | ||
74 | router_list = tgen.routers() | |
75 | ||
76 | for i, (rname, router) in enumerate(router_list.items(), 1): | |
77 | router.load_config( | |
78 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) | |
79 | ) | |
80 | router.load_config( | |
81 | TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) | |
82 | ) | |
83 | router.load_config( | |
84 | TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname)) | |
85 | ) | |
86 | router.load_config( | |
87 | TopoRouter.RD_LDP, os.path.join(CWD, "{}/ldpd.conf".format(rname)) | |
88 | ) | |
89 | ||
90 | tgen.start_router() | |
91 | ||
92 | ||
93 | def teardown_module(mod): | |
94 | tgen = get_topogen() | |
95 | tgen.stop_topology() | |
96 | ||
97 | ||
98 | def test_bgp_soo(): | |
99 | tgen = get_topogen() | |
100 | ||
101 | pe2 = tgen.gears["pe2"] | |
102 | ||
103 | if tgen.routers_have_failure(): | |
104 | pytest.skip(tgen.errors) | |
105 | ||
106 | def _bgp_soo_unconfigured(): | |
107 | output = json.loads( | |
108 | pe2.vtysh_cmd( | |
109 | "show bgp vrf RED ipv4 unicast neighbors 192.168.2.1 advertised-routes json" | |
110 | ) | |
111 | ) | |
112 | expected = {"advertisedRoutes": {"172.16.255.1/32": {"path": "65001"}}} | |
113 | return topotest.json_cmp(output, expected) | |
114 | ||
115 | test_func = functools.partial(_bgp_soo_unconfigured) | |
116 | _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5) | |
117 | assert result is None, "Failed to see BGP convergence in pe2" | |
118 | ||
119 | step("Configure SoO (65000:1) for PE2 -- CPE2 session") | |
120 | pe2.vtysh_cmd( | |
121 | """ | |
122 | configure terminal | |
123 | router bgp 65001 vrf RED | |
124 | address-family ipv4 unicast | |
125 | neighbor 192.168.2.1 soo 65000:1 | |
126 | """ | |
127 | ) | |
128 | ||
129 | def _bgp_soo_configured(): | |
130 | output = json.loads( | |
131 | pe2.vtysh_cmd( | |
132 | "show bgp vrf RED ipv4 unicast neighbors 192.168.2.1 advertised-routes json" | |
133 | ) | |
134 | ) | |
135 | expected = {"advertisedRoutes": {"172.16.255.1/32": None}} | |
136 | return topotest.json_cmp(output, expected) | |
137 | ||
138 | test_func = functools.partial(_bgp_soo_configured) | |
139 | _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5) | |
140 | assert result is None, "SoO filtering does not work from pe2" | |
141 | ||
142 | step("Configure SoO (65000:2) for PE2 -- CPE2 session") | |
143 | pe2.vtysh_cmd( | |
144 | """ | |
145 | configure terminal | |
146 | router bgp 65001 vrf RED | |
147 | address-family ipv4 unicast | |
148 | neighbor 192.168.2.1 soo 65000:2 | |
149 | """ | |
150 | ) | |
151 | ||
152 | test_func = functools.partial(_bgp_soo_unconfigured) | |
153 | _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5) | |
154 | assert result is None, "SoO filtering does not work from pe2" | |
155 | ||
156 | step("Unconfigure SoO for PE2 -- CPE2 session") | |
157 | pe2.vtysh_cmd( | |
158 | """ | |
159 | configure terminal | |
160 | router bgp 65001 vrf RED | |
161 | address-family ipv4 unicast | |
162 | no neighbor 192.168.2.1 soo | |
163 | """ | |
164 | ) | |
165 | ||
166 | test_func = functools.partial(_bgp_soo_unconfigured) | |
167 | _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5) | |
168 | assert result is None, "SoO filtering does not work from pe2" | |
169 | ||
170 | ||
171 | if __name__ == "__main__": | |
172 | args = ["-s"] + sys.argv[1:] | |
173 | sys.exit(pytest.main(args)) |