1 # Copyright (c) 2018 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 """Implements IPv4 RobotFramework keywords"""
16 from robot.api import logger as log
17 from robot.api.deco import keyword
19 from resources.libraries.python.topology import Topology
20 from resources.libraries.python.IPv4Setup import get_node
21 from resources.libraries.python.VatExecutor import VatTerminal
22 from resources.libraries.python.ssh import exec_cmd
25 class IPv4Util(object):
26 """Implements keywords for IPv4 tests."""
29 @keyword('From node "${node}" interface "${port}" ARP-ping '
30 'IPv4 address "${ip_address}"')
31 def arp_ping(node, interface, ip_address):
32 """Send an ARP ping from the specified node.
34 :param node: Node in topology.
35 :param ip_address: Destination IP address for the ARP packet.
36 :param interface: Name of an interface to send the ARP packet from.
41 log.debug('From node {} interface {} ARP-ping IPv4 address {}'.
42 format(Topology.get_node_hostname(node),
43 interface, ip_address))
44 get_node(node).arp_ping(ip_address, interface)
47 def set_interface_address(node, interface, address, prefix_length):
48 """See IPv4Node.set_ip for more information.
50 :param node: Node where IP address should be set to.
51 :param interface: Interface name.
52 :param address: IP address.
53 :param prefix_length: Prefix length.
57 :type prefix_length: int
59 log.debug('Node {} interface {} has IPv4 address {} with prefix '
60 'length {}'.format(Topology.get_node_hostname(node),
61 interface, address, prefix_length))
62 get_node(node).set_ip(interface, address, int(prefix_length))
65 def set_route(node, network, prefix_length, interface, gateway):
66 """See IPv4Node.set_route for more information.
68 :param node: Node where IP address should be set to.
69 :param network: IP network.
70 :param prefix_length: Prefix length.
71 :param interface: Interface name.
72 :param gateway: Gateway.
75 :type prefix_length: int
79 log.debug('Node {} routes to network {} with prefix length {} '
80 'via {} interface {}'.format(Topology.get_node_hostname(node),
81 network, prefix_length,
83 get_node(node).set_route(network, int(prefix_length),
87 @keyword('Get IPv4 address prefix of node "${node}" interface "${port}" '
88 'from "${nodes_addr}"')
89 def get_ip_addr_prefix_length(node, port, nodes_addr):
90 """ Get IPv4 address prefix for specified interface.
92 :param node: Node dictionary.
93 :param port: Interface name.
94 :param nodes_addr: Available nodes IPv4 addresses.
97 :type nodes_addr: dict
98 :returns: IPv4 prefix length.
101 for net in nodes_addr.values():
102 for net_port in net['ports'].values():
103 if net_port['node'] == node['host'] and net_port['if'] == port:
106 raise Exception('Subnet not found for node {n} port {p}'.
107 format(n=node['host'], p=port))
110 @keyword('Get IPv4 subnet of node "${node}" interface "${port}" from '
112 def get_ip_addr_subnet(node, port, nodes_addr):
113 """ Get IPv4 subnet of specified interface.
115 :param node: Node dictionary.
116 :param port: Interface name.
117 :param nodes_addr: Available nodes IPv4 addresses.
120 :type nodes_addr: dict
121 :returns: IPv4 subnet.
124 for net in nodes_addr.values():
125 for net_port in net['ports'].values():
126 if net_port['node'] == node['host'] and net_port['if'] == port:
127 return net['net_addr']
129 raise Exception('Subnet not found for node {n} port {p}'.
130 format(n=node['host'], p=port))
133 @keyword('Flush IPv4 addresses "${port}" "${node}"')
134 def flush_ip_addresses(port, node):
135 """See IPv4Node.flush_ip_addresses for more information.
141 get_node(node).flush_ip_addresses(port)
144 def get_link_address(link, nodes_addr):
145 """Get link IPv4 address.
147 :param link: Link name.
148 :param nodes_addr: Available nodes IPv4 addresses.
150 :type nodes_addr: dict
151 :returns: Link IPv4 address.
154 net = nodes_addr.get(link)
156 raise ValueError('Link "{0}" not found'.format(link))
157 return net.get('net_addr')
160 def get_link_prefix(link, nodes_addr):
161 """Get link IPv4 address prefix.
163 :param link: Link name.
164 :param nodes_addr: Available nodes IPv4 addresses.
166 :type nodes_addr: dict
167 :returns: Link IPv4 address prefix.
170 net = nodes_addr.get(link)
172 raise ValueError('Link "{0}" not found'.format(link))
173 return net.get('prefix')
176 def send_ping_from_node_to_dst(node, destination, namespace=None,
177 ping_count=3, interface=None):
178 """Send a ping from node to destination. Optionally, you can define a
179 namespace and interface from where to send a ping.
181 :param node: Node to start ping on.
182 :param destination: IPv4 address where to send ping.
183 :param namespace: Namespace to send ping from. Optional
184 :param ping_count: Number of pings to send. Default 3
185 :param interface: Interface from where to send ping. Optional
187 :type destination: str
189 :type ping_count: int
191 :raises RuntimeError: If no response for ping, raise error
194 if namespace is not None:
195 cmd = 'ip netns exec {0} ping -c{1} {2}'.format(
196 namespace, ping_count, destination)
197 elif interface is not None:
198 cmd = 'ping -I {0} -c{1} {2}'.format(
199 interface, ping_count, destination)
201 cmd = 'ping -c{0} {1}'.format(ping_count, destination)
202 ret_code, _, _ = exec_cmd(node, cmd, sudo=True)
204 raise RuntimeError("Ping Not Successful")
207 def set_linux_interface_arp(node, interface, ip_addr, mac, namespace=None):
208 """Set arp on interface in linux.
210 :param node: Node where to execute command.
211 :param interface: Interface in namespace.
212 :param ip_addr: IP address for ARP entry.
213 :param mac: MAC address.
214 :param namespace: Execute command in namespace. Optional
220 :raises RuntimeError: Could not set ARP properly.
222 if namespace is not None:
223 cmd = 'ip netns exec {} arp -i {} -s {} {}'.format(
224 namespace, interface, ip_addr, mac)
226 cmd = 'arp -i {} -s {} {}'.format(interface, ip_addr, mac)
227 ret_code, _, stderr = exec_cmd(node, cmd, sudo=True)
229 raise RuntimeError("Arp set not successful, reason:{}".
233 def vpp_show_ip_table(node):
234 """Get IP FIB table data from a VPP node.
236 :param node: VPP node.
239 with VatTerminal(node, json_param=False) as vat:
240 vat.vat_terminal_exec_cmd_from_template("show_ip_fib.vat")