github.com/osrg/gobgp/v3@v3.30.0/test/scenario_test/graceful_restart_test.py (about) 1 # Copyright (C) 2016 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_IDLE, 31 BGP_FSM_ACTIVE, 32 BGP_FSM_ESTABLISHED, 33 GRACEFUL_RESTART_TIME, 34 local, 35 ) 36 from lib.gobgp import GoBGPContainer 37 38 39 class GoBGPTestBase(unittest.TestCase): 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 g2 = GoBGPContainer(name='g2', asn=65001, router_id='192.168.0.2', 50 ctn_image_name=gobgp_ctn_image_name, 51 log_level=parser_option.gobgp_log_level) 52 ctns = [g1, g2] 53 54 initial_wait_time = max(ctn.run() for ctn in ctns) 55 56 time.sleep(initial_wait_time) 57 58 g1.add_route('10.10.10.0/24') 59 g1.add_route('10.10.20.0/24') 60 61 g1.add_peer(g2, graceful_restart=True) 62 g2.add_peer(g1, graceful_restart=True) 63 64 cls.bgpds = {'g1': g1, 'g2': g2} 65 66 # test each neighbor state is turned establish 67 def test_01_neighbor_established(self): 68 g1 = self.bgpds['g1'] 69 g2 = self.bgpds['g2'] 70 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g2) 71 72 def test_02_graceful_restart(self): 73 g1 = self.bgpds['g1'] 74 g2 = self.bgpds['g2'] 75 g1.stop_gobgp() 76 g2.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g1) 77 self.assertEqual(len(g2.get_global_rib('10.10.20.0/24')), 1) 78 self.assertEqual(len(g2.get_global_rib('10.10.10.0/24')), 1) 79 for d in g2.get_global_rib(): 80 for p in d['paths']: 81 self.assertTrue(p['stale']) 82 83 # Confirm the paths on the adj-RIB-in table are synced with the Global 84 # table. 85 self.assertEqual(len(g2.get_adj_rib_in(g1, '10.10.20.0/24')), 1) 86 self.assertEqual(len(g2.get_adj_rib_in(g1, '10.10.10.0/24')), 1) 87 for p in g2.get_adj_rib_in(g1): 88 self.assertTrue(p['stale']) 89 90 g1.routes = {} 91 g1.start_gobgp(graceful_restart=True) 92 g1.add_route('10.10.20.0/24') 93 94 def test_03_neighbor_established(self): 95 g1 = self.bgpds['g1'] 96 g2 = self.bgpds['g2'] 97 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g2) 98 99 # Confirm the restart timer not expired. 100 self.assertEqual( 101 g2.local( 102 "grep 'graceful restart timer expired' %s/gobgpd.log" 103 " | wc -l" % (g2.SHARED_VOLUME), capture=True), 104 '0') 105 time.sleep(1) 106 107 self.assertEqual(len(g2.get_global_rib('10.10.20.0/24')), 1) 108 self.assertEqual(len(g2.get_global_rib('10.10.10.0/24')), 0) 109 for d in g2.get_global_rib(): 110 for p in d['paths']: 111 self.assertFalse(p.get('stale', False)) 112 113 # Confirm the stale paths are also removed from the adj-RIB-in table. 114 # https://github.com/osrg/gobgp/pull/1707 115 self.assertEqual(len(g2.get_adj_rib_in(g1, '10.10.20.0/24')), 1) 116 self.assertEqual(len(g2.get_adj_rib_in(g1, '10.10.10.0/24')), 0) 117 for p in g2.get_adj_rib_in(g1): 118 self.assertFalse(p.get('stale', False)) 119 120 def test_04_add_non_graceful_restart_enabled_peer(self): 121 g1 = self.bgpds['g1'] 122 # g2 = self.bgpds['g2'] 123 gobgp_ctn_image_name = parser_option.gobgp_image 124 g3 = GoBGPContainer(name='g3', asn=65002, router_id='192.168.0.3', 125 ctn_image_name=gobgp_ctn_image_name, 126 log_level=parser_option.gobgp_log_level) 127 self.bgpds['g3'] = g3 128 time.sleep(g3.run()) 129 g3.add_route('10.10.30.0/24') 130 g1.add_peer(g3, graceful_restart=True) 131 g3.add_peer(g1) 132 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g3) 133 time.sleep(1) 134 self.assertEqual(len(g3.get_global_rib('10.10.20.0/24')), 1) 135 self.assertEqual(len(g1.get_global_rib('10.10.30.0/24')), 1) 136 137 # Restart g1 with graceful restart flag and check that g1 routes are still propagated to g3. 138 g1.stop_gobgp() 139 g3.stop_gobgp() 140 g1.routes = {} 141 g3.routes = {} 142 g1.start_gobgp(graceful_restart=True) 143 g1.add_route('10.10.20.0/24') 144 g3.start_gobgp() 145 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g3) 146 time.sleep(1) 147 self.assertEqual(len(g3.get_global_rib('10.10.20.0/24')), 1) 148 g3.add_route('10.10.30.0/24') 149 150 def test_05_holdtime_expiry_graceful_restart(self): 151 g1 = self.bgpds['g1'] 152 g2 = self.bgpds['g2'] 153 g3 = self.bgpds['g3'] 154 g1.local("ip route add blackhole {}/32".format(g2.ip_addrs[0][1].split("/")[0])) 155 g1.local("ip route add blackhole {}/32".format(g3.ip_addrs[0][1].split("/")[0])) 156 g2.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g1) 157 self.assertEqual(len(g2.get_global_rib('10.10.20.0/24')), 1) 158 self.assertEqual(len(g2.get_global_rib('10.10.30.0/24')), 1) 159 for d in g2.get_global_rib(): 160 for p in d['paths']: 161 self.assertTrue(p['stale']) 162 163 self.assertEqual(len(g3.get_global_rib('10.10.20.0/24')), 0) 164 self.assertEqual(len(g3.get_global_rib('10.10.30.0/24')), 1) 165 166 def test_06_test_restart_timer_expire(self): 167 g2 = self.bgpds['g2'] 168 time.sleep(GRACEFUL_RESTART_TIME + 5) 169 g2 = self.bgpds['g2'] 170 self.assertEqual(len(g2.get_global_rib()), 0) 171 172 def test_07_establish_after_graceful_restart(self): 173 g1 = self.bgpds['g1'] 174 g2 = self.bgpds['g2'] 175 g3 = self.bgpds['g3'] 176 g1.local("ip route del blackhole {}/32".format(g2.ip_addrs[0][1].split("/")[0])) 177 g1.local("ip route del blackhole {}/32".format(g3.ip_addrs[0][1].split("/")[0])) 178 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g2) 179 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g3) 180 self.assertEqual(len(g2.get_global_rib('10.10.20.0/24')), 1) 181 self.assertEqual(len(g2.get_global_rib('10.10.30.0/24')), 1) 182 self.assertEqual(len(g3.get_global_rib('10.10.20.0/24')), 1) 183 self.assertEqual(len(g3.get_global_rib('10.10.30.0/24')), 1) 184 185 def test_08_graceful_restart(self): 186 g1 = self.bgpds['g1'] 187 g2 = self.bgpds['g2'] 188 g3 = self.bgpds['g3'] 189 g1.stop_gobgp() 190 g2.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g1) 191 self.assertEqual(len(g2.get_global_rib('10.10.20.0/24')), 1) 192 self.assertEqual(len(g2.get_global_rib('10.10.30.0/24')), 1) 193 for d in g2.get_global_rib(): 194 for p in d['paths']: 195 self.assertTrue(p['stale']) 196 197 self.assertEqual(len(g3.get_global_rib('10.10.20.0/24')), 0) 198 self.assertEqual(len(g3.get_global_rib('10.10.30.0/24')), 1) 199 200 def test_09_test_restart_timer_expire(self): 201 time.sleep(GRACEFUL_RESTART_TIME + 5) 202 g2 = self.bgpds['g2'] 203 self.assertEqual(len(g2.get_global_rib()), 0) 204 205 def test_10_multineighbor_established(self): 206 g1 = self.bgpds['g1'] 207 g2 = self.bgpds['g2'] 208 g3 = self.bgpds['g3'] 209 210 g1.start_gobgp() 211 212 g1.del_peer(g2) 213 g1.del_peer(g3) 214 g2.del_peer(g1) 215 g3.del_peer(g1) 216 g1.add_peer(g2, graceful_restart=True, llgr=True) 217 g1.add_peer(g3, graceful_restart=True, llgr=True) 218 g2.add_peer(g1, graceful_restart=True, llgr=True) 219 g3.add_peer(g1, graceful_restart=True, llgr=True) 220 221 g2.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g1) 222 g3.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g1) 223 224 def test_11_multineighbor_graceful_restart(self): 225 g1 = self.bgpds['g1'] 226 g2 = self.bgpds['g2'] 227 g3 = self.bgpds['g3'] 228 229 g1.stop_gobgp() 230 g2.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g1) 231 g3.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g1) 232 233 g1.start_gobgp(graceful_restart=True) 234 235 count = 0 236 while (g1.get_neighbor_state(g2) != BGP_FSM_ESTABLISHED 237 or g1.get_neighbor_state(g3) != BGP_FSM_ESTABLISHED): 238 count += 1 239 # assert connections are not refused 240 self.assertTrue(g1.get_neighbor_state(g2) != BGP_FSM_IDLE) 241 self.assertTrue(g1.get_neighbor_state(g3) != BGP_FSM_IDLE) 242 if count > 120: 243 raise Exception('timeout') 244 time.sleep(1) 245 246 247 if __name__ == '__main__': 248 output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) 249 if int(output) != 0: 250 print("docker not found") 251 sys.exit(1) 252 253 nose.main(argv=sys.argv, addplugins=[OptionParser()], 254 defaultTest=sys.argv[0])