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 """IPv4 setup library"""
16 from socket import inet_ntoa
17 from struct import pack
18 from abc import ABCMeta, abstractmethod
19 from robot.api.deco import keyword
21 import resources.libraries.python.ssh as ssh
22 from resources.libraries.python.Routing import Routing
23 from resources.libraries.python.InterfaceUtil import InterfaceUtil
24 from resources.libraries.python.topology import NodeType, Topology
25 from resources.libraries.python.VatExecutor import VatExecutor
28 class IPv4Node(object):
29 """Abstract class of a node in a topology."""
30 __metaclass__ = ABCMeta
32 def __init__(self, node_info):
33 self.node_info = node_info
36 def _get_netmask(prefix_length):
37 bits = 0xffffffff ^ (1 << 32 - prefix_length) - 1
38 return inet_ntoa(pack('>I', bits))
41 def set_ip(self, interface, address, prefix_length):
42 """Configure IPv4 address on interface
44 :param interface: interface name
49 :type prefix_length: int
55 def set_route(self, network, prefix_length, gateway, interface):
56 """Configure IPv4 route
58 :param network: network IPv4 address
59 :param prefix_length: mask length
60 :param gateway: IPv4 address of the gateway
61 :param interface: interface name
63 :type prefix_length: int
71 def unset_route(self, network, prefix_length, gateway, interface):
72 """Remove specified IPv4 route
74 :param network: network IPv4 address
75 :param prefix_length: mask length
76 :param gateway: IPv4 address of the gateway
77 :param interface: interface name
79 :type prefix_length: int
87 def flush_ip_addresses(self, interface):
88 """Flush all IPv4 addresses from specified interface
90 :param interface: interface name
97 def ping(self, destination_address, source_interface):
98 """Send an ICMP request to destination node
100 :param destination_address: address to send the ICMP request
101 :param source_interface:
102 :type destination_address: str
103 :type source_interface: str
110 """Traffic generator node"""
111 def __init__(self, node_info):
112 super(Tg, self).__init__(node_info)
114 def _execute(self, cmd):
115 return ssh.exec_cmd_no_error(self.node_info, cmd)
117 def _sudo_execute(self, cmd):
118 return ssh.exec_cmd_no_error(self.node_info, cmd, sudo=True)
120 def set_ip(self, interface, address, prefix_length):
121 cmd = 'ip -4 addr flush dev {}'.format(interface)
122 self._sudo_execute(cmd)
123 cmd = 'ip addr add {}/{} dev {}'.format(address, prefix_length,
125 self._sudo_execute(cmd)
127 def set_route(self, network, prefix_length, gateway, interface):
128 netmask = self._get_netmask(prefix_length)
129 cmd = 'route add -net {} netmask {} gw {}'.\
130 format(network, netmask, gateway)
131 self._sudo_execute(cmd)
133 def unset_route(self, network, prefix_length, gateway, interface):
134 self._sudo_execute('ip route delete {}/{}'.
135 format(network, prefix_length))
137 def arp_ping(self, destination_address, source_interface):
138 self._sudo_execute('arping -c 1 -I {} {}'.format(source_interface,
139 destination_address))
141 def ping(self, destination_address, source_interface):
142 self._execute('ping -c 1 -w 5 -I {} {}'.format(source_interface,
143 destination_address))
145 def flush_ip_addresses(self, interface):
146 self._sudo_execute('ip addr flush dev {}'.format(interface))
150 """Device under test"""
151 def __init__(self, node_info):
152 super(Dut, self).__init__(node_info)
154 def get_sw_if_index(self, interface):
155 """Get sw_if_index of specified interface from current node
157 :param interface: interface name
159 :return: sw_if_index of 'int' type
161 return Topology().get_interface_sw_index(self.node_info, interface)
163 def exec_vat(self, script, **args):
164 """Wrapper for VAT executor.
166 :param script: script to execute
167 :param args: parameters to the script
172 # TODO: check return value
173 VatExecutor.cmd_from_template(self.node_info, script, **args)
175 def set_arp(self, interface, ip_address, mac_address):
176 """Set entry in ARP cache.
178 :param interface: Interface name.
179 :param ip_address: IP address.
180 :param mac_address: MAC address.
182 :type ip_address: str
183 :type mac_address: str
185 self.exec_vat('add_ip_neighbor.vat',
186 sw_if_index=self.get_sw_if_index(interface),
187 ip_address=ip_address, mac_address=mac_address)
189 def set_ip(self, interface, address, prefix_length):
190 self.exec_vat('add_ip_address.vat',
191 sw_if_index=self.get_sw_if_index(interface),
192 address=address, prefix_length=prefix_length)
194 def set_route(self, network, prefix_length, gateway, interface):
195 Routing.vpp_route_add(self.node_info,
196 network=network, prefix_len=prefix_length,
197 gateway=gateway, interface=interface)
199 def unset_route(self, network, prefix_length, gateway, interface):
200 self.exec_vat('del_route.vat', network=network,
201 prefix_length=prefix_length, gateway=gateway,
202 sw_if_index=self.get_sw_if_index(interface))
204 def arp_ping(self, destination_address, source_interface):
207 def flush_ip_addresses(self, interface):
208 self.exec_vat('flush_ip_addresses.vat',
209 sw_if_index=self.get_sw_if_index(interface))
211 def ping(self, destination_address, source_interface):
215 def get_node(node_info):
216 """Creates a class instance derived from Node based on type.
218 :param node_info: dictionary containing information on nodes in topology
219 :return: Class instance that is derived from Node
221 if node_info['type'] == NodeType.TG:
223 elif node_info['type'] == NodeType.DUT:
224 return Dut(node_info)
226 raise NotImplementedError('Node type "{}" unsupported!'.
227 format(node_info['type']))
230 class IPv4Setup(object):
231 """IPv4 setup in topology."""
234 def vpp_nodes_setup_ipv4_addresses(nodes, nodes_addr):
235 """Setup IPv4 addresses on all VPP nodes in topology.
237 :param nodes: Nodes of the test topology.
238 :param nodes_addr: Available nodes IPv4 adresses.
240 :type nodes_addr: dict
242 for net in nodes_addr.values():
243 for port in net['ports'].values():
244 host = port.get('node')
248 node = topo.get_node_by_hostname(nodes, host)
251 if node['type'] != NodeType.DUT:
253 get_node(node).set_ip(port['if'], port['addr'], net['prefix'])
254 InterfaceUtil.set_interface_state(node, port['if'], 'up')
257 @keyword('Get IPv4 address of node "${node}" interface "${port}" '
258 'from "${nodes_addr}"')
259 def get_ip_addr(node, interface, nodes_addr):
260 """Return IPv4 address of the node port.
261 :param node: Node in the topology.
262 :param interface: Interface name of the node.
263 :param nodes_addr: Nodes IPv4 adresses.
266 :type nodes_addr: dict
267 :return: IPv4 address string
269 for net in nodes_addr.values():
270 for port in net['ports'].values():
271 host = port.get('node')
273 if host == node['host'] and dev == interface:
274 ip = port.get('addr')
279 'Node {n} port {p} IPv4 address is not set'.format(
280 n=node['host'], p=interface))
282 raise Exception('Node {n} port {p} IPv4 address not found.'.format(
283 n=node['host'], p=interface))
286 def setup_arp_on_all_duts(nodes_info, nodes_addr):
287 """For all DUT nodes extract MAC and IP addresses of adjacent
288 interfaces from topology and use them to setup ARP entries.
290 :param nodes_info: Dictionary containing information on all nodes
292 :param nodes_addr: Nodes IPv4 adresses.
293 :type nodes_info: dict
294 :type nodes_addr: dict
296 for node in nodes_info.values():
297 if node['type'] == NodeType.TG:
299 for interface, interface_data in node['interfaces'].iteritems():
300 if interface == 'mgmt':
302 interface_name = interface_data['name']
303 adj_node, adj_int = Topology.\
304 get_adjacent_node_and_interface(nodes_info, node,
306 ip_address = IPv4Setup.get_ip_addr(adj_node, adj_int['name'],
308 mac_address = adj_int['mac_address']
309 get_node(node).set_arp(interface_name, ip_address, mac_address)