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