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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """Library to set up IPv6 in topology."""
17 from ipaddress import IPv6Network
18 from topology import NodeType
19 from topology import Topology
20 from constants import Constants
23 class IPv6Networks(object):
24 """IPv6 network iterator.
26 :param networks: List of the available IPv6 networks.
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)
36 raise Exception('No IPv6 networks')
38 def next_network(self):
39 """Get the next elemnt of the iterator.
41 :return: IPv6 network.
42 :rtype: IPv6Network object
43 :raises: StopIteration if there is no more elements.
45 if len(self._networks):
46 return self._networks.pop()
51 class IPv6Setup(object):
52 """IPv6 setup in topology."""
57 def nodes_setup_ipv6_addresses(self, nodes, nodes_addr):
58 """Setup IPv6 addresses on all VPP nodes in topology.
60 :param nodes: Nodes of the test topology.
61 :param nodes_addr: Available nodes IPv6 adresses.
63 :type nodes_addr: dict
65 for net in nodes_addr.values():
66 for port in net['ports'].values():
67 host = port.get('node')
71 node = topo.get_node_by_hostname(nodes, host)
74 if node['type'] == NodeType.DUT:
75 self.vpp_set_if_ipv6_addr(node, port['if'], port['addr'],
78 def nodes_clear_ipv6_addresses(self, nodes, nodes_addr):
79 """Remove IPv6 addresses from all VPP nodes in topology.
81 :param nodes: Nodes of the test topology.
82 :param nodes_addr: Available nodes IPv6 adresses.
84 :type nodes_addr: dict
86 for net in nodes_addr.values():
87 for port in net['ports'].values():
88 host = port.get('node')
92 node = topo.get_node_by_hostname(nodes, host)
95 if node['type'] == NodeType.DUT:
96 self.vpp_del_if_ipv6_addr(node, port['if'], port['addr'],
100 def linux_set_if_ipv6_addr(node, interface, addr, prefix):
101 """Set IPv6 address on linux host.
103 :param node: Linux node.
104 :param interface: Node interface.
105 :param addr: IPv6 address.
106 :param prefix: IPv6 address prefix.
115 cmd = "ifconfig {dev} inet6 add {ip}/{p} up".format(dev=interface,
117 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
118 if int(ret_code) != 0:
119 raise Exception('TG ifconfig failed')
122 def linux_del_if_ipv6_addr(node, interface, addr, prefix):
123 """Delete IPv6 address on linux host.
125 :param node: Linux node.
126 :param interface: Node interface.
127 :param addr: IPv6 address.
128 :param prefix: IPv6 address prefix.
137 cmd = "ifconfig {dev} inet6 del {ip}/{p}".format(dev=interface,
140 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
141 if int(ret_code) != 0:
142 raise Exception('TG ifconfig failed')
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')
150 def vpp_set_if_ipv6_addr(node, interface, addr, prefix):
151 """Set IPv6 address on VPP.
153 :param node: VPP node.
154 :param interface: Node interface.
155 :param addr: IPv6 address.
156 :param prefix: IPv6 address prefix.
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']))
173 cmd_input = 'sw_interface_set_flags {dev} admin-up'.format(
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(
181 def vpp_del_if_ipv6_addr(node, interface, addr, prefix):
182 """Delete IPv6 address on VPP.
184 :param node: VPP node.
185 :param interface: Node interface.
186 :param addr: IPv6 address.
187 :param prefix: IPv6 address prefix.
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:
202 'sw_interface_add_del_address failed on {h}'.
203 format(h=node['host']))
205 cmd_input = 'sw_interface_set_flags {dev} admin-down'.format(
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(
213 def vpp_ra_supress_link_layer(node, interface):
214 """Supress ICMPv6 router advertisement message for link scope address
216 :param node: VPP node.
217 :param interface: Interface name.
224 cmd = '{c}'.format(c=Constants.VAT_BIN_NAME)
225 cmd_input = 'exec ip6 nd {0} ra-surpress-link-layer'.format(
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,
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
236 :param nodes: Nodes of the test topology.
239 for node in nodes.values():
240 if node['type'] == NodeType.TG:
242 for port_k, port_v in node['interfaces'].items():
245 if_name = port_v.get('name')
248 self.vpp_ra_supress_link_layer(node, if_name)
251 def vpp_ipv6_route_add(node, link, interface, nodes_addr):
252 """Setup IPv6 route on the VPP node.
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.
261 :type nodes_addr: dict
266 # Get route destination address from link name
267 net = nodes_addr.get(link)
269 raise ValueError('No network for link "{0}"'.format(link))
270 dst_net = '{0}/{1}'.format(net['net_addr'], net['prefix'])
272 # Get next-hop address
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']:
281 raise Exception('next-hop not found')
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,
287 if int(ret_code) != 0:
288 raise Exception("'{0}' failed on {1}".format(cmd_input,