From dbe149c85501bc15dde1496a722e2b9dce86ee92 Mon Sep 17 00:00:00 2001 From: Jan Gelety Date: Tue, 18 Jun 2019 13:17:31 +0200 Subject: [PATCH] FIX: VXLAN scale tests Change-Id: I9287d5ed6d7876b98add3fb3d523e9764094843b Signed-off-by: Jan Gelety --- resources/libraries/python/InterfaceUtil.py | 300 +-------------- resources/libraries/python/TestConfig.py | 428 +++++++++++++++++++++ .../performance/performance_configuration.robot | 7 +- 3 files changed, 438 insertions(+), 297 deletions(-) create mode 100644 resources/libraries/python/TestConfig.py diff --git a/resources/libraries/python/InterfaceUtil.py b/resources/libraries/python/InterfaceUtil.py index 34bfc1efe5..7706c14e06 100644 --- a/resources/libraries/python/InterfaceUtil.py +++ b/resources/libraries/python/InterfaceUtil.py @@ -13,12 +13,11 @@ """Interface util library.""" -from socket import AF_INET, AF_INET6, inet_ntop, inet_pton +from socket import AF_INET, AF_INET6, inet_ntop from time import sleep from enum import IntEnum -from ipaddress import IPv4Address, IPv6Address -from ipaddress import AddressValueError, NetmaskValueError +from ipaddress import ip_address from robot.api import logger from resources.libraries.python.Constants import Constants @@ -760,23 +759,15 @@ 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)) - af_inet = AF_INET6 - is_ipv6 = 1 - except (AddressValueError, NetmaskValueError): - src_address = IPv4Address(unicode(source_ip)) - dst_address = IPv4Address(unicode(destination_ip)) - af_inet = AF_INET - is_ipv6 = 0 + src_address = ip_address(unicode(source_ip)) + dst_address = ip_address(unicode(destination_ip)) cmd = 'vxlan_add_del_tunnel' args = dict(is_add=1, - is_ipv6=is_ipv6, + is_ipv6=1 if src_address.version == 6 else 0, instance=Constants.BITWISE_NON_ZERO, - src_address=inet_pton(af_inet, str(src_address)), - dst_address=inet_pton(af_inet, str(dst_address)), + src_address=src_address.packed, + dst_address=dst_address.packed, mcast_sw_if_index=Constants.BITWISE_NON_ZERO, encap_vrf_id=0, decap_next_index=Constants.BITWISE_NON_ZERO, @@ -1600,283 +1591,6 @@ class InterfaceUtil(object): return vf_ifc_keys - @staticmethod - def vpp_create_multiple_vxlan_ipv4_tunnels( - node, node_vxlan_if, node_vlan_if, op_node, op_node_if, - n_tunnels, vni_start, src_ip_start, dst_ip_start, ip_step, ip_limit, - bd_id_start): - """Create multiple VXLAN tunnel interfaces and VLAN sub-interfaces on - VPP node. - - Put each pair of VXLAN tunnel interface and VLAN sub-interface to - separate bridge-domain. - - :param node: VPP node to create VXLAN tunnel interfaces. - :param node_vxlan_if: VPP node interface key to create VXLAN tunnel - interfaces. - :param node_vlan_if: VPP node interface key to create VLAN - sub-interface. - :param op_node: Opposite VPP node for VXLAN tunnel interfaces. - :param op_node_if: Opposite VPP node interface key for VXLAN tunnel - interfaces. - :param n_tunnels: Number of tunnel interfaces to create. - :param vni_start: VNI start ID. - :param src_ip_start: VXLAN tunnel source IP address start. - :param dst_ip_start: VXLAN tunnel destination IP address start. - :param ip_step: IP address incremental step. - :param ip_limit: IP address limit. - :param bd_id_start: Bridge-domain ID start. - :type node: dict - :type node_vxlan_if: str - :type node_vlan_if: str - :type op_node: dict - :type op_node_if: str - :type n_tunnels: int - :type vni_start: int - :type src_ip_start: str - :type dst_ip_start: str - :type ip_step: int - :type ip_limit: str - :type bd_id_start: int - """ - # configure IPs, create VXLAN interfaces and VLAN sub-interfaces - vxlan_count = InterfaceUtil.vpp_create_vxlan_and_vlan_interfaces( - node, node_vxlan_if, node_vlan_if, n_tunnels, vni_start, - src_ip_start, dst_ip_start, ip_step, ip_limit) - - # update topology with VXLAN interfaces and VLAN sub-interfaces data - # and put interfaces up - InterfaceUtil.vpp_put_vxlan_and_vlan_interfaces_up( - node, vxlan_count, node_vlan_if) - - # configure bridge domains, ARPs and routes - InterfaceUtil.vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain( - node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start, - ip_step, bd_id_start) - - @staticmethod - def vpp_create_vxlan_and_vlan_interfaces( - node, node_vxlan_if, node_vlan_if, vxlan_count, vni_start, - src_ip_start, dst_ip_start, ip_step, ip_limit): - """ - Configure IPs, create VXLAN interfaces and VLAN sub-interfaces on VPP - node. - - :param node: VPP node. - :param node_vxlan_if: VPP node interface key to create VXLAN tunnel - interfaces. - :param node_vlan_if: VPP node interface key to create VLAN - sub-interface. - :param vxlan_count: Number of tunnel interfaces to create. - :param vni_start: VNI start ID. - :param src_ip_start: VXLAN tunnel source IP address start. - :param dst_ip_start: VXLAN tunnel destination IP address start. - :param ip_step: IP address incremental step. - :param ip_limit: IP address limit. - :type node: dict - :type node_vxlan_if: str - :type node_vlan_if: str - :type vxlan_count: int - :type vni_start: int - :type src_ip_start: str - :type dst_ip_start: str - :type ip_step: int - :type ip_limit: str - :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)) - ip_address_limit = IPv6Address(unicode(ip_limit)) - af_inet = AF_INET6 - is_ipv6 = 1 - except (AddressValueError, NetmaskValueError): - src_address_start = IPv4Address(unicode(src_ip_start)) - dst_address_start = IPv4Address(unicode(dst_ip_start)) - ip_address_limit = IPv4Address(unicode(ip_limit)) - af_inet = AF_INET - is_ipv6 = 0 - - with PapiExecutor(node) as papi_exec: - for i in xrange(0, vxlan_count): - src_ip = src_address_start + i * ip_step - dst_ip = dst_address_start + i * ip_step - if src_ip > ip_address_limit or dst_ip > ip_address_limit: - logger.warn("Can't do more iterations - IP address limit " - "has been reached.") - vxlan_count = i - break - cmd = 'sw_interface_add_del_address' - args = dict( - sw_if_index=InterfaceUtil.get_interface_index( - node, node_vxlan_if), - is_add=1, - is_ipv6=0, - del_all=0, - address_length=128 if is_ipv6 else 32, - address=inet_pton(af_inet, str(src_ip))) - papi_exec.add(cmd, **args) - cmd = 'vxlan_add_del_tunnel' - args = dict( - is_add=1, - is_ipv6=0, - instance=Constants.BITWISE_NON_ZERO, - src_address=inet_pton(af_inet, str(src_ip)), - dst_address=inet_pton(af_inet, str(dst_ip)), - mcast_sw_if_index=Constants.BITWISE_NON_ZERO, - encap_vrf_id=0, - decap_next_index=Constants.BITWISE_NON_ZERO, - vni=int(vni_start)+i) - papi_exec.add(cmd, **args) - cmd = 'create_vlan_subif' - args = dict( - sw_if_index=InterfaceUtil.get_interface_index( - node, node_vlan_if), - vlan_id=i+1) - papi_exec.add(cmd, **args) - papi_exec.get_replies().verify_replies() - - return vxlan_count - - @staticmethod - def vpp_put_vxlan_and_vlan_interfaces_up(node, vxlan_count, node_vlan_if): - """ - Update topology with VXLAN interfaces and VLAN sub-interfaces data - and put interfaces up. - - :param node: VPP node. - :param vxlan_count: Number of tunnel interfaces. - :param node_vlan_if: VPP node interface key where VLAN sub-interfaces - have been created. - :type node: dict - :type vxlan_count: int - :type node_vlan_if: str - """ - if_data = InterfaceUtil.vpp_get_interface_data(node) - - with PapiExecutor(node) as papi_exec: - for i in xrange(0, vxlan_count): - vxlan_subif_key = Topology.add_new_port(node, 'vxlan_tunnel') - vxlan_subif_name = 'vxlan_tunnel{nr}'.format(nr=i) - vxlan_found = False - vxlan_subif_idx = None - vlan_subif_key = Topology.add_new_port(node, 'vlan_subif') - vlan_subif_name = '{if_name}.{vlan}'.format( - if_name=Topology.get_interface_name( - node, node_vlan_if), vlan=i+1) - vlan_found = False - vlan_idx = None - for data in if_data: - if not vxlan_found \ - and data['interface_name'] == vxlan_subif_name: - vxlan_subif_idx = data['sw_if_index'] - vxlan_found = True - elif not vlan_found \ - and data['interface_name'] == vlan_subif_name: - vlan_idx = data['sw_if_index'] - vlan_found = True - if vxlan_found and vlan_found: - break - Topology.update_interface_sw_if_index( - node, vxlan_subif_key, vxlan_subif_idx) - Topology.update_interface_name( - node, vxlan_subif_key, vxlan_subif_name) - cmd = 'sw_interface_set_flags' - args1 = dict(sw_if_index=vxlan_subif_idx, - admin_up_down=1) - Topology.update_interface_sw_if_index( - node, vlan_subif_key, vlan_idx) - Topology.update_interface_name( - node, vlan_subif_key, vlan_subif_name) - args2 = dict(sw_if_index=vlan_idx, - admin_up_down=1) - papi_exec.add(cmd, **args1).add(cmd, **args2) - papi_exec.get_replies().verify_replies() - - @staticmethod - def vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain( - node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start, - ip_step, bd_id_start): - """ - Configure ARPs and routes for VXLAN interfaces and put each pair of - VXLAN tunnel interface and VLAN sub-interface to separate bridge-domain. - - :param node: VPP node. - :param node_vxlan_if: VPP node interface key where VXLAN tunnel - interfaces have been created. - :param vxlan_count: Number of tunnel interfaces. - :param op_node: Opposite VPP node for VXLAN tunnel interfaces. - :param op_node_if: Opposite VPP node interface key for VXLAN tunnel - interfaces. - :param dst_ip_start: VXLAN tunnel destination IP address start. - :param ip_step: IP address incremental step. - :param bd_id_start: Bridge-domain ID start. - :type node: dict - :type node_vxlan_if: str - :type vxlan_count: int - :type op_node: dict - :type op_node_if: - :type dst_ip_start: str - :type ip_step: int - :type bd_id_start: int - """ - try: - dst_address_start = IPv6Address(unicode(dst_ip_start)) - af_inet = AF_INET6 - is_ipv6 = 1 - except (AddressValueError, NetmaskValueError): - dst_address_start = IPv4Address(unicode(dst_ip_start)) - af_inet = AF_INET - is_ipv6 = 0 - - with PapiExecutor(node) as papi_exec: - for i in xrange(0, vxlan_count): - dst_ip = dst_address_start + i * ip_step - neighbor = dict( - sw_if_index=Topology.get_interface_sw_index( - node, node_vxlan_if), - flags=0, - mac_address=str( - Topology.get_interface_mac(op_node, op_node_if)), - ip_address=str(dst_ip)) - cmd = 'ip_neighbor_add_del' - args = dict( - is_add=1, - neighbor=neighbor) - papi_exec.add(cmd, **args) - cmd = 'ip_add_del_route' - args = dict( - next_hop_sw_if_index=Topology.get_interface_sw_index( - node, node_vxlan_if), - table_id=0, - is_add=1, - is_ipv6=is_ipv6, - next_hop_weight=1, - next_hop_proto=1 if is_ipv6 else 0, - dst_address_length=128 if is_ipv6 else 32, - dst_address=inet_pton(af_inet, str(dst_ip)), - next_hop_address=inet_pton(af_inet, str(dst_ip))) - papi_exec.add(cmd, **args) - cmd = 'sw_interface_set_l2_bridge' - args = dict( - rx_sw_if_index=Topology.get_interface_sw_index( - node, 'vxlan_tunnel{nr}'.format(nr=i+1)), - bd_id=int(bd_id_start+i), - shg=0, - port_type=0, - enable=1) - papi_exec.add(cmd, **args) - args = dict( - rx_sw_if_index=Topology.get_interface_sw_index( - node, 'vlan_subif{nr}'.format(nr=i+1)), - bd_id=int(bd_id_start+i), - shg=0, - port_type=0, - enable=1) - papi_exec.add(cmd, **args) - papi_exec.get_replies().verify_replies() - @staticmethod def vpp_sw_interface_rx_placement_dump(node): """Dump VPP interface RX placement on node. diff --git a/resources/libraries/python/TestConfig.py b/resources/libraries/python/TestConfig.py new file mode 100644 index 0000000000..1f8af5d457 --- /dev/null +++ b/resources/libraries/python/TestConfig.py @@ -0,0 +1,428 @@ +# 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: +# +# 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. + +"""Special test configurations library.""" + +from ipaddress import ip_address, AddressValueError +from robot.api import logger + +from resources.libraries.python.Constants import Constants +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 Topology +from resources.libraries.python.VatExecutor import VatExecutor + + +class TestConfig(object): + """Contains special test configurations implemented in python for faster + execution.""" + + @staticmethod + def vpp_create_multiple_vxlan_ipv4_tunnels( + node, node_vxlan_if, node_vlan_if, op_node, op_node_if, + n_tunnels, vni_start, src_ip_start, dst_ip_start, ip_step, + bd_id_start): + """Create multiple VXLAN tunnel interfaces and VLAN sub-interfaces on + VPP node. + + Put each pair of VXLAN tunnel interface and VLAN sub-interface to + separate bridge-domain. + + :param node: VPP node to create VXLAN tunnel interfaces. + :param node_vxlan_if: VPP node interface key to create VXLAN tunnel + interfaces. + :param node_vlan_if: VPP node interface key to create VLAN + sub-interface. + :param op_node: Opposite VPP node for VXLAN tunnel interfaces. + :param op_node_if: Opposite VPP node interface key for VXLAN tunnel + interfaces. + :param n_tunnels: Number of tunnel interfaces to create. + :param vni_start: VNI start ID. + :param src_ip_start: VXLAN tunnel source IP address start. + :param dst_ip_start: VXLAN tunnel destination IP address start. + :param ip_step: IP address incremental step. + :param bd_id_start: Bridge-domain ID start. + :type node: dict + :type node_vxlan_if: str + :type node_vlan_if: str + :type op_node: dict + :type op_node_if: str + :type n_tunnels: int + :type vni_start: int + :type src_ip_start: str + :type dst_ip_start: str + :type ip_step: int + :type bd_id_start: int + """ + # configure IPs, create VXLAN interfaces and VLAN sub-interfaces + vxlan_count = TestConfig.vpp_create_vxlan_and_vlan_interfaces( + node, node_vxlan_if, node_vlan_if, n_tunnels, vni_start, + src_ip_start, dst_ip_start, ip_step) + + # update topology with VXLAN interfaces and VLAN sub-interfaces data + # and put interfaces up + TestConfig.vpp_put_vxlan_and_vlan_interfaces_up( + node, vxlan_count, node_vlan_if) + + # configure bridge domains, ARPs and routes + TestConfig.vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain( + node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start, + ip_step, bd_id_start) + + @staticmethod + def vpp_create_vxlan_and_vlan_interfaces( + node, node_vxlan_if, node_vlan_if, vxlan_count, vni_start, + src_ip_start, dst_ip_start, ip_step): + """ + Configure IPs, create VXLAN interfaces and VLAN sub-interfaces on VPP + node. + + :param node: VPP node. + :param node_vxlan_if: VPP node interface key to create VXLAN tunnel + interfaces. + :param node_vlan_if: VPP node interface key to create VLAN + sub-interface. + :param vxlan_count: Number of tunnel interfaces to create. + :param vni_start: VNI start ID. + :param src_ip_start: VXLAN tunnel source IP address start. + :param dst_ip_start: VXLAN tunnel destination IP address start. + :param ip_step: IP address incremental step. + :type node: dict + :type node_vxlan_if: str + :type node_vlan_if: str + :type vxlan_count: int + :type vni_start: int + :type src_ip_start: str + :type dst_ip_start: str + :type ip_step: int + :returns: Number of created VXLAN interfaces. + :rtype: int + """ + src_ip_addr_start = ip_address(unicode(src_ip_start)) + dst_ip_addr_start = ip_address(unicode(dst_ip_start)) + + if vxlan_count > 10: + commands = list() + tmp_fn = '/tmp/create_vxlan_interfaces.config' + for i in xrange(0, vxlan_count): + try: + src_ip = src_ip_addr_start + i * ip_step + dst_ip = dst_ip_addr_start + i * ip_step + except AddressValueError: + logger.warn("Can't do more iterations - IP address limit " + "has been reached.") + vxlan_count = i + break + commands.append( + 'sw_interface_add_del_address sw_if_index {sw_idx} ' + '{ip}/{ip_len}\n'.format( + sw_idx=Topology.get_interface_sw_index( + node, node_vxlan_if), + ip=src_ip, + ip_len=128 if src_ip.version == 6 else 32)) + commands.append( + 'vxlan_add_del_tunnel src {src_ip} dst {dst_ip} vni {vni}\n' + .format(src_ip=src_ip, dst_ip=dst_ip, + vni=vni_start + i)) + commands.append( + 'create_vlan_subif sw_if_index {sw_idx} vlan {vlan}\n' + .format(sw_idx=Topology.get_interface_sw_index( + node, node_vlan_if), vlan=i + 1)) + VatExecutor().write_and_execute_script(node, tmp_fn, commands) + return vxlan_count + + cmd1 = 'sw_interface_add_del_address' + args1 = dict( + sw_if_index=InterfaceUtil.get_interface_index(node, node_vxlan_if), + is_add=1, + is_ipv6=1 if src_ip_addr_start.version == 6 else 0, + del_all=0, + address_length=128 if src_ip_addr_start.version == 6 else 32, + address=None) + cmd2 = 'vxlan_add_del_tunnel' + args2 = dict( + is_add=1, + is_ipv6=0, + instance=Constants.BITWISE_NON_ZERO, + src_address=None, + dst_address=None, + mcast_sw_if_index=Constants.BITWISE_NON_ZERO, + encap_vrf_id=0, + decap_next_index=Constants.BITWISE_NON_ZERO, + vni=None) + cmd3 = 'create_vlan_subif' + args3 = dict( + sw_if_index=InterfaceUtil.get_interface_index( + node, node_vlan_if), + vlan_id=None) + err_msg = 'Failed to create VXLAN and VLAN interfaces on host {host}'.\ + format(host=node['host']) + + with PapiExecutor(node) as papi_exec: + for i in xrange(0, vxlan_count): + try: + src_ip = src_ip_addr_start + i * ip_step + dst_ip = dst_ip_addr_start + i * ip_step + except AddressValueError: + logger.warn("Can't do more iterations - IP address limit " + "has been reached.") + vxlan_count = i + break + args1['address'] = src_ip.packed + args2['src_address'] = src_ip.packed + args2['dst_address'] = dst_ip.packed + args2['vni'] = int(vni_start) + i + args3['vlan_id'] = i + 1 + history = False if 1 < i < vxlan_count else True + papi_exec.add(cmd1, history=history, **args1).\ + add(cmd2, history=history, **args2).\ + add(cmd3, history=history, **args3) + if i > 0 and i % (Constants.PAPI_MAX_API_BULK / 3) == 0: + papi_exec.get_replies(err_msg).verify_replies( + err_msg=err_msg) + papi_exec.get_replies().verify_replies() + + return vxlan_count + + @staticmethod + def vpp_put_vxlan_and_vlan_interfaces_up(node, vxlan_count, node_vlan_if): + """ + Update topology with VXLAN interfaces and VLAN sub-interfaces data + and put interfaces up. + + :param node: VPP node. + :param vxlan_count: Number of tunnel interfaces. + :param node_vlan_if: VPP node interface key where VLAN sub-interfaces + have been created. + :type node: dict + :type vxlan_count: int + :type node_vlan_if: str + """ + if_data = InterfaceUtil.vpp_get_interface_data(node) + vlan_if_name = Topology.get_interface_name(node, node_vlan_if) + + if vxlan_count > 10: + tmp_fn = '/tmp/put_subinterfaces_up.config' + commands = list() + for i in xrange(0, vxlan_count): + vxlan_subif_key = Topology.add_new_port(node, 'vxlan_tunnel') + vxlan_subif_name = 'vxlan_tunnel{nr}'.format(nr=i) + vxlan_found = False + vxlan_subif_idx = None + vlan_subif_key = Topology.add_new_port(node, 'vlan_subif') + vlan_subif_name = '{if_name}.{vlan}'.format( + if_name=vlan_if_name, vlan=i + 1) + vlan_found = False + vlan_idx = None + for data in if_data: + if_name = data['interface_name'] + if not vxlan_found and if_name == vxlan_subif_name: + vxlan_subif_idx = data['sw_if_index'] + vxlan_found = True + elif not vlan_found and if_name == vlan_subif_name: + vlan_idx = data['sw_if_index'] + vlan_found = True + if vxlan_found and vlan_found: + break + Topology.update_interface_sw_if_index( + node, vxlan_subif_key, vxlan_subif_idx) + Topology.update_interface_name( + node, vxlan_subif_key, vxlan_subif_name) + commands.append( + 'sw_interface_set_flags sw_if_index {sw_idx} admin-up ' + 'link-up\n'.format(sw_idx=vxlan_subif_idx)) + Topology.update_interface_sw_if_index( + node, vlan_subif_key, vlan_idx) + Topology.update_interface_name( + node, vlan_subif_key, vlan_subif_name) + commands.append( + 'sw_interface_set_flags sw_if_index {sw_idx} admin-up ' + 'link-up\n'.format(sw_idx=vlan_idx)) + VatExecutor().write_and_execute_script(node, tmp_fn, commands) + return + + cmd = 'sw_interface_set_flags' + args1 = dict( + sw_if_index=None, + admin_up_down=1) + args2 = dict( + sw_if_index=None, + admin_up_down=1) + err_msg = 'Failed to put VXLAN and VLAN interfaces up on host {host}'. \ + format(host=node['host']) + + with PapiExecutor(node) as papi_exec: + for i in xrange(0, vxlan_count): + vxlan_subif_key = Topology.add_new_port(node, 'vxlan_tunnel') + vxlan_subif_name = 'vxlan_tunnel{nr}'.format(nr=i) + vxlan_found = False + vxlan_subif_idx = None + vlan_subif_key = Topology.add_new_port(node, 'vlan_subif') + vlan_subif_name = '{if_name}.{vlan}'.format( + if_name=vlan_if_name, vlan=i+1) + vlan_found = False + vlan_idx = None + for data in if_data: + if not vxlan_found \ + and data['interface_name'] == vxlan_subif_name: + vxlan_subif_idx = data['sw_if_index'] + vxlan_found = True + elif not vlan_found \ + and data['interface_name'] == vlan_subif_name: + vlan_idx = data['sw_if_index'] + vlan_found = True + if vxlan_found and vlan_found: + break + Topology.update_interface_sw_if_index( + node, vxlan_subif_key, vxlan_subif_idx) + Topology.update_interface_name( + node, vxlan_subif_key, vxlan_subif_name) + args1['sw_if_index'] = vxlan_subif_idx + Topology.update_interface_sw_if_index( + node, vlan_subif_key, vlan_idx) + Topology.update_interface_name( + node, vlan_subif_key, vlan_subif_name) + args2['sw_if_index'] = vlan_idx + history = False if 1 < i < vxlan_count else True + papi_exec.add(cmd, history=history, **args1). \ + add(cmd, history=history, **args2) + if i > 0 and i % (Constants.PAPI_MAX_API_BULK / 2) == 0: + papi_exec.get_replies(err_msg).verify_replies( + err_msg=err_msg) + papi_exec.add(cmd, **args1).add(cmd, **args2) + papi_exec.get_replies().verify_replies() + + @staticmethod + def vpp_put_vxlan_and_vlan_interfaces_to_bridge_domain( + node, node_vxlan_if, vxlan_count, op_node, op_node_if, dst_ip_start, + ip_step, bd_id_start): + """ + Configure ARPs and routes for VXLAN interfaces and put each pair of + VXLAN tunnel interface and VLAN sub-interface to separate bridge-domain. + + :param node: VPP node. + :param node_vxlan_if: VPP node interface key where VXLAN tunnel + interfaces have been created. + :param vxlan_count: Number of tunnel interfaces. + :param op_node: Opposite VPP node for VXLAN tunnel interfaces. + :param op_node_if: Opposite VPP node interface key for VXLAN tunnel + interfaces. + :param dst_ip_start: VXLAN tunnel destination IP address start. + :param ip_step: IP address incremental step. + :param bd_id_start: Bridge-domain ID start. + :type node: dict + :type node_vxlan_if: str + :type vxlan_count: int + :type op_node: dict + :type op_node_if: + :type dst_ip_start: str + :type ip_step: int + :type bd_id_start: int + """ + dst_ip_addr_start = ip_address(unicode(dst_ip_start)) + + if vxlan_count > 1: + sw_idx_vxlan = Topology.get_interface_sw_index(node, node_vxlan_if) + tmp_fn = '/tmp/configure_routes_and_bridge_domains.config' + commands = list() + for i in xrange(0, vxlan_count): + dst_ip = dst_ip_addr_start + i * ip_step + commands.append( + 'ip_neighbor_add_del sw_if_index {sw_idx} dst {ip} ' + 'mac {mac}\n'.format( + sw_idx=sw_idx_vxlan, + ip=dst_ip, + mac=Topology.get_interface_mac(op_node, op_node_if))) + commands.append( + 'ip_route_add_del {ip}/{ip_len} count 1 via {ip} ' + 'sw_if_index {sw_idx}\n'.format( + ip=dst_ip, + ip_len=128 if dst_ip.version == 6 else 32, + sw_idx=sw_idx_vxlan)) + commands.append( + 'sw_interface_set_l2_bridge sw_if_index {sw_idx} ' + 'bd_id {bd_id} shg 0 enable\n'.format( + sw_idx=Topology.get_interface_sw_index( + node, 'vxlan_tunnel{nr}'.format(nr=i + 1)), + bd_id=bd_id_start + i)) + commands.append( + 'sw_interface_set_l2_bridge sw_if_index {sw_idx} ' + 'bd_id {bd_id} shg 0 enable\n'.format( + sw_idx=Topology.get_interface_sw_index( + node, 'vlan_subif{nr}'.format(nr=i + 1)), + bd_id=bd_id_start + i)) + VatExecutor().write_and_execute_script(node, tmp_fn, commands) + return + + cmd1 = 'ip_neighbor_add_del' + neighbor = dict( + sw_if_index=Topology.get_interface_sw_index(node, node_vxlan_if), + flags=0, + mac_address=Topology.get_interface_mac(op_node, op_node_if), + ip_address='') + args1 = dict( + is_add=1, + neighbor=neighbor) + cmd2 = 'ip_route_add_del' + kwargs = dict( + interface=node_vxlan_if, + gateway=str(dst_ip_addr_start)) + route = IPUtil.compose_vpp_route_structure( + node, + str(dst_ip_addr_start), + 128 if dst_ip_addr_start.version == 6 else 32, + **kwargs) + args2 = dict( + is_add=1, + is_multipath=0, + route=route) + cmd3 = 'sw_interface_set_l2_bridge' + args3 = dict( + rx_sw_if_index=None, + bd_id=None, + shg=0, + port_type=0, + enable=1) + args4 = dict( + rx_sw_if_index=None, + bd_id=None, + shg=0, + port_type=0, + enable=1) + err_msg = 'Failed to put VXLAN and VLAN interfaces to bridge domain ' \ + 'on host {host}'.format(host=node['host']) + + with PapiExecutor(node) as papi_exec: + for i in xrange(0, vxlan_count): + dst_ip = dst_ip_addr_start + i * ip_step + args1['neighbor']['ip_address'] = str(dst_ip) + args2['route']['prefix']['address']['un'] = \ + IPUtil.union_addr(dst_ip) + args2['route']['paths'][0]['nh']['address'] = \ + IPUtil.union_addr(dst_ip) + args3['rx_sw_if_index'] = Topology.get_interface_sw_index( + node, 'vxlan_tunnel{nr}'.format(nr=i+1)) + args3['bd_id'] = int(bd_id_start+i) + args4['rx_sw_if_index'] = Topology.get_interface_sw_index( + node, 'vlan_subif{nr}'.format(nr=i+1)) + args4['bd_id'] = int(bd_id_start+i) + history = False if 1 < i < vxlan_count else True + papi_exec.add(cmd1, history=history, **args1). \ + add(cmd2, history=history, **args2). \ + add(cmd3, history=history, **args3). \ + add(cmd3, history=history, **args4) + if i > 0 and i % (Constants.PAPI_MAX_API_BULK / 4) == 0: + papi_exec.get_replies(err_msg).verify_replies( + err_msg=err_msg) + papi_exec.get_replies().verify_replies() diff --git a/resources/libraries/robot/performance/performance_configuration.robot b/resources/libraries/robot/performance/performance_configuration.robot index 2fb82ab47e..63810ee471 100644 --- a/resources/libraries/robot/performance/performance_configuration.robot +++ b/resources/libraries/robot/performance/performance_configuration.robot @@ -21,6 +21,7 @@ | Library | resources.libraries.python.L2Util | Library | resources.libraries.python.NodePath | Library | resources.libraries.python.topology.Topology +| Library | resources.libraries.python.TestConfig | Library | resources.libraries.python.TrafficGenerator | Library | resources.libraries.python.TrafficGenerator.TGDropRateSearchImpl | Library | resources.libraries.python.VhostUser @@ -1729,20 +1730,18 @@ | | ${dut1_ip_start}= | Set Variable | 172.16.0.1 | | ${dut2_ip_start}= | Set Variable | 172.16.0.2 | | ... -| | ${ip_limit} = | Set Variable | 255.255.255.255 -| | ... | | Vpp create multiple VXLAN IPv4 tunnels | node=${dut1} | | ... | node_vxlan_if=${dut1_if2} | node_vlan_if=${dut1_if1} | | ... | op_node=${dut2} | op_node_if=${dut2_if1} | n_tunnels=${vxlan_count} | | ... | vni_start=${vni_start} | src_ip_start=${dut1_ip_start} | | ... | dst_ip_start=${dut2_ip_start} | ip_step=${ip_step} -| | ... | ip_limit=${ip_limit} | bd_id_start=${bd_id_start} +| | ... | bd_id_start=${bd_id_start} | | Vpp create multiple VXLAN IPv4 tunnels | node=${dut2} | | ... | node_vxlan_if=${dut2_if1} | node_vlan_if=${dut2_if2} | | ... | op_node=${dut1} | op_node_if=${dut1_if2} | n_tunnels=${vxlan_count} | | ... | vni_start=${vni_start} | src_ip_start=${dut2_ip_start} | | ... | dst_ip_start=${dut1_ip_start} | ip_step=${ip_step} -| | ... | ip_limit=${ip_limit} | bd_id_start=${bd_id_start} +| | ... | bd_id_start=${bd_id_start} | Initialize L2 bridge domains with Vhost-User and VXLANoIPv4 in 3-node circular topology | | [Documentation] -- 2.16.6