github.com/osrg/gobgp@v2.0.0+incompatible/test/scenario_test/long_lived_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 from __future__ import absolute_import 17 18 from itertools import chain 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_ACTIVE, 31 BGP_FSM_ESTABLISHED, 32 LONG_LIVED_GRACEFUL_RESTART_TIME, 33 ) 34 from lib.gobgp import GoBGPContainer 35 36 37 class GoBGPTestBase(unittest.TestCase): 38 39 @classmethod 40 def setUpClass(cls): 41 gobgp_ctn_image_name = parser_option.gobgp_image 42 base.TEST_PREFIX = parser_option.test_prefix 43 44 g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1', 45 ctn_image_name=gobgp_ctn_image_name, 46 log_level=parser_option.gobgp_log_level) 47 g2 = GoBGPContainer(name='g2', asn=65001, router_id='192.168.0.2', 48 ctn_image_name=gobgp_ctn_image_name, 49 log_level=parser_option.gobgp_log_level) 50 g3 = GoBGPContainer(name='g3', asn=65002, router_id='192.168.0.3', 51 ctn_image_name=gobgp_ctn_image_name, 52 log_level=parser_option.gobgp_log_level) 53 g4 = GoBGPContainer(name='g4', asn=65003, router_id='192.168.0.4', 54 ctn_image_name=gobgp_ctn_image_name, 55 log_level=parser_option.gobgp_log_level) 56 ctns = [g1, g2, g3, g4] 57 58 initial_wait_time = max(ctn.run() for ctn in ctns) 59 60 time.sleep(initial_wait_time) 61 62 g1.add_peer(g2, graceful_restart=True, llgr=True) 63 g2.add_peer(g1, graceful_restart=True, llgr=True) 64 g1.add_peer(g3, graceful_restart=True, llgr=True) 65 g3.add_peer(g1, graceful_restart=True, llgr=True) 66 g1.add_peer(g4, graceful_restart=True) 67 g4.add_peer(g1, graceful_restart=True) 68 69 cls.bgpds = {'g1': g1, 'g2': g2, 'g3': g3, 'g4': g4} 70 71 # test each neighbor state is turned establish 72 def test_01_neighbor_established(self): 73 g1 = self.bgpds['g1'] 74 g2 = self.bgpds['g2'] 75 g3 = self.bgpds['g3'] 76 g4 = self.bgpds['g4'] 77 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g2) 78 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g3) 79 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g4) 80 81 def test_02_graceful_restart(self): 82 g1 = self.bgpds['g1'] 83 g2 = self.bgpds['g2'] 84 g3 = self.bgpds['g3'] 85 g4 = self.bgpds['g4'] 86 87 g2.local('gobgp global rib add 10.0.0.0/24') 88 g2.local('gobgp global rib add 10.10.0.0/24 community no-llgr') 89 90 time.sleep(1) 91 92 g2.stop_gobgp() 93 g1.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g2) 94 95 time.sleep(1) 96 97 self.assertEqual(len(g1.get_global_rib('10.0.0.0/24')), 1) 98 # 10.10.0.0/24 is announced with no-llgr community 99 # must not exist in the rib 100 self.assertEqual(len(g1.get_global_rib('10.10.0.0/24')), 0) 101 for d in g1.get_global_rib(): 102 for p in d['paths']: 103 self.assertTrue(p['stale']) 104 105 self.assertEqual(len(g3.get_global_rib('10.0.0.0/24')), 1) 106 # check llgr-stale community is added to 10.0.0.0/24 107 r = g3.get_global_rib('10.0.0.0/24')[0]['paths'][0] 108 comms = list(chain.from_iterable([attr['communities'] for attr in r['attrs'] if attr['type'] == 8])) 109 self.assertTrue(0xffff0006 in comms) 110 # g4 is not llgr capable, llgr-stale route must be 111 # withdrawn 112 self.assertEqual(len(g4.get_global_rib('10.0.0.0/24')), 0) 113 114 g2.start_gobgp(graceful_restart=True) 115 g2.local('gobgp global rib add 10.0.0.0/24') 116 g2.local('gobgp global rib add 10.10.0.0/24') 117 118 def test_03_neighbor_established(self): 119 g1 = self.bgpds['g1'] 120 g2 = self.bgpds['g2'] 121 # g3 = self.bgpds['g3'] 122 # g4 = self.bgpds['g4'] 123 g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g2) 124 time.sleep(1) 125 self.assertEqual(len(g1.get_global_rib('10.0.0.0/24')), 1) 126 self.assertEqual(len(g1.get_global_rib('10.10.0.0/24')), 1) 127 for d in g1.get_global_rib(): 128 for p in d['paths']: 129 self.assertFalse(p.get('stale', False)) 130 131 def test_04_llgr_stale_route_depreferenced(self): 132 g1 = self.bgpds['g1'] 133 g2 = self.bgpds['g2'] 134 g3 = self.bgpds['g3'] 135 g4 = self.bgpds['g4'] 136 g4.local('gobgp global rib add 10.0.0.0/24 med 100') 137 time.sleep(1) 138 # check g2's path is chosen as best and advertised 139 rib = g3.get_global_rib('10.0.0.0/24') 140 self.assertEqual(len(rib), 1) 141 self.assertTrue(g2.asn in rib[0]['paths'][0]['aspath']) 142 143 g2.stop_gobgp() 144 g1.wait_for(expected_state=BGP_FSM_ACTIVE, peer=g2) 145 146 time.sleep(1) 147 148 # llgr_stale route depreference must happend 149 # check g4's path is chosen as best and advertised 150 rib = g3.get_global_rib('10.0.0.0/24') 151 self.assertEqual(len(rib), 1) 152 self.assertTrue(g4.asn in rib[0]['paths'][0]['aspath']) 153 154 # if no candidate exists, llgr_stale route will be chosen as best 155 rib = g3.get_global_rib('10.10.0.0/24') 156 self.assertEqual(len(rib), 1) 157 self.assertTrue(g2.asn in rib[0]['paths'][0]['aspath']) 158 159 def test_05_llgr_restart_timer_expire(self): 160 time.sleep(LONG_LIVED_GRACEFUL_RESTART_TIME + 5) 161 g3 = self.bgpds['g3'] 162 rib = g3.get_global_rib('10.10.0.0/24') 163 self.assertEqual(len(rib), 0) 164 165 166 if __name__ == '__main__': 167 output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) 168 if int(output) is not 0: 169 print "docker not found" 170 sys.exit(1) 171 172 nose.main(argv=sys.argv, addplugins=[OptionParser()], 173 defaultTest=sys.argv[0])