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