]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/lib/topojson.py
Merge pull request #6071 from ton31337/feature/rfc6286
[mirror_frr.git] / tests / topotests / lib / topojson.py
CommitLineData
2ad3d000
AP
1#
2# Modified work Copyright (c) 2019 by VMware, Inc. ("VMware")
3# Original work Copyright (c) 2018 by Network Device Education
4# Foundation, Inc. ("NetDEF")
5#
6# Permission to use, copy, modify, and/or distribute this software
7# for any purpose with or without fee is hereby granted, provided
8# that the above copyright notice and this permission notice appear
9# in all copies.
10#
11# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
12# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
14# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
15# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
16# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
17# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
18# OF THIS SOFTWARE.
19#
20
7659b8d4 21from collections import OrderedDict
2ad3d000 22from json import dumps as json_dumps
bca79837 23from re import search as re_search
2ad3d000 24import ipaddr
7659b8d4 25import pytest
2ad3d000
AP
26
27# Import topogen and topotest helpers
28from lib.topolog import logger
29
30# Required to instantiate the topology builder class.
7659b8d4
AP
31from lib.common_config import (
32 number_to_row, number_to_column,
33 load_config_to_router,
e4663527 34 create_interfaces_cfg,
00db2a89
AP
35 create_static_routes,
36 create_prefix_lists,
e6db2bb1 37 create_route_maps,
9920237e 38 create_bgp_community_lists
7659b8d4 39)
2ad3d000 40
7fa2079a 41from lib.bgp import create_router_bgp
2ad3d000 42
bca79837
AP
43ROUTER_LIST = []
44
45
2ad3d000
AP
46def build_topo_from_json(tgen, topo):
47 """
48 Reads configuration from JSON file. Adds routers, creates interface
49 names dynamically and link routers as defined in JSON to create
50 topology. Assigns IPs dynamically to all interfaces of each router.
51
52 * `tgen`: Topogen object
53 * `topo`: json file data
54 """
55
bca79837
AP
56 ROUTER_LIST = sorted(topo['routers'].keys(),
57 key=lambda x: int(re_search('\d+', x).group(0)))
58
59 listRouters = ROUTER_LIST[:]
60 for routerN in ROUTER_LIST:
61 logger.info('Topo: Add router {}'.format(routerN))
62 tgen.add_router(routerN)
63 listRouters.append(routerN)
2ad3d000 64
2ad3d000
AP
65 if 'ipv4base' in topo:
66 ipv4Next = ipaddr.IPv4Address(topo['link_ip_start']['ipv4'])
67 ipv4Step = 2 ** (32 - topo['link_ip_start']['v4mask'])
68 if topo['link_ip_start']['v4mask'] < 32:
69 ipv4Next += 1
70 if 'ipv6base' in topo:
71 ipv6Next = ipaddr.IPv6Address(topo['link_ip_start']['ipv6'])
72 ipv6Step = 2 ** (128 - topo['link_ip_start']['v6mask'])
73 if topo['link_ip_start']['v6mask'] < 127:
74 ipv6Next += 1
75 for router in listRouters:
76 topo['routers'][router]['nextIfname'] = 0
77
78 while listRouters != []:
79 curRouter = listRouters.pop(0)
80 # Physical Interfaces
81 if 'links' in topo['routers'][curRouter]:
82 def link_sort(x):
83 if x == 'lo':
84 return 0
85 elif 'link' in x:
86 return int(x.split('-link')[1])
87 else:
bca79837 88 return int(re_search('\d+', x).group(0))
2ad3d000
AP
89 for destRouterLink, data in sorted(topo['routers'][curRouter]['links']. \
90 iteritems(),
91 key=lambda x: link_sort(x[0])):
92 currRouter_lo_json = \
93 topo['routers'][curRouter]['links'][destRouterLink]
94 # Loopback interfaces
95 if 'type' in data and data['type'] == 'loopback':
96 if 'ipv4' in currRouter_lo_json and \
97 currRouter_lo_json['ipv4'] == 'auto':
98 currRouter_lo_json['ipv4'] = '{}{}.{}/{}'. \
99 format(topo['lo_prefix']['ipv4'], number_to_row(curRouter), \
100 number_to_column(curRouter), topo['lo_prefix']['v4mask'])
101 if 'ipv6' in currRouter_lo_json and \
102 currRouter_lo_json['ipv6'] == 'auto':
103 currRouter_lo_json['ipv6'] = '{}{}:{}/{}'. \
104 format(topo['lo_prefix']['ipv6'], number_to_row(curRouter), \
105 number_to_column(curRouter), topo['lo_prefix']['v6mask'])
106
107 if "-" in destRouterLink:
108 # Spliting and storing destRouterLink data in tempList
109 tempList = destRouterLink.split("-")
110
111 # destRouter
112 destRouter = tempList.pop(0)
113
114 # Current Router Link
115 tempList.insert(0, curRouter)
116 curRouterLink = "-".join(tempList)
117 else:
118 destRouter = destRouterLink
119 curRouterLink = curRouter
120
121 if destRouter in listRouters:
122 currRouter_link_json = \
123 topo['routers'][curRouter]['links'][destRouterLink]
124 destRouter_link_json = \
125 topo['routers'][destRouter]['links'][curRouterLink]
126
127 # Assigning name to interfaces
128 currRouter_link_json['interface'] = \
129 '{}-{}-eth{}'.format(curRouter, destRouter, topo['routers'] \
130 [curRouter]['nextIfname'])
131 destRouter_link_json['interface'] = \
132 '{}-{}-eth{}'.format(destRouter, curRouter, topo['routers'] \
133 [destRouter]['nextIfname'])
134
135 topo['routers'][curRouter]['nextIfname'] += 1
136 topo['routers'][destRouter]['nextIfname'] += 1
137
138 # Linking routers to each other as defined in JSON file
139 tgen.gears[curRouter].add_link(tgen.gears[destRouter],
140 topo['routers'][curRouter]['links'][destRouterLink] \
141 ['interface'], topo['routers'][destRouter]['links'] \
142 [curRouterLink]['interface'])
143
144 # IPv4
145 if 'ipv4' in currRouter_link_json:
146 if currRouter_link_json['ipv4'] == 'auto':
147 currRouter_link_json['ipv4'] = \
148 '{}/{}'.format(ipv4Next, topo['link_ip_start'][ \
149 'v4mask'])
150 destRouter_link_json['ipv4'] = \
151 '{}/{}'.format(ipv4Next + 1, topo['link_ip_start'][ \
152 'v4mask'])
153 ipv4Next += ipv4Step
154 # IPv6
155 if 'ipv6' in currRouter_link_json:
156 if currRouter_link_json['ipv6'] == 'auto':
157 currRouter_link_json['ipv6'] = \
158 '{}/{}'.format(ipv6Next, topo['link_ip_start'][ \
159 'v6mask'])
160 destRouter_link_json['ipv6'] = \
161 '{}/{}'.format(ipv6Next + 1, topo['link_ip_start'][ \
162 'v6mask'])
163 ipv6Next = ipaddr.IPv6Address(int(ipv6Next) + ipv6Step)
164
165 logger.debug("Generated link data for router: %s\n%s", curRouter,
166 json_dumps(topo["routers"][curRouter]["links"],
7fa2079a
AP
167 indent=4, sort_keys=True))
168
7659b8d4
AP
169
170def build_config_from_json(tgen, topo, save_bkup=True):
171 """
172 Reads initial configuraiton from JSON for each router, builds
173 configuration and loads its to router.
174
175 * `tgen`: Topogen object
176 * `topo`: json file data
177 """
178
179 func_dict = OrderedDict([
180 ("links", create_interfaces_cfg),
e4663527 181 ("static_routes", create_static_routes),
00db2a89 182 ("prefix_lists", create_prefix_lists),
9920237e 183 ("bgp_community_list", create_bgp_community_lists),
e6db2bb1 184 ("route_maps", create_route_maps),
7fa2079a 185 ("bgp", create_router_bgp)
7659b8d4
AP
186 ])
187
188 data = topo["routers"]
189 for func_type in func_dict.keys():
bca79837
AP
190 logger.info('Checking for {} configuration in input data'.format(
191 func_type))
7659b8d4
AP
192
193 func_dict.get(func_type)(tgen, data, build=True)
194
195 for router in sorted(topo['routers'].keys()):
bca79837 196 logger.debug('Configuring router {}...'.format(router))
7659b8d4
AP
197
198 result = load_config_to_router(tgen, router, save_bkup)
199 if not result:
200 logger.info("Failed while configuring {}".format(router))
201 pytest.exit(1)
202