github.com/osrg/gobgp/v3@v3.30.0/test/scenario_test/route_server_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 BGP_FSM_ACTIVE, 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 40 wait_per_retry = 5 41 retry_limit = 15 42 43 @classmethod 44 def setUpClass(cls): 45 gobgp_ctn_image_name = parser_option.gobgp_image 46 base.TEST_PREFIX = parser_option.test_prefix 47 48 g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1', 49 ctn_image_name=gobgp_ctn_image_name, 50 log_level=parser_option.gobgp_log_level) 51 52 rs_clients = [ 53 QuaggaBGPContainer(name='q{0}'.format(i + 1), asn=(65001 + i), 54 router_id='192.168.0.{0}'.format(i + 2)) 55 for i in range(3)] 56 ctns = [g1] + rs_clients 57 q1 = rs_clients[0] 58 q2 = rs_clients[1] 59 q3 = rs_clients[2] 60 61 initial_wait_time = max(ctn.run() for ctn in ctns) 62 time.sleep(initial_wait_time) 63 64 for rs_client in rs_clients: 65 g1.add_peer(rs_client, is_rs_client=True, passwd='passwd', passive=True, prefix_limit=10) 66 rs_client.add_peer(g1, passwd='passwd') 67 68 # advertise a route from route-server-clients 69 routes = [] 70 for idx, rs_client in enumerate(rs_clients): 71 route = '10.0.{0}.0/24'.format(idx + 1) 72 rs_client.add_route(route) 73 routes.append(route) 74 75 cls.gobgp = g1 76 cls.quaggas = {'q1': q1, 'q2': q2, 'q3': q3} 77 78 def check_gobgp_local_rib(self): 79 for rs_client in self.quaggas.values(): 80 done = False 81 for _ in range(self.retry_limit): 82 if done: 83 break 84 local_rib = self.gobgp.get_local_rib(rs_client) 85 local_rib = [p['prefix'] for p in local_rib] 86 87 state = self.gobgp.get_neighbor_state(rs_client) 88 self.assertEqual(state, BGP_FSM_ESTABLISHED) 89 if len(local_rib) < (len(self.quaggas) - 1): 90 time.sleep(self.wait_per_retry) 91 continue 92 93 self.assertEqual(len(local_rib), (len(self.quaggas) - 1)) 94 95 for c in self.quaggas.values(): 96 if rs_client != c: 97 for r in c.routes: 98 self.assertTrue(r in local_rib) 99 100 done = True 101 if done: 102 continue 103 # should not reach here 104 raise AssertionError 105 106 def check_rs_client_rib(self): 107 for rs_client in self.quaggas.values(): 108 done = False 109 for _ in range(self.retry_limit): 110 if done: 111 break 112 global_rib = rs_client.get_global_rib() 113 global_rib = [p['prefix'] for p in global_rib] 114 if len(global_rib) < len(self.quaggas): 115 time.sleep(self.wait_per_retry) 116 continue 117 118 self.assertEqual(len(global_rib), len(self.quaggas)) 119 120 for c in self.quaggas.values(): 121 for r in c.routes: 122 self.assertTrue(r in global_rib) 123 124 done = True 125 if done: 126 continue 127 # should not reach here 128 raise AssertionError 129 130 # test each neighbor state is turned establish 131 def test_01_neighbor_established(self): 132 for q in self.quaggas.values(): 133 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q) 134 135 # check advertised routes are stored in route-server's local-rib 136 def test_02_check_gobgp_local_rib(self): 137 self.check_gobgp_local_rib() 138 139 # check gobgp's global rib. when configured as route-server, global rib 140 # must be empty 141 def test_03_check_gobgp_global_rib(self): 142 self.assertEqual(len(self.gobgp.get_global_rib()), 0) 143 144 # check routes are properly advertised to route-server-client 145 def test_04_check_rs_clients_rib(self): 146 self.check_rs_client_rib() 147 148 # check if quagga that is appended can establish connection with gobgp 149 def test_05_add_rs_client(self): 150 q4 = QuaggaBGPContainer(name='q4', asn=65004, router_id='192.168.0.5') 151 self.quaggas['q4'] = q4 152 initial_wait_time = q4.run() 153 time.sleep(initial_wait_time) 154 155 self.gobgp.add_peer(q4, is_rs_client=True) 156 q4.add_peer(self.gobgp) 157 158 route = '10.0.4.0/24' 159 q4.add_route(route) 160 161 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q4) 162 163 # check advertised routes are stored in gobgp's local-rib 164 def test_05_check_gobgp_local_rib(self): 165 self.check_gobgp_local_rib() 166 167 # check routes are properly advertised to quagga 168 def test_06_check_rs_clients_rib(self): 169 self.check_rs_client_rib() 170 171 def test_07_stop_one_rs_client(self): 172 q4 = self.quaggas['q4'] 173 q4.stop() 174 self.gobgp.wait_for(expected_state=BGP_FSM_ACTIVE, peer=q4) 175 176 del self.quaggas['q4'] 177 178 # check a route advertised from q4 is deleted from gobgp's local-rib 179 def test_08_check_gobgp_local_rib(self): 180 self.check_gobgp_local_rib() 181 182 # check whether gobgp properly sent withdrawal message with q4's route 183 def test_09_check_rs_clients_rib(self): 184 self.check_rs_client_rib() 185 186 @unittest.skip("med shouldn't work with different AS peers by default") 187 def test_10_add_distant_relative(self): 188 q1 = self.quaggas['q1'] 189 q2 = self.quaggas['q2'] 190 q3 = self.quaggas['q3'] 191 q5 = QuaggaBGPContainer(name='q5', asn=65005, router_id='192.168.0.6') 192 193 initial_wait_time = q5.run() 194 time.sleep(initial_wait_time) 195 196 for q in [q2, q3]: 197 q5.add_peer(q) 198 q.add_peer(q5) 199 200 med200 = {'name': 'med200', 201 'type': 'permit', 202 'match': '0.0.0.0/0', 203 'med': 200, 204 'priority': 10} 205 q2.add_policy(med200, self.gobgp, 'out') 206 med100 = {'name': 'med100', 207 'type': 'permit', 208 'match': '0.0.0.0/0', 209 'med': 100, 210 'priority': 10} 211 q3.add_policy(med100, self.gobgp, 'out') 212 213 q5.add_route('10.0.6.0/24') 214 215 q2.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q5) 216 q3.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q5) 217 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q2) 218 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q3) 219 220 def check_nexthop(target_prefix, expected_nexthop): 221 is_done = False 222 for _ in range(self.retry_limit): 223 if is_done: 224 break 225 time.sleep(self.wait_per_retry) 226 for path in q1.get_global_rib(): 227 if path['prefix'] == target_prefix: 228 print("{0}'s nexthop is {1}".format(path['prefix'], 229 path['nexthop'])) 230 n_addrs = [i[1].split('/')[0] for i in 231 expected_nexthop.ip_addrs] 232 if path['nexthop'] in n_addrs: 233 is_done = True 234 break 235 return is_done 236 237 done = check_nexthop('10.0.6.0/24', q3) 238 self.assertTrue(done) 239 240 med300 = {'name': 'med300', 241 'type': 'permit', 242 'match': '0.0.0.0/0', 243 'med': 300, 244 'priority': 5} 245 q3.add_policy(med300, self.gobgp, 'out') 246 247 time.sleep(self.wait_per_retry) 248 249 done = check_nexthop('10.0.6.0/24', q2) 250 self.assertTrue(done) 251 252 253 if __name__ == '__main__': 254 output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) 255 if int(output) != 0: 256 print("docker not found") 257 sys.exit(1) 258 259 nose.main(argv=sys.argv, addplugins=[OptionParser()], 260 defaultTest=sys.argv[0])