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