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