github.com/osrg/gobgp/v3@v3.30.0/test/scenario_test/bgp_zebra_test.py (about) 1 # Copyright (C) 2015 Nippon Telegraph and Telephone Corporation. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 # implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 16 17 import sys 18 import time 19 import unittest 20 21 import collections 22 collections.Callable = collections.abc.Callable 23 24 import nose 25 26 from lib.noseplugin import OptionParser, parser_option 27 28 from lib import base 29 from lib.base import ( 30 Bridge, 31 BGP_FSM_ESTABLISHED, 32 local, 33 ) 34 from lib.gobgp import GoBGPContainer 35 from lib.quagga import QuaggaBGPContainer 36 37 38 class GoBGPTestBase(unittest.TestCase): 39 # The same topology for IPv4 and IPv6 environment. 40 # o1: Quagga (not router) 41 # g1: GoBGP 42 # q1: Quagga (Zebra + BGPd) 43 # o2: Quagga (not router) 44 # 45 # +----+ +----+ +----+ +----+ 46 # | o1 | | g1 |===(BGP)===| q1 | | o2 | 47 # +----+ +----+ +----+ +----+ 48 # | | | | | | 49 # +--(br01)--+ +---(br02)----+ +--(br03)--+ 50 51 @classmethod 52 def setUpClass(cls): 53 gobgp_ctn_image_name = parser_option.gobgp_image 54 base.TEST_PREFIX = parser_option.test_prefix 55 56 # preparing the container for ipv4 57 g1_v4 = GoBGPContainer(name='g1_v4', asn=65000, router_id='192.168.0.1', 58 ctn_image_name=gobgp_ctn_image_name, 59 log_level=parser_option.gobgp_log_level, 60 zebra=True) 61 q1_v4 = QuaggaBGPContainer(name='q1_v4', asn=65001, router_id='192.168.0.2', zebra=True) 62 o1_v4 = QuaggaBGPContainer(name='o1_v4', asn=65002, router_id='192.168.0.3') 63 o2_v4 = QuaggaBGPContainer(name='o2_v4', asn=65002, router_id='192.168.0.4') 64 65 # preparing the container for ipv6 66 g1_v6 = GoBGPContainer(name='g1_v6', asn=65000, router_id='192.168.0.1', 67 ctn_image_name=gobgp_ctn_image_name, 68 log_level=parser_option.gobgp_log_level, 69 zebra=True) 70 q1_v6 = QuaggaBGPContainer(name='q1_v6', asn=65001, router_id='192.168.0.2', zebra=True) 71 o1_v6 = QuaggaBGPContainer(name='o1_v6', asn=65002, router_id='192.168.0.3') 72 o2_v6 = QuaggaBGPContainer(name='o2_v6', asn=65002, router_id='192.168.0.4') 73 74 # preparing the bridge for ipv4 75 br01_v4 = Bridge(name='br01_v4', subnet='192.168.10.0/24') 76 br02_v4 = Bridge(name='br02_v4', subnet='192.168.20.0/24') 77 br03_v4 = Bridge(name='br03_v4', subnet='192.168.30.0/24') 78 79 # preparing the bridge for ipv6 80 br01_v6 = Bridge(name='br01_v6', subnet='2001:10::/32') 81 br02_v6 = Bridge(name='br02_v6', subnet='2001:20::/32') 82 br03_v6 = Bridge(name='br03_v6', subnet='2001:30::/32') 83 84 cls.ctns = { 85 'ipv4': [g1_v4, q1_v4, o1_v4, o2_v4], 86 'ipv6': [g1_v6, q1_v6, o1_v6, o2_v6], 87 } 88 cls.gobgps = { 89 'ipv4': g1_v4, 90 'ipv6': g1_v6, 91 } 92 cls.quaggas = { 93 'ipv4': q1_v4, 94 'ipv6': q1_v6, 95 } 96 cls.others = { 97 'ipv4': [o1_v4, o2_v4], 98 'ipv6': [o1_v6, o2_v6], 99 } 100 cls.bridges = { 101 'br01_v4': br01_v4, 102 'br02_v4': br02_v4, 103 'br03_v4': br03_v4, 104 'br01_v6': br01_v6, 105 'br02_v6': br02_v6, 106 'br03_v6': br03_v6, 107 } 108 109 """ 110 No.1 start up ipv4 containers and check state 111 each neighbor is established in ipv4 environment 112 """ 113 114 def test_01_check_neighbor_established(self): 115 g1 = self.gobgps['ipv4'] 116 q1 = self.quaggas['ipv4'] 117 o1 = self.others['ipv4'][0] 118 o2 = self.others['ipv4'][1] 119 # start up containers of ipv4 environment 120 initial_wait_time = max(ctn.run() for ctn in self.ctns['ipv4']) 121 time.sleep(initial_wait_time) 122 123 # make ipv4 bridge and set ip to each container 124 [self.bridges['br01_v4'].addif(ctn) for ctn in [o1, g1]] 125 [self.bridges['br02_v4'].addif(ctn) for ctn in [g1, q1]] 126 [self.bridges['br03_v4'].addif(ctn) for ctn in [q1, o2]] 127 128 g1.add_peer(q1, bridge=self.bridges['br02_v4'].name) 129 q1.add_peer(g1, bridge=self.bridges['br02_v4'].name) 130 131 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q1) 132 133 """ 134 No.2 check whether the ping is reachable in container 135 that have previously beyond the GoBGP in ipv4 environment 136 """ 137 138 def test_02_check_reachability_between_o1_and_o2(self): 139 g1 = self.gobgps['ipv4'] 140 q1 = self.quaggas['ipv4'] 141 o1 = self.others['ipv4'][0] 142 o2 = self.others['ipv4'][1] 143 144 # set o1's default gateway as g1 145 g1_addr = g1.ip_addrs[1][1].split('/')[0] 146 o1.add_static_route(self.bridges['br03_v4'].subnet, g1_addr) 147 148 # set o2's default gateway as q1 149 q1_addr = q1.ip_addrs[2][1].split('/')[0] 150 o2.add_static_route(self.bridges['br01_v4'].subnet, q1_addr) 151 152 # test reachability between o1 and o2 153 addrs = [e[1] for e in o2.ip_addrs if 'br03_v4' in e[2]] 154 self.assertEqual(len(addrs), 1) 155 o2_addr = addrs[0] 156 o1.get_reachability(o2_addr) 157 158 """ 159 No.4 start up ipv6 containers and check state 160 each neighbor is established in ipv6 environment 161 """ 162 163 def test_04_check_neighbor_established_v6(self): 164 g1 = self.gobgps['ipv6'] 165 q1 = self.quaggas['ipv6'] 166 o1 = self.others['ipv6'][0] 167 o2 = self.others['ipv6'][1] 168 # start up containers of ipv6 environment 169 initial_wait_time = max(ctn.run() for ctn in self.ctns['ipv6']) 170 time.sleep(initial_wait_time) 171 172 # make ipv6 bridge and set ip to each container 173 [self.bridges['br01_v6'].addif(ctn) for ctn in [o1, g1]] 174 [self.bridges['br02_v6'].addif(ctn) for ctn in [g1, q1]] 175 [self.bridges['br03_v6'].addif(ctn) for ctn in [q1, o2]] 176 177 g1.add_peer(q1, bridge=self.bridges['br02_v6'].name, v6=True) 178 q1.add_peer(g1, bridge=self.bridges['br02_v6'].name, v6=True) 179 180 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q1) 181 182 """ 183 No.5 check whether the ping is reachable in container 184 that have previously beyond the GoBGP in ipv6 environment 185 """ 186 187 def test_05_check_reachability_between_o1_and_o2(self): 188 g1 = self.gobgps['ipv6'] 189 q1 = self.quaggas['ipv6'] 190 o1 = self.others['ipv6'][0] 191 o2 = self.others['ipv6'][1] 192 193 # set o1's default gateway as g1 194 g1_addr = [a for a in g1.ip6_addrs if a[2] == self.bridges['br01_v6'].name][0][1].split('/')[0] 195 o1.add_static_route(self.bridges['br03_v6'].subnet, g1_addr) 196 197 # set o2's default gateway as q1 198 q1_addr = [a for a in q1.ip6_addrs if a[2] == self.bridges['br03_v6'].name][0][1].split('/')[0] 199 o2.add_static_route(self.bridges['br01_v6'].subnet, q1_addr) 200 201 # test reachability between o1 and o2 202 addrs = [e[1] for e in o2.ip6_addrs if 'br03_v6' in e[2]] 203 self.assertEqual(len(addrs), 1) 204 o2_addr = addrs[0] 205 o1.get_reachability(o2_addr) 206 207 def test_07_mpath_test_setup(self): 208 g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1', 209 ctn_image_name=parser_option.gobgp_image, 210 log_level=parser_option.gobgp_log_level, 211 config_format=parser_option.config_format, 212 zebra=True) 213 g2 = GoBGPContainer(name='g2', asn=65001, router_id='192.168.0.2', 214 ctn_image_name=parser_option.gobgp_image) 215 g3 = GoBGPContainer(name='g3', asn=65001, router_id='192.168.0.3', 216 ctn_image_name=parser_option.gobgp_image) 217 g4 = GoBGPContainer(name='g4', asn=65000, router_id='192.168.0.4', 218 ctn_image_name=parser_option.gobgp_image) 219 g5 = GoBGPContainer(name='g5', asn=65000, router_id='192.168.0.5', 220 ctn_image_name=parser_option.gobgp_image) 221 222 ctns = [g1, g2, g3, g4, g5] 223 for ctn in ctns: 224 self.ctns[ctn.name] = ctn 225 226 initial_wait_time = max(ctn.run() for ctn in ctns) 227 228 time.sleep(initial_wait_time) 229 230 # advertise same prefix 231 g2.add_route('10.0.10.0/24') 232 g3.add_route('10.0.10.0/24') 233 g4.add_route('10.0.10.0/24') 234 g5.add_route('10.0.10.0/24') 235 236 for g in [g2, g3, g4, g5]: 237 g1.add_peer(g) 238 g.add_peer(g1) 239 240 def test_08_mpath_test_check_neighbor_established(self): 241 g1 = self.ctns['g1'] 242 g2 = self.ctns['g2'] 243 g3 = self.ctns['g3'] 244 g4 = self.ctns['g4'] 245 g5 = self.ctns['g5'] 246 for g in [g2, g3, g4, g5]: 247 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g) 248 249 def test_09_mpath_test_check_mpath_injected(self): 250 g1 = self.ctns['g1'] 251 g2 = self.ctns['g2'] 252 g3 = self.ctns['g3'] 253 g4 = self.ctns['g4'] 254 g5 = self.ctns['g5'] 255 256 def nexthops(): 257 n = [] 258 for line in g1.local('ip route show 10.0.10.0/24', capture=True).split('\n'): 259 line = line.strip() 260 if 'via' in line: 261 n.append(line.split(' ')[2].strip()) 262 return n 263 264 def validate_nexthops(peers): 265 interval = 1 266 count = 0 267 timeout = 30 268 while True: 269 valid = False 270 nhs = nexthops() 271 if len(nhs) == len(peers): 272 valid = True 273 for peer in peers: 274 if g1.peers[peer]['neigh_addr'].split('/')[0] not in nhs: 275 valid = False 276 break 277 if valid: 278 return 279 280 time.sleep(interval) 281 count += interval 282 if count >= timeout: 283 raise Exception(nhs) 284 285 validate_nexthops([g4, g5]) 286 287 g4.local('gobgp g ri del 10.0.10.0/24') 288 validate_nexthops([g5]) 289 290 g4.local('gobgp g ri add 10.0.10.0/24 local-pref 200') 291 validate_nexthops([g4]) 292 293 g4.local('gobgp g ri del 10.0.10.0/24') 294 g5.local('gobgp g ri del 10.0.10.0/24') 295 validate_nexthops([g2, g3]) 296 297 g3.local('gobgp g ri del 10.0.10.0/24') 298 validate_nexthops([g2]) 299 300 g3.local('gobgp g ri add 10.0.10.0/24 med 10') 301 validate_nexthops([g2]) 302 303 g2.local('gobgp g ri add 10.0.10.0/24 med 20') 304 validate_nexthops([g3]) 305 306 307 if __name__ == '__main__': 308 output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) 309 if int(output) != 0: 310 print("docker not found") 311 sys.exit(1) 312 313 nose.main(argv=sys.argv, addplugins=[OptionParser()], 314 defaultTest=sys.argv[0])