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