New version of RF tests.
[csit.git] / resources / libraries / python / IPv6Setup.py
1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """Library to set up IPv6 in topology."""
15
16 from ssh import SSH
17 from ipaddress import IPv6Network
18 from topology import NodeType
19 from topology import Topology
20 from constants import Constants
21
22
23 class IPv6Networks(object):
24     """IPv6 network iterator.
25
26        :param networks: List of the available IPv6 networks.
27        :type networks: list
28     """
29     def __init__(self, networks):
30         self._networks = list()
31         for network in networks:
32             net = IPv6Network(unicode(network))
33             self._networks.append(net)
34         num = len(self._networks)
35         if num == 0:
36             raise Exception('No IPv6 networks')
37
38     def next_network(self):
39         """Get the next elemnt of the iterator.
40
41            :return: IPv6 network.
42            :rtype: IPv6Network object
43            :raises: StopIteration if there is no more elements.
44         """
45         if len(self._networks):
46             return self._networks.pop()
47         else:
48             raise StopIteration()
49
50
51 class IPv6Setup(object):
52     """IPv6 setup in topology."""
53
54     def __init__(self):
55         pass
56
57     def nodes_setup_ipv6_addresses(self, nodes, nodes_addr):
58         """Setup IPv6 addresses on all VPP nodes in topology.
59
60            :param nodes: Nodes of the test topology.
61            :param nodes_addr: Available nodes IPv6 adresses.
62            :type nodes: dict
63            :type nodes_addr: dict
64         """
65         for net in nodes_addr.values():
66             for port in net['ports'].values():
67                 host = port.get('node')
68                 if host is None:
69                     continue
70                 topo = Topology()
71                 node = topo.get_node_by_hostname(nodes, host)
72                 if node is None:
73                     continue
74                 if node['type'] == NodeType.DUT:
75                     self.vpp_set_if_ipv6_addr(node, port['if'], port['addr'],
76                                               net['prefix'])
77
78     def nodes_clear_ipv6_addresses(self, nodes, nodes_addr):
79         """Remove IPv6 addresses from all VPP nodes in topology.
80
81            :param nodes: Nodes of the test topology.
82            :param nodes_addr: Available nodes IPv6 adresses.
83            :type nodes: dict
84            :type nodes_addr: dict
85          """
86         for net in nodes_addr.values():
87             for port in net['ports'].values():
88                 host = port.get('node')
89                 if host is None:
90                     continue
91                 topo = Topology()
92                 node = topo.get_node_by_hostname(nodes, host)
93                 if node is None:
94                     continue
95                 if node['type'] == NodeType.DUT:
96                     self.vpp_del_if_ipv6_addr(node, port['if'], port['addr'],
97                                               net['prefix'])
98
99     @staticmethod
100     def linux_set_if_ipv6_addr(node, interface, addr, prefix):
101         """Set IPv6 address on linux host.
102
103            :param node: Linux node.
104            :param interface: Node interface.
105            :param addr: IPv6 address.
106            :param prefix: IPv6 address prefix.
107            :type node: dict
108            :type interface: str
109            :type addr: str
110            :type prefix: str
111         """
112         ssh = SSH()
113         ssh.connect(node)
114
115         cmd = "ifconfig {dev} inet6 add {ip}/{p} up".format(dev=interface,
116                                                             ip=addr, p=prefix)
117         (ret_code, _, _) = ssh.exec_command_sudo(cmd)
118         if int(ret_code) != 0:
119             raise Exception('TG ifconfig failed')
120
121     @staticmethod
122     def linux_del_if_ipv6_addr(node, interface, addr, prefix):
123         """Delete IPv6 address on linux host.
124
125            :param node: Linux node.
126            :param interface: Node interface.
127            :param addr: IPv6 address.
128            :param prefix: IPv6 address prefix.
129            :type node: dict
130            :type interface: str
131            :type addr: str
132            :type prefix: str
133         """
134         ssh = SSH()
135         ssh.connect(node)
136
137         cmd = "ifconfig {dev} inet6 del {ip}/{p}".format(dev=interface,
138                                                          ip=addr,
139                                                          p=prefix)
140         (ret_code, _, _) = ssh.exec_command_sudo(cmd)
141         if int(ret_code) != 0:
142             raise Exception('TG ifconfig failed')
143
144         cmd = "ifconfig {dev} down".format(dev=interface)
145         (ret_code, _, _) = ssh.exec_command_sudo(cmd)
146         if int(ret_code) != 0:
147             raise Exception('TG ifconfig failed')
148
149     @staticmethod
150     def vpp_set_if_ipv6_addr(node, interface, addr, prefix):
151         """Set IPv6 address on VPP.
152
153            :param node: VPP node.
154            :param interface: Node interface.
155            :param addr: IPv6 address.
156            :param prefix: IPv6 address prefix.
157            :type node: dict
158            :type interface: str
159            :type addr: str
160            :type prefix: str
161         """
162         ssh = SSH()
163         ssh.connect(node)
164
165         cmd = '{c}'.format(c=Constants.VAT_BIN_NAME)
166         cmd_input = 'sw_interface_add_del_address {dev} {ip}/{p}'.format(
167             dev=interface, ip=addr, p=prefix)
168         (ret_code, _, _) = ssh.exec_command_sudo(cmd, cmd_input)
169         if int(ret_code) != 0:
170             raise Exception('VPP sw_interface_add_del_address failed on {h}'
171                             .format(h=node['host']))
172
173         cmd_input = 'sw_interface_set_flags {dev} admin-up'.format(
174             dev=interface)
175         (ret_code, _, _) = ssh.exec_command_sudo(cmd, cmd_input)
176         if int(ret_code) != 0:
177             raise Exception('VPP sw_interface_set_flags failed on {h}'.format(
178                 h=node['host']))
179
180     @staticmethod
181     def vpp_del_if_ipv6_addr(node, interface, addr, prefix):
182         """Delete IPv6 address on VPP.
183
184            :param node: VPP node.
185            :param interface: Node interface.
186            :param addr: IPv6 address.
187            :param prefix: IPv6 address prefix.
188            :type node: dict
189            :type interface: str
190            :type addr: str
191            :type prefix: str
192         """
193         ssh = SSH()
194         ssh.connect(node)
195
196         cmd = '{c}'.format(c=Constants.VAT_BIN_NAME)
197         cmd_input = 'sw_interface_add_del_address {dev} {ip}/{p} del'.format(
198             dev=interface, ip=addr, p=prefix)
199         (ret_code, _, _) = ssh.exec_command_sudo(cmd, cmd_input)
200         if int(ret_code) != 0:
201             raise Exception(
202                 'sw_interface_add_del_address failed on {h}'.
203                 format(h=node['host']))
204
205         cmd_input = 'sw_interface_set_flags {dev} admin-down'.format(
206             dev=interface)
207         (ret_code, _, _) = ssh.exec_command_sudo(cmd, cmd_input)
208         if int(ret_code) != 0:
209             raise Exception('VPP sw_interface_set_flags failed on {h}'.format(
210                 h=node['host']))
211
212     @staticmethod
213     def vpp_ra_supress_link_layer(node, interface):
214         """Supress ICMPv6 router advertisement message for link scope address
215
216            :param node: VPP node.
217            :param interface: Interface name.
218            :type node: dict
219            :type interface: str
220         """
221         ssh = SSH()
222         ssh.connect(node)
223
224         cmd = '{c}'.format(c=Constants.VAT_BIN_NAME)
225         cmd_input = 'exec ip6 nd {0} ra-surpress-link-layer'.format(
226             interface)
227         (ret_code, _, _) = ssh.exec_command_sudo(cmd, cmd_input)
228         if int(ret_code) != 0:
229             raise Exception("'{0}' failed on {1}".format(cmd_input,
230                                                          node['host']))
231
232     def vpp_all_ra_supress_link_layer(self, nodes):
233         """Supress ICMPv6 router advertisement message for link scope address
234            on all VPP nodes in the topology
235
236            :param nodes: Nodes of the test topology.
237            :type nodes: dict
238         """
239         for node in nodes.values():
240             if node['type'] == NodeType.TG:
241                 continue
242             for port_k, port_v in node['interfaces'].items():
243                 if port_k == 'mgmt':
244                     continue
245                 if_name = port_v.get('name')
246                 if if_name is None:
247                     continue
248                 self.vpp_ra_supress_link_layer(node, if_name)
249
250     @staticmethod
251     def vpp_ipv6_route_add(node, link, interface, nodes_addr):
252         """Setup IPv6 route on the VPP node.
253
254            :param node: Node to add route on.
255            :param link: Route to following link.
256            :param interface: Route output interface.
257            :param nodes_addr: Available nodes IPv6 adresses.
258            :type node: dict
259            :type link: str
260            :type interface: str
261            :type nodes_addr: dict
262         """
263         ssh = SSH()
264         ssh.connect(node)
265
266         # Get route destination address from link name
267         net = nodes_addr.get(link)
268         if net is None:
269             raise ValueError('No network for link "{0}"'.format(link))
270         dst_net = '{0}/{1}'.format(net['net_addr'], net['prefix'])
271
272         # Get next-hop address
273         nh_addr = None
274         for net in nodes_addr.values():
275             for port in net['ports'].values():
276                 if port['if'] == interface and port['node'] == node['host']:
277                     for nh in net['ports'].values():
278                         if nh['if'] != interface and nh['node'] != node['host']:
279                             nh_addr = nh['addr']
280         if nh_addr is None:
281             raise Exception('next-hop not found')
282
283         cmd_input = 'ip_add_del_route {0} via {1} {2} resolve-attempts 10'. \
284             format(dst_net, nh_addr, interface)
285         (ret_code, _, _) = ssh.exec_command_sudo(Constants.VAT_BIN_NAME,
286                                                  cmd_input)
287         if int(ret_code) != 0:
288             raise Exception("'{0}' failed on {1}".format(cmd_input,
289                                                          node['host']))