github.com/osrg/gobgp/v3@v3.30.0/test/scenario_test/zapi_v3_multipath_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  import sys
    17  import time
    18  import unittest
    19  
    20  import collections
    21  collections.Callable = collections.abc.Callable
    22  
    23  import nose
    24  
    25  from lib.noseplugin import OptionParser, parser_option
    26  
    27  from lib import base
    28  from lib.base import BGP_FSM_ESTABLISHED, local
    29  from lib.gobgp import GoBGPContainer
    30  
    31  
    32  class GoBGPTestBase(unittest.TestCase):
    33  
    34      @classmethod
    35      def setUpClass(cls):
    36          gobgp_ctn_image_name = parser_option.gobgp_image
    37          base.TEST_PREFIX = parser_option.test_prefix
    38  
    39          g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1',
    40                              ctn_image_name=gobgp_ctn_image_name,
    41                              log_level=parser_option.gobgp_log_level,
    42                              zebra=True, zapi_version=3, zebra_multipath_enabled=True)
    43  
    44          g2 = GoBGPContainer(name='g2', asn=65001, router_id='192.168.0.2',
    45                              ctn_image_name=gobgp_ctn_image_name,
    46                              log_level=parser_option.gobgp_log_level,
    47                              zebra=True, zapi_version=3, zebra_multipath_enabled=True)
    48  
    49          g3 = GoBGPContainer(name='g3', asn=65001, router_id='192.168.0.3',
    50                              ctn_image_name=gobgp_ctn_image_name,
    51                              log_level=parser_option.gobgp_log_level,
    52                              zebra=True, zapi_version=3, zebra_multipath_enabled=True)
    53  
    54          initial_wait_time = max(ctn.run() for ctn in [g1, g2, g3])
    55  
    56          time.sleep(initial_wait_time)
    57  
    58          g1.add_peer(g2, vpn=True, addpath=16)
    59          g2.add_peer(g1, vpn=True, addpath=16)
    60          g1.add_peer(g3, vpn=True, addpath=16)
    61          g3.add_peer(g1, vpn=True, addpath=16)
    62  
    63          cls.g1 = g1
    64          cls.g2 = g2
    65          cls.g3 = g3
    66  
    67      """
    68      # Multipath route
    69      10.0.0.0/24 proto zebra metric 20
    70          nexthop via 127.0.0.1  dev lo weight 1
    71          nexthop via 127.0.0.2  dev lo weight 1
    72      # Single nexthop route
    73      10.0.0.0/24 via 127.0.0.2 dev lo proto zebra metric 20
    74      """
    75  
    76      def parse_ip_route(self, ip_route_output):
    77          routes = {}
    78          current_mpath_dest = ""
    79          for line in ip_route_output:
    80              tokens = line.split()
    81              if len(tokens) == 0:
    82                  continue
    83              if tokens[0] == "nexthop":
    84                  # multipath nexthops
    85                  routes[current_mpath_dest].add(tokens[2])
    86              elif tokens[1] == "via":
    87                  # single nexthop route
    88                  routes[tokens[0]] = set([tokens[2]])
    89                  current_mpath_dest = ""
    90              elif tokens[1] == "proto":
    91                  # multipath route line 1
    92                  routes[tokens[0]] = set()
    93                  current_mpath_dest = tokens[0]
    94          return routes
    95  
    96      def test_01_neighbors_established(self):
    97          self.g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=self.g2)
    98          self.g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=self.g3)
    99  
   100      def test_02_add_multipath_vrf_route(self):
   101          self.g1.local('ip netns add ns01')
   102          self.g1.local('ip netns add ns02')
   103          self.g2.local('ip netns add ns01')
   104          self.g2.local('ip netns add ns02')
   105          self.g3.local('ip netns add ns01')
   106          self.g3.local('ip netns add ns02')
   107  
   108          self.g1.local('ip netns exec ns01 ip li set up dev lo')
   109          self.g1.local('ip netns exec ns01 ip addr add 127.0.0.2/8 dev lo')
   110          self.g1.local('ip netns exec ns02 ip li set up dev lo')
   111          self.g1.local('ip netns exec ns02 ip addr add 127.0.0.2/8 dev lo')
   112  
   113          self.g2.local('ip netns exec ns01 ip li set up dev lo')
   114          self.g2.local('ip netns exec ns01 ip addr add 127.0.0.2/8 dev lo')
   115          self.g2.local('ip netns exec ns02 ip li set up dev lo')
   116          self.g2.local('ip netns exec ns02 ip addr add 127.0.0.2/8 dev lo')
   117  
   118          self.g3.local('ip netns exec ns01 ip li set up dev lo')
   119          self.g3.local('ip netns exec ns01 ip addr add 127.0.0.2/8 dev lo')
   120          self.g3.local('ip netns exec ns02 ip li set up dev lo')
   121          self.g3.local('ip netns exec ns02 ip addr add 127.0.0.2/8 dev lo')
   122  
   123          self.g1.local("vtysh -c 'enable' -c 'conf t' -c 'vrf 1 netns ns01'")
   124          self.g1.local("vtysh -c 'enable' -c 'conf t' -c 'vrf 2 netns ns02'")
   125          self.g2.local("vtysh -c 'enable' -c 'conf t' -c 'vrf 1 netns ns01'")
   126          self.g2.local("vtysh -c 'enable' -c 'conf t' -c 'vrf 2 netns ns02'")
   127          self.g3.local("vtysh -c 'enable' -c 'conf t' -c 'vrf 1 netns ns01'")
   128          self.g3.local("vtysh -c 'enable' -c 'conf t' -c 'vrf 2 netns ns02'")
   129  
   130          self.g1.local("gobgp vrf add vrf01 id 1 rd 1:1 rt both 1:1")
   131          self.g1.local("gobgp vrf add vrf02 id 2 rd 2:2 rt both 2:2")
   132          self.g2.local("gobgp vrf add vrf01 id 1 rd 1:1 rt both 1:1")
   133          self.g2.local("gobgp vrf add vrf02 id 2 rd 2:2 rt both 2:2")
   134          self.g3.local("gobgp vrf add vrf01 id 1 rd 1:1 rt both 1:1")
   135          self.g3.local("gobgp vrf add vrf02 id 2 rd 2:2 rt both 2:2")
   136  
   137          self.g2.local("gobgp vrf vrf01 rib add 10.0.0.0/24 nexthop 127.0.0.1")
   138          self.g2.local("gobgp vrf vrf02 rib add 20.0.0.0/24 nexthop 127.0.0.1")
   139  
   140          time.sleep(2)
   141  
   142          lines = self.g1.local("ip netns exec ns01 ip r", capture=True).split('\n')
   143          kernel_routes = self.parse_ip_route(lines)
   144          self.assertEqual(len(kernel_routes), 1)
   145          self.assertEqual(kernel_routes['10.0.0.0/24'], set(['127.0.0.1']))
   146  
   147          lines = self.g1.local("ip netns exec ns02 ip r", capture=True).split('\n')
   148          kernel_routes = self.parse_ip_route(lines)
   149          self.assertEqual(len(kernel_routes), 1)
   150          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1']))
   151  
   152          self.g3.local("gobgp vrf vrf01 rib add 10.0.0.0/24 nexthop 127.0.0.2")
   153          self.g3.local("gobgp vrf vrf02 rib add 20.0.0.0/24 nexthop 127.0.0.2")
   154  
   155          time.sleep(2)
   156  
   157          lines = self.g1.local("ip netns exec ns01 ip r", capture=True).split('\n')
   158          kernel_routes = self.parse_ip_route(lines)
   159          self.assertEqual(len(kernel_routes), 1)
   160          self.assertEqual(kernel_routes['10.0.0.0/24'], set(['127.0.0.1', '127.0.0.2']))
   161  
   162          lines = self.g1.local("ip netns exec ns02 ip r", capture=True).split('\n')
   163          kernel_routes = self.parse_ip_route(lines)
   164          self.assertEqual(len(kernel_routes), 1)
   165          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1', '127.0.0.2']))
   166  
   167      def test_03_remove_vrf_route_from_multipath(self):
   168          self.g3.local("gobgp vrf vrf01 rib del 10.0.0.0/24 nexthop 127.0.0.2")
   169          self.g3.local("gobgp vrf vrf02 rib del 20.0.0.0/24 nexthop 127.0.0.2")
   170  
   171          time.sleep(2)
   172  
   173          lines = self.g1.local("ip netns exec ns01 ip r", capture=True).split('\n')
   174          kernel_routes = self.parse_ip_route(lines)
   175          self.assertEqual(len(kernel_routes), 1)
   176          self.assertEqual(kernel_routes['10.0.0.0/24'], set(['127.0.0.1']))
   177  
   178          lines = self.g1.local("ip netns exec ns02 ip r", capture=True).split('\n')
   179          kernel_routes = self.parse_ip_route(lines)
   180          self.assertEqual(len(kernel_routes), 1)
   181          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1']))
   182  
   183          self.g2.local("gobgp vrf vrf01 rib del 10.0.0.0/24 nexthop 127.0.0.1")
   184          self.g2.local("gobgp vrf vrf02 rib del 20.0.0.0/24 nexthop 127.0.0.1")
   185  
   186          lines = self.g1.local("ip netns exec ns01 ip r", capture=True).split('\n')
   187          kernel_routes = self.parse_ip_route(lines)
   188          self.assertEqual(len(kernel_routes), 0)
   189  
   190          lines = self.g1.local("ip netns exec ns02 ip r", capture=True).split('\n')
   191          kernel_routes = self.parse_ip_route(lines)
   192          self.assertEqual(len(kernel_routes), 0)
   193  
   194      def test_04_multipath_with_vrf_import(self):
   195          self.g1.local("gobgp vrf del vrf01")
   196          self.g1.local("gobgp vrf add vrf01 id 1 rd 1:1 rt import 1:1 2:2 3:3 export 1:1")
   197  
   198          self.g2.local("gobgp vrf vrf01 rib add 10.0.0.0/24 nexthop 127.0.0.1")
   199          self.g2.local("gobgp vrf vrf02 rib add 20.0.0.0/24 nexthop 127.0.0.1")
   200  
   201          time.sleep(2)
   202  
   203          lines = self.g1.local("ip netns exec ns01 ip r", capture=True).split('\n')
   204          kernel_routes = self.parse_ip_route(lines)
   205          self.assertEqual(len(kernel_routes), 2)
   206          self.assertEqual(kernel_routes['10.0.0.0/24'], set(['127.0.0.1']))
   207          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1']))
   208  
   209          lines = self.g1.local("ip netns exec ns02 ip r", capture=True).split('\n')
   210          kernel_routes = self.parse_ip_route(lines)
   211          self.assertEqual(len(kernel_routes), 1)
   212          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1']))
   213  
   214          self.g3.local("gobgp vrf vrf01 rib add 10.0.0.0/24 nexthop 127.0.0.2")
   215          self.g3.local("gobgp vrf vrf02 rib add 20.0.0.0/24 nexthop 127.0.0.2")
   216  
   217          time.sleep(2)
   218  
   219          lines = self.g1.local("ip netns exec ns01 ip r", capture=True).split('\n')
   220          kernel_routes = self.parse_ip_route(lines)
   221          self.assertEqual(len(kernel_routes), 2)
   222          self.assertEqual(kernel_routes['10.0.0.0/24'], set(['127.0.0.1', '127.0.0.2']))
   223          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1', '127.0.0.2']))
   224  
   225          lines = self.g1.local("ip netns exec ns02 ip r", capture=True).split('\n')
   226          kernel_routes = self.parse_ip_route(lines)
   227          self.assertEqual(len(kernel_routes), 1)
   228          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1', '127.0.0.2']))
   229  
   230      def test_05_cleanup_multipath_vrf_import(self):
   231          self.g3.local("gobgp vrf vrf01 rib del 10.0.0.0/24 nexthop 127.0.0.2")
   232          self.g3.local("gobgp vrf vrf02 rib del 20.0.0.0/24 nexthop 127.0.0.2")
   233  
   234          time.sleep(2)
   235  
   236          lines = self.g1.local("ip netns exec ns01 ip r", capture=True).split('\n')
   237          kernel_routes = self.parse_ip_route(lines)
   238          self.assertEqual(len(kernel_routes), 2)
   239          self.assertEqual(kernel_routes['10.0.0.0/24'], set(['127.0.0.1']))
   240          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1']))
   241  
   242          lines = self.g1.local("ip netns exec ns02 ip r", capture=True).split('\n')
   243          kernel_routes = self.parse_ip_route(lines)
   244          self.assertEqual(len(kernel_routes), 1)
   245          self.assertEqual(kernel_routes['20.0.0.0/24'], set(['127.0.0.1']))
   246  
   247          self.g2.local("gobgp vrf vrf01 rib del 10.0.0.0/24 nexthop 127.0.0.1")
   248          self.g2.local("gobgp vrf vrf02 rib del 20.0.0.0/24 nexthop 127.0.0.1")
   249  
   250          lines = self.g1.local("ip netns exec ns01 ip r", capture=True).split('\n')
   251          kernel_routes = self.parse_ip_route(lines)
   252          self.assertEqual(len(kernel_routes), 0)
   253  
   254          lines = self.g1.local("ip netns exec ns02 ip r", capture=True).split('\n')
   255          kernel_routes = self.parse_ip_route(lines)
   256          self.assertEqual(len(kernel_routes), 0)
   257  
   258  
   259  if __name__ == '__main__':
   260      output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True)
   261      if int(output) != 0:
   262          print("docker not found")
   263          sys.exit(1)
   264  
   265      nose.main(argv=sys.argv, addplugins=[OptionParser()],
   266                defaultTest=sys.argv[0])