github.com/osrg/gobgp@v2.0.0+incompatible/test/scenario_test/ibgp_router_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 from itertools import combinations 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 BGP_FSM_IDLE, 31 BGP_FSM_ESTABLISHED, 32 ) 33 from lib.base import wait_for_completion 34 from lib.gobgp import GoBGPContainer 35 from lib.quagga import QuaggaBGPContainer 36 37 38 class GoBGPTestBase(unittest.TestCase): 39 40 @classmethod 41 def setUpClass(cls): 42 gobgp_ctn_image_name = parser_option.gobgp_image 43 base.TEST_PREFIX = parser_option.test_prefix 44 45 g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1', 46 ctn_image_name=gobgp_ctn_image_name, 47 log_level=parser_option.gobgp_log_level) 48 q1 = QuaggaBGPContainer(name='q1', asn=65000, router_id='192.168.0.2') 49 q2 = QuaggaBGPContainer(name='q2', asn=65000, router_id='192.168.0.3') 50 51 qs = [q1, q2] 52 ctns = [g1, q1, q2] 53 54 initial_wait_time = max(ctn.run() for ctn in ctns) 55 time.sleep(initial_wait_time) 56 57 # ibgp peer. loop topology 58 for a, b in combinations(ctns, 2): 59 a.add_peer(b) 60 b.add_peer(a) 61 62 # advertise a route from q1, q2 63 for idx, c in enumerate(qs): 64 route = '10.0.{0}.0/24'.format(idx + 1) 65 c.add_route(route) 66 67 cls.gobgp = g1 68 cls.quaggas = {'q1': q1, 'q2': q2} 69 70 # test each neighbor state is turned establish 71 def test_01_neighbor_established(self): 72 for q in self.quaggas.itervalues(): 73 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q) 74 75 def test_02_check_gobgp_global_rib(self): 76 for q in self.quaggas.itervalues(): 77 # paths expected to exist in gobgp's global rib 78 routes = q.routes.keys() 79 timeout = 120 80 interval = 1 81 count = 0 82 while True: 83 # gobgp's global rib 84 state = self.gobgp.get_neighbor_state(q) 85 self.assertEqual(state, BGP_FSM_ESTABLISHED) 86 global_rib = [p['prefix'] for p in self.gobgp.get_global_rib()] 87 88 for p in global_rib: 89 if p in routes: 90 routes.remove(p) 91 92 if len(routes) == 0: 93 break 94 95 time.sleep(interval) 96 count += interval 97 if count >= timeout: 98 raise Exception('timeout') 99 100 def test_03_check_gobgp_adj_rib_out(self): 101 for q in self.quaggas.itervalues(): 102 paths = self.gobgp.get_adj_rib_out(q) 103 # bgp speaker mustn't forward iBGP routes to iBGP peers 104 self.assertEqual(len(paths), 0) 105 106 def test_04_originate_path(self): 107 self.gobgp.add_route('10.10.0.0/24') 108 dst = self.gobgp.get_global_rib('10.10.0.0/24') 109 self.assertEqual(len(dst), 1) 110 self.assertEqual(len(dst[0]['paths']), 1) 111 path = dst[0]['paths'][0] 112 self.assertEqual(path['nexthop'], '0.0.0.0') 113 self.assertEqual(len(path['aspath']), 0) 114 115 def test_05_check_gobgp_adj_rib_out(self): 116 for q in self.quaggas.itervalues(): 117 paths = self.gobgp.get_adj_rib_out(q) 118 self.assertEqual(len(paths), len(self.gobgp.routes)) 119 path = paths[0] 120 self.assertEqual(path['nlri']['prefix'], '10.10.0.0/24') 121 peer_info = self.gobgp.peers[q] 122 local_addr = peer_info['local_addr'].split('/')[0] 123 self.assertEqual(path['nexthop'], local_addr) 124 self.assertEqual(len(path['aspath']), 0) 125 126 # check routes are properly advertised to all BGP speaker 127 def test_06_check_quagga_global_rib(self): 128 interval = 1 129 timeout = int(120 / interval) 130 for q in self.quaggas.itervalues(): 131 done = False 132 for _ in range(timeout): 133 if done: 134 break 135 global_rib = q.get_global_rib() 136 # quagga's global_rib must have two routes at least, 137 # a self-generated route and a gobgp-generated route 138 if len(global_rib) < len(q.routes) + len(self.gobgp.routes): 139 time.sleep(interval) 140 continue 141 142 peer_info = self.gobgp.peers[q] 143 local_addr = peer_info['local_addr'].split('/')[0] 144 for r in self.gobgp.routes: 145 self.assertTrue(r in (p['prefix'] for p in global_rib)) 146 for rr in global_rib: 147 if rr['prefix'] == r: 148 self.assertEqual(rr['nexthop'], local_addr) 149 150 for r in q.routes.keys(): 151 self.assertTrue(r in (p['prefix'] for p in global_rib)) 152 for rr in global_rib: 153 if rr['prefix'] == r: 154 self.assertEqual(rr['nexthop'], '0.0.0.0') 155 156 done = True 157 if done: 158 continue 159 # should not reach here 160 raise AssertionError 161 162 def test_07_add_ebgp_peer(self): 163 q3 = QuaggaBGPContainer(name='q3', asn=65001, router_id='192.168.0.4') 164 self.quaggas['q3'] = q3 165 initial_wait_time = q3.run() 166 time.sleep(initial_wait_time) 167 168 self.gobgp.add_peer(q3) 169 q3.add_peer(self.gobgp) 170 171 q3.add_route('10.0.3.0/24') 172 173 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q3) 174 175 def test_08_check_global_rib(self): 176 self.test_02_check_gobgp_global_rib() 177 178 def test_09_check_gobgp_ebgp_adj_rib_out(self): 179 q1 = self.quaggas['q1'] 180 q2 = self.quaggas['q2'] 181 q3 = self.quaggas['q3'] 182 paths = self.gobgp.get_adj_rib_out(q3) 183 total_len = len(q1.routes) + len(q2.routes) + len(self.gobgp.routes) 184 assert len(paths) == total_len 185 for path in paths: 186 peer_info = self.gobgp.peers[q3] 187 local_addr = peer_info['local_addr'].split('/')[0] 188 self.assertEqual(path['nexthop'], local_addr) 189 self.assertEqual(path['aspath'], [self.gobgp.asn]) 190 191 def test_10_check_gobgp_ibgp_adj_rib_out(self): 192 q1 = self.quaggas['q1'] 193 q3 = self.quaggas['q3'] 194 peer_info = self.gobgp.peers[q3] 195 neigh_addr = peer_info['neigh_addr'].split('/')[0] 196 197 for prefix in q3.routes.iterkeys(): 198 paths = self.gobgp.get_adj_rib_out(q1, prefix) 199 self.assertEqual(len(paths), 1) 200 path = paths[0] 201 # bgp router mustn't change nexthop of routes from eBGP peers 202 # which are sent to iBGP peers 203 self.assertEqual(path['nexthop'], neigh_addr) 204 # bgp router mustn't change aspath of routes from eBGP peers 205 # which are sent to iBGP peers 206 self.assertEqual(path['aspath'], [q3.asn]) 207 208 # disable ebgp peer, check ebgp routes are removed 209 def test_11_disable_ebgp_peer(self): 210 q3 = self.quaggas['q3'] 211 self.gobgp.disable_peer(q3) 212 del self.quaggas['q3'] 213 self.gobgp.wait_for(expected_state=BGP_FSM_IDLE, peer=q3) 214 215 for route in q3.routes.iterkeys(): 216 dst = self.gobgp.get_global_rib(route) 217 self.assertEqual(len(dst), 0) 218 219 for q in self.quaggas.itervalues(): 220 paths = self.gobgp.get_adj_rib_out(q) 221 # only gobgp's locally generated routes must exists 222 print paths 223 self.assertEqual(len(paths), len(self.gobgp.routes)) 224 225 def test_12_disable_ibgp_peer(self): 226 q1 = self.quaggas['q1'] 227 self.gobgp.disable_peer(q1) 228 self.gobgp.wait_for(expected_state=BGP_FSM_IDLE, peer=q1) 229 230 for route in q1.routes.iterkeys(): 231 dst = self.gobgp.get_global_rib(route) 232 self.assertEqual(len(dst), 0) 233 234 def test_13_enable_ibgp_peer(self): 235 q1 = self.quaggas['q1'] 236 self.gobgp.enable_peer(q1) 237 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q1) 238 239 def test_14_check_gobgp_adj_rib_out(self): 240 for q in self.quaggas.itervalues(): 241 paths = self.gobgp.get_adj_rib_out(q) 242 # only gobgp's locally generated routes must exists 243 self.assertEqual(len(paths), len(self.gobgp.routes)) 244 245 def test_15_add_ebgp_peer(self): 246 q4 = QuaggaBGPContainer(name='q4', asn=65001, router_id='192.168.0.5') 247 self.quaggas['q4'] = q4 248 initial_wait_time = q4.run() 249 time.sleep(initial_wait_time) 250 251 self.gobgp.add_peer(q4) 252 q4.add_peer(self.gobgp) 253 254 prefix = '10.0.4.0/24' 255 q4.add_route(prefix) 256 257 self.gobgp.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q4) 258 259 q1 = self.quaggas['q1'] 260 q2 = self.quaggas['q2'] 261 for q in [q1, q2]: 262 def _f(): 263 return prefix in [p['nlri']['prefix'] for p in self.gobgp.get_adj_rib_out(q)] 264 wait_for_completion(_f) 265 266 def f(): 267 return len(q2.get_global_rib(prefix)) == 1 268 wait_for_completion(f) 269 270 def test_16_add_best_path_from_ibgp(self): 271 q1 = self.quaggas['q1'] 272 q2 = self.quaggas['q2'] 273 274 prefix = '10.0.4.0/24' 275 q1.add_route(prefix) 276 277 def f1(): 278 l = self.gobgp.get_global_rib(prefix) 279 return len(l) == 1 and len(l[0]['paths']) == 2 280 wait_for_completion(f1) 281 282 def f2(): 283 return prefix not in [p['nlri']['prefix'] for p in self.gobgp.get_adj_rib_out(q2)] 284 wait_for_completion(f2) 285 286 def f3(): 287 l = q2.get_global_rib(prefix) 288 # route from ibgp so aspath should be empty 289 return len(l) == 1 and len(l[0]['aspath']) == 0 290 wait_for_completion(f3) 291 292 293 if __name__ == '__main__': 294 output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) 295 if int(output) is not 0: 296 print "docker not found" 297 sys.exit(1) 298 299 nose.main(argv=sys.argv, addplugins=[OptionParser()], 300 defaultTest=sys.argv[0])