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])