github.com/osrg/gobgp/v3@v3.30.0/test/scenario_test/bgp_zebra_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      Bridge,
    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      # The same topology for IPv4 and IPv6 environment.
    40      # o1: Quagga (not router)
    41      # g1: GoBGP
    42      # q1: Quagga (Zebra + BGPd)
    43      # o2: Quagga (not router)
    44      #
    45      # +----+       +----+           +----+       +----+
    46      # | o1 |       | g1 |===(BGP)===| q1 |       | o2 |
    47      # +----+       +----+           +----+       +----+
    48      #    |          |  |             |  |          |
    49      #    +--(br01)--+  +---(br02)----+  +--(br03)--+
    50  
    51      @classmethod
    52      def setUpClass(cls):
    53          gobgp_ctn_image_name = parser_option.gobgp_image
    54          base.TEST_PREFIX = parser_option.test_prefix
    55  
    56          # preparing the container for ipv4
    57          g1_v4 = GoBGPContainer(name='g1_v4', asn=65000, router_id='192.168.0.1',
    58                                 ctn_image_name=gobgp_ctn_image_name,
    59                                 log_level=parser_option.gobgp_log_level,
    60                                 zebra=True)
    61          q1_v4 = QuaggaBGPContainer(name='q1_v4', asn=65001, router_id='192.168.0.2', zebra=True)
    62          o1_v4 = QuaggaBGPContainer(name='o1_v4', asn=65002, router_id='192.168.0.3')
    63          o2_v4 = QuaggaBGPContainer(name='o2_v4', asn=65002, router_id='192.168.0.4')
    64  
    65          # preparing the container for ipv6
    66          g1_v6 = GoBGPContainer(name='g1_v6', asn=65000, router_id='192.168.0.1',
    67                                 ctn_image_name=gobgp_ctn_image_name,
    68                                 log_level=parser_option.gobgp_log_level,
    69                                 zebra=True)
    70          q1_v6 = QuaggaBGPContainer(name='q1_v6', asn=65001, router_id='192.168.0.2', zebra=True)
    71          o1_v6 = QuaggaBGPContainer(name='o1_v6', asn=65002, router_id='192.168.0.3')
    72          o2_v6 = QuaggaBGPContainer(name='o2_v6', asn=65002, router_id='192.168.0.4')
    73  
    74          # preparing the bridge for ipv4
    75          br01_v4 = Bridge(name='br01_v4', subnet='192.168.10.0/24')
    76          br02_v4 = Bridge(name='br02_v4', subnet='192.168.20.0/24')
    77          br03_v4 = Bridge(name='br03_v4', subnet='192.168.30.0/24')
    78  
    79          # preparing the bridge for ipv6
    80          br01_v6 = Bridge(name='br01_v6', subnet='2001:10::/32')
    81          br02_v6 = Bridge(name='br02_v6', subnet='2001:20::/32')
    82          br03_v6 = Bridge(name='br03_v6', subnet='2001:30::/32')
    83  
    84          cls.ctns = {
    85              'ipv4': [g1_v4, q1_v4, o1_v4, o2_v4],
    86              'ipv6': [g1_v6, q1_v6, o1_v6, o2_v6],
    87          }
    88          cls.gobgps = {
    89              'ipv4': g1_v4,
    90              'ipv6': g1_v6,
    91          }
    92          cls.quaggas = {
    93              'ipv4': q1_v4,
    94              'ipv6': q1_v6,
    95          }
    96          cls.others = {
    97              'ipv4': [o1_v4, o2_v4],
    98              'ipv6': [o1_v6, o2_v6],
    99          }
   100          cls.bridges = {
   101              'br01_v4': br01_v4,
   102              'br02_v4': br02_v4,
   103              'br03_v4': br03_v4,
   104              'br01_v6': br01_v6,
   105              'br02_v6': br02_v6,
   106              'br03_v6': br03_v6,
   107          }
   108  
   109      """
   110        No.1 start up ipv4 containers and check state
   111             each neighbor is established in ipv4 environment
   112      """
   113  
   114      def test_01_check_neighbor_established(self):
   115          g1 = self.gobgps['ipv4']
   116          q1 = self.quaggas['ipv4']
   117          o1 = self.others['ipv4'][0]
   118          o2 = self.others['ipv4'][1]
   119          # start up containers of ipv4 environment
   120          initial_wait_time = max(ctn.run() for ctn in self.ctns['ipv4'])
   121          time.sleep(initial_wait_time)
   122  
   123          # make ipv4 bridge and set ip to each container
   124          [self.bridges['br01_v4'].addif(ctn) for ctn in [o1, g1]]
   125          [self.bridges['br02_v4'].addif(ctn) for ctn in [g1, q1]]
   126          [self.bridges['br03_v4'].addif(ctn) for ctn in [q1, o2]]
   127  
   128          g1.add_peer(q1, bridge=self.bridges['br02_v4'].name)
   129          q1.add_peer(g1, bridge=self.bridges['br02_v4'].name)
   130  
   131          g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q1)
   132  
   133      """
   134        No.2 check whether the ping is reachable in container
   135             that have previously beyond the GoBGP in ipv4 environment
   136      """
   137  
   138      def test_02_check_reachability_between_o1_and_o2(self):
   139          g1 = self.gobgps['ipv4']
   140          q1 = self.quaggas['ipv4']
   141          o1 = self.others['ipv4'][0]
   142          o2 = self.others['ipv4'][1]
   143  
   144          # set o1's default gateway as g1
   145          g1_addr = g1.ip_addrs[1][1].split('/')[0]
   146          o1.add_static_route(self.bridges['br03_v4'].subnet, g1_addr)
   147  
   148          # set o2's default gateway as q1
   149          q1_addr = q1.ip_addrs[2][1].split('/')[0]
   150          o2.add_static_route(self.bridges['br01_v4'].subnet, q1_addr)
   151  
   152          # test reachability between o1 and o2
   153          addrs = [e[1] for e in o2.ip_addrs if 'br03_v4' in e[2]]
   154          self.assertEqual(len(addrs), 1)
   155          o2_addr = addrs[0]
   156          o1.get_reachability(o2_addr)
   157  
   158      """
   159        No.4 start up ipv6 containers and check state
   160             each neighbor is established in ipv6 environment
   161      """
   162  
   163      def test_04_check_neighbor_established_v6(self):
   164          g1 = self.gobgps['ipv6']
   165          q1 = self.quaggas['ipv6']
   166          o1 = self.others['ipv6'][0]
   167          o2 = self.others['ipv6'][1]
   168          # start up containers of ipv6 environment
   169          initial_wait_time = max(ctn.run() for ctn in self.ctns['ipv6'])
   170          time.sleep(initial_wait_time)
   171  
   172          # make ipv6 bridge and set ip to each container
   173          [self.bridges['br01_v6'].addif(ctn) for ctn in [o1, g1]]
   174          [self.bridges['br02_v6'].addif(ctn) for ctn in [g1, q1]]
   175          [self.bridges['br03_v6'].addif(ctn) for ctn in [q1, o2]]
   176  
   177          g1.add_peer(q1, bridge=self.bridges['br02_v6'].name, v6=True)
   178          q1.add_peer(g1, bridge=self.bridges['br02_v6'].name, v6=True)
   179  
   180          g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=q1)
   181  
   182      """
   183        No.5 check whether the ping is reachable in container
   184             that have previously beyond the GoBGP in ipv6 environment
   185      """
   186  
   187      def test_05_check_reachability_between_o1_and_o2(self):
   188          g1 = self.gobgps['ipv6']
   189          q1 = self.quaggas['ipv6']
   190          o1 = self.others['ipv6'][0]
   191          o2 = self.others['ipv6'][1]
   192  
   193          # set o1's default gateway as g1
   194          g1_addr = [a for a in g1.ip6_addrs if a[2] == self.bridges['br01_v6'].name][0][1].split('/')[0]
   195          o1.add_static_route(self.bridges['br03_v6'].subnet, g1_addr)
   196  
   197          # set o2's default gateway as q1
   198          q1_addr = [a for a in q1.ip6_addrs if a[2] == self.bridges['br03_v6'].name][0][1].split('/')[0]
   199          o2.add_static_route(self.bridges['br01_v6'].subnet, q1_addr)
   200  
   201          # test reachability between o1 and o2
   202          addrs = [e[1] for e in o2.ip6_addrs if 'br03_v6' in e[2]]
   203          self.assertEqual(len(addrs), 1)
   204          o2_addr = addrs[0]
   205          o1.get_reachability(o2_addr)
   206  
   207      def test_07_mpath_test_setup(self):
   208          g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1',
   209                              ctn_image_name=parser_option.gobgp_image,
   210                              log_level=parser_option.gobgp_log_level,
   211                              config_format=parser_option.config_format,
   212                              zebra=True)
   213          g2 = GoBGPContainer(name='g2', asn=65001, router_id='192.168.0.2',
   214                              ctn_image_name=parser_option.gobgp_image)
   215          g3 = GoBGPContainer(name='g3', asn=65001, router_id='192.168.0.3',
   216                              ctn_image_name=parser_option.gobgp_image)
   217          g4 = GoBGPContainer(name='g4', asn=65000, router_id='192.168.0.4',
   218                              ctn_image_name=parser_option.gobgp_image)
   219          g5 = GoBGPContainer(name='g5', asn=65000, router_id='192.168.0.5',
   220                              ctn_image_name=parser_option.gobgp_image)
   221  
   222          ctns = [g1, g2, g3, g4, g5]
   223          for ctn in ctns:
   224              self.ctns[ctn.name] = ctn
   225  
   226          initial_wait_time = max(ctn.run() for ctn in ctns)
   227  
   228          time.sleep(initial_wait_time)
   229  
   230          # advertise same prefix
   231          g2.add_route('10.0.10.0/24')
   232          g3.add_route('10.0.10.0/24')
   233          g4.add_route('10.0.10.0/24')
   234          g5.add_route('10.0.10.0/24')
   235  
   236          for g in [g2, g3, g4, g5]:
   237              g1.add_peer(g)
   238              g.add_peer(g1)
   239  
   240      def test_08_mpath_test_check_neighbor_established(self):
   241          g1 = self.ctns['g1']
   242          g2 = self.ctns['g2']
   243          g3 = self.ctns['g3']
   244          g4 = self.ctns['g4']
   245          g5 = self.ctns['g5']
   246          for g in [g2, g3, g4, g5]:
   247              g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=g)
   248  
   249      def test_09_mpath_test_check_mpath_injected(self):
   250          g1 = self.ctns['g1']
   251          g2 = self.ctns['g2']
   252          g3 = self.ctns['g3']
   253          g4 = self.ctns['g4']
   254          g5 = self.ctns['g5']
   255  
   256          def nexthops():
   257              n = []
   258              for line in g1.local('ip route show 10.0.10.0/24', capture=True).split('\n'):
   259                  line = line.strip()
   260                  if 'via' in line:
   261                      n.append(line.split(' ')[2].strip())
   262              return n
   263  
   264          def validate_nexthops(peers):
   265              interval = 1
   266              count = 0
   267              timeout = 30
   268              while True:
   269                  valid = False
   270                  nhs = nexthops()
   271                  if len(nhs) == len(peers):
   272                      valid = True
   273                      for peer in peers:
   274                          if g1.peers[peer]['neigh_addr'].split('/')[0] not in nhs:
   275                              valid = False
   276                              break
   277                  if valid:
   278                      return
   279  
   280                  time.sleep(interval)
   281                  count += interval
   282                  if count >= timeout:
   283                      raise Exception(nhs)
   284  
   285          validate_nexthops([g4, g5])
   286  
   287          g4.local('gobgp g ri del 10.0.10.0/24')
   288          validate_nexthops([g5])
   289  
   290          g4.local('gobgp g ri add 10.0.10.0/24 local-pref 200')
   291          validate_nexthops([g4])
   292  
   293          g4.local('gobgp g ri del 10.0.10.0/24')
   294          g5.local('gobgp g ri del 10.0.10.0/24')
   295          validate_nexthops([g2, g3])
   296  
   297          g3.local('gobgp g ri del 10.0.10.0/24')
   298          validate_nexthops([g2])
   299  
   300          g3.local('gobgp g ri add 10.0.10.0/24 med 10')
   301          validate_nexthops([g2])
   302  
   303          g2.local('gobgp g ri add 10.0.10.0/24 med 20')
   304          validate_nexthops([g3])
   305  
   306  
   307  if __name__ == '__main__':
   308      output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True)
   309      if int(output) != 0:
   310          print("docker not found")
   311          sys.exit(1)
   312  
   313      nose.main(argv=sys.argv, addplugins=[OptionParser()],
   314                defaultTest=sys.argv[0])