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])