-# Copyright (c) 2016 Cisco and/or its affiliates.
+# 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:
:type node: dict
:type timeout: int
:returns: Nothing.
- :raises: RuntimeError if the timeout period value has elapsed.
+ :raises RuntimeError: If the timeout period value has elapsed.
"""
if_ready = False
not_ready = []
:type node: dict
:type interface: int or str
:returns: List of dictionaries containing data for each interface, or a
- single dictionary for the specified interface.
+ single dictionary for the specified interface.
:rtype: list or dict
:raises TypeError: if the data type of interface is neither basestring
- nor int.
+ nor int.
"""
with VatTerminal(node) as vat:
response = vat.vat_terminal_exec_cmd_from_template(
return dict()
return data
+ @staticmethod
+ def vpp_get_interface_name(node, sw_if_index):
+ """Get interface name for the given SW interface index from actual
+ interface dump.
+
+ :param node: VPP node to get interface data from.
+ :param sw_if_index: SW interface index of the specific interface.
+ :type node: dict
+ :type sw_if_index: int
+ :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(
+ node, if_data['sup_sw_if_index'])
+ try:
+ if_name = if_data["interface_name"]
+ except KeyError:
+ if_name = None
+ return if_name
+
@staticmethod
def vpp_get_interface_mac(node, interface=None):
"""Get MAC address for the given interface from actual interface dump.
: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.
+ prefix length and also the subnet mask for ipv4 addresses.
+ Note: A single interface may have multiple IP addresses assigned.
:rtype: list
"""
- sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
+
+ 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
with VatTerminal(node) as vat:
response = vat.vat_terminal_exec_cmd_from_template(
:type node: dict
:type pci_addr: str
:type driver: str
- :returns: None.
:raises RuntimeError: If unbinding from the current driver fails.
:raises RuntimeError: If binding to the new driver fails.
"""
:returns: Interface driver or None if not found.
:rtype: str
:raises RuntimeError: If it is not possible to get the interface driver
- information from the node.
+ information from the node.
.. note::
# lspci -vmmks 0000:00:05.0
ssh = SSH()
ssh.connect(node)
- cmd = 'lspci -vmmks {0}'.format(pci_addr)
-
- (ret_code, stdout, _) = ssh.exec_command(cmd)
- if int(ret_code) != 0:
- raise RuntimeError("'{0}' failed on '{1}'"
- .format(cmd, node['host']))
+ for i in range(3):
+ logger.trace('Try {}: Get interface driver'.format(i))
+ cmd = 'sh -c "echo 1 > /sys/bus/pci/rescan"'
+ (ret_code, _, _) = ssh.exec_command_sudo(cmd)
+ if int(ret_code) != 0:
+ raise RuntimeError("'{0}' failed on '{1}'"
+ .format(cmd, node['host']))
- for line in stdout.splitlines():
- if len(line) == 0:
- continue
- (name, value) = line.split("\t", 1)
- if name == 'Driver:':
- return value
+ cmd = 'lspci -vmmks {0}'.format(pci_addr)
+ (ret_code, stdout, _) = ssh.exec_command(cmd)
+ if int(ret_code) != 0:
+ raise RuntimeError("'{0}' failed on '{1}'"
+ .format(cmd, node['host']))
- return None
+ for line in stdout.splitlines():
+ if len(line) == 0:
+ continue
+ try:
+ (name, value) = line.split("\t", 1)
+ except ValueError:
+ if name != "Driver:":
+ pass
+ else:
+ return None
+ if name == 'Driver:':
+ return value if value else None
+ raise RuntimeError('Get interface driver for: {0}'
+ .format(pci_addr))
@staticmethod
def tg_set_interfaces_udev_rules(node):
interface_dump_json)
@staticmethod
- def update_tg_interface_data_on_node(node):
- """Update interface name for TG/linux node in DICT__nodes.
+ def update_nic_interface_names(node):
+ """Update interface names based on nic type and PCI address.
- :param node: Node selected from DICT__nodes.
+ This method updates interface names in the same format as VPP does.
+
+ :param node: Node dictionary.
:type node: dict
- :raises RuntimeError: If getting of interface name and MAC fails.
+ """
+ for ifc in node['interfaces'].values():
+ if_pci = ifc['pci_address'].replace('.', ':').split(':')
+ bus = '{:x}'.format(int(if_pci[1], 16))
+ dev = '{:x}'.format(int(if_pci[2], 16))
+ fun = '{:x}'.format(int(if_pci[3], 16))
+ loc = '{bus}/{dev}/{fun}'.format(bus=bus, dev=dev, fun=fun)
+ if ifc['model'] == 'Intel-XL710':
+ ifc['name'] = 'FortyGigabitEthernet{loc}'.format(loc=loc)
+ elif ifc['model'] == 'Intel-X710':
+ ifc['name'] = 'TenGigabitEthernet{loc}'.format(loc=loc)
+ elif ifc['model'] == 'Intel-X520-DA2':
+ ifc['name'] = 'TenGigabitEthernet{loc}'.format(loc=loc)
+ elif ifc['model'] == 'Cisco-VIC-1385':
+ ifc['name'] = 'FortyGigabitEthernet{loc}'.format(loc=loc)
+ elif ifc['model'] == 'Cisco-VIC-1227':
+ ifc['name'] = 'TenGigabitEthernet{loc}'.format(loc=loc)
+ else:
+ ifc['name'] = 'UnknownEthernet{loc}'.format(loc=loc)
+
+ @staticmethod
+ def update_nic_interface_names_on_all_duts(nodes):
+ """Update interface names based on nic type and PCI address on all DUTs.
+
+ This method updates interface names in the same format as VPP does.
+
+ :param nodes: Topology nodes.
+ :type nodes: dict
+ """
+ for node in nodes.values():
+ if node['type'] == NodeType.DUT:
+ InterfaceUtil.update_nic_interface_names(node)
+
+ @staticmethod
+ def update_tg_interface_data_on_node(node):
+ """Update interface name for TG/linux node in DICT__nodes.
.. note::
# for dev in `ls /sys/class/net/`;
"52:54:00:e1:8a:0f": "eth2"
"00:00:00:00:00:00": "lo"
- .. todo:: parse lshw -json instead
+ .. note:: TODO: parse lshw -json instead
+
+ :param node: Node selected from DICT__nodes.
+ :type node: dict
+ :raises RuntimeError: If getting of interface name and MAC fails.
"""
# First setup interface driver specified in yaml file
InterfaceUtil.tg_set_interfaces_default_driver(node)
:returns: Name and index of created subinterface.
:rtype: tuple
:raises RuntimeError: if it is unable to create VLAN subinterface on the
- node.
+ node.
"""
iface_key = Topology.get_interface_by_name(node, interface)
sw_if_index = Topology.get_interface_sw_index(node, iface_key)
sw_if_index=sw_if_index,
vlan=vlan)
if output[0]["retval"] == 0:
- sw_subif_index = output[0]["sw_if_index"]
+ sw_subif_idx = output[0]["sw_if_index"]
logger.trace('VLAN subinterface with sw_if_index {} and VLAN ID {} '
- 'created on node {}'.format(sw_subif_index,
+ 'created on node {}'.format(sw_subif_idx,
vlan, node['host']))
+ if_key = Topology.add_new_port(node, "vlan_subif")
+ Topology.update_interface_sw_if_index(node, if_key, sw_subif_idx)
+ ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_subif_idx)
+ Topology.update_interface_name(node, if_key, ifc_name)
else:
raise RuntimeError('Unable to create VLAN subinterface on node {}'
.format(node['host']))
with VatTerminal(node, False) as vat:
vat.vat_terminal_exec_cmd('exec show interfaces')
- return '{}.{}'.format(interface, vlan), sw_subif_index
+ return '{}.{}'.format(interface, vlan), sw_subif_idx
@staticmethod
def create_vxlan_interface(node, vni, source_ip, destination_ip):
:returns: SW IF INDEX of created interface.
:rtype: int
:raises RuntimeError: if it is unable to create VxLAN interface on the
- node.
+ node.
"""
output = VatExecutor.cmd_from_template(node, "vxlan_create.vat",
src=source_ip,
output = output[0]
if output["retval"] == 0:
- return output["sw_if_index"]
+ sw_if_idx = output["sw_if_index"]
+ if_key = Topology.add_new_port(node, "vxlan_tunnel")
+ Topology.update_interface_sw_if_index(node, if_key, sw_if_idx)
+ ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx)
+ Topology.update_interface_name(node, if_key, ifc_name)
+ return sw_if_idx
else:
- raise RuntimeError('Unable to create VXLAN interface on node {0}'
+ raise RuntimeError("Unable to create VXLAN interface on node {0}"
.format(node))
@staticmethod
:param node: VPP node to get interface data from.
:param interface: Numeric index or name string of a specific interface.
- If None, information about all VxLAN interfaces is returned.
+ If None, information about all VxLAN interfaces is returned.
:type node: dict
:type interface: int or str
:returns: Dictionary containing data for the given VxLAN interface or if
- interface=None, the list of dictionaries with all VxLAN interfaces.
+ interface=None, the list of dictionaries with all VxLAN interfaces.
:rtype: dict or list
:raises TypeError: if the data type of interface is neither basestring
- nor int.
+ nor int.
"""
param = "sw_if_index"
if interface is None:
:type node: dict
:type name: str
:returns: Dictionary of information about a specific TAP interface, or
- a List of dictionaries containing all TAP data for the given node.
+ a List of dictionaries containing all TAP data for the given node.
:rtype: dict or list
"""
with VatTerminal(node) as vat:
:param outer_vlan_id: Optional outer VLAN ID.
:param inner_vlan_id: Optional inner VLAN ID.
:param type_subif: Optional type of sub-interface. Values supported by
- VPP: [no_tags] [one_tag] [two_tags] [dot1ad] [exact_match] [default_sub]
+ VPP: [no_tags] [one_tag] [two_tags] [dot1ad] [exact_match]
+ [default_sub]
:type node: dict
:type interface: str or int
:type sub_id: int
type_subif=type_subif)
if output[0]["retval"] == 0:
- sw_subif_index = output[0]["sw_if_index"]
+ sw_subif_idx = output[0]["sw_if_index"]
logger.trace('Created subinterface with index {}'
- .format(sw_subif_index))
+ .format(sw_subif_idx))
+ if_key = Topology.add_new_port(node, "subinterface")
+ Topology.update_interface_sw_if_index(node, if_key, sw_subif_idx)
+ ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_subif_idx)
+ Topology.update_interface_name(node, if_key, ifc_name)
else:
raise RuntimeError('Unable to create sub-interface on node {}'
.format(node['host']))
vat.vat_terminal_exec_cmd('exec show interfaces')
name = '{}.{}'.format(interface, sub_id)
- return name, sw_subif_index
+ return name, sw_subif_idx
@staticmethod
def create_gre_tunnel_interface(node, source_ip, destination_ip):
output = output[0]
if output["retval"] == 0:
- sw_if_index = output["sw_if_index"]
+ sw_if_idx = output["sw_if_index"]
vat_executor = VatExecutor()
vat_executor.execute_script_json_out("dump_interfaces.vat", node)
interface_dump_json = vat_executor.get_script_stdout()
name = VatJsonUtil.get_interface_name_from_json(
- interface_dump_json, sw_if_index)
- return name, sw_if_index
+ interface_dump_json, sw_if_idx)
+
+ if_key = Topology.add_new_port(node, "gre_tunnel")
+ Topology.update_interface_sw_if_index(node, if_key, sw_if_idx)
+ Topology.update_interface_name(node, if_key, name)
+
+ return name, sw_if_idx
else:
raise RuntimeError('Unable to create GRE tunnel on node {}.'
.format(node))
:returns: SW interface index.
:rtype: int
:raises RuntimeError: If it is not possible to create loopback on the
- node.
+ node.
"""
out = VatExecutor.cmd_from_template(node, "create_loopback.vat")
if out[0].get('retval') == 0:
- return out[0].get('sw_if_index')
+ sw_if_idx = out[0].get('sw_if_index')
+ if_key = Topology.add_new_port(node, "loopback")
+ Topology.update_interface_sw_if_index(node, if_key, sw_if_idx)
+ ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx)
+ Topology.update_interface_name(node, if_key, ifc_name)
+ return sw_if_idx
else:
raise RuntimeError('Create loopback failed on node "{}"'
.format(node['host']))
sw_if_index=sw_if_index)
return data[0]
+ @staticmethod
+ def get_interface_vrf_table(node, interface):
+ """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
+ :type interface: str or int
+ :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
+
+ with VatTerminal(node) as vat:
+ data = vat.vat_terminal_exec_cmd_from_template(
+ "interface_vrf_dump.vat",
+ sw_if_index=sw_if_index)
+ return data[0]["vrf_id"]
+
@staticmethod
def get_sw_if_index(node, interface_name):
"""Get sw_if_index for the given interface from actual interface dump.
:param node: VPP node to get interface data from.
:param interface_name: Name of the specific interface. If None,
- information about all VxLAN GPE interfaces is returned.
+ information about all VxLAN GPE interfaces is returned.
:type node: dict
:type interface_name: str
:returns: Dictionary containing data for the given VxLAN GPE interface
- or if interface=None, the list of dictionaries with all VxLAN GPE
- interfaces.
+ or if interface=None, the list of dictionaries with all VxLAN GPE
+ interfaces.
:rtype: dict or list
"""
raise RuntimeError('Unable to assign interface to FIB node {}.'
.format(node))
-
@staticmethod
def set_linux_interface_mac(node, interface, mac, namespace=None):
"""Set MAC address for interface in linux.