aboutsummaryrefslogtreecommitdiffstats
path: root/resources/libraries/python
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libraries/python')
-rw-r--r--resources/libraries/python/IPUtil.py433
-rw-r--r--resources/libraries/python/IPv4NodeAddress.py102
-rw-r--r--resources/libraries/python/IPv4Setup.py363
-rw-r--r--resources/libraries/python/IPv4Util.py240
-rw-r--r--resources/libraries/python/IPv6NodesAddr.py68
-rw-r--r--resources/libraries/python/IPv6Setup.py297
-rw-r--r--resources/libraries/python/IPv6Util.py152
-rw-r--r--resources/libraries/python/InterfaceUtil.py144
-rw-r--r--resources/libraries/python/Routing.py123
-rw-r--r--resources/libraries/python/ssh.py1
10 files changed, 408 insertions, 1515 deletions
diff --git a/resources/libraries/python/IPUtil.py b/resources/libraries/python/IPUtil.py
index cf7034c0fd..52640d1658 100644
--- a/resources/libraries/python/IPUtil.py
+++ b/resources/libraries/python/IPUtil.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
+# Copyright (c) 2019 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
@@ -15,12 +15,17 @@
import re
-from ipaddress import IPv4Network, ip_address
+from socket import AF_INET, AF_INET6, inet_ntop, inet_pton
+
+from ipaddress import ip_address
+from ipaddress import IPv4Network, IPv6Network, IPv4Address, IPv6Address
+from ipaddress import AddressValueError, NetmaskValueError
-from resources.libraries.python.ssh import SSH
from resources.libraries.python.Constants import Constants
+from resources.libraries.python.InterfaceUtil import InterfaceUtil
+from resources.libraries.python.PapiExecutor import PapiExecutor
from resources.libraries.python.ssh import exec_cmd_no_error, exec_cmd
-from resources.libraries.python.topology import Topology
+from resources.libraries.python.topology import NodeType, Topology
class IPUtil(object):
@@ -51,36 +56,128 @@ class IPUtil(object):
return str(ip_address(ip_int))
@staticmethod
- def vpp_ip_probe(node, interface, addr, if_type="key"):
+ def vpp_get_interface_ip_addresses(node, interface, ip_version):
+ """Get list of IP addresses from an interface on a VPP node.
+
+ :param node: VPP node.
+ :param interface: Name of an interface on the VPP node.
+ :param ip_version: IP protocol version (ipv4 or ipv6).
+ :type node: dict
+ :type interface: str
+ :type ip_version: str
+ :returns: List of dictionaries, each containing IP address, subnet
+ prefix length and also the subnet mask for ipv4 addresses.
+ Note: A single interface may have multiple IP addresses assigned.
+ :rtype: list
+ """
+ try:
+ sw_if_index = Topology.convert_interface_reference(
+ node, interface, 'sw_if_index')
+ except RuntimeError:
+ if isinstance(interface, basestring):
+ sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
+ else:
+ raise
+
+ is_ipv6 = 1 if ip_version == 'ipv6' else 0
+
+ cmd = 'ip_address_dump'
+ cmd_reply = 'ip_address_details'
+ args = dict(sw_if_index=sw_if_index,
+ is_ipv6=is_ipv6)
+ err_msg = 'Failed to get L2FIB dump on host {host}'.format(
+ host=node['host'])
+
+ with PapiExecutor(node) as papi_exec:
+ papi_resp = papi_exec.add(cmd, **args).get_dump(err_msg)
+
+ data = list()
+ for item in papi_resp.reply[0]['api_reply']:
+ item[cmd_reply]['ip'] = inet_ntop(AF_INET6, item[cmd_reply]['ip']) \
+ if is_ipv6 else inet_ntop(AF_INET, item[cmd_reply]['ip'][0:4])
+ item[cmd_reply]['netmask'] = str(
+ IPv6Network(unicode('::/{pl}'.format(
+ pl=item[cmd_reply]['prefix_length']))).netmask) if is_ipv6 \
+ else str(IPv4Network(unicode('0.0.0.0/{pl}'.format(
+ pl=item[cmd_reply]['prefix_length']))).netmask)
+ data.append(item[cmd_reply])
+
+ return data
+
+ @staticmethod
+ def get_interface_vrf_table(node, interface, ip_version='ipv4'):
+ """Get vrf ID for the given interface.
+
+ :param node: VPP node.
+ :param interface: Name or sw_if_index of a specific interface.
+ :type node: dict
+ :param ip_version: IP protocol version (ipv4 or ipv6).
+ :type interface: str or int
+ :type ip_version: str
+ :returns: vrf ID of the specified interface.
+ :rtype: int
+ """
+ if isinstance(interface, basestring):
+ sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
+ else:
+ sw_if_index = interface
+
+ is_ipv6 = 1 if ip_version == 'ipv6' else 0
+
+ cmd = 'sw_interface_get_table'
+ args = dict(sw_if_index=sw_if_index,
+ is_ipv6=is_ipv6)
+ err_msg = 'Failed to get VRF id assigned to interface {ifc}'.format(
+ ifc=interface)
+
+ with PapiExecutor(node) as papi_exec:
+ papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(err_msg=err_msg)
+
+ return papi_resp['vrf_id']
+
+ @staticmethod
+ def vpp_ip_source_check_setup(node, if_name):
+ """Setup Reverse Path Forwarding source check on interface.
+
+ :param node: VPP node.
+ :param if_name: Interface name to setup RPF source check.
+ :type node: dict
+ :type if_name: str
+ """
+ cmd = 'ip_source_check_interface_add_del'
+ args = dict(
+ sw_if_index=InterfaceUtil.get_interface_index(node, if_name),
+ is_add=1,
+ loose=0)
+ err_msg = 'Failed to enable source check on interface {ifc}'.format(
+ ifc=if_name)
+ with PapiExecutor(node) as papi_exec:
+ papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(err_msg=err_msg)
+
+ @staticmethod
+ def vpp_ip_probe(node, interface, addr):
"""Run ip probe on VPP node.
:param node: VPP node.
:param interface: Interface key or name.
:param addr: IPv4/IPv6 address.
- :param if_type: Interface type
:type node: dict
:type interface: str
:type addr: str
- :type if_type: str
- :raises ValueError: If the if_type is unknown.
- :raises Exception: If vpp probe fails.
"""
- ssh = SSH()
- ssh.connect(node)
-
- if if_type == "key":
- iface_name = Topology.get_interface_name(node, interface)
- elif if_type == "name":
- iface_name = interface
- else:
- raise ValueError("if_type unknown: {0}".format(if_type))
-
- cmd = "{c}".format(c=Constants.VAT_BIN_NAME)
- cmd_input = 'exec ip probe {dev} {ip}'.format(dev=iface_name, ip=addr)
- (ret_code, _, _) = ssh.exec_command_sudo(cmd, cmd_input)
- if int(ret_code) != 0:
- raise Exception('VPP ip probe {dev} {ip} failed on {h}'.format(
- dev=iface_name, ip=addr, h=node['host']))
+ cmd = 'ip_probe_neighbor'
+ cmd_reply = 'proxy_arp_intfc_enable_disable_reply'
+ args = dict(
+ sw_if_index=InterfaceUtil.get_interface_index(node, interface),
+ dst=str(addr))
+ err_msg = 'VPP ip probe {dev} {ip} failed on {h}'.format(
+ dev=interface, ip=addr, h=node['host'])
+
+ with PapiExecutor(node) as papi_exec:
+ papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(cmd_reply=cmd_reply, err_msg=err_msg)
@staticmethod
def ip_addresses_should_be_equal(ip1, ip2):
@@ -91,7 +188,6 @@ class IPUtil(object):
:type ip1: str
:type ip2: str
"""
-
addr1 = ip_address(unicode(ip1))
addr2 = ip_address(unicode(ip2))
@@ -105,14 +201,14 @@ class IPUtil(object):
"""Setup namespace on given node and attach interface and IP to
this namespace. Applicable also on TG node.
- :param node: Node to set namespace on.
+ :param node: VPP node.
:param namespace_name: Namespace name.
:param interface_name: Interface name.
:param ip_addr: IP address of namespace's interface.
:param prefix: IP address prefix length.
:type node: dict
:type namespace_name: str
- :type vhost_if: str
+ :type interface_name: str
:type ip_addr: str
:type prefix: int
"""
@@ -131,7 +227,7 @@ class IPUtil(object):
def linux_enable_forwarding(node, ip_ver='ipv4'):
"""Enable forwarding on a Linux node, e.g. VM.
- :param node: Node to enable forwarding on.
+ :param node: VPP node.
:param ip_ver: IP version, 'ipv4' or 'ipv6'.
:type node: dict
:type ip_ver: str
@@ -143,7 +239,7 @@ class IPUtil(object):
def get_linux_interface_name(node, pci_addr):
"""Get the interface name.
- :param node: Node where to execute command.
+ :param node: VPP/TG node.
:param pci_addr: PCI address
:type node: dict
:type pci_addr: str
@@ -151,7 +247,6 @@ class IPUtil(object):
:rtype: str
:raises RuntimeError: If cannot get the information about interfaces.
"""
-
regex_intf_info = r"pci@" \
r"([0-9a-f]{4}:[0-9a-f]{2}:[0-9a-f]{2}.[0-9a-f])\s*" \
r"([a-zA-Z0-9]*)\s*network"
@@ -159,8 +254,8 @@ class IPUtil(object):
cmd = "lshw -class network -businfo"
ret_code, stdout, stderr = exec_cmd(node, cmd, timeout=30, sudo=True)
if ret_code != 0:
- raise RuntimeError('Could not get information about interfaces, '
- 'reason:{0}'.format(stderr))
+ raise RuntimeError('Could not get information about interfaces:\n'
+ '{err}'.format(err=stderr))
for line in stdout.splitlines()[2:]:
try:
@@ -174,25 +269,21 @@ class IPUtil(object):
def set_linux_interface_up(node, interface):
"""Set the specified interface up.
- :param node: Node where to execute command.
+ :param node: VPP/TG node.
:param interface: Interface in namespace.
:type node: dict
:type interface: str
:raises RuntimeError: If the interface could not be set up.
"""
-
cmd = "ip link set {0} up".format(interface)
- ret_code, _, stderr = exec_cmd(node, cmd, timeout=30, sudo=True)
- if ret_code != 0:
- raise RuntimeError('Could not set the interface up, reason:{0}'.
- format(stderr))
+ exec_cmd_no_error(node, cmd, timeout=30, sudo=True)
@staticmethod
def set_linux_interface_ip(node, interface, ip_addr, prefix,
namespace=None):
"""Set IP address to interface in linux.
- :param node: Node where to execute command.
+ :param node: VPP/TG node.
:param interface: Interface in namespace.
:param ip_addr: IP to be set on interface.
:param prefix: IP prefix.
@@ -205,52 +296,242 @@ class IPUtil(object):
:raises RuntimeError: IP could not be set.
"""
if namespace is not None:
- cmd = 'ip netns exec {} ip addr add {}/{} dev {}'.format(
- namespace, ip_addr, prefix, interface)
+ cmd = 'ip netns exec {ns} ip addr add {ip}/{p} dev {dev}'.format(
+ ns=namespace, ip=ip_addr, p=prefix, dev=interface)
else:
- cmd = 'ip addr add {}/{} dev {}'.format(ip_addr, prefix, interface)
- (ret_code, _, stderr) = exec_cmd(node, cmd, timeout=5, sudo=True)
- if ret_code != 0:
- raise RuntimeError(
- 'Could not set IP for interface, reason:{}'.format(stderr))
+ cmd = 'ip addr add {ip}/{p} dev {dev}'.format(
+ ip=ip_addr, p=prefix, dev=interface)
+
+ exec_cmd_no_error(node, cmd, timeout=5, sudo=True)
@staticmethod
- def set_linux_interface_route(node, interface, route, namespace=None):
- """Set route via interface in linux.
+ def add_linux_route(node, ip_addr, prefix, gateway, namespace=None):
+ """Add linux route in namespace.
:param node: Node where to execute command.
- :param interface: Interface in namespace.
- :param route: Route to be added via interface.
- :param namespace: Execute command in namespace. Optional parameter.
+ :param ip_addr: Route destination IP address.
+ :param prefix: IP prefix.
+ :param namespace: Execute command in namespace. Optional.
+ :param gateway: Gateway address.
:type node: dict
- :type interface: str
- :type route: str
+ :type ip_addr: str
+ :type prefix: int
+ :type gateway: str
:type namespace: str
"""
if namespace is not None:
- cmd = 'ip netns exec {} ip route add {} dev {}'.format(
- namespace, route, interface)
+ cmd = 'ip netns exec {} ip route add {}/{} via {}'.format(
+ namespace, ip_addr, prefix, gateway)
else:
- cmd = 'ip route add {} dev {}'.format(route, interface)
+ cmd = 'ip route add {}/{} via {}'.format(ip_addr, prefix, gateway)
exec_cmd_no_error(node, cmd, sudo=True)
+ @staticmethod
+ def vpp_interface_set_ip_address(node, interface, address,
+ prefix_length=None):
+ """Set IP address to VPP interface.
+
+ :param node: VPP node.
+ :param interface: Interface name.
+ :param address: IP address.
+ :param prefix_length: Prefix length.
+ :type node: dict
+ :type interface: str
+ :type address: str
+ :type prefix_length: int
+ """
+ try:
+ ip_addr = IPv6Address(unicode(address))
+ af_inet = AF_INET6
+ is_ipv6 = 1
+ except (AddressValueError, NetmaskValueError):
+ ip_addr = IPv4Address(unicode(address))
+ af_inet = AF_INET
+ is_ipv6 = 0
+
+ cmd = 'sw_interface_add_del_address'
+ args = dict(
+ sw_if_index=InterfaceUtil.get_interface_index(node, interface),
+ is_add=1,
+ is_ipv6=is_ipv6,
+ del_all=0,
+ address_length=int(prefix_length) if prefix_length else 128
+ if is_ipv6 else 32,
+ address=inet_pton(af_inet, str(ip_addr)))
+ err_msg = 'Failed to add IP address on interface {ifc}'.format(
+ ifc=interface)
+ with PapiExecutor(node) as papi_exec:
+ papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(err_msg=err_msg)
+
+ @staticmethod
+ def vpp_add_ip_neighbor(node, iface_key, ip_addr, mac_address):
+ """Add IP neighbor on DUT node.
+
+ :param node: VPP node.
+ :param iface_key: Interface key.
+ :param ip_addr: IP address of the interface.
+ :param mac_address: MAC address of the interface.
+ :type node: dict
+ :type iface_key: str
+ :type ip_addr: str
+ :type mac_address: str
+ """
+ try:
+ dst_ip = IPv6Address(unicode(ip_addr))
+ except (AddressValueError, NetmaskValueError):
+ dst_ip = IPv4Address(unicode(ip_addr))
+
+ neighbor = dict(
+ sw_if_index=Topology.get_interface_sw_index(
+ node, iface_key),
+ flags=0,
+ mac_address=str(mac_address),
+ ip_address=str(dst_ip))
+ cmd = 'ip_neighbor_add_del'
+ args = dict(
+ is_add=1,
+ neighbor=neighbor)
+ err_msg = 'Failed to add IP neighbor on interface {ifc}'.format(
+ ifc=iface_key)
+ with PapiExecutor(node) as papi_exec:
+ papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(err_msg=err_msg)
+
+ @staticmethod
+ def vpp_route_add(node, network, prefix_len, **kwargs):
+ """Add route to the VPP node.
+
+ :param node: VPP node.
+ :param network: Route destination network address.
+ :param prefix_len: Route destination network prefix length.
+ :param kwargs: Optional key-value arguments:
+
+ gateway: Route gateway address. (str)
+ interface: Route interface. (str)
+ vrf: VRF table ID. (int)
+ count: number of IP addresses to add starting from network IP (int)
+ local: The route is local with same prefix (increment is 1).
+ If None, then is not used. (bool)
+ lookup_vrf: VRF table ID for lookup. (int)
+ multipath: Enable multipath routing. (bool)
+ weight: Weight value for unequal cost multipath routing. (int)
+
+ :type node: dict
+ :type network: str
+ :type prefix_len: int
+ :type kwargs: dict
+ """
+ interface = kwargs.get('interface', None)
+ gateway = kwargs.get('gateway', None)
+
+ try:
+ net_addr = IPv6Address(unicode(network))
+ af_inet = AF_INET6
+ is_ipv6 = 1
+ except (AddressValueError, NetmaskValueError):
+ net_addr = IPv4Address(unicode(network))
+ af_inet = AF_INET
+ is_ipv6 = 0
+
+ if gateway:
+ try:
+ gt_addr = IPv6Address(unicode(gateway))
+ af_inet_gt = AF_INET6
+ except (AddressValueError, NetmaskValueError):
+ gt_addr = IPv4Address(unicode(gateway))
+ af_inet_gt = AF_INET
+
+ cmd = 'ip_add_del_route'
+ args = dict(
+ next_hop_sw_if_index=InterfaceUtil.get_interface_index(
+ node, interface) if interface else Constants.BITWISE_NON_ZERO,
+ table_id=int(kwargs.get('vrf', 0)),
+ is_add=1,
+ is_ipv6=is_ipv6,
+ is_local=int(kwargs.get('local', False)),
+ is_multipath=int(kwargs.get('multipath', False)),
+ next_hop_weight=int(kwargs.get('weight', 1)),
+ next_hop_proto=1 if is_ipv6 else 0,
+ dst_address_length=int(prefix_len),
+ next_hop_address=inet_pton(af_inet_gt, str(gt_addr)) if gateway
+ else 0,
+ next_hop_table_id=int(kwargs.get('lookup_vrf', 0)))
+ err_msg = 'Failed to add route(s) on host {host}'.format(
+ host=node['host'])
+ with PapiExecutor(node) as papi_exec:
+ for i in xrange(kwargs.get('count', 1)):
+ papi_exec.add(cmd, dst_address=inet_pton(
+ af_inet, str(net_addr+i)), **args)
+ papi_exec.get_replies(err_msg).verify_replies(err_msg=err_msg)
+
+ @staticmethod
+ def vpp_nodes_set_ipv4_addresses(nodes, nodes_addr):
+ """Set IPv4 addresses on all VPP nodes in topology.
+
+ :param nodes: Nodes of the test topology.
+ :param nodes_addr: Available nodes IPv4 addresses.
+ :type nodes: dict
+ :type nodes_addr: dict
+ :returns: Affected interfaces as list of (node, interface) tuples.
+ :rtype: list
+ """
+ interfaces = []
+ for net in nodes_addr.values():
+ for port in net['ports'].values():
+ host = port.get('node')
+ if host is None:
+ continue
+ topo = Topology()
+ node = topo.get_node_by_hostname(nodes, host)
+ if node is None:
+ continue
+ if node['type'] != NodeType.DUT:
+ continue
+ iface_key = topo.get_interface_by_name(node, port['if'])
+ IPUtil.vpp_interface_set_ip_address(
+ node, iface_key, port['addr'], net['prefix'])
+ interfaces.append((node, port['if']))
+
+ return interfaces
+
+ @staticmethod
+ def flush_ip_addresses(node, interface):
+ """Flush all IPv4addresses from specified interface.
+
+ :param node: VPP node.
+ :param interface: Interface name.
+ :type node: dict
+ :type interface: str
+ """
+ cmd = 'sw_interface_add_del_address'
+ args = dict(
+ sw_if_index=InterfaceUtil.get_interface_index(node, interface),
+ del_all=1)
+ err_msg = 'Failed to flush IP address on interface {ifc}'.format(
+ ifc=interface)
+ with PapiExecutor(node) as papi_exec:
+ papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(err_msg=err_msg)
+
+ @staticmethod
+ def add_fib_table(node, table_id, ipv6=False):
+ """Create new FIB table according to ID.
-def convert_ipv4_netmask_prefix(network):
- """Convert network mask to equivalent network prefix length or vice versa.
-
- Example: mask 255.255.0.0 -> prefix length 16
- :param network: Network mask or network prefix length.
- :type network: str or int
- :returns: Network mask or network prefix length.
- :rtype: str or int
- """
- temp_address = "0.0.0.0"
- net = IPv4Network(u"{0}/{1}".format(temp_address, network), False)
-
- if isinstance(network, int) and (0 < network < 33):
- return str(net.netmask)
- elif isinstance(network, basestring):
- return int(net.prefixlen)
- else:
- raise Exception("Value {0} is not a valid ipv4 netmask or network"
- " prefix length".format(network))
+ :param node: Node to add FIB on.
+ :param table_id: FIB table ID.
+ :param ipv6: Is this an IPv6 table
+ :type node: dict
+ :type table_id: int
+ :type ipv6: bool
+ """
+ cmd = 'ip_table_add_del'
+ args = dict(
+ table_id=int(table_id),
+ is_ipv6=int(ipv6),
+ is_add=1)
+ err_msg = 'Failed to add FIB table on host {host}'.format(
+ host=node['host'])
+ with PapiExecutor(node) as papi_exec:
+ papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(err_msg=err_msg)
diff --git a/resources/libraries/python/IPv4NodeAddress.py b/resources/libraries/python/IPv4NodeAddress.py
deleted file mode 100644
index de96c189e5..0000000000
--- a/resources/libraries/python/IPv4NodeAddress.py
+++ /dev/null
@@ -1,102 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Robot framework variable file.
-
-Create dictionary variable nodes_ipv4_addr of IPv4 addresses from
-available networks.
-"""
-
-from ipaddress import IPv4Network
-
-from resources.libraries.python.topology import Topology
-
-# Default list of IPv4 subnets
-IPV4_NETWORKS = ['192.168.{}.0/24'.format(i) for i in range(1, 100)]
-
-
-class IPv4NetworkGenerator(object):
- """IPv4 network generator.
-
- TODO: Conform to https://docs.python.org/2/library/stdtypes.html#typeiter
- """
-
- def __init__(self, networks):
- """Populate internal list of valid networks.
-
- :param networks: List of strings containing IPv4 subnet
- with prefix length.
- :type networks: list
- :raise RuntimeError: If no IPv4 networks are added.
- """
- self._networks = []
- for network in networks:
- net = IPv4Network(unicode(network))
- self._networks.append(net)
- if not self._networks:
- raise RuntimeError("No IPv4 networks")
-
- def next_network(self):
- """Pop and return network from internal list.
-
- :returns: Next network in form (IPv4Network, subnet).
- :raises StopIteration: If there are no more elements.
- """
- if self._networks:
- return self._networks.pop()
- else:
- raise StopIteration()
-
-
-def get_variables(nodes, networks=IPV4_NETWORKS[:]):
- """Special robot framework method that returns dictionary nodes_ipv4_addr,
- mapping of node and interface name to IPv4 address.
-
- :param nodes: Nodes of the test topology.
- :param networks: List of available IPv4 networks.
- :type nodes: dict
- :type networks: list
-
- .. note::
- Robot framework calls it automatically.
- """
- topo = Topology()
- links = topo.get_links(nodes)
-
- if len(links) > len(networks):
- raise Exception('Not enough available IPv4 networks for topology.')
-
- ip4_n = IPv4NetworkGenerator(networks)
-
- nets = {}
-
- for link in links:
- ip4_net = ip4_n.next_network()
- net_hosts = ip4_net.hosts()
- port_idx = 0
- ports = {}
- for node in nodes.values():
- if_key = topo.get_interface_by_link_name(node, link)
- if_name = topo.get_interface_name(node, if_key)
- if if_name is not None:
- port = {'addr': str(next(net_hosts)),
- 'node': node['host'],
- 'if': if_name}
- port_idx += 1
- port_id = 'port{0}'.format(port_idx)
- ports.update({port_id: port})
- nets.update({link: {'net_addr': str(ip4_net.network_address),
- 'prefix': ip4_net.prefixlen,
- 'ports': ports}})
-
- return {'DICT__nodes_ipv4_addr': nets}
diff --git a/resources/libraries/python/IPv4Setup.py b/resources/libraries/python/IPv4Setup.py
deleted file mode 100644
index b018bceacf..0000000000
--- a/resources/libraries/python/IPv4Setup.py
+++ /dev/null
@@ -1,363 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""IPv4 setup library"""
-
-from socket import inet_ntoa
-from struct import pack
-from abc import ABCMeta, abstractmethod
-
-from robot.api.deco import keyword
-
-from resources.libraries.python.ssh import exec_cmd_no_error
-from resources.libraries.python.Routing import Routing
-from resources.libraries.python.topology import NodeType, Topology
-from resources.libraries.python.VatExecutor import VatExecutor
-
-
-class IPv4Node(object):
- """Abstract class of a node in a topology."""
- __metaclass__ = ABCMeta
-
- def __init__(self, node_info):
- self.node_info = node_info
-
- @staticmethod
- def _get_netmask(prefix_length):
- """Convert IPv4 network prefix length into IPV4 network mask.
-
- :param prefix_length: Length of network prefix.
- :type prefix_length: int
- :returns: Network mask.
- :rtype: str
- """
-
- bits = 0xffffffff ^ (1 << 32 - prefix_length) - 1
- return inet_ntoa(pack('>I', bits))
-
- @abstractmethod
- def set_ip(self, interface, address, prefix_length):
- """Configure IPv4 address on interface.
-
- :param interface: Interface name.
- :param address: IPv4 address.
- :param prefix_length: IPv4 prefix length.
- :type interface: str
- :type address: str
- :type prefix_length: int
- :returns: nothing
- """
- pass
-
- @abstractmethod
- def set_route(self, network, prefix_length, gateway, interface, count=1):
- """Configure IPv4 route.
-
- :param network: Network IPv4 address.
- :param prefix_length: IPv4 prefix length.
- :param gateway: IPv4 address of the gateway.
- :param interface: Interface name.
- :param count: Number of consecutive routes to add.
- :type network: str
- :type prefix_length: int
- :type gateway: str
- :type interface: str
- :type route: int
- :returns: nothing
- """
- pass
-
- @abstractmethod
- def unset_route(self, network, prefix_length, gateway, interface):
- """Remove specified IPv4 route.
-
- :param network: Network IPv4 address.
- :param prefix_length: IPv4 prefix length.
- :param gateway: IPv4 address of the gateway.
- :param interface: Interface name.
- :type network: str
- :type prefix_length: int
- :type gateway: str
- :type interface: str
- :returns: nothing
- """
- pass
-
- @abstractmethod
- def flush_ip_addresses(self, interface):
- """Flush all IPv4 addresses from specified interface.
-
- :param interface: Interface name.
- :type interface: str
- :returns: nothing
- """
- pass
-
- @abstractmethod
- def ping(self, destination_address, source_interface):
- """Send an ICMP request to destination node.
-
- :param destination_address: Address to send the ICMP request.
- :param source_interface: Source interface name.
- :type destination_address: str
- :type source_interface: str
- :returns: nothing
- """
- pass
-
-
-class Tg(IPv4Node):
- """Traffic generator node"""
-
- # Implicit constructor is inherited.
-
- def _execute(self, cmd):
- """Executes the specified command on TG using SSH.
-
- :param cmd: Command to be executed.
- :type cmd: str
- :returns: Content of stdout and stderr returned by command.
- :rtype: tuple
- """
- return exec_cmd_no_error(self.node_info, cmd)
-
- def _sudo_execute(self, cmd):
- """Executes the specified command with sudo on TG using SSH.
-
- :param cmd: Command to be executed.
- :type cmd: str
- :returns: Content of stdout and stderr returned by command.
- :rtype: tuple
- """
- return exec_cmd_no_error(self.node_info, cmd, sudo=True)
-
- def set_ip(self, interface, address, prefix_length):
- cmd = 'ip -4 addr flush dev {}'.format(interface)
- self._sudo_execute(cmd)
- cmd = 'ip addr add {}/{} dev {}'.format(address, prefix_length,
- interface)
- self._sudo_execute(cmd)
-
- def set_route(self, network, prefix_length, gateway, interface, count=1):
- netmask = self._get_netmask(prefix_length)
- cmd = 'route add -net {} netmask {} gw {}'.\
- format(network, netmask, gateway)
- self._sudo_execute(cmd)
-
- def unset_route(self, network, prefix_length, gateway, interface):
- self._sudo_execute('ip route delete {}/{}'.
- format(network, prefix_length))
-
- def arp_ping(self, destination_address, source_interface):
- """Execute 'arping' command to send one ARP packet from the TG node.
-
- :param destination_address: Destination IP address for the ARP packet.
- :param source_interface: Name of an interface to send ARP packet from.
- :type destination_address: str
- :type source_interface: str
- """
- self._sudo_execute('arping -c 1 -I {} {}'.format(source_interface,
- destination_address))
-
- def ping(self, destination_address, source_interface):
- self._execute('ping -c 1 -w 5 -I {} {}'.format(source_interface,
- destination_address))
-
- def flush_ip_addresses(self, interface):
- self._sudo_execute('ip addr flush dev {}'.format(interface))
-
-
-class Dut(IPv4Node):
- """Device under test"""
-
- # Implicit contructor is inherited.
-
- def get_sw_if_index(self, interface):
- """Get sw_if_index of specified interface from current node.
-
- :param interface: Interface name.
- :type interface: str
- :returns: sw_if_index of the interface or None.
- :rtype: int
- """
- return Topology().get_interface_sw_index(self.node_info, interface)
-
- def exec_vat(self, script, **args):
- """Wrapper for VAT executor.
-
- :param script: Script to execute.
- :param args: Parameters to the script.
- :type script: str
- :type args: dict
- :returns: nothing
- """
- # TODO: check return value
- VatExecutor.cmd_from_template(self.node_info, script, **args)
-
- def set_arp(self, iface_key, ip_address, mac_address):
- """Set entry in ARP cache.
-
- :param iface_key: Interface key.
- :param ip_address: IP address.
- :param mac_address: MAC address.
- :type iface_key: str
- :type ip_address: str
- :type mac_address: str
- """
- self.exec_vat('add_ip_neighbor.vat',
- sw_if_index=self.get_sw_if_index(iface_key),
- ip_address=ip_address, mac_address=mac_address)
-
- def set_ip(self, interface, address, prefix_length):
- self.exec_vat('add_ip_address.vat',
- sw_if_index=self.get_sw_if_index(interface),
- address=address, prefix_length=prefix_length)
-
- def set_route(self, network, prefix_length, gateway, interface, count=1):
- Routing.vpp_route_add(self.node_info,
- network=network, prefix_len=prefix_length,
- gateway=gateway, interface=interface, count=count)
-
- def unset_route(self, network, prefix_length, gateway, interface):
- self.exec_vat('del_route.vat', network=network,
- prefix_length=prefix_length, gateway=gateway,
- sw_if_index=self.get_sw_if_index(interface))
-
- def arp_ping(self, destination_address, source_interface):
- """Does nothing."""
- pass
-
- def flush_ip_addresses(self, interface):
- self.exec_vat('flush_ip_addresses.vat',
- sw_if_index=self.get_sw_if_index(interface))
-
- def ping(self, destination_address, source_interface):
- pass
-
-
-def get_node(node_info):
- """Creates a class instance derived from Node based on type.
-
- :param node_info: Dictionary containing information on nodes in topology.
- :type node_info: dict
- :returns: Class instance that is derived from Node.
- """
- if node_info['type'] == NodeType.TG:
- return Tg(node_info)
- elif node_info['type'] == NodeType.DUT:
- return Dut(node_info)
- else:
- raise NotImplementedError('Node type "{}" unsupported!'.
- format(node_info['type']))
-
-
-class IPv4Setup(object):
- """IPv4 setup in topology."""
-
- @staticmethod
- def vpp_nodes_set_ipv4_addresses(nodes, nodes_addr):
- """Set IPv4 addresses on all VPP nodes in topology.
-
- :param nodes: Nodes of the test topology.
- :param nodes_addr: Available nodes IPv4 addresses.
- :type nodes: dict
- :type nodes_addr: dict
- :returns: Affected interfaces as list of (node, interface) tuples.
- :rtype: list
- """
- interfaces = []
- for net in nodes_addr.values():
- for port in net['ports'].values():
- host = port.get('node')
- if host is None:
- continue
- topo = Topology()
- node = topo.get_node_by_hostname(nodes, host)
- if node is None:
- continue
- if node['type'] != NodeType.DUT:
- continue
- iface_key = topo.get_interface_by_name(node, port['if'])
- get_node(node).set_ip(iface_key, port['addr'], net['prefix'])
- interfaces.append((node, port['if']))
-
- return interfaces
-
- @staticmethod
- @keyword('Get IPv4 address of node "${node}" interface "${port}" '
- 'from "${nodes_addr}"')
- def get_ip_addr(node, iface_key, nodes_addr):
- """Return IPv4 address of the node port.
-
- :param node: Node in the topology.
- :param iface_key: Interface key of the node.
- :param nodes_addr: Nodes IPv4 addresses.
- :type node: dict
- :type iface_key: str
- :type nodes_addr: dict
- :returns: IPv4 address.
- :rtype: str
- """
- interface = Topology.get_interface_name(node, iface_key)
- for net in nodes_addr.values():
- for port in net['ports'].values():
- host = port.get('node')
- dev = port.get('if')
- if host == node['host'] and dev == interface:
- ip_addr = port.get('addr')
- if ip_addr is not None:
- return ip_addr
- else:
- raise Exception(
- 'Node {n} port {p} IPv4 address is not set'.format(
- n=node['host'], p=interface))
-
- raise Exception('Node {n} port {p} IPv4 address not found.'.format(
- n=node['host'], p=interface))
-
- @staticmethod
- def setup_arp_on_all_duts(nodes_info, nodes_addr):
- """For all DUT nodes extract MAC and IP addresses of adjacent
- interfaces from topology and use them to setup ARP entries.
-
- :param nodes_info: Dictionary containing information on all nodes
- in topology.
- :param nodes_addr: Nodes IPv4 addresses.
- :type nodes_info: dict
- :type nodes_addr: dict
- """
- for node in nodes_info.values():
- if node['type'] == NodeType.TG:
- continue
- for iface_key in node['interfaces'].keys():
- adj_node, adj_int = Topology.\
- get_adjacent_node_and_interface(nodes_info, node, iface_key)
- ip_address = IPv4Setup.get_ip_addr(adj_node, adj_int,
- nodes_addr)
- mac_address = Topology.get_interface_mac(adj_node, adj_int)
- get_node(node).set_arp(iface_key, ip_address, mac_address)
-
- @staticmethod
- def add_arp_on_dut(node, iface_key, ip_address, mac_address):
- """Set ARP cache entree on DUT node.
-
- :param node: VPP Node in the topology.
- :param iface_key: Interface key.
- :param ip_address: IP address of the interface.
- :param mac_address: MAC address of the interface.
- :type node: dict
- :type iface_key: str
- :type ip_address: str
- :type mac_address: str
- """
- get_node(node).set_arp(iface_key, ip_address, mac_address)
diff --git a/resources/libraries/python/IPv4Util.py b/resources/libraries/python/IPv4Util.py
deleted file mode 100644
index c40e391c36..0000000000
--- a/resources/libraries/python/IPv4Util.py
+++ /dev/null
@@ -1,240 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Implements IPv4 RobotFramework keywords"""
-
-from robot.api import logger as log
-from robot.api.deco import keyword
-
-from resources.libraries.python.topology import Topology
-from resources.libraries.python.IPv4Setup import get_node
-from resources.libraries.python.VatExecutor import VatTerminal
-from resources.libraries.python.ssh import exec_cmd
-
-
-class IPv4Util(object):
- """Implements keywords for IPv4 tests."""
-
- @staticmethod
- @keyword('From node "${node}" interface "${port}" ARP-ping '
- 'IPv4 address "${ip_address}"')
- def arp_ping(node, interface, ip_address):
- """Send an ARP ping from the specified node.
-
- :param node: Node in topology.
- :param ip_address: Destination IP address for the ARP packet.
- :param interface: Name of an interface to send the ARP packet from.
- :type node: dict
- :type ip_address: str
- :type interface: str
- """
- log.debug('From node {} interface {} ARP-ping IPv4 address {}'.
- format(Topology.get_node_hostname(node),
- interface, ip_address))
- get_node(node).arp_ping(ip_address, interface)
-
- @staticmethod
- def set_interface_address(node, interface, address, prefix_length):
- """See IPv4Node.set_ip for more information.
-
- :param node: Node where IP address should be set to.
- :param interface: Interface name.
- :param address: IP address.
- :param prefix_length: Prefix length.
- :type node: dict
- :type interface: str
- :type address: str
- :type prefix_length: int
- """
- log.debug('Node {} interface {} has IPv4 address {} with prefix '
- 'length {}'.format(Topology.get_node_hostname(node),
- interface, address, prefix_length))
- get_node(node).set_ip(interface, address, int(prefix_length))
-
- @staticmethod
- def set_route(node, network, prefix_length, interface, gateway):
- """See IPv4Node.set_route for more information.
-
- :param node: Node where IP address should be set to.
- :param network: IP network.
- :param prefix_length: Prefix length.
- :param interface: Interface name.
- :param gateway: Gateway.
- :type node: dict
- :type network: str
- :type prefix_length: int
- :type interface: str
- :type gateway: str
- """
- log.debug('Node {} routes to network {} with prefix length {} '
- 'via {} interface {}'.format(Topology.get_node_hostname(node),
- network, prefix_length,
- gateway, interface))
- get_node(node).set_route(network, int(prefix_length),
- gateway, interface)
-
- @staticmethod
- @keyword('Get IPv4 address prefix of node "${node}" interface "${port}" '
- 'from "${nodes_addr}"')
- def get_ip_addr_prefix_length(node, port, nodes_addr):
- """ Get IPv4 address prefix for specified interface.
-
- :param node: Node dictionary.
- :param port: Interface name.
- :param nodes_addr: Available nodes IPv4 addresses.
- :type node: dict
- :type port: str
- :type nodes_addr: dict
- :returns: IPv4 prefix length.
- :rtype: int
- """
- for net in nodes_addr.values():
- for net_port in net['ports'].values():
- if net_port['node'] == node['host'] and net_port['if'] == port:
- return net['prefix']
-
- raise Exception('Subnet not found for node {n} port {p}'.
- format(n=node['host'], p=port))
-
- @staticmethod
- @keyword('Get IPv4 subnet of node "${node}" interface "${port}" from '
- '"${nodes_addr}"')
- def get_ip_addr_subnet(node, port, nodes_addr):
- """ Get IPv4 subnet of specified interface.
-
- :param node: Node dictionary.
- :param port: Interface name.
- :param nodes_addr: Available nodes IPv4 addresses.
- :type node: dict
- :type port: int
- :type nodes_addr: dict
- :returns: IPv4 subnet.
- :rtype: str
- """
- for net in nodes_addr.values():
- for net_port in net['ports'].values():
- if net_port['node'] == node['host'] and net_port['if'] == port:
- return net['net_addr']
-
- raise Exception('Subnet not found for node {n} port {p}'.
- format(n=node['host'], p=port))
-
- @staticmethod
- @keyword('Flush IPv4 addresses "${port}" "${node}"')
- def flush_ip_addresses(port, node):
- """See IPv4Node.flush_ip_addresses for more information.
-
- :param port: FIXME
- :param node: FIXME
- :returns: FIXME
- """
- get_node(node).flush_ip_addresses(port)
-
- @staticmethod
- def get_link_address(link, nodes_addr):
- """Get link IPv4 address.
-
- :param link: Link name.
- :param nodes_addr: Available nodes IPv4 addresses.
- :type link: str
- :type nodes_addr: dict
- :returns: Link IPv4 address.
- :rtype: str
- """
- net = nodes_addr.get(link)
- if net is None:
- raise ValueError('Link "{0}" not found'.format(link))
- return net.get('net_addr')
-
- @staticmethod
- def get_link_prefix(link, nodes_addr):
- """Get link IPv4 address prefix.
-
- :param link: Link name.
- :param nodes_addr: Available nodes IPv4 addresses.
- :type link: str
- :type nodes_addr: dict
- :returns: Link IPv4 address prefix.
- :rtype: int
- """
- net = nodes_addr.get(link)
- if net is None:
- raise ValueError('Link "{0}" not found'.format(link))
- return net.get('prefix')
-
- @staticmethod
- def send_ping_from_node_to_dst(node, destination, namespace=None,
- ping_count=3, interface=None):
- """Send a ping from node to destination. Optionally, you can define a
- namespace and interface from where to send a ping.
-
- :param node: Node to start ping on.
- :param destination: IPv4 address where to send ping.
- :param namespace: Namespace to send ping from. Optional
- :param ping_count: Number of pings to send. Default 3
- :param interface: Interface from where to send ping. Optional
- :type node: dict
- :type destination: str
- :type namespace: str
- :type ping_count: int
- :type interface: str
- :raises RuntimeError: If no response for ping, raise error
- """
- cmd = ''
- if namespace is not None:
- cmd = 'ip netns exec {0} ping -c{1} {2}'.format(
- namespace, ping_count, destination)
- elif interface is not None:
- cmd = 'ping -I {0} -c{1} {2}'.format(
- interface, ping_count, destination)
- else:
- cmd = 'ping -c{0} {1}'.format(ping_count, destination)
- ret_code, _, _ = exec_cmd(node, cmd, sudo=True)
- if ret_code != 0:
- raise RuntimeError("Ping Not Successful")
-
- @staticmethod
- def set_linux_interface_arp(node, interface, ip_addr, mac, namespace=None):
- """Set arp on interface in linux.
-
- :param node: Node where to execute command.
- :param interface: Interface in namespace.
- :param ip_addr: IP address for ARP entry.
- :param mac: MAC address.
- :param namespace: Execute command in namespace. Optional
- :type node: dict
- :type interface: str
- :type ip_addr: str
- :type mac: str
- :type namespace: str
- :raises RuntimeError: Could not set ARP properly.
- """
- if namespace is not None:
- cmd = 'ip netns exec {} arp -i {} -s {} {}'.format(
- namespace, interface, ip_addr, mac)
- else:
- cmd = 'arp -i {} -s {} {}'.format(interface, ip_addr, mac)
- ret_code, _, stderr = exec_cmd(node, cmd, sudo=True)
- if ret_code != 0:
- raise RuntimeError("Arp set not successful, reason:{}".
- format(stderr))
-
- @staticmethod
- def vpp_show_ip_table(node):
- """Get IP FIB table data from a VPP node.
-
- :param node: VPP node.
- :type node: dict
- """
- with VatTerminal(node, json_param=False) as vat:
- vat.vat_terminal_exec_cmd_from_template("show_ip_fib.vat")
diff --git a/resources/libraries/python/IPv6NodesAddr.py b/resources/libraries/python/IPv6NodesAddr.py
deleted file mode 100644
index 0482cf3cf4..0000000000
--- a/resources/libraries/python/IPv6NodesAddr.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (c) 2016 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Robot framework variable file.
-
-Create dictionary variable nodes_ipv6_addr with IPv6 addresses from available
-networks.
-"""
-
-from resources.libraries.python.IPv6Setup import IPv6Networks
-from resources.libraries.python.topology import Topology
-
-# Default list of available IPv6 networks
-IPV6_NETWORKS = ['3ffe:{0:04x}::/64'.format(i) for i in range(1, 100)]
-
-
-def get_variables(nodes, networks=IPV6_NETWORKS):
- """Special robot framework method that returns dictionary nodes_ipv6_addr,
- mapping of node and interface name to IPv6 address.
-
- :param nodes: Nodes of the test topology.
- :param networks: List of available IPv6 networks.
- :type nodes: dict
- :type networks: list
-
- .. note::
- Robot framework calls it automatically.
- """
- topo = Topology()
- links = topo.get_links(nodes)
-
- if len(links) > len(networks):
- raise Exception('Not enough available IPv6 networks for topology.')
-
- ip6_n = IPv6Networks(networks)
-
- nets = {}
-
- for link in links:
- ip6_net = ip6_n.next_network()
- net_hosts = ip6_net.hosts()
- port_idx = 0
- ports = {}
- for node in nodes.values():
- if_key = topo.get_interface_by_link_name(node, link)
- if_name = topo.get_interface_name(node, if_key)
- if if_name is not None:
- port = {'addr': str(next(net_hosts)),
- 'node': node['host'],
- 'if': if_name}
- port_idx += 1
- port_id = 'port{0}'.format(port_idx)
- ports.update({port_id: port})
- nets.update({link: {'net_addr': str(ip6_net.network_address),
- 'prefix': ip6_net.prefixlen,
- 'ports': ports}})
-
- return {'DICT__nodes_ipv6_addr': nets}
diff --git a/resources/libraries/python/IPv6Setup.py b/resources/libraries/python/IPv6Setup.py
deleted file mode 100644
index 72aeb305a2..0000000000
--- a/resources/libraries/python/IPv6Setup.py
+++ /dev/null
@@ -1,297 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Library to set up IPv6 in topology."""
-
-from ipaddress import IPv6Network
-from robot.api import logger
-
-from resources.libraries.python.ssh import SSH
-from resources.libraries.python.topology import NodeType, Topology
-from resources.libraries.python.Constants import Constants
-from resources.libraries.python.VatExecutor import VatTerminal, VatExecutor
-
-
-class IPv6Networks(object):
- """IPv6 network iterator.
-
- TODO: Conform to https://docs.python.org/2/library/stdtypes.html#typeiter
- """
-
- def __init__(self, networks):
- """Initialize internal list of valid networks.
-
- :param networks: List of the available IPv6 networks.
- :type networks: list
- :raise RuntimeError: If no networks were added.
- """
- self._networks = []
- for network in networks:
- net = IPv6Network(unicode(network))
- self._networks.append(net)
- if not self._networks:
- raise RuntimeError('No IPv6 networks')
-
- def next_network(self):
- """Get the next element of the iterator.
-
- :returns: IPv6 network.
- :rtype: IPv6Network object
- :raises StopIteration: If there is no more elements.
- """
- if self._networks:
- return self._networks.pop()
- else:
- raise StopIteration()
-
-
-class IPv6Setup(object):
- """IPv6 setup in topology."""
-
- def __init__(self):
- pass
-
- def nodes_set_ipv6_addresses(self, nodes, nodes_addr):
- """Set IPv6 addresses on all VPP nodes in topology.
-
- :param nodes: Nodes of the test topology.
- :param nodes_addr: Available nodes IPv6 addresses.
- :type nodes: dict
- :type nodes_addr: dict
- :returns: Affected interfaces as list of (node, interface) tuples.
- :rtype: list
- """
- interfaces = []
-
- for net in nodes_addr.values():
- for port in net['ports'].values():
- host = port.get('node')
- if host is None:
- continue
- topo = Topology()
- node = topo.get_node_by_hostname(nodes, host)
- if node is None:
- continue
- if node['type'] == NodeType.DUT:
- port_key = topo.get_interface_by_name(node, port['if'])
- self.vpp_set_if_ipv6_addr(node, port_key, port['addr'],
- net['prefix'])
-
- interfaces.append((node, port['if']))
- return interfaces
-
- def nodes_clear_ipv6_addresses(self, nodes, nodes_addr):
- """Remove IPv6 addresses from all VPP nodes in topology.
-
- :param nodes: Nodes of the test topology.
- :param nodes_addr: Available nodes IPv6 addresses.
- :type nodes: dict
- :type nodes_addr: dict
- """
- for net in nodes_addr.values():
- for port in net['ports'].values():
- host = port.get('node')
- if host is None:
- continue
- topo = Topology()
- node = topo.get_node_by_hostname(nodes, host)
- if node is None:
- continue
- if node['type'] == NodeType.DUT:
- self.vpp_del_if_ipv6_addr(node, port['if'], port['addr'],
- net['prefix'])
-
- @staticmethod
- def linux_set_if_ipv6_addr(node, interface, addr, prefix):
- """Set IPv6 address on linux host.
-
- :param node: Linux node.
- :param interface: Node interface.
- :param addr: IPv6 address.
- :param prefix: IPv6 address prefix.
- :type node: dict
- :type interface: str
- :type addr: str
- :type prefix: str
- """
- ssh = SSH()
- ssh.connect(node)
-
- cmd = "ifconfig {dev} inet6 add {ip}/{p} up".format(dev=interface,
- ip=addr, p=prefix)
- (ret_code, _, _) = ssh.exec_command_sudo(cmd)
- if int(ret_code) != 0:
- raise Exception('TG ifconfig failed')
-
- @staticmethod
- def linux_del_if_ipv6_addr(node, interface, addr, prefix):
- """Delete IPv6 address on linux host.
-
- :param node: Linux node.
- :param interface: Node interface.
- :param addr: IPv6 address.
- :param prefix: IPv6 address prefix.
- :type node: dict
- :type interface: str
- :type addr: str
- :type prefix: str
- """
- ssh = SSH()
- ssh.connect(node)
-
- cmd = "ifconfig {dev} inet6 del {ip}/{p}".format(dev=interface,
- ip=addr,
- p=prefix)
- (ret_code, _, _) = ssh.exec_command_sudo(cmd)
- if int(ret_code) != 0:
- raise Exception('TG ifconfig failed')
-
- cmd = "ifconfig {dev} down".format(dev=interface)
- (ret_code, _, _) = ssh.exec_command_sudo(cmd)
- if int(ret_code) != 0:
- raise Exception('TG ifconfig failed')
-
- @staticmethod
- def vpp_set_if_ipv6_addr(node, iface_key, addr, prefix):
- """Set IPv6 address on VPP.
-
- :param node: VPP node.
- :param iface_key: Node interface key.
- :param addr: IPv6 address.
- :param prefix: IPv6 address prefix.
- :type node: dict
- :type iface_key: str
- :type addr: str
- :type prefix: str
- """
- sw_if_index = Topology.get_interface_sw_index(node, iface_key)
- with VatTerminal(node) as vat:
- vat.vat_terminal_exec_cmd_from_template('add_ip_address.vat',
- sw_if_index=sw_if_index,
- address=addr,
- prefix_length=prefix)
- vat.vat_terminal_exec_cmd_from_template('set_if_state.vat',
- sw_if_index=sw_if_index,
- state='admin-up')
-
- ssh = SSH()
- ssh.connect(node)
- cmd_input = 'exec show int'
- (ret_code, stdout, stderr) = ssh.exec_command_sudo(
- Constants.VAT_BIN_NAME, cmd_input)
- logger.debug('ret: {0}'.format(ret_code))
- logger.debug('stdout: {0}'.format(stdout))
- logger.debug('stderr: {0}'.format(stderr))
-
- @staticmethod
- def vpp_del_if_ipv6_addr(node, interface, addr, prefix):
- """Delete IPv6 address on VPP.
-
- :param node: VPP node.
- :param interface: Node interface.
- :param addr: IPv6 address.
- :param prefix: IPv6 address prefix.
- :type node: dict
- :type interface: str
- :type addr: str
- :type prefix: str
- """
- sw_if_index = Topology.get_interface_sw_index(node, interface)
- with VatTerminal(node) as vat:
- vat.vat_terminal_exec_cmd_from_template('del_ip_address.vat',
- sw_if_index=sw_if_index,
- address=addr,
- prefix_length=prefix)
- vat.vat_terminal_exec_cmd_from_template('set_if_state.vat',
- sw_if_index=sw_if_index,
- state='admin-down')
-
- @staticmethod
- def vpp_ra_suppress_link_layer(node, interface):
- """Suppress ICMPv6 router advertisement message for link scope address.
-
- :param node: VPP node.
- :param interface: Interface name.
- :type node: dict
- :type interface: str
- """
- sw_if_index = Topology.get_interface_sw_index(node, interface)
- if sw_if_index:
- VatExecutor.cmd_from_template(node,
- 'sw_interface_ip6nd_ra_config.vat',
- sw_if_id=sw_if_index,
- param='surpress')
-
- @staticmethod
- def vpp_ra_send_after_interval(node, interface, interval=2):
- """Setup vpp router advertisement(RA) in such way it sends RA packet
- after and every interval value.
-
- :param node: VPP node.
- :param interface: Interface name.
- :param interval: Interval for RA resend
- :type node: dict
- :type interface: str
- :type interval: int
- """
- sw_if_index = Topology.get_interface_sw_index(node, interface)
- if sw_if_index:
- VatExecutor.cmd_from_template(node,
- 'sw_interface_ip6nd_ra_config.vat',
- sw_if_id=sw_if_index,
- param='interval {0}'.format(interval))
-
- def vpp_all_ra_suppress_link_layer(self, nodes):
- """Suppress ICMPv6 router advertisement message for link scope address
- on all VPP nodes in the topology.
-
- :param nodes: Nodes of the test topology.
- :type nodes: dict
- """
- for node in nodes.values():
- if node['type'] == NodeType.TG:
- continue
- for port_k in node['interfaces'].keys():
- self.vpp_ra_suppress_link_layer(node, port_k)
-
- @staticmethod
- def get_link_address(link, nodes_addr):
- """Get link IPv6 address.
-
- :param link: Link name.
- :param nodes_addr: Available nodes IPv6 addresses.
- :type link: str
- :type nodes_addr: dict
- :returns: Link IPv6 address.
- :rtype: str
- """
- net = nodes_addr.get(link)
- if net is None:
- raise ValueError('Link "{0}" address not found'.format(link))
- return net.get('net_addr')
-
- @staticmethod
- def get_link_prefix(link, nodes_addr):
- """Get link IPv6 address prefix.
-
- :param link: Link name.
- :param nodes_addr: Available nodes IPv6 addresses.
- :type link: str
- :type nodes_addr: dict
- :returns: Link IPv6 address prefix.
- :rtype: int
- """
- net = nodes_addr.get(link)
- if net is None:
- raise ValueError('Link "{0}" address not found'.format(link))
- return net.get('prefix')
diff --git a/resources/libraries/python/IPv6Util.py b/resources/libraries/python/IPv6Util.py
index f89d17169b..28e5f7d2fb 100644
--- a/resources/libraries/python/IPv6Util.py
+++ b/resources/libraries/python/IPv6Util.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
+# Copyright (c) 2019 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
@@ -13,123 +13,71 @@
"""IPv6 utilities library."""
-import re
-
-from resources.libraries.python.ssh import SSH
-from resources.libraries.python.VatExecutor import VatTerminal
-from resources.libraries.python.topology import Topology
+from resources.libraries.python.InterfaceUtil import InterfaceUtil
+from resources.libraries.python.IPUtil import IPUtil
+from resources.libraries.python.PapiExecutor import PapiExecutor
+from resources.libraries.python.topology import NodeType
class IPv6Util(object):
"""IPv6 utilities"""
@staticmethod
- def ipv6_ping(src_node, dst_addr, count=3, data_size=56, timeout=1):
- """IPv6 ping.
+ def vpp_ra_suppress_link_layer(node, interface):
+ """Suppress ICMPv6 router advertisement message for link scope address.
- :param src_node: Node where ping run.
- :param dst_addr: Destination IPv6 address.
- :param count: Number of echo requests. (Optional)
- :param data_size: Number of the data bytes. (Optional)
- :param timeout: Time to wait for a response, in seconds. (Optional)
- :type src_node: dict
- :type dst_addr: str
- :type count: int
- :type data_size: int
- :type timeout: int
- :returns: Number of lost packets.
- :rtype: int
+ :param node: VPP node.
+ :param interface: Interface name.
+ :type node: dict
+ :type interface: str
"""
- ssh = SSH()
- ssh.connect(src_node)
-
- cmd = "ping6 -c {c} -s {s} -W {W} {dst}".format(c=count, s=data_size,
- W=timeout,
- dst=dst_addr)
- (_, stdout, _) = ssh.exec_command(cmd)
-
- regex = re.compile(r'(\d+) packets transmitted, (\d+) received')
- match = regex.search(stdout)
- sent, received = match.groups()
- packet_lost = int(sent) - int(received)
-
- return packet_lost
+ cmd = 'sw_interface_ip6nd_ra_config'
+ args = dict(
+ sw_if_index=InterfaceUtil.get_interface_index(node, interface),
+ suppress=1)
+ err_msg = 'Failed to suppress ICMPv6 router advertisement message on ' \
+ 'interface {ifc}'.format(ifc=interface)
- @staticmethod
- def ipv6_ping_port(nodes_ip, src_node, dst_node, port, cnt=3,
- size=56, timeout=1):
- """Send IPv6 ping to the node port.
-
- :param nodes_ip: Nodes IPv6 addresses.
- :param src_node: Node where ping run.
- :param dst_node: Destination node.
- :param port: Port on the destination node.
- :param cnt: Number of echo requests. (Optional)
- :param size: Number of the data bytes. (Optional)
- :param timeout: Time to wait for a response, in seconds. (Optional)
- :type nodes_ip: dict
- :type src_node: dict
- :type dst_node: dict
- :type port: str
- :type cnt: int
- :type size: int
- :type timeout: int
- :returns: Number of lost packets.
- :rtype: int
- """
- dst_ip = IPv6Util.get_node_port_ipv6_address(dst_node, port, nodes_ip)
- return IPv6Util.ipv6_ping(src_node, dst_ip, cnt, size, timeout)
+ with PapiExecutor(node) as papi_exec:
+ papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(err_msg=err_msg)
@staticmethod
- def get_node_port_ipv6_address(node, iface_key, nodes_addr):
- """Return IPv6 address of the node port.
+ def vpp_ra_send_after_interval(node, interface, interval=2):
+ """Setup vpp router advertisement(RA) in such way it sends RA packet
+ after every interval value.
- :param node: Node in the topology.
- :param iface_key: Interface key of the node.
- :param nodes_addr: Nodes IPv6 addresses.
+ :param node: VPP node.
+ :param interface: Interface name.
+ :param interval: Interval in seconds for RA resend.
:type node: dict
- :type iface_key: str
- :type nodes_addr: dict
- :returns: IPv6 address string.
- :rtype: str
+ :type interface: str
+ :type interval: int
"""
- interface = Topology.get_interface_name(node, iface_key)
- for net in nodes_addr.values():
- for port in net['ports'].values():
- host = port.get('node')
- dev = port.get('if')
- if host == node['host'] and dev == interface:
- ip_addr = port.get('addr')
- if ip_addr is not None:
- return ip_addr
- else:
- raise Exception(
- 'Node {n} port {p} IPv6 address is not set'.format(
- n=node['host'], p=interface))
+ cmd = 'sw_interface_ip6nd_ra_config'
+ args = dict(
+ sw_if_index=InterfaceUtil.get_interface_index(node, interface),
+ initial_interval=int(interval))
+ err_msg = 'Failed to set router advertisement interval on ' \
+ 'interface {ifc}'.format(ifc=interface)
- raise Exception('Node {n} port {p} IPv6 address not found.'.format(
- n=node['host'], p=interface))
+ with PapiExecutor(node) as papi_exec:
+ papi_exec.add(cmd, **args).get_replies(err_msg). \
+ verify_reply(err_msg=err_msg)
@staticmethod
- def add_ip_neighbor(node, interface, ip_address, mac_address):
- """Add IP neighbor.
+ def vpp_all_ra_suppress_link_layer(nodes):
+ """Suppress ICMPv6 router advertisement message for link scope address
+ on all VPP nodes in the topology.
- :param node: VPP node to add ip neighbor.
- :param interface: Interface name or sw_if_index.
- :param ip_address: IP address.
- :param mac_address: MAC address.
- :type node: dict
- :type interface: str or int
- :type ip_address: str
- :type mac_address: str
+ :param nodes: Nodes of the test topology.
+ :type nodes: dict
"""
- if isinstance(interface, basestring):
- sw_if_index = Topology.get_interface_sw_index(node, interface)
- else:
- sw_if_index = interface
-
- with VatTerminal(node) as vat:
- vat.vat_terminal_exec_cmd_from_template("add_ip_neighbor.vat",
- sw_if_index=sw_if_index,
- ip_address=ip_address,
- mac_address=mac_address)
+ for node in nodes.values():
+ if node['type'] == NodeType.TG:
+ continue
+ for port_k in node['interfaces'].keys():
+ ip6_addr_list = IPUtil.vpp_get_interface_ip_addresses(
+ node, port_k, 'ipv6')
+ if ip6_addr_list:
+ IPv6Util.vpp_ra_suppress_link_layer(node, port_k)
diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py
index 6e001243db..46b1ffb034 100644
--- a/resources/libraries/python/InterfaceUtil.py
+++ b/resources/libraries/python/InterfaceUtil.py
@@ -24,7 +24,6 @@ from robot.api import logger
from resources.libraries.python.Constants import Constants
from resources.libraries.python.CpuUtils import CpuUtils
from resources.libraries.python.DUTSetup import DUTSetup
-from resources.libraries.python.IPUtil import convert_ipv4_netmask_prefix
from resources.libraries.python.L2Util import L2Util
from resources.libraries.python.PapiExecutor import PapiExecutor
from resources.libraries.python.parsers.JsonParser import JsonParser
@@ -64,7 +63,6 @@ class InterfaceUtil(object):
:returns: Integer representation of PCI address.
:rtype: int
"""
-
pci = list(pci_str.split(':')[0:2])
pci.extend(pci_str.split(':')[2].split('.'))
@@ -82,7 +80,6 @@ class InterfaceUtil(object):
:returns: SW interface index.
:rtype: int
"""
-
try:
sw_if_index = int(interface)
except ValueError:
@@ -115,7 +112,6 @@ class InterfaceUtil(object):
:raises ValueError: If the state of interface is unexpected.
:raises ValueError: If the node has an unknown node type.
"""
-
if if_type == 'key':
if isinstance(interface, basestring):
sw_if_index = Topology.get_interface_sw_index(node, interface)
@@ -170,7 +166,6 @@ class InterfaceUtil(object):
:raises ValueError: If the node type is "DUT".
:raises ValueError: If the node has an unknown node type.
"""
-
if node['type'] == NodeType.DUT:
raise ValueError('Node {}: Setting Ethernet MTU for interface '
'on DUT nodes not supported', node['host'])
@@ -192,7 +187,6 @@ class InterfaceUtil(object):
:type node: dict
:returns: Nothing.
"""
-
for ifc in node['interfaces']:
InterfaceUtil.set_interface_ethernet_mtu(node, ifc, 1500)
@@ -207,7 +201,6 @@ class InterfaceUtil(object):
:type interface: str or int
:type mtu: int
"""
-
if isinstance(interface, basestring):
sw_if_index = Topology.get_interface_sw_index(node, interface)
else:
@@ -231,7 +224,6 @@ class InterfaceUtil(object):
:type node: dict
:type mtu: int
"""
-
for interface in node['interfaces']:
InterfaceUtil.vpp_set_interface_mtu(node, interface, mtu)
@@ -244,7 +236,6 @@ class InterfaceUtil(object):
:type nodes: dict
:type mtu: int
"""
-
for node in nodes.values():
if node['type'] == NodeType.DUT:
InterfaceUtil.vpp_set_interfaces_mtu_on_node(node, mtu)
@@ -262,7 +253,6 @@ class InterfaceUtil(object):
:raises RuntimeError: If any interface is not in link-up state after
defined number of retries.
"""
-
for _ in xrange(0, retries):
not_ready = list()
out = InterfaceUtil.vpp_get_interface_data(node)
@@ -293,7 +283,6 @@ class InterfaceUtil(object):
:type retries: int
:returns: Nothing.
"""
-
for node in nodes.values():
if node['type'] == NodeType.DUT:
InterfaceUtil.vpp_node_interfaces_ready_wait(node, retries)
@@ -314,7 +303,6 @@ class InterfaceUtil(object):
:raises TypeError: if the data type of interface is neither basestring
nor int.
"""
-
if interface is not None:
if isinstance(interface, basestring):
param = 'interface_name'
@@ -376,7 +364,6 @@ class InterfaceUtil(object):
:returns: Name of the given interface.
:rtype: str
"""
-
if_data = InterfaceUtil.vpp_get_interface_data(node, sw_if_index)
if if_data['sup_sw_if_index'] != if_data['sw_if_index']:
if_data = InterfaceUtil.vpp_get_interface_data(
@@ -396,7 +383,6 @@ class InterfaceUtil(object):
:returns: Name of the given interface.
:rtype: str
"""
-
if_data = InterfaceUtil.vpp_get_interface_data(node, interface_name)
return if_data.get('sw_if_index')
@@ -412,7 +398,6 @@ class InterfaceUtil(object):
:returns: MAC address.
:rtype: str
"""
-
if_data = InterfaceUtil.vpp_get_interface_data(node, interface)
if if_data['sup_sw_if_index'] != if_data['sw_if_index']:
if_data = InterfaceUtil.vpp_get_interface_data(
@@ -421,56 +406,6 @@ class InterfaceUtil(object):
return if_data.get('l2_address')
@staticmethod
- def vpp_get_interface_ip_addresses(node, interface, ip_version):
- """Get list of IP addresses from an interface on a VPP node.
-
- TODO: Move to IPUtils
-
- :param node: VPP node to get data from.
- :param interface: Name of an interface on the VPP node.
- :param ip_version: IP protocol version (ipv4 or ipv6).
- :type node: dict
- :type interface: str
- :type ip_version: str
- :returns: List of dictionaries, each containing IP address, subnet
- prefix length and also the subnet mask for ipv4 addresses.
- Note: A single interface may have multiple IP addresses assigned.
- :rtype: list
- """
-
- try:
- sw_if_index = Topology.convert_interface_reference(
- node, interface, 'sw_if_index')
- except RuntimeError:
- if isinstance(interface, basestring):
- sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
- else:
- raise
-
- is_ipv6 = 1 if ip_version == 'ipv6' else 0
-
- cmd = 'ip_address_dump'
- cmd_reply = 'ip_address_details'
- args = dict(sw_if_index=sw_if_index,
- is_ipv6=is_ipv6)
- err_msg = 'Failed to get L2FIB dump on host {host}'.format(
- host=node['host'])
- with PapiExecutor(node) as papi_exec:
- papi_resp = papi_exec.add(cmd, **args).get_dump(err_msg)
-
- data = list()
- for item in papi_resp.reply[0]['api_reply']:
- item[cmd_reply]['ip'] = inet_ntop(AF_INET6, item[cmd_reply]['ip']) \
- if is_ipv6 else inet_ntop(AF_INET, item[cmd_reply]['ip'][0:4])
- data.append(item[cmd_reply])
-
- if ip_version == 'ipv4':
- for item in data:
- item['netmask'] = convert_ipv4_netmask_prefix(
- item['prefix_length'])
- return data
-
- @staticmethod
def tg_set_interface_driver(node, pci_addr, driver):
"""Set interface driver on the TG node.
@@ -586,7 +521,6 @@ class InterfaceUtil(object):
:param node: Node selected from DICT__nodes.
:type node: dict
"""
-
interface_list = InterfaceUtil.vpp_get_interface_data(node)
interface_dict = dict()
for ifc in interface_list:
@@ -789,7 +723,6 @@ class InterfaceUtil(object):
:raises RuntimeError: if it is unable to create VLAN subinterface on the
node.
"""
-
iface_key = Topology.get_interface_by_name(node, interface)
sw_if_index = Topology.get_interface_sw_index(node, iface_key)
@@ -827,7 +760,6 @@ class InterfaceUtil(object):
:raises RuntimeError: if it is unable to create VxLAN interface on the
node.
"""
-
try:
src_address = IPv6Address(unicode(source_ip))
dst_address = IPv6Address(unicode(destination_ip))
@@ -878,7 +810,6 @@ class InterfaceUtil(object):
:raises TypeError: if the data type of interface is neither basestring
nor int.
"""
-
if interface is not None:
sw_if_index = InterfaceUtil.get_interface_index(node, interface)
else:
@@ -936,7 +867,6 @@ class InterfaceUtil(object):
:returns: List of dictionaries with all vhost-user interfaces.
:rtype: list
"""
-
cmd = 'sw_interface_vhost_user_dump'
cmd_reply = 'sw_interface_vhost_user_details'
err_msg = 'Failed to get vhost-user dump on host {host}'.format(
@@ -982,7 +912,6 @@ class InterfaceUtil(object):
a List of dictionaries containing all TAP data for the given node.
:rtype: dict or list
"""
-
cmd = 'sw_interface_tap_v2_dump'
cmd_reply = 'sw_interface_tap_v2_details'
err_msg = 'Failed to get TAP dump on host {host}'.format(
@@ -1047,7 +976,6 @@ class InterfaceUtil(object):
:rtype: tuple
:raises RuntimeError: If it is not possible to create sub-interface.
"""
-
subif_types = type_subif.split()
cmd = 'create_subif'
@@ -1092,7 +1020,6 @@ class InterfaceUtil(object):
:rtype: tuple
:raises RuntimeError: If unable to create GRE tunnel interface.
"""
-
cmd = 'gre_tunnel_add_del'
tunnel = dict(type=0,
instance=Constants.BITWISE_NON_ZERO,
@@ -1127,7 +1054,6 @@ class InterfaceUtil(object):
:raises RuntimeError: If it is not possible to create loopback on the
node.
"""
-
cmd = 'create_loopback'
args = dict(mac_address=0)
err_msg = 'Failed to create loopback interface on host {host}'.format(
@@ -1162,7 +1088,6 @@ class InterfaceUtil(object):
:raises RuntimeError: If it is not possible to create bond interface on
the node.
"""
-
cmd = 'bond_create'
args = dict(id=int(Constants.BITWISE_NON_ZERO),
use_custom_mac=0 if mac is None else 1,
@@ -1198,7 +1123,6 @@ class InterfaceUtil(object):
:type sw_if_idx: int
:type ifc_pfx: str
"""
-
if_key = Topology.add_new_port(node, ifc_pfx)
if ifc_name and sw_if_idx is None:
@@ -1225,7 +1149,6 @@ class InterfaceUtil(object):
:raises RuntimeError: If it is not possible to create AVF interface on
the node.
"""
-
cmd = 'avf_create'
args = dict(pci_addr=InterfaceUtil.pci_to_int(vf_pci_addr),
enable_elog=0,
@@ -1258,7 +1181,6 @@ class InterfaceUtil(object):
:raises RuntimeError: If it is not possible to enslave physical
interface to bond interface on the node.
"""
-
cmd = 'bond_enslave'
args = dict(
sw_if_index=Topology.get_interface_sw_index(node, interface),
@@ -1282,7 +1204,6 @@ class InterfaceUtil(object):
:type node: dict
:type details: bool
"""
-
cmd = 'sw_interface_bond_dump'
cmd_reply = 'sw_interface_bond_details'
err_msg = 'Failed to get bond interface dump on host {host}'.format(
@@ -1391,7 +1312,6 @@ class InterfaceUtil(object):
:type ip_version: str
:type table_index: int
"""
-
cmd = 'input_acl_set_interface'
args = dict(
sw_if_index=InterfaceUtil.get_interface_index(node, interface),
@@ -1437,39 +1357,6 @@ class InterfaceUtil(object):
return papi_resp
@staticmethod
- def get_interface_vrf_table(node, interface, ip_version='ipv4'):
- """Get vrf ID for the given interface.
-
- TODO: Move to proper IP library when implementing CSIT-1459.
-
- :param node: VPP node.
- :param interface: Name or sw_if_index of a specific interface.
- :type node: dict
- :param ip_version: IP protocol version (ipv4 or ipv6).
- :type interface: str or int
- :type ip_version: str
- :returns: vrf ID of the specified interface.
- :rtype: int
- """
- if isinstance(interface, basestring):
- sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
- else:
- sw_if_index = interface
-
- is_ipv6 = 1 if ip_version == 'ipv6' else 0
-
- cmd = 'sw_interface_get_table'
- args = dict(sw_if_index=sw_if_index,
- is_ipv6=is_ipv6)
- err_msg = 'Failed to get VRF id assigned to interface {ifc}'.format(
- ifc=interface)
- with PapiExecutor(node) as papi_exec:
- papi_resp = papi_exec.add(cmd, **args).get_replies(err_msg). \
- verify_reply(err_msg=err_msg)
-
- return papi_resp['vrf_id']
-
- @staticmethod
def get_sw_if_index(node, interface_name):
"""Get sw_if_index for the given interface from actual interface dump.
@@ -1480,7 +1367,6 @@ class InterfaceUtil(object):
:returns: sw_if_index of the given interface.
:rtype: str
"""
-
interface_data = InterfaceUtil.vpp_get_interface_data(
node, interface=interface_name)
return interface_data.get('sw_if_index')
@@ -1499,7 +1385,6 @@ class InterfaceUtil(object):
interfaces.
:rtype: dict or list
"""
-
if interface_name is not None:
sw_if_index = InterfaceUtil.get_interface_index(
node, interface_name)
@@ -1549,29 +1434,6 @@ class InterfaceUtil(object):
return data
@staticmethod
- def vpp_ip_source_check_setup(node, if_name):
- """Setup Reverse Path Forwarding source check on interface.
-
- TODO: Move to proper IP library when implementing CSIT-1459.
-
- :param node: Node to setup RPF source check.
- :param if_name: Interface name to setup RPF source check.
- :type node: dict
- :type if_name: str
- """
-
- cmd = 'ip_source_check_interface_add_del'
- args = dict(
- sw_if_index=InterfaceUtil.get_interface_index(node, if_name),
- is_add=1,
- loose=0)
- err_msg = 'Failed to enable source check on interface {ifc}'.format(
- ifc=if_name)
- with PapiExecutor(node) as papi_exec:
- papi_exec.add(cmd, **args).get_replies(err_msg). \
- verify_reply(err_msg=err_msg)
-
- @staticmethod
def assign_interface_to_fib_table(node, interface, table_id, ipv6=False):
"""Assign VPP interface to specific VRF/FIB table.
@@ -1584,7 +1446,6 @@ class InterfaceUtil(object):
:type table_id: int
:type ipv6: bool
"""
-
cmd = 'sw_interface_set_table'
args = dict(
sw_if_index=InterfaceUtil.get_interface_index(node, interface),
@@ -1827,7 +1688,6 @@ class InterfaceUtil(object):
:returns: Number of created VXLAN interfaces.
:rtype: int
"""
-
try:
src_address_start = IPv6Address(unicode(src_ip_start))
dst_address_start = IPv6Address(unicode(dst_ip_start))
@@ -1896,7 +1756,6 @@ class InterfaceUtil(object):
:type vxlan_count: int
:type node_vlan_if: str
"""
-
if_data = InterfaceUtil.vpp_get_interface_data(node)
with PapiExecutor(node) as papi_exec:
@@ -1965,7 +1824,6 @@ class InterfaceUtil(object):
:type ip_step: int
:type bd_id_start: int
"""
-
try:
dst_address_start = IPv6Address(unicode(dst_ip_start))
af_inet = AF_INET6
@@ -2031,7 +1889,6 @@ class InterfaceUtil(object):
:returns: Thread mapping information as a list of dictionaries.
:rtype: list
"""
-
cmd = 'sw_interface_rx_placement_dump'
cmd_reply = 'sw_interface_rx_placement_details'
err_msg = "Failed to run '{cmd}' PAPI command on host {host}!".format(
@@ -2061,7 +1918,6 @@ class InterfaceUtil(object):
:raises RuntimeError: If failed to run command on host or if no API
reply received.
"""
-
cmd = 'sw_interface_set_rx_placement'
err_msg = "Failed to set interface RX placement to worker on host " \
"{host}!".format(host=node['host'])
diff --git a/resources/libraries/python/Routing.py b/resources/libraries/python/Routing.py
deleted file mode 100644
index a682c90102..0000000000
--- a/resources/libraries/python/Routing.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright (c) 2018 Cisco and/or its affiliates.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at:
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Routing utilities library."""
-
-from resources.libraries.python.VatExecutor import VatTerminal
-from resources.libraries.python.topology import Topology
-from resources.libraries.python.ssh import exec_cmd_no_error
-
-
-class Routing(object):
- """Routing utilities."""
-
- @staticmethod
- def vpp_route_add(node, network, prefix_len, **kwargs):
- """Add route to the VPP node.
-
- :param node: Node to add route on.
- :param network: Route destination network address.
- :param prefix_len: Route destination network prefix length.
- :param kwargs: Optional key-value arguments:
-
- gateway: Route gateway address. (str)
- interface: Route interface. (str)
- vrf: VRF table ID. (int)
- use_sw_index: Use sw_if_index in VAT command. (bool)
- resolve_attempts: Resolve attempts IP route add parameter. (int)
- count: number of IP addresses to add starting from network IP (int)
- local: The route is local with same prefix (increment is 1).
- If None, then is not used. (bool)
- lookup_vrf: VRF table ID for lookup. (int)
- multipath: Enable multipath routing. (bool)
- weight: Weight value for unequal cost multipath routing. (int)
-
- :type node: dict
- :type network: str
- :type prefix_len: int
- :type kwargs: dict
- """
-
- gateway = kwargs.get("gateway", '')
- intf = kwargs.get("interface", '')
- use_sw_index = kwargs.get("use_sw_index", True)
- resolve_attempts = kwargs.get("resolve_attempts", 10)
- count = kwargs.get("count", 1)
- vrf = kwargs.get("vrf", None)
- l_vrf = kwargs.get("lookup_vrf", None)
- multipath = kwargs.get("multipath", False)
- weight = kwargs.get("weight", None)
- local = kwargs.get("local", False)
-
- if intf:
- if use_sw_index:
- int_cmd = ('sw_if_index {}'.
- format(Topology.get_interface_sw_index(node, intf)))
- else:
- int_cmd = intf
- else:
- int_cmd = ''
-
- with VatTerminal(node, json_param=False) as vat:
- vat.vat_terminal_exec_cmd_from_template(
- 'add_route.vat',
- network=network,
- prefix_length=prefix_len,
- via='via {}'.format(gateway) if gateway else '',
- vrf='vrf {}'.format(vrf) if vrf else '',
- interface=int_cmd,
- resolve_attempts='resolve-attempts {}'.
- format(resolve_attempts) if resolve_attempts else '',
- count='count {}'.format(count) if count else '',
- lookup_vrf='lookup-in-vrf {}'.format(l_vrf) if l_vrf else '',
- multipath='multipath' if multipath else '',
- weight='weight {}'.format(weight) if weight else '',
- local='local' if local else '')
-
- @staticmethod
- def add_fib_table(node, table_id, ipv6=False):
- """Create new FIB table according to ID.
-
- :param node: Node to add FIB on.
- :param table_id: FIB table ID.
- :param ipv6: Is this an IPv6 table
- :type node: dict
- :type table_id: int
- :type ipv6: bool
- """
- with VatTerminal(node) as vat:
- vat.vat_terminal_exec_cmd_from_template('add_fib_table.vat',
- table_id=table_id,
- ipv6="ipv6" if ipv6 else "")
-
- @staticmethod
- def add_route(node, ip_addr, prefix, gateway, namespace=None):
- """Add route in namespace.
-
- :param node: Node where to execute command.
- :param ip_addr: Route destination IP address.
- :param prefix: IP prefix.
- :param namespace: Execute command in namespace. Optional.
- :param gateway: Gateway address.
- :type node: dict
- :type ip_addr: str
- :type prefix: int
- :type gateway: str
- :type namespace: str
- """
- if namespace is not None:
- cmd = 'ip netns exec {} ip route add {}/{} via {}'.format(
- namespace, ip_addr, prefix, gateway)
- else:
- cmd = 'ip route add {}/{} via {}'.format(ip_addr, prefix, gateway)
- exec_cmd_no_error(node, cmd, sudo=True)
diff --git a/resources/libraries/python/ssh.py b/resources/libraries/python/ssh.py
index e89daf2915..3523d57302 100644
--- a/resources/libraries/python/ssh.py
+++ b/resources/libraries/python/ssh.py
@@ -507,6 +507,7 @@ def exec_cmd_no_error(
return stdout, stderr
+
def scp_node(
node, local_path, remote_path, get=False, timeout=30, disconnect=False):
"""Copy files from local_path to remote_path or vice versa.