1 # Copyright (c) 2018 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """Interface util library."""
16 from time import time, sleep
18 from robot.api import logger
20 from resources.libraries.python.CpuUtils import CpuUtils
21 from resources.libraries.python.DUTSetup import DUTSetup
22 from resources.libraries.python.IPUtil import convert_ipv4_netmask_prefix
23 from resources.libraries.python.IPUtil import IPUtil
24 from resources.libraries.python.parsers.JsonParser import JsonParser
25 from resources.libraries.python.ssh import SSH, exec_cmd_no_error
26 from resources.libraries.python.topology import NodeType, Topology
27 from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal
28 from resources.libraries.python.VatJsonUtil import VatJsonUtil
29 from resources.libraries.python.VPPUtil import VPPUtil
32 class InterfaceUtil(object):
33 """General utilities for managing interfaces"""
35 __UDEV_IF_RULES_FILE = '/etc/udev/rules.d/10-network.rules'
38 def set_interface_state(node, interface, state, if_type="key"):
39 """Set interface state on a node.
41 Function can be used for DUTs as well as for TGs.
43 :param node: Node where the interface is.
44 :param interface: Interface key or sw_if_index or name.
45 :param state: One of 'up' or 'down'.
46 :param if_type: Interface type
48 :type interface: str or int
52 :raises ValueError: If the interface type is unknown.
53 :raises ValueError: If the state of interface is unexpected.
54 :raises ValueError: If the node has an unknown node type.
58 if isinstance(interface, basestring):
59 sw_if_index = Topology.get_interface_sw_index(node, interface)
60 iface_name = Topology.get_interface_name(node, interface)
62 sw_if_index = interface
63 elif if_type == "name":
64 iface_key = Topology.get_interface_by_name(node, interface)
65 if iface_key is not None:
66 sw_if_index = Topology.get_interface_sw_index(node, iface_key)
67 iface_name = interface
69 raise ValueError("if_type unknown: {}".format(if_type))
71 if node['type'] == NodeType.DUT:
73 state = 'admin-up link-up'
75 state = 'admin-down link-down'
77 raise ValueError('Unexpected interface state: {}'.format(state))
78 VatExecutor.cmd_from_template(node, 'set_if_state.vat',
79 sw_if_index=sw_if_index, state=state)
80 elif node['type'] == NodeType.TG or node['type'] == NodeType.VM:
81 cmd = 'ip link set {} {}'.format(iface_name, state)
82 exec_cmd_no_error(node, cmd, sudo=True)
84 raise ValueError('Node {} has unknown NodeType: "{}"'
85 .format(node['host'], node['type']))
88 def set_interface_ethernet_mtu(node, iface_key, mtu):
89 """Set Ethernet MTU for specified interface.
91 Function can be used only for TGs.
93 :param node: Node where the interface is.
94 :param iface_key: Interface key from topology file.
95 :param mtu: MTU to set.
100 :raises ValueError: If the node type is "DUT".
101 :raises ValueError: If the node has an unknown node type.
103 if node['type'] == NodeType.DUT:
104 raise ValueError('Node {}: Setting Ethernet MTU for interface '
105 'on DUT nodes not supported', node['host'])
106 elif node['type'] == NodeType.TG:
107 iface_name = Topology.get_interface_name(node, iface_key)
108 cmd = 'ip link set {} mtu {}'.format(iface_name, mtu)
109 exec_cmd_no_error(node, cmd, sudo=True)
111 raise ValueError('Node {} has unknown NodeType: "{}"'
112 .format(node['host'], node['type']))
115 def set_default_ethernet_mtu_on_all_interfaces_on_node(node):
116 """Set default Ethernet MTU on all interfaces on node.
118 Function can be used only for TGs.
120 :param node: Node where to set default MTU.
124 for ifc in node['interfaces']:
125 InterfaceUtil.set_interface_ethernet_mtu(node, ifc, 1500)
128 def vpp_set_interface_mtu(node, interface, mtu=9200):
129 """Set Ethernet MTU on interface.
131 :param node: VPP node.
132 :param interface: Interface to setup MTU. Default: 9200.
133 :param mtu: Ethernet MTU size in Bytes.
135 :type interface: str or int
138 if isinstance(interface, basestring):
139 sw_if_index = Topology.get_interface_sw_index(node, interface)
141 sw_if_index = interface
144 with VatTerminal(node, json_param=False) as vat:
145 vat.vat_terminal_exec_cmd_from_template(
146 "hw_interface_set_mtu.vat", sw_if_index=sw_if_index,
150 def vpp_set_interfaces_mtu_on_node(node, mtu=9200):
151 """Set Ethernet MTU on all interfaces.
153 :param node: VPP node.
154 :param mtu: Ethernet MTU size in Bytes. Default: 9200.
158 for interface in node['interfaces']:
159 InterfaceUtil.vpp_set_interface_mtu(node, interface, mtu)
162 def vpp_set_interfaces_mtu_on_all_duts(nodes, mtu=9200):
163 """Set Ethernet MTU on all interfaces on all DUTs.
165 :param nodes: VPP nodes.
166 :param mtu: Ethernet MTU size in Bytes. Default: 9200.
170 for node in nodes.values():
171 if node['type'] == NodeType.DUT:
172 InterfaceUtil.vpp_set_interfaces_mtu_on_node(node, mtu)
175 def vpp_node_interfaces_ready_wait(node, timeout=30):
176 """Wait until all interfaces with admin-up are in link-up state.
178 :param node: Node to wait on.
179 :param timeout: Waiting timeout in seconds (optional, default 10s).
183 :raises RuntimeError: If the timeout period value has elapsed.
189 out = InterfaceUtil.vpp_get_interface_data(node)
190 if time() - start > timeout:
191 for interface in out:
192 if interface.get('admin_up_down') == 1:
193 if interface.get('link_up_down') != 1:
194 logger.debug('{0} link-down'.format(
195 interface.get('interface_name')))
196 raise RuntimeError('timeout, not up {0}'.format(not_ready))
198 for interface in out:
199 if interface.get('admin_up_down') == 1:
200 if interface.get('link_up_down') != 1:
201 not_ready.append(interface.get('interface_name'))
205 logger.debug('Interfaces still in link-down state: {0}, '
206 'waiting...'.format(not_ready))
210 def vpp_nodes_interfaces_ready_wait(nodes, timeout=30):
211 """Wait until all interfaces with admin-up are in link-up state for
214 :param nodes: List of nodes to wait on.
215 :param timeout: Seconds to wait per node for all interfaces to come up.
221 InterfaceUtil.vpp_node_interfaces_ready_wait(node, timeout)
224 def all_vpp_interfaces_ready_wait(nodes, timeout=30):
225 """Wait until all interfaces with admin-up are in link-up state for all
226 nodes in the topology.
228 :param nodes: Nodes in the topology.
229 :param timeout: Seconds to wait per node for all interfaces to come up.
234 for node in nodes.values():
235 if node['type'] == NodeType.DUT:
236 InterfaceUtil.vpp_node_interfaces_ready_wait(node, timeout)
239 def vpp_get_interface_data(node, interface=None):
240 """Get all interface data from a VPP node. If a name or
241 sw_interface_index is provided, return only data for the matching
244 :param node: VPP node to get interface data from.
245 :param interface: Numeric index or name string of a specific interface.
247 :type interface: int or str
248 :returns: List of dictionaries containing data for each interface, or a
249 single dictionary for the specified interface.
251 :raises TypeError: if the data type of interface is neither basestring
254 with VatTerminal(node) as vat:
255 response = vat.vat_terminal_exec_cmd_from_template(
256 "interface_dump.vat")
260 if interface is not None:
261 if isinstance(interface, basestring):
262 param = "interface_name"
263 elif isinstance(interface, int):
264 param = "sw_if_index"
268 if data_if[param] == interface:
274 def vpp_get_interface_name(node, sw_if_index):
275 """Get interface name for the given SW interface index from actual
278 :param node: VPP node to get interface data from.
279 :param sw_if_index: SW interface index of the specific interface.
281 :type sw_if_index: int
282 :returns: Name of the given interface.
286 if_data = InterfaceUtil.vpp_get_interface_data(node, sw_if_index)
287 if if_data['sup_sw_if_index'] != if_data['sw_if_index']:
288 if_data = InterfaceUtil.vpp_get_interface_data(
289 node, if_data['sup_sw_if_index'])
291 if_name = if_data["interface_name"]
297 def vpp_get_interface_mac(node, interface=None):
298 """Get MAC address for the given interface from actual interface dump.
300 :param node: VPP node to get interface data from.
301 :param interface: Numeric index or name string of a specific interface.
303 :type interface: int or str
304 :returns: MAC address.
308 if_data = InterfaceUtil.vpp_get_interface_data(node, interface)
309 if if_data['sup_sw_if_index'] != if_data['sw_if_index']:
310 if_data = InterfaceUtil.vpp_get_interface_data(
311 node, if_data['sup_sw_if_index'])
312 mac_data = [str(hex(item))[2:] for item in if_data['l2_address'][:6]]
314 for item in mac_data:
317 mac_data_nice.append(item)
318 mac = ":".join(mac_data_nice)
322 def vpp_get_interface_ip_addresses(node, interface, ip_version):
323 """Get list of IP addresses from an interface on a VPP node.
325 :param node: VPP node to get data from.
326 :param interface: Name of an interface on the VPP node.
327 :param ip_version: IP protocol version (ipv4 or ipv6).
330 :type ip_version: str
331 :returns: List of dictionaries, each containing IP address, subnet
332 prefix length and also the subnet mask for ipv4 addresses.
333 Note: A single interface may have multiple IP addresses assigned.
338 sw_if_index = Topology.convert_interface_reference(
339 node, interface, "sw_if_index")
341 if isinstance(interface, basestring):
342 sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
346 with VatTerminal(node) as vat:
347 response = vat.vat_terminal_exec_cmd_from_template(
348 "ip_address_dump.vat", ip_version=ip_version,
349 sw_if_index=sw_if_index)
353 if ip_version == "ipv4":
355 item["netmask"] = convert_ipv4_netmask_prefix(
356 item["prefix_length"])
360 def tg_set_interface_driver(node, pci_addr, driver):
361 """Set interface driver on the TG node.
363 :param node: Node to set interface driver on (must be TG node).
364 :param pci_addr: PCI address of the interface.
365 :param driver: Driver name.
369 :raises RuntimeError: If unbinding from the current driver fails.
370 :raises RuntimeError: If binding to the new driver fails.
372 old_driver = InterfaceUtil.tg_get_interface_driver(node, pci_addr)
373 if old_driver == driver:
379 # Unbind from current driver
380 if old_driver is not None:
381 cmd = 'sh -c "echo {0} > /sys/bus/pci/drivers/{1}/unbind"'\
382 .format(pci_addr, old_driver)
383 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
384 if int(ret_code) != 0:
385 raise RuntimeError("'{0}' failed on '{1}'"
386 .format(cmd, node['host']))
388 # Bind to the new driver
389 cmd = 'sh -c "echo {0} > /sys/bus/pci/drivers/{1}/bind"'\
390 .format(pci_addr, driver)
391 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
392 if int(ret_code) != 0:
393 raise RuntimeError("'{0}' failed on '{1}'"
394 .format(cmd, node['host']))
397 def tg_get_interface_driver(node, pci_addr):
398 """Get interface driver from the TG node.
400 :param node: Node to get interface driver on (must be TG node).
401 :param pci_addr: PCI address of the interface.
404 :returns: Interface driver or None if not found.
406 :raises RuntimeError: If PCI rescan or lspci command execution failed.
408 return DUTSetup.get_pci_dev_driver(node, pci_addr)
411 def tg_set_interfaces_udev_rules(node):
412 """Set udev rules for interfaces.
414 Create udev rules file in /etc/udev/rules.d where are rules for each
415 interface used by TG node, based on MAC interface has specific name.
416 So after unbind and bind again to kernel driver interface has same
417 name as before. This must be called after TG has set name for each
418 port in topology dictionary.
420 SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="52:54:00:e1:8a:0f",
423 :param node: Node to set udev rules on (must be TG node).
425 :raises RuntimeError: If setting of udev rules fails.
430 cmd = 'rm -f {0}'.format(InterfaceUtil.__UDEV_IF_RULES_FILE)
431 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
432 if int(ret_code) != 0:
433 raise RuntimeError("'{0}' failed on '{1}'"
434 .format(cmd, node['host']))
436 for interface in node['interfaces'].values():
437 rule = 'SUBSYSTEM==\\"net\\", ACTION==\\"add\\", ATTR{address}' + \
438 '==\\"' + interface['mac_address'] + '\\", NAME=\\"' + \
439 interface['name'] + '\\"'
440 cmd = 'sh -c "echo \'{0}\' >> {1}"'.format(
441 rule, InterfaceUtil.__UDEV_IF_RULES_FILE)
442 (ret_code, _, _) = ssh.exec_command_sudo(cmd)
443 if int(ret_code) != 0:
444 raise RuntimeError("'{0}' failed on '{1}'"
445 .format(cmd, node['host']))
447 cmd = '/etc/init.d/udev restart'
448 ssh.exec_command_sudo(cmd)
451 def tg_set_interfaces_default_driver(node):
452 """Set interfaces default driver specified in topology yaml file.
454 :param node: Node to setup interfaces driver on (must be TG node).
457 for interface in node['interfaces'].values():
458 InterfaceUtil.tg_set_interface_driver(node,
459 interface['pci_address'],
463 def update_vpp_interface_data_on_node(node):
464 """Update vpp generated interface data for a given node in DICT__nodes.
466 Updates interface names, software if index numbers and any other details
467 generated specifically by vpp that are unknown before testcase run.
468 It does this by dumping interface list to JSON output from all
469 devices using vpp_api_test, and pairing known information from topology
470 (mac address/pci address of interface) to state from VPP.
472 :param node: Node selected from DICT__nodes.
475 vat_executor = VatExecutor()
476 vat_executor.execute_script_json_out("dump_interfaces.vat", node)
477 interface_dump_json = vat_executor.get_script_stdout()
478 VatJsonUtil.update_vpp_interface_data_from_json(node,
482 def update_nic_interface_names(node):
483 """Update interface names based on nic type and PCI address.
485 This method updates interface names in the same format as VPP does.
487 :param node: Node dictionary.
490 for ifc in node['interfaces'].values():
491 if_pci = ifc['pci_address'].replace('.', ':').split(':')
492 bus = '{:x}'.format(int(if_pci[1], 16))
493 dev = '{:x}'.format(int(if_pci[2], 16))
494 fun = '{:x}'.format(int(if_pci[3], 16))
495 loc = '{bus}/{dev}/{fun}'.format(bus=bus, dev=dev, fun=fun)
496 if ifc['model'] == 'Intel-XL710':
497 ifc['name'] = 'FortyGigabitEthernet{loc}'.format(loc=loc)
498 elif ifc['model'] == 'Intel-X710':
499 ifc['name'] = 'TenGigabitEthernet{loc}'.format(loc=loc)
500 elif ifc['model'] == 'Intel-X520-DA2':
501 ifc['name'] = 'TenGigabitEthernet{loc}'.format(loc=loc)
502 elif ifc['model'] == 'Cisco-VIC-1385':
503 ifc['name'] = 'FortyGigabitEthernet{loc}'.format(loc=loc)
504 elif ifc['model'] == 'Cisco-VIC-1227':
505 ifc['name'] = 'TenGigabitEthernet{loc}'.format(loc=loc)
507 ifc['name'] = 'UnknownEthernet{loc}'.format(loc=loc)
510 def update_nic_interface_names_on_all_duts(nodes):
511 """Update interface names based on nic type and PCI address on all DUTs.
513 This method updates interface names in the same format as VPP does.
515 :param nodes: Topology nodes.
518 for node in nodes.values():
519 if node['type'] == NodeType.DUT:
520 InterfaceUtil.update_nic_interface_names(node)
523 def update_tg_interface_data_on_node(node, skip_tg_udev=False):
524 """Update interface name for TG/linux node in DICT__nodes.
527 # for dev in `ls /sys/class/net/`;
528 > do echo "\"`cat /sys/class/net/$dev/address`\": \"$dev\""; done
529 "52:54:00:9f:82:63": "eth0"
530 "52:54:00:77:ae:a9": "eth1"
531 "52:54:00:e1:8a:0f": "eth2"
532 "00:00:00:00:00:00": "lo"
534 :param node: Node selected from DICT__nodes.
535 :param skip_tg_udev: Skip udev rename on TG node.
537 :type skip_tg_udev: bool
538 :raises RuntimeError: If getting of interface name and MAC fails.
540 # First setup interface driver specified in yaml file
541 InterfaceUtil.tg_set_interfaces_default_driver(node)
543 # Get interface names
547 cmd = ('for dev in `ls /sys/class/net/`; do echo "\\"`cat '
548 '/sys/class/net/$dev/address`\\": \\"$dev\\""; done;')
550 (ret_code, stdout, _) = ssh.exec_command(cmd)
551 if int(ret_code) != 0:
552 raise RuntimeError('Get interface name and MAC failed')
553 tmp = "{" + stdout.rstrip().replace('\n', ',') + "}"
554 interfaces = JsonParser().parse_data(tmp)
555 for interface in node['interfaces'].values():
556 name = interfaces.get(interface['mac_address'])
559 interface['name'] = name
561 # Set udev rules for interfaces
563 InterfaceUtil.tg_set_interfaces_udev_rules(node)
566 def iface_update_numa_node(node):
567 """For all interfaces from topology file update numa node based on
568 information from the node.
570 :param node: Node from topology.
573 :raises ValueError: If numa node ia less than 0.
574 :raises RuntimeError: If update of numa node failes.
577 for if_key in Topology.get_node_interfaces(node):
578 if_pci = Topology.get_interface_pci_addr(node, if_key)
580 cmd = "cat /sys/bus/pci/devices/{}/numa_node".format(if_pci)
582 (ret, out, _) = ssh.exec_command(cmd)
587 if CpuUtils.cpu_node_count(node) == 1:
592 logger.trace('Reading numa location failed for: {0}'
595 Topology.set_interface_numa_node(node, if_key,
599 raise RuntimeError('Update numa node failed for: {0}'
603 def update_all_numa_nodes(nodes, skip_tg=False):
604 """For all nodes and all their interfaces from topology file update numa
605 node information based on information from the node.
607 :param nodes: Nodes in the topology.
608 :param skip_tg: Skip TG node
613 for node in nodes.values():
614 if node['type'] == NodeType.DUT:
615 InterfaceUtil.iface_update_numa_node(node)
616 elif node['type'] == NodeType.TG and not skip_tg:
617 InterfaceUtil.iface_update_numa_node(node)
620 def update_all_interface_data_on_all_nodes(nodes, skip_tg=False,
623 """Update interface names on all nodes in DICT__nodes.
625 This method updates the topology dictionary by querying interface lists
626 of all nodes mentioned in the topology dictionary.
628 :param nodes: Nodes in the topology.
629 :param skip_tg: Skip TG node.
630 :param skip_tg_udev: Skip udev rename on TG node.
631 :param numa_node: Retrieve numa_node location.
634 :type skip_tg_udev: bool
635 :type numa_node: bool
637 for node_data in nodes.values():
638 if node_data['type'] == NodeType.DUT:
639 InterfaceUtil.update_vpp_interface_data_on_node(node_data)
640 elif node_data['type'] == NodeType.TG and not skip_tg:
641 InterfaceUtil.update_tg_interface_data_on_node(
642 node_data, skip_tg_udev)
645 if node_data['type'] == NodeType.DUT:
646 InterfaceUtil.iface_update_numa_node(node_data)
647 elif node_data['type'] == NodeType.TG and not skip_tg:
648 InterfaceUtil.iface_update_numa_node(node_data)
651 def create_vlan_subinterface(node, interface, vlan):
652 """Create VLAN subinterface on node.
654 :param node: Node to add VLAN subinterface on.
655 :param interface: Interface name on which create VLAN subinterface.
656 :param vlan: VLAN ID of the subinterface to be created.
660 :returns: Name and index of created subinterface.
662 :raises RuntimeError: if it is unable to create VLAN subinterface on the
665 iface_key = Topology.get_interface_by_name(node, interface)
666 sw_if_index = Topology.get_interface_sw_index(node, iface_key)
668 output = VatExecutor.cmd_from_template(node, "create_vlan_subif.vat",
669 sw_if_index=sw_if_index,
671 if output[0]["retval"] == 0:
672 sw_vlan_idx = output[0]["sw_if_index"]
673 logger.trace('VLAN subinterface with sw_if_index {} and VLAN ID {} '
674 'created on node {}'.format(sw_vlan_idx,
676 if_key = Topology.add_new_port(node, "vlan_subif")
677 Topology.update_interface_sw_if_index(node, if_key, sw_vlan_idx)
678 ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_vlan_idx)
679 Topology.update_interface_name(node, if_key, ifc_name)
681 raise RuntimeError('Unable to create VLAN subinterface on node {}'
682 .format(node['host']))
684 with VatTerminal(node, False) as vat:
685 vat.vat_terminal_exec_cmd('exec show interfaces')
687 return '{}.{}'.format(interface, vlan), sw_vlan_idx
690 def create_vxlan_interface(node, vni, source_ip, destination_ip):
691 """Create VXLAN interface and return sw if index of created interface.
693 Executes "vxlan_add_del_tunnel src {src} dst {dst} vni {vni}" VAT
696 :param node: Node where to create VXLAN interface.
697 :param vni: VXLAN Network Identifier.
698 :param source_ip: Source IP of a VXLAN Tunnel End Point.
699 :param destination_ip: Destination IP of a VXLAN Tunnel End Point.
703 :type destination_ip: str
704 :returns: SW IF INDEX of created interface.
706 :raises RuntimeError: if it is unable to create VxLAN interface on the
709 output = VatExecutor.cmd_from_template(node, "vxlan_create.vat",
715 if output["retval"] == 0:
716 sw_if_idx = output["sw_if_index"]
717 if_key = Topology.add_new_port(node, "vxlan_tunnel")
718 Topology.update_interface_sw_if_index(node, if_key, sw_if_idx)
719 ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx)
720 Topology.update_interface_name(node, if_key, ifc_name)
723 raise RuntimeError("Unable to create VXLAN interface on node {0}"
727 def vxlan_dump(node, interface=None):
728 """Get VxLAN data for the given interface.
730 :param node: VPP node to get interface data from.
731 :param interface: Numeric index or name string of a specific interface.
732 If None, information about all VxLAN interfaces is returned.
734 :type interface: int or str
735 :returns: Dictionary containing data for the given VxLAN interface or if
736 interface=None, the list of dictionaries with all VxLAN interfaces.
738 :raises TypeError: if the data type of interface is neither basestring
741 param = "sw_if_index"
742 if interface is None:
745 elif isinstance(interface, basestring):
746 sw_if_index = Topology.get_interface_sw_index(node, interface)
747 elif isinstance(interface, int):
748 sw_if_index = interface
750 raise TypeError("Wrong interface format {0}".format(interface))
752 with VatTerminal(node) as vat:
753 response = vat.vat_terminal_exec_cmd_from_template(
754 "vxlan_dump.vat", param=param, sw_if_index=sw_if_index)
757 for vxlan in response[0]:
758 if vxlan["sw_if_index"] == sw_if_index:
764 def vhost_user_dump(node):
765 """Get vhost-user data for the given node.
767 :param node: VPP node to get interface data from.
769 :returns: List of dictionaries with all vhost-user interfaces.
772 with VatTerminal(node) as vat:
773 response = vat.vat_terminal_exec_cmd_from_template(
774 "vhost_user_dump.vat")
779 def tap_dump(node, name=None):
780 """Get all TAP interface data from the given node, or data about
781 a specific TAP interface.
783 :param node: VPP node to get data from.
784 :param name: Optional name of a specific TAP interface.
787 :returns: Dictionary of information about a specific TAP interface, or
788 a List of dictionaries containing all TAP data for the given node.
791 with VatTerminal(node) as vat:
792 response = vat.vat_terminal_exec_cmd_from_template(
796 for item in response[0]:
797 if name == item['dev_name']:
802 def create_subinterface(node, interface, sub_id, outer_vlan_id=None,
803 inner_vlan_id=None, type_subif=None):
804 """Create sub-interface on node. It is possible to set required
805 sub-interface type and VLAN tag(s).
807 :param node: Node to add sub-interface.
808 :param interface: Interface name on which create sub-interface.
809 :param sub_id: ID of the sub-interface to be created.
810 :param outer_vlan_id: Optional outer VLAN ID.
811 :param inner_vlan_id: Optional inner VLAN ID.
812 :param type_subif: Optional type of sub-interface. Values supported by
813 VPP: [no_tags] [one_tag] [two_tags] [dot1ad] [exact_match]
816 :type interface: str or int
818 :type outer_vlan_id: int
819 :type inner_vlan_id: int
820 :type type_subif: str
821 :returns: Name and index of created sub-interface.
823 :raises RuntimeError: If it is not possible to create sub-interface.
826 outer_vlan_id = 'outer_vlan_id {0}'.format(outer_vlan_id)\
827 if outer_vlan_id else ''
829 inner_vlan_id = 'inner_vlan_id {0}'.format(inner_vlan_id)\
830 if inner_vlan_id else ''
832 if type_subif is None:
835 if isinstance(interface, basestring):
836 iface_key = Topology.get_interface_by_name(node, interface)
837 sw_if_index = Topology.get_interface_sw_index(node, iface_key)
839 sw_if_index = interface
841 output = VatExecutor.cmd_from_template(node, "create_sub_interface.vat",
842 sw_if_index=sw_if_index,
844 outer_vlan_id=outer_vlan_id,
845 inner_vlan_id=inner_vlan_id,
846 type_subif=type_subif)
848 if output[0]["retval"] == 0:
849 sw_vlan_idx = output[0]["sw_if_index"]
850 logger.trace('Created subinterface with index {}'
851 .format(sw_vlan_idx))
852 if_key = Topology.add_new_port(node, "subinterface")
853 Topology.update_interface_sw_if_index(node, if_key, sw_vlan_idx)
854 ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_vlan_idx)
855 Topology.update_interface_name(node, if_key, ifc_name)
857 raise RuntimeError('Unable to create sub-interface on node {}'
858 .format(node['host']))
860 with VatTerminal(node, json_param=False) as vat:
861 vat.vat_terminal_exec_cmd('exec show interfaces')
863 name = '{}.{}'.format(interface, sub_id)
864 return name, sw_vlan_idx
867 def create_gre_tunnel_interface(node, source_ip, destination_ip):
868 """Create GRE tunnel interface on node.
870 :param node: VPP node to add tunnel interface.
871 :param source_ip: Source of the GRE tunnel.
872 :param destination_ip: Destination of the GRE tunnel.
875 :type destination_ip: str
876 :returns: Name and index of created GRE tunnel interface.
878 :raises RuntimeError: If unable to create GRE tunnel interface.
880 output = VatExecutor.cmd_from_template(node, "create_gre.vat",
885 if output["retval"] == 0:
886 sw_if_idx = output["sw_if_index"]
888 vat_executor = VatExecutor()
889 vat_executor.execute_script_json_out("dump_interfaces.vat", node)
890 interface_dump_json = vat_executor.get_script_stdout()
891 name = VatJsonUtil.get_interface_name_from_json(
892 interface_dump_json, sw_if_idx)
894 if_key = Topology.add_new_port(node, "gre_tunnel")
895 Topology.update_interface_sw_if_index(node, if_key, sw_if_idx)
896 Topology.update_interface_name(node, if_key, name)
898 return name, sw_if_idx
900 raise RuntimeError('Unable to create GRE tunnel on node {}.'
904 def vpp_create_loopback(node):
905 """Create loopback interface on VPP node.
907 :param node: Node to create loopback interface on.
909 :returns: SW interface index.
911 :raises RuntimeError: If it is not possible to create loopback on the
914 out = VatExecutor.cmd_from_template(node, "create_loopback.vat")
915 if out[0].get('retval') == 0:
916 sw_if_idx = out[0].get('sw_if_index')
917 if_key = Topology.add_new_port(node, "loopback")
918 Topology.update_interface_sw_if_index(node, if_key, sw_if_idx)
919 ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx)
920 Topology.update_interface_name(node, if_key, ifc_name)
923 raise RuntimeError('Create loopback failed on node "{}"'
924 .format(node['host']))
927 def vpp_create_bond_interface(node, mode, load_balance=None, mac=None):
928 """Create bond interface on VPP node.
930 :param node: DUT node from topology.
931 :param mode: Link bonding mode.
932 :param load_balance: Load balance (optional, valid for xor and lacp
933 modes, otherwise ignored).
934 :param mac: MAC address to assign to the bond interface (optional).
937 :type load_balance: str
939 :returns: Interface key (name) in topology.
941 :raises RuntimeError: If it is not possible to create bond interface on
944 hw_addr = '' if mac is None else 'hw-addr {mac}'.format(mac=mac)
945 ldb = '' if load_balance is None \
946 else 'lb {ldb}'.format(ldb=load_balance)
948 output = VatExecutor.cmd_from_template(
949 node, 'create_bond_interface.vat', mode=mode, lb=ldb, mac=hw_addr)
951 if output[0].get('retval') == 0:
952 sw_if_idx = output[0].get('sw_if_index')
953 InterfaceUtil.add_eth_interface(node, sw_if_idx=sw_if_idx,
955 if_key = Topology.get_interface_by_sw_index(node, sw_if_idx)
958 raise RuntimeError('Create bond interface failed on "{host}"'.
959 format(host=node['host']))
962 def add_eth_interface(node, ifc_name=None, sw_if_idx=None, ifc_pfx=None):
963 """Add ethernet interface to current topology.
965 :param node: DUT node from topology.
966 :param ifc_name: Name of the interface.
967 :param sw_if_idx: SW interface index.
968 :param ifc_pfx: Interface key prefix.
974 if_key = Topology.add_new_port(node, ifc_pfx)
976 vat_executor = VatExecutor()
977 vat_executor.execute_script_json_out("dump_interfaces.vat", node)
978 interface_dump_json = vat_executor.get_script_stdout()
980 if ifc_name and sw_if_idx is None:
981 sw_if_idx = VatJsonUtil.get_interface_sw_index_from_json(
982 interface_dump_json, ifc_name)
983 Topology.update_interface_sw_if_index(node, if_key, sw_if_idx)
984 if sw_if_idx and ifc_name is None:
985 ifc_name = InterfaceUtil.vpp_get_interface_name(node, sw_if_idx)
986 Topology.update_interface_name(node, if_key, ifc_name)
987 ifc_mac = VatJsonUtil.get_interface_mac_from_json(
988 interface_dump_json, sw_if_idx)
989 Topology.update_interface_mac_address(node, if_key, ifc_mac)
992 def vpp_create_avf_interface(node, vf_pci_addr):
993 """Create AVF interface on VPP node.
995 :param node: DUT node from topology.
996 :param vf_pci_addr: Virtual Function PCI address.
998 :type vf_pci_addr: str
999 :returns: Interface key (name) in topology.
1001 :raises RuntimeError: If it is not possible to create AVF interface on
1004 with VatTerminal(node, json_param=False) as vat:
1005 vat.vat_terminal_exec_cmd_from_template('create_avf_interface.vat',
1006 vf_pci_addr=vf_pci_addr)
1007 output = vat.vat_stdout
1009 if output is not None:
1010 sw_if_idx = int(output.split()[4])
1011 InterfaceUtil.add_eth_interface(node, sw_if_idx=sw_if_idx,
1013 if_key = Topology.get_interface_by_sw_index(node, sw_if_idx)
1016 raise RuntimeError('Create AVF interface failed on {host}'.
1017 format(host=node['host']))
1020 def vpp_enslave_physical_interface(node, interface, bond_interface):
1021 """Enslave physical interface to bond interface on VPP node.
1023 :param node: DUT node from topology.
1024 :param interface: Physical interface key from topology file.
1025 :param bond_interface: Load balance
1027 :type interface: str
1028 :type bond_interface: str
1029 :raises RuntimeError: If it is not possible to enslave physical
1030 interface to bond interface on the node.
1032 ifc = Topology.get_interface_sw_index(node, interface)
1033 bond_ifc = Topology.get_interface_sw_index(node, bond_interface)
1035 output = VatExecutor.cmd_from_template(
1036 node, 'enslave_physical_interface.vat', p_int=ifc, b_int=bond_ifc)
1038 retval = output[0].get('retval', None)
1039 if retval is None or int(retval) != 0:
1040 raise RuntimeError('Enslave physical interface {ifc} to bond '
1041 'interface {bond} failed on node "{n}"'
1042 .format(ifc=interface, bond=bond_interface,
1046 def vpp_show_bond_data_on_node(node, details=False):
1047 """Show (detailed) bond information on VPP node.
1049 :param node: DUT node from topology.
1050 :param details: If detailed information is required or not.
1054 cmd = 'exec show bond details' if details else 'exec show bond'
1055 with VatTerminal(node, json_param=False) as vat:
1056 vat.vat_terminal_exec_cmd(cmd)
1059 def vpp_show_bond_data_on_all_nodes(nodes, details=False):
1060 """Show (detailed) bond information on all VPP nodes in DICT__nodes.
1062 :param nodes: Nodes in the topology.
1063 :param details: If detailed information is required or not.
1067 for node_data in nodes.values():
1068 if node_data['type'] == NodeType.DUT:
1069 InterfaceUtil.vpp_show_bond_data_on_node(node_data, details)
1072 def vpp_enable_input_acl_interface(node, interface, ip_version,
1074 """Enable input acl on interface.
1076 :param node: VPP node to setup interface for input acl.
1077 :param interface: Interface to setup input acl.
1078 :param ip_version: Version of IP protocol.
1079 :param table_index: Classify table index.
1081 :type interface: str or int
1082 :type ip_version: str
1083 :type table_index: int
1085 if isinstance(interface, basestring):
1086 sw_if_index = Topology.get_interface_sw_index(node, interface)
1088 sw_if_index = interface
1090 with VatTerminal(node) as vat:
1091 vat.vat_terminal_exec_cmd_from_template("input_acl_int.vat",
1092 sw_if_index=sw_if_index,
1093 ip_version=ip_version,
1094 table_index=table_index)
1097 def get_interface_classify_table(node, interface):
1098 """Get name of classify table for the given interface.
1100 :param node: VPP node to get data from.
1101 :param interface: Name or sw_if_index of a specific interface.
1103 :type interface: str or int
1104 :returns: Classify table name.
1107 if isinstance(interface, basestring):
1108 sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
1110 sw_if_index = interface
1112 with VatTerminal(node) as vat:
1113 data = vat.vat_terminal_exec_cmd_from_template(
1114 "classify_interface_table.vat",
1115 sw_if_index=sw_if_index)
1119 def get_interface_vrf_table(node, interface):
1120 """Get vrf ID for the given interface.
1122 :param node: VPP node.
1123 :param interface: Name or sw_if_index of a specific interface.
1125 :type interface: str or int
1126 :returns: vrf ID of the specified interface.
1130 if isinstance(interface, basestring):
1131 sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
1133 sw_if_index = interface
1135 with VatTerminal(node) as vat:
1136 data = vat.vat_terminal_exec_cmd_from_template(
1137 "interface_vrf_dump.vat",
1138 sw_if_index=sw_if_index)
1139 return data[0]["vrf_id"]
1142 def get_sw_if_index(node, interface_name):
1143 """Get sw_if_index for the given interface from actual interface dump.
1145 :param node: VPP node to get interface data from.
1146 :param interface_name: Name of the specific interface.
1148 :type interface_name: str
1149 :returns: sw_if_index of the given interface.
1153 with VatTerminal(node) as vat:
1154 if_data = vat.vat_terminal_exec_cmd_from_template(
1155 "interface_dump.vat")
1156 for interface in if_data[0]:
1157 if interface["interface_name"] == interface_name:
1158 return interface["sw_if_index"]
1163 def vxlan_gpe_dump(node, interface_name=None):
1164 """Get VxLAN GPE data for the given interface.
1166 :param node: VPP node to get interface data from.
1167 :param interface_name: Name of the specific interface. If None,
1168 information about all VxLAN GPE interfaces is returned.
1170 :type interface_name: str
1171 :returns: Dictionary containing data for the given VxLAN GPE interface
1172 or if interface=None, the list of dictionaries with all VxLAN GPE
1174 :rtype: dict or list
1177 with VatTerminal(node) as vat:
1178 vxlan_gpe_data = vat.vat_terminal_exec_cmd_from_template(
1179 "vxlan_gpe_dump.vat")
1182 sw_if_index = InterfaceUtil.get_sw_if_index(node, interface_name)
1184 for vxlan_gpe in vxlan_gpe_data[0]:
1185 if vxlan_gpe["sw_if_index"] == sw_if_index:
1189 return vxlan_gpe_data[0]
1192 def vpp_proxy_arp_interface_enable(node, interface):
1193 """Enable proxy ARP on interface.
1195 :param node: VPP node to enable proxy ARP on interface.
1196 :param interface: Interface to enable proxy ARP.
1198 :type interface: str or int
1200 if isinstance(interface, basestring):
1201 sw_if_index = InterfaceUtil.get_sw_if_index(node, interface)
1203 sw_if_index = interface
1205 with VatTerminal(node) as vat:
1206 vat.vat_terminal_exec_cmd_from_template(
1207 "proxy_arp_intfc_enable.vat",
1208 sw_if_index=sw_if_index)
1211 def vpp_ip_source_check_setup(node, interface):
1212 """Setup Reverse Path Forwarding source check on interface.
1214 :param node: Node to setup RPF source check.
1215 :param interface: Interface name to setup RPF source check.
1217 :type interface: str
1219 with VatTerminal(node) as vat:
1220 vat.vat_terminal_exec_cmd_from_template("ip_source_check.vat",
1221 interface_name=interface)
1224 def assign_interface_to_fib_table(node, interface, table_id, ipv6=False):
1225 """Assign VPP interface to specific VRF/FIB table.
1227 :param node: VPP node where the FIB and interface are located.
1228 :param interface: Interface to be assigned to FIB.
1229 :param table_id: VRF table ID.
1230 :param ipv6: Assign to IPv6 table. Default False.
1232 :type interface: str or int
1236 if isinstance(interface, basestring):
1237 sw_if_index = Topology.get_interface_sw_index(node, interface)
1239 sw_if_index = interface
1241 ipv6 = 'ipv6' if ipv6 else ''
1243 with VatTerminal(node) as vat:
1244 ret = vat.vat_terminal_exec_cmd_from_template(
1245 "set_fib_to_interface.vat",
1246 sw_index=sw_if_index, vrf=table_id, ipv6=ipv6)
1248 if ret[0]["retval"] != 0:
1249 raise RuntimeError('Unable to assign interface to FIB node {}.'
1253 def set_linux_interface_mac(node, interface, mac, namespace=None,
1255 """Set MAC address for interface in linux.
1257 :param node: Node where to execute command.
1258 :param interface: Interface in namespace.
1259 :param mac: MAC to be assigned to interface.
1260 :param namespace: Execute command in namespace. Optional
1261 :param vf_id: Virtual Function id. Optional
1263 :type interface: str
1265 :type namespace: str
1268 mac_str = 'vf {vf_id} mac {mac}'.format(vf_id=vf_id, mac=mac) \
1269 if vf_id is not None else 'address {mac}'.format(mac=mac)
1270 ns_str = 'ip netns exec {ns}'.format(ns=namespace) if namespace else ''
1272 cmd = ('{ns} ip link set {interface} {mac}'.
1273 format(ns=ns_str, interface=interface, mac=mac_str))
1274 exec_cmd_no_error(node, cmd, sudo=True)
1277 def set_linux_interface_trust_on(node, interface, namespace=None,
1279 """Set trust on (promisc) for interface in linux.
1281 :param node: Node where to execute command.
1282 :param interface: Interface in namespace.
1283 :param namespace: Execute command in namespace. Optional
1284 :param vf_id: Virtual Function id. Optional
1286 :type interface: str
1287 :type namespace: str
1290 trust_str = 'vf {vf_id} trust on'.format(vf_id=vf_id) \
1291 if vf_id is not None else 'trust on'
1292 ns_str = 'ip netns exec {ns}'.format(ns=namespace) if namespace else ''
1294 cmd = ('{ns} ip link set dev {interface} {trust}'.
1295 format(ns=ns_str, interface=interface, trust=trust_str))
1296 exec_cmd_no_error(node, cmd, sudo=True)
1299 def set_linux_interface_spoof_off(node, interface, namespace=None,
1301 """Set spoof off for interface in linux.
1303 :param node: Node where to execute command.
1304 :param interface: Interface in namespace.
1305 :param namespace: Execute command in namespace. Optional
1306 :param vf_id: Virtual Function id. Optional
1308 :type interface: str
1309 :type namespace: str
1312 spoof_str = 'vf {vf_id} spoof off'.format(vf_id=vf_id) \
1313 if vf_id is not None else 'spoof off'
1314 ns_str = 'ip netns exec {ns}'.format(ns=namespace) if namespace else ''
1316 cmd = ('{ns} ip link set dev {interface} {spoof}'.
1317 format(ns=ns_str, interface=interface, spoof=spoof_str))
1318 exec_cmd_no_error(node, cmd, sudo=True)
1321 def init_avf_interface(node, ifc_key, numvfs=1, topology_type='L2'):
1322 """Init PCI device by creating VFs and bind them to vfio-pci for AVF
1323 driver testing on DUT.
1325 :param node: DUT node.
1326 :param ifc_key: Interface key from topology file.
1327 :param numvfs: Number of VFs to initialize, 0 - disable the VFs.
1328 :param topology_type: Topology type.
1332 :type topology_type: str
1333 :returns: Virtual Function topology interface keys.
1339 # Read PCI address and driver.
1340 pf_pci_addr = Topology.get_interface_pci_addr(node, ifc_key)
1341 pf_mac_addr = Topology.get_interface_mac(node, ifc_key).split(":")
1342 uio_driver = Topology.get_uio_driver(node)
1343 kernel_driver = Topology.get_interface_driver(node, ifc_key)
1344 current_driver = DUTSetup.get_pci_dev_driver(
1345 node, pf_pci_addr.replace(':', r'\:'))
1347 VPPUtil.stop_vpp_service(node)
1348 if current_driver != kernel_driver:
1349 # PCI device must be re-bound to kernel driver before creating VFs.
1350 DUTSetup.verify_kernel_module(node, kernel_driver, force_load=True)
1351 # Stop VPP to prevent deadlock.
1352 # Unbind from current driver.
1353 DUTSetup.pci_driver_unbind(node, pf_pci_addr)
1354 # Bind to kernel driver.
1355 DUTSetup.pci_driver_bind(node, pf_pci_addr, kernel_driver)
1357 # Initialize PCI VFs
1358 DUTSetup.set_sriov_numvfs(node, pf_pci_addr, numvfs)
1361 # Set MAC address and bind each virtual function to uio driver.
1362 for vf_id in range(numvfs):
1363 vf_mac_addr = ":".join([pf_mac_addr[0], pf_mac_addr[2],
1364 pf_mac_addr[3], pf_mac_addr[4],
1365 pf_mac_addr[5], "{:02x}".format(vf_id)])
1367 pf_dev = '`basename /sys/bus/pci/devices/{pci}/net/*`'.\
1368 format(pci=pf_pci_addr)
1369 InterfaceUtil.set_linux_interface_trust_on(node, pf_dev,
1371 if topology_type == 'L2':
1372 InterfaceUtil.set_linux_interface_spoof_off(node, pf_dev,
1374 InterfaceUtil.set_linux_interface_mac(node, pf_dev, vf_mac_addr,
1377 DUTSetup.pci_vf_driver_unbind(node, pf_pci_addr, vf_id)
1378 DUTSetup.pci_vf_driver_bind(node, pf_pci_addr, vf_id, uio_driver)
1380 # Add newly created ports into topology file
1381 vf_ifc_name = '{pf_if_key}_vf'.format(pf_if_key=ifc_key)
1382 vf_pci_addr = DUTSetup.get_virtfn_pci_addr(node, pf_pci_addr, vf_id)
1383 vf_ifc_key = Topology.add_new_port(node, vf_ifc_name)
1384 Topology.update_interface_name(node, vf_ifc_key,
1385 vf_ifc_name+str(vf_id+1))
1386 Topology.update_interface_mac_address(node, vf_ifc_key, vf_mac_addr)
1387 Topology.update_interface_pci_address(node, vf_ifc_key, vf_pci_addr)
1388 vf_ifc_keys.append(vf_ifc_key)
1393 def vpp_create_multiple_vxlan_ipv4_tunnels(
1394 node, node_vxlan_if, node_vlan_if, op_node, op_node_if,
1395 n_tunnels, vni_start, src_ip_start, dst_ip_start, ip_step, ip_limit,
1397 """Create multiple VXLAN tunnel interfaces and VLAN sub-interfaces on
1400 Put each pair of VXLAN tunnel interface and VLAN sub-interface to
1401 separate bridge-domain.
1403 :param node: VPP node to create VXLAN tunnel interfaces.
1404 :param node_vxlan_if: VPP node interface key to create VXLAN tunnel
1406 :param node_vlan_if: VPP node interface key to create VLAN
1408 :param op_node: Opposite VPP node for VXLAN tunnel interfaces.
1409 :param op_node_if: Opposite VPP node interface key for VXLAN tunnel
1411 :param n_tunnels: Number of tunnel interfaces to create.
1412 :param vni_start: VNI start ID.
1413 :param src_ip_start: VXLAN tunnel source IP address start.
1414 :param dst_ip_start: VXLAN tunnel destination IP address start.
1415 :param ip_step: IP address incremental step.
1416 :param ip_limit: IP address limit.
1417 :param bd_id_start: Bridge-domain ID start.
1419 :type node_vxlan_if: str
1420 :type node_vlan_if: str
1422 :type op_node_if: str
1423 :type n_tunnels: int
1424 :type vni_start: int
1425 :type src_ip_start: str
1426 :type dst_ip_start: str
1429 :type bd_id_start: int
1431 # configure IPs, create VXLAN interfaces and VLAN sub-interfaces
1432 vxlan_count = InterfaceUtil.vpp_create_vxlan_and_vlan_interfaces(
1433 node, node_vxlan_if, node_vlan_if, n_tunnels, vni_start,
1434 src_ip_start, dst_ip_start, ip_step, ip_limit)
1436 # update topology with VXLAN interfaces and VLAN sub-interfaces data
1437 # and put interfaces up
1438 InterfaceUtil.vpp_put_vxlan_and_vlan_interfaces_up(
1439 node, vxlan_count, node_vlan_if)
1441 # configure bridge domains, ARPs and routes
1442 InterfaceUtil.vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain(
1443 node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start,
1444 ip_step, bd_id_start)
1447 def vpp_create_vxlan_and_vlan_interfaces(
1448 node, node_vxlan_if, node_vlan_if, vxlan_count, vni_start,
1449 src_ip_start, dst_ip_start, ip_step, ip_limit):
1451 Configure IPs, create VXLAN interfaces and VLAN sub-interfaces on VPP
1454 :param node: VPP node.
1455 :param node_vxlan_if: VPP node interface key to create VXLAN tunnel
1457 :param node_vlan_if: VPP node interface key to create VLAN
1459 :param vxlan_count: Number of tunnel interfaces to create.
1460 :param vni_start: VNI start ID.
1461 :param src_ip_start: VXLAN tunnel source IP address start.
1462 :param dst_ip_start: VXLAN tunnel destination IP address start.
1463 :param ip_step: IP address incremental step.
1464 :param ip_limit: IP address limit.
1466 :type node_vxlan_if: str
1467 :type node_vlan_if: str
1468 :type vxlan_count: int
1469 :type vni_start: int
1470 :type src_ip_start: str
1471 :type dst_ip_start: str
1474 :returns: Number of created VXLAN interfaces.
1479 src_ip_start_int = IPUtil.ip_to_int(src_ip_start)
1480 dst_ip_start_int = IPUtil.ip_to_int(dst_ip_start)
1481 ip_limit_int = IPUtil.ip_to_int(ip_limit)
1483 tmp_fn = '/tmp/create_vxlan_interfaces.config'
1484 for i in range(0, vxlan_count):
1485 src_ip_int = src_ip_start_int + i * ip_step
1486 dst_ip_int = dst_ip_start_int + i * ip_step
1487 if src_ip_int > ip_limit_int or dst_ip_int > ip_limit_int:
1488 logger.warn("Can't do more iterations - IPv4 address limit "
1489 "has been reached.")
1492 src_ip = IPUtil.int_to_ip(src_ip_int)
1493 dst_ip = IPUtil.int_to_ip(dst_ip_int)
1495 'sw_interface_add_del_address sw_if_index {sw_idx} {ip}/32\n'
1496 .format(sw_idx=Topology.get_interface_sw_index(
1497 node, node_vxlan_if), ip=src_ip))
1499 'vxlan_add_del_tunnel src {src_ip} dst {dst_ip} vni {vni}\n'
1500 .format(src_ip=src_ip, dst_ip=dst_ip, vni=vni_start+i))
1502 'create_vlan_subif sw_if_index {sw_idx} vlan {vlan}\n'
1503 .format(sw_idx=Topology.get_interface_sw_index(
1504 node, node_vlan_if), vlan=i+1))
1506 VatExecutor().write_and_execute_script(node, tmp_fn, commands)
1511 def vpp_put_vxlan_and_vlan_interfaces_up(node, vxlan_count, node_vlan_if):
1513 Update topology with VXLAN interfaces and VLAN sub-interfaces data
1514 and put interfaces up.
1516 :param node: VPP node.
1517 :param vxlan_count: Number of tunnel interfaces.
1518 :param node_vlan_if: VPP node interface key where VLAN sub-interfaces
1521 :type vxlan_count: int
1522 :type node_vlan_if: str
1524 with VatTerminal(node) as vat_ter:
1525 if_data = vat_ter.vat_terminal_exec_cmd_from_template(
1526 'interface_dump.vat')[0]
1528 tmp_fn = '/tmp/put_subinterfaces_up.config'
1530 for i in range(0, vxlan_count):
1531 vxlan_subif_key = Topology.add_new_port(node, 'vxlan_tunnel')
1532 vxlan_subif_name = 'vxlan_tunnel{nr}'.format(nr=i)
1534 vxlan_subif_idx = None
1535 vlan_subif_key = Topology.add_new_port(node, 'vlan_subif')
1536 vlan_subif_name = '{if_name}.{vlan}'.format(
1537 if_name=Topology.get_interface_name(
1538 node, node_vlan_if), vlan=i+1)
1541 for data in if_data:
1542 if_name = data['interface_name']
1543 if not vxlan_found and if_name == vxlan_subif_name:
1544 vxlan_subif_idx = data['sw_if_index']
1546 elif not vlan_found and if_name == vlan_subif_name:
1547 vlan_idx = data['sw_if_index']
1549 if vxlan_found and vlan_found:
1551 Topology.update_interface_sw_if_index(
1552 node, vxlan_subif_key, vxlan_subif_idx)
1553 Topology.update_interface_name(
1554 node, vxlan_subif_key, vxlan_subif_name)
1556 'sw_interface_set_flags sw_if_index {sw_idx} admin-up link-up\n'
1557 .format(sw_idx=vxlan_subif_idx))
1558 Topology.update_interface_sw_if_index(
1559 node, vlan_subif_key, vlan_idx)
1560 Topology.update_interface_name(
1561 node, vlan_subif_key, vlan_subif_name)
1563 'sw_interface_set_flags sw_if_index {sw_idx} admin-up link-up\n'
1564 .format(sw_idx=vlan_idx))
1566 VatExecutor().write_and_execute_script(node, tmp_fn, commands)
1569 def vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain(
1570 node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start,
1571 ip_step, bd_id_start):
1573 Configure ARPs and routes for VXLAN interfaces and put each pair of
1574 VXLAN tunnel interface and VLAN sub-interface to separate bridge-domain.
1576 :param node: VPP node.
1577 :param node_vxlan_if: VPP node interface key where VXLAN tunnel
1578 interfaces have been created.
1579 :param vxlan_count: Number of tunnel interfaces.
1580 :param op_node: Opposite VPP node for VXLAN tunnel interfaces.
1581 :param op_node_if: Opposite VPP node interface key for VXLAN tunnel
1583 :param dst_ip_start: VXLAN tunnel destination IP address start.
1584 :param ip_step: IP address incremental step.
1585 :param bd_id_start: Bridge-domain ID start.
1587 :type node_vxlan_if: str
1588 :type vxlan_count: int
1591 :type dst_ip_start: str
1593 :type bd_id_start: int
1595 sw_idx_vxlan = Topology.get_interface_sw_index(node, node_vxlan_if)
1597 dst_ip_start_int = IPUtil.ip_to_int(dst_ip_start)
1599 tmp_fn = '/tmp/configure_routes_and_bridge_domains.config'
1601 for i in range(0, vxlan_count):
1602 dst_ip = IPUtil.int_to_ip(dst_ip_start_int + i * ip_step)
1604 'ip_neighbor_add_del sw_if_index {sw_idx} dst {ip} mac {mac}\n'
1605 .format(sw_idx=sw_idx_vxlan, ip=dst_ip,
1606 mac=Topology.get_interface_mac(op_node, op_node_if)))
1608 'ip_add_del_route {ip}/32 via {ip} sw_if_index {sw_idx}'
1609 ' resolve-attempts 10 count 1\n'.format(
1610 ip=dst_ip, sw_idx=sw_idx_vxlan))
1611 bd_id = bd_id_start + i
1614 'sw_interface_set_l2_bridge sw_if_index {sw_idx} bd_id {bd_id} '
1615 'shg 0 enable\n'.format(sw_idx=Topology.get_interface_sw_index(
1616 node, 'vxlan_tunnel{nr}'.format(nr=subif_id)), bd_id=bd_id))
1618 'sw_interface_set_l2_bridge sw_if_index {sw_idx} bd_id {bd_id} '
1619 'shg 0 enable\n'.format(sw_idx=Topology.get_interface_sw_index(
1620 node, 'vlan_subif{nr}'.format(nr=subif_id)), bd_id=bd_id))
1622 VatExecutor().write_and_execute_script(node, tmp_fn, commands)