-# 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:
"""Defines nodes and topology structure."""
+import re
+
from collections import Counter
from yaml import load
# IxNetwork
IXNET = 'IXNET'
+
DICT__nodes = load_topo_from_yaml()
:returns: Nothing
"""
port_types = ('subinterface', 'vlan_subif', 'memif', 'tap', 'vhost',
- 'loopback', 'gre_tunnel', 'vxlan_tunnel', 'eth_bond')
+ 'loopback', 'gre_tunnel', 'vxlan_tunnel', 'eth_bond',
+ 'eth_avf')
for node_data in nodes.values():
if node_data['type'] == NodeType.DUT:
for ptype in port_types:
Topology.remove_all_ports(node_data, ptype)
+ @staticmethod
+ def remove_all_vif_ports(node):
+ """Remove all Virtual Interfaces on DUT node.
+
+ :param node: Node to remove VIF ports on.
+ :type node: dict
+ :returns: Nothing
+ """
+ reg_ex = re.compile(r'port\d+_vif\d+')
+ for if_key in list(node['interfaces']):
+ if re.match(reg_ex, if_key):
+ node['interfaces'].pop(if_key)
+
+ @staticmethod
+ def remove_all_added_vif_ports_on_all_duts_from_topology(nodes):
+ """Remove all added Virtual Interfaces on all DUT nodes in
+ the topology.
+
+ :param nodes: Nodes in the topology.
+ :type nodes: dict
+ :returns: Nothing
+ """
+ for node_data in nodes.values():
+ if node_data['type'] == NodeType.DUT:
+ Topology.remove_all_vif_ports(node_data)
+
@staticmethod
def update_interface_sw_if_index(node, iface_key, sw_if_index):
"""Update sw_if_index on the interface from the node.
"""
node['interfaces'][iface_key]['mac_address'] = str(mac_address)
+ @staticmethod
+ def update_interface_pci_address(node, iface_key, pci_address):
+ """Update pci_address on the interface from the node.
+
+ :param node: Node to update PCI on.
+ :param iface_key: Topology key of the interface.
+ :param pci_address: PCI address.
+ :type node: dict
+ :type iface_key: str
+ :type pci_address: str
+ """
+ node['interfaces'][iface_key]['pci_address'] = str(pci_address)
+
+ @staticmethod
+ def update_interface_vlan(node, iface_key, vlan):
+ """Update VLAN on the interface from the node.
+
+ :param node: Node to update VLAN on.
+ :param iface_key: Topology key of the interface.
+ :param vlan: VLAN ID.
+ :type node: dict
+ :type iface_key: str
+ :type vlan: str
+ """
+ node['interfaces'][iface_key]['vlan'] = int(vlan)
+
@staticmethod
def update_interface_vhost_socket(node, iface_key, vhost_socket):
"""Update vhost socket name on the interface from the node.
return retval
@staticmethod
- def get_interface_by_sw_index(node, sw_index):
+ def get_interface_by_sw_index(node, sw_if_index):
"""Return interface name of link on node.
This method returns the interface name associated with a software
interface index assigned to the interface by vpp for a given node.
:param node: The node topology dictionary.
- :param sw_index: Sw_index of the link that a interface is connected to.
+ :param sw_if_index: sw_if_index of the link that a interface is
+ connected to.
:type node: dict
- :type sw_index: int
+ :type sw_if_index: int
:returns: Interface name of the interface connected to the given link.
:rtype: str
"""
return Topology._get_interface_by_key_value(node, "vpp_sw_index",
- sw_index)
+ sw_if_index)
@staticmethod
def get_interface_sw_index(node, iface_key):
"""Get VPP sw_if_index for the interface using interface key.
:param node: Node to get interface sw_if_index on.
- :param iface_key: Interface key from topology file, or sw_index.
+ :param iface_key: Interface key from topology file, or sw_if_index.
:type node: dict
:type iface_key: str/int
:returns: Return sw_if_index or None if not found.
+ :rtype: int or None
"""
try:
if isinstance(iface_key, basestring):
return node['interfaces'][iface_key].get('vpp_sw_index')
# TODO: use only iface_key, do not use integer
- else:
- return int(iface_key)
+ return int(iface_key)
except (KeyError, ValueError):
return None
:raises TypeError: If provided interface name is not a string.
"""
try:
- if isinstance(iface_name, basestring):
- iface_key = Topology.get_interface_by_name(node, iface_name)
- return node['interfaces'][iface_key].get('vpp_sw_index')
- else:
+ if not isinstance(iface_name, basestring):
raise TypeError("Interface name must be a string.")
+ iface_key = Topology.get_interface_by_name(node, iface_name)
+ return node['interfaces'][iface_key].get('vpp_sw_index')
except (KeyError, ValueError):
return None
:param iface_keys: Interface keys for lookup.
:type node: dict
:type iface_keys: strings
+ :returns: Numa node of most given interfaces or 0.
+ :rtype: int
"""
numa_list = []
for if_key in iface_keys:
numa_cnt_mc = Counter(numa_list).most_common()
- if len(numa_cnt_mc) > 0 and numa_cnt_mc[0][0] != -1:
+ if numa_cnt_mc and numa_cnt_mc[0][0] != -1:
return numa_cnt_mc[0][0]
- elif len(numa_cnt_mc) > 1 and numa_cnt_mc[0][0] == -1:
+ if len(numa_cnt_mc) > 1 and numa_cnt_mc[0][0] == -1:
return numa_cnt_mc[1][0]
- else:
- return 0
+ return 0
@staticmethod
def get_interface_mac(node, iface_key):
continue
if if_val['link'] == link_name:
return node_data, if_key
+ return None
@staticmethod
def get_interface_pci_addr(node, iface_key):
except KeyError:
return None
+ @staticmethod
+ def get_interface_vlan(node, iface_key):
+ """Get interface vlan.
+
+ :param node: Node to get interface driver on.
+ :param iface_key: Interface key from topology file.
+ :type node: dict
+ :type iface_key: str
+ :returns: Return interface vlan or None if not found.
+ """
+ try:
+ return node['interfaces'][iface_key].get('vlan')
+ except KeyError:
+ return None
+
@staticmethod
def get_node_interfaces(node):
"""Get all node interfaces.
def get_node_link_mac(node, link_name):
"""Return interface mac address by link name.
- :param node: Node to get interface sw_index on.
+ :param node: Node to get interface sw_if_index on.
:param link_name: Link name.
:type node: dict
:type link_name: str
:param filter_list: Link filter criteria.
:type node: dict
:type filter_list: list of strings
- :returns: List of strings representing link names occupied by the node.
- :rtype: list
+ :returns: List of link names occupied by the node.
+ :rtype: None or list of string
"""
interfaces = node['interfaces']
link_names = []
.format(str(interface)))
else:
link_names.append(interface['link'])
- if len(link_names) == 0:
+ if not link_names:
link_names = None
return link_names
:param node2: Connected node.
:type node1: dict
:type node2: dict
- :returns: Name of link connecting the two nodes together.
+ :returns: Name of a link connecting the two nodes together.
:rtype: str
:raises RuntimeError: If no links are found.
"""
connecting_links = self.get_active_connecting_links(node1, node2)
- if len(connecting_links) == 0:
+ if not connecting_links:
raise RuntimeError("No links connecting the nodes were found")
- else:
- return connecting_links[0]
+ return connecting_links[0]
@keyword('Get egress interfaces name on "${node1}" for link with '
'"${node2}"')
"""
interfaces = []
links = self.get_active_connecting_links(node1, node2)
- if len(links) == 0:
+ if not links:
raise RuntimeError('No link between nodes')
for interface in node1['interfaces'].values():
link = interface.get('link')