github.com/osrg/gobgp/v3@v3.30.0/test/scenario_test/mup_test.py (about) 1 # Copyright (C) 2022 Yuya Kusakabe <yuya.kusakabe@gmail.com> 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 from itertools import combinations 18 import sys 19 import time 20 import unittest 21 import logging 22 log = logging.getLogger(__name__) 23 24 import collections 25 collections.Callable = collections.abc.Callable 26 27 import nose 28 29 from lib.noseplugin import OptionParser, parser_option 30 31 from lib import base 32 from lib.base import ( 33 BGP_FSM_ESTABLISHED, 34 BGP_ATTR_TYPE_EXTENDED_COMMUNITIES, 35 local, 36 ) 37 from lib.gobgp import GoBGPContainer 38 39 40 class GoBGPTestBase(unittest.TestCase): 41 42 @classmethod 43 def setUpClass(cls): 44 gobgp_ctn_image_name = parser_option.gobgp_image 45 base.TEST_PREFIX = parser_option.test_prefix 46 47 g1 = GoBGPContainer(name='g1', asn=65000, router_id='192.168.0.1', 48 ctn_image_name=gobgp_ctn_image_name, 49 log_level=parser_option.gobgp_log_level) 50 g2 = GoBGPContainer(name='g2', asn=65000, router_id='192.168.0.2', 51 ctn_image_name=gobgp_ctn_image_name, 52 log_level=parser_option.gobgp_log_level) 53 ctns = [g1, g2] 54 55 initial_wait_time = max(ctn.run() for ctn in ctns) 56 57 time.sleep(initial_wait_time) 58 59 for a, b in combinations(ctns, 2): 60 a.add_peer(b, mup=True, passwd='mup') 61 b.add_peer(a, mup=True, passwd='mup') 62 63 cls.g1 = g1 64 cls.g2 = g2 65 66 67 # test each neighbor state is turned establish 68 def test_01_neighbor_established(self): 69 self.g1.wait_for(expected_state=BGP_FSM_ESTABLISHED, peer=self.g2) 70 71 72 def test_02_add_del_mup_route(self): 73 tests = [ 74 ('mup_isd_route_ipv4', 'ipv4-mup', 'isd 10.0.0.0/24 rd 100:100 prefix 2001:db8:1:1::/64 locator-node-length 24 function-length 16 behavior ENDM_GTP4E rt 10:10 nexthop 2001::2', '2001::2'), 75 ('mup_dsd_route_ipv4', 'ipv4-mup', 'dsd 10.0.0.1 rd 100:100 prefix 2001:db8:2:2::/64 locator-node-length 24 function-length 16 behavior END_DT4 rt 10:10 mup 10:10 nexthop 2001::2', '2001::2'), 76 ('mup_t1st_route_ipv4', 'ipv4-mup', 't1st 192.168.0.1/32 rd 100:100 rt 10:10 teid 12345 qfi 9 endpoint 10.0.0.1 nexthop 10.0.0.2', '10.0.0.2'), 77 ('mup_t1st_route_ipv4_with_source', 'ipv4-mup', 't1st 192.168.0.1/32 rd 100:100 rt 10:10 teid 12345 qfi 9 endpoint 10.0.0.1 source 10.0.0.3 nexthop 10.0.0.2', '10.0.0.2'), 78 ('mup_t1st_route_ipv4_hex_teid', 'ipv4-mup', 't1st 192.168.0.1/32 rd 100:100 rt 10:10 teid 0x00003039 qfi 9 endpoint 10.0.0.1 nexthop 10.0.0.2', '10.0.0.2'), 79 ('mup_t1st_route_ipv4_ip_teid', 'ipv4-mup', 't1st 192.168.0.1/32 rd 100:100 rt 10:10 teid 0.0.0.100 qfi 9 endpoint 10.0.0.1 nexthop 10.0.0.2', '10.0.0.2'), 80 ('mup_t2st_route_ipv4', 'ipv4-mup', 't2st 10.0.0.1 rd 100:100 rt 10:10 endpoint-address-length 64 teid 12345 mup 10:10 nexthop 10.0.0.2', '10.0.0.2'), 81 ('mup_t2st_route_ipv4_hex_teid', 'ipv4-mup', 't2st 10.0.0.1 rd 100:100 rt 10:10 endpoint-address-length 48 teid 0xbeef mup 10:10 nexthop 10.0.0.2', '10.0.0.2'), 82 ('mup_t2st_route_ipv4_ip_teid', 'ipv4-mup', 't2st 10.0.0.1 rd 100:100 rt 10:10 endpoint-address-length 64 teid 0.0.0.100 mup 10:10 nexthop 10.0.0.2', '10.0.0.2'), 83 ('mup_isd_route_ipv6', 'ipv6-mup', 'isd 2001::/64 rd 100:100 prefix 2001:db8:1:1::/64 locator-node-length 24 function-length 16 behavior ENDM_GTP6E rt 10:10 nexthop 2001::2', '2001::2'), 84 ('mup_dsd_route_ipv6', 'ipv6-mup', 'dsd 2001::1 rd 100:100 prefix 2001:db8:2:2::/64 locator-node-length 24 function-length 16 behavior END_DT6 rt 10:10 mup 10:10 nexthop 2001::2', '2001::2'), 85 ('mup_t1st_route_ipv6', 'ipv6-mup', 't1st 2001:db8:1:1::1/128 rd 100:100 rt 10:10 teid 12345 qfi 9 endpoint 2001::1 nexthop 10.0.0.2', '10.0.0.2'), 86 ('mup_t1st_route_ipv6_with_source', 'ipv6-mup', 't1st 2001:db8:1:1::1/128 rd 100:100 rt 10:10 teid 12345 qfi 9 endpoint 2001::1 source 2001::2 nexthop 10.0.0.2', '10.0.0.2'), 87 ('mup_t1st_route_ipv6_hex_teid', 'ipv6-mup', 't1st 2001:db8:1:1::1/128 rd 100:100 rt 10:10 teid 0x00003039 qfi 9 endpoint 2001::1 nexthop 10.0.0.2', '10.0.0.2'), 88 ('mup_t1st_route_ipv6_ip_teid', 'ipv6-mup', 't1st 2001:db8:1:1::1/128 rd 100:100 rt 10:10 teid 0.0.0.100 qfi 9 endpoint 2001::1 nexthop 10.0.0.2', '10.0.0.2'), 89 ('mup_t2st_route_ipv6', 'ipv6-mup', 't2st 2001::1 rd 100:100 rt 10:10 endpoint-address-length 160 teid 12345 mup 10:10 nexthop 10.0.0.2', '10.0.0.2'), 90 ('mup_t2st_route_ipv6_hex_teid', 'ipv6-mup', 't2st 2001::1 rd 100:100 rt 10:10 endpoint-address-length 144 teid 0xbeef mup 10:10 nexthop 10.0.0.2', '10.0.0.2'), 91 ('mup_t2st_route_ipv6_ip_teid', 'ipv6-mup', 't2st 2001::1 rd 100:100 rt 10:10 endpoint-address-length 160 teid 0.0.0.100 mup 10:10 nexthop 10.0.0.2', '10.0.0.2'), 92 ] 93 for msg, rf, route, nh in tests: 94 with self.subTest(msg): 95 self.g1.local('gobgp global rib add ' 96 '-a {} {}'.format(rf, route)) 97 grib = self.g1.get_global_rib(rf=rf) 98 log.debug('grib: {}'.format(grib)) 99 self.assertEqual(len(grib), 1) 100 dst = grib[0] 101 self.assertEqual(len(dst['paths']), 1) 102 path = dst['paths'][0] 103 self.assertEqual(path['nexthop'], nh) 104 105 interval = 1 106 timeout = int(30 / interval) 107 done = False 108 for _ in range(timeout): 109 if done: 110 break 111 grib = self.g2.get_global_rib(rf=rf) 112 113 if len(grib) < 1: 114 time.sleep(interval) 115 continue 116 117 self.assertEqual(len(grib), 1) 118 dst = grib[0] 119 self.assertEqual(len(dst['paths']), 1) 120 path = dst['paths'][0] 121 n_addrs = [i[1].split('/')[0] for i in self.g1.ip_addrs] 122 self.assertEqual(path['nexthop'], nh) 123 done = True 124 125 self.g1.local('gobgp global rib del ' 126 '-a {} {}'.format(rf, route)) 127 128 done = False 129 for _ in range(timeout): 130 if done: 131 break 132 grib = self.g2.get_global_rib(rf=rf) 133 134 if len(grib) > 0: 135 time.sleep(interval) 136 continue 137 done = True 138 139 140 if __name__ == '__main__': 141 output = local("which docker 2>&1 > /dev/null ; echo $?", capture=True) 142 if int(output) != 0: 143 print("docker not found") 144 sys.exit(1) 145 146 nose.main(argv=sys.argv, addplugins=[OptionParser()], 147 defaultTest=sys.argv[0])