#!/usr/bin/env python3 """ Vpp VCL tests """ import unittest import os import subprocess import signal import glob from config import config from framework import VppTestCase, VppTestRunner, Worker from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath, FibPathProto iperf3 = '/usr/bin/iperf3' def have_app(app): try: subprocess.check_output([app, '-v']) except (subprocess.CalledProcessError, OSError): return False return True _have_iperf3 = have_app(iperf3) class VCLAppWorker(Worker): """ VCL Test Application Worker """ libname = "libvcl_ldpreload.so" class LibraryNotFound(Exception): pass def __init__(self, appname, executable_args, logger, env=None, role=None, *args, **kwargs): self.role = role vcl_ldpreload_glob = f"{config.vpp_install_dir}/**/{self.libname}" vcl_ldpreload_so = glob.glob(vcl_ldpreload_glob, recursive=True) if len(vcl_ldpreload_so) < 1: raise LibraryNotFound("cannot locate library: {}".format( self.libname)) vcl_ldpreload_so = vcl_ldpreload_so[0] if env is None: env = {} if "iperf" in appname: app = appname env.update({'LD_PRELOAD': vcl_ldpreload_so}) elif "sock" in appname: app = f"{config.vpp_build_dir}/vpp/bin/{appname}" env.update({'LD_PRELOAD': vcl_ldpreload_so}) else: app = f"{config.vpp_build_dir}/vpp/bin/{appname}" self.args = [app] + executable_args super(VCLAppWorker, self).__init__(self.args, logger, env, *args, **kwargs) class VCLTestCase(VppTestCase): """ VCL Test Class """ session_startup = ["poll-main"] @classmethod def setUpClass(cls): if cls.session_startup: conf = "session {" + " ".join(cls.session_startup) + "}" cls.extra_vpp_punt_config = [conf] super(VCLTestCase, cls).setUpClass() @classmethod def tearDownClass(cls): super(VCLTestCase, cls).tearDownClass() def setUp(self): self.vppDebug = 'vpp_debug' in config.vpp_install_dir self.server_addr = "127.0.0.1" self.server_port = "22000" self.server_args = [self.server_port] self.server_ipv6_addr = "::1" self.server_ipv6_args = ["-6", self.server_port] self.timeout = 20 self.echo_phrase = "Hello, world! Jenny is a friend of mine." self.pre_test_sleep = 0.3 self.post_test_sleep = 0.2 self.sapi_client_sock = "" self.sapi_server_sock = "" if os.path.isfile("/tmp/ldp_server_af_unix_socket"): os.remove("/tmp/ldp_server_af_unix_socket") super(VCLTestCase, self).setUp() def update_vcl_app_env(self, ns_id, ns_secret, attach_sock): if not ns_id: if 'VCL_APP_NAMESPACE_ID' in self.vcl_app_env: del self.vcl_app_env['VCL_APP_NAMESPACE_ID'] else: self.vcl_app_env['VCL_APP_NAMESPACE_ID'] = ns_id if not ns_secret: if 'VCL_APP_NAMESPACE_SECRET' in self.vcl_app_env: del self.vcl_app_env['VCL_APP_NAMESPACE_SECRET'] else: self.vcl_app_env['VCL_APP_NAMESPACE_SECRET'] = ns_secret if not attach_sock: self.vcl_app_env['VCL_VPP_API_SOCKET'] = self.get_api_sock_path() if 'VCL_VPP_SAPI_SOCKET' in self.vcl_app_env: del self.vcl_app_env['VCL_VPP_SAPI_SOCKET'] else: sapi_sock = "%s/app_ns_sockets/%s" % (self.tempdir, attach_sock) self.vcl_app_env['VCL_VPP_SAPI_SOCKET'] = sapi_sock if 'VCL_VPP_API_SOCKET' in self.vcl_app_env: del self.vcl_app_env['VCL_VPP_API_SOCKET'] def cut_thru_setup(self): self.vapi.session_enable_disable(is_enable=1) def cut_thru_tear_down(self): self.vapi.session_enable_disable(is_enable=0) def cut_thru_test(self, server_app, server_args, client_app, client_args): self.vcl_app_env = {'VCL_APP_SCOPE_LOCAL': "true"} self.update_vcl_app_env("", "", self.sapi_server_sock) worker_server = VCLAppWorker(server_app, server_args, self.logger, self.vcl_app_env, "server") worker_server.start() self.sleep(self.pre_test_sleep) self.update_vcl_app_env("", "", self.sapi_client_sock) worker_client = VCLAppWorker(client_app, client_args, self.logger, self.vcl_app_env, "client") worker_client.start() worker_client.join(self.timeout) try: self.validateResults(worker_client, worker_server, self.timeout) except Exception as error: self.fail("Failed with %s" % error) self.sleep(self.post_test_sleep) def thru_host_stack_setup(self): self.vapi.session_enable_disable(is_enable=1) self.create_loopback_interfaces(2) table_id = 1 for i in self.lo_interfaces: i.admin_up() if table_id != 0: tbl = VppIpTable(self, table_id) tbl.add_vpp_config() i.set_table_ip4(table_id) i.config_ip4() table_id += 1 # Configure namespaces self.vapi.app_namespace_add_del(namespace_id="1", secret=1234, sw_if_index=self.loop0.sw_if_index) self.vapi.app_namespace_add_del(namespace_id="2", secret=5678, sw_if_index=self.loop1.sw_if_index) # Add inter-table routes ip_t01 = VppIpRoute(self, self.loop1.local_ip4, 32, [VppRoutePath("0.0.0.0", 0xffffffff, nh_table_id=2)], table_id=1) ip_t10 = VppIpRoute(self, self.loop0.local_ip4, 32, [VppRoutePath("0.0.0.0", 0xffffffff, nh_table_id=1)], table_id=2) ip_t01.add_vpp_config() ip_t10.add_vpp_config() self.logger.debug(self.vapi.cli("show ip fib")) def thru_host_stack_tear_down(self): for i in self.lo_interfaces: i.unconfig_ip4() i.set_table_ip4(0) i.admin_down() def thru_host_stack_ipv6_setup(self): self.vapi.session_enable_disable(is_enable=1) self.create_loopback_interfaces(2) table_id = 1 for i in self.lo_interfaces: i.admin_up() tbl = VppIpTable(self, table_id, is_ip6=1) tbl.add_vpp_config() i.set_table_ip6(table_id) i.config_ip6() table_id += 1 # Configure namespaces self.vapi.app_namespace_add_del(namespace_id="1", secret=1234, sw_if_index=self.loop0.sw_if_index) self.vapi.app_namespace_add_del(namespace_id="2", secret=5678, sw_if_index=self.loop1.sw_if_index) # Add inter-table routes ip_t01 = VppIpRoute(self, self.loop1.local_ip6, 128, [VppRoutePath("::0", 0xffffffff, nh_table_id=2)], table_id=1) ip_t10 = VppIpRoute(self, self.loop0.local_ip6, 128, [VppRoutePath("::0", 0xffffffff, nh_table_id=1)], table_id=2) ip_t01.add_vpp_config() ip_t10.add_vpp_config() self.logger.debug(self.vapi.cli("show interface addr")) self.logger.debug(self.vapi.cli("show ip6 fib")) def thru_host_stack_ipv6_tear_down(self): for i in self.lo_interfaces: i.unconfig_ip6() i.set_table_ip6(0) i.admin_down() self.vapi.session_enable_disable(is_enable=0) @unittest.skipUnless(_have_iperf3, "'%s' not found, Skipping.") def thru_host_stack_test(self, server_app, server_args, client_app, client_args): self.vcl_app_env = {'VCL_APP_SCOPE_GLOBAL': "true"} self.update_vcl_app_env("1", "1234", self.sapi_server_sock) worker_server = VCLAppWorker(server_app, server_args, self.logger, self.vcl_app_env, "server") worker_server.start() self.sleep(self.pre_test_sleep) self.updat
/*
 * Copyright (c) 2017 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.
 */
#undef CLIB_CUCKOO_TYPE

#define CLIB_CUCKOO_TYPE _8_8
#define CLIB_CUCKOO_KVP_PER_BUCKET (4)
#define CLIB_CUCKOO_LOG2_KVP_PER_BUCKET (2)
#define CLIB_CUCKOO_BFS_MAX_STEPS (2000)
#define CLIB_CUCKOO_BFS_MAX_PATH_LENGTH (8)

#ifndef __included_cuckoo_8_8_h__
#define __included_cuckoo_8_8_h__

#include <vppinfra/heap.h>
#include <vppinfra/format.h>
#include <vppinfra/pool.h>
#include <vppinfra/xxhash.h>
#include <vppinfra/cuckoo_debug.h>
#include <vppinfra/cuckoo_common.h>

#undef CLIB_CUCKOO_OPTIMIZE_PREFETCH
#undef CLIB_CUCKOO_OPTIMIZE_CMP_REDUCED_HASH
#undef CLIB_CUCKOO_OPTIMIZE_UNROLL
#undef CLIB_CUCKOO_OPTIMIZE_USE_COUNT_LIMITS_SEARCH
#define CLIB_CUCKOO_OPTIMIZE_PREFETCH 1
#define CLIB_CUCKOO_OPTIMIZE_CMP_REDUCED_HASH 1
#define CLIB_CUCKOO_OPTIMIZE_UNROLL 1
#define CLIB_CUCKOO_OPTIMIZE_USE_COUNT_LIMITS_SEARCH 1

#if __SSE4_2__ && !defined (__i386__)
#include <x86intrin.h>
#endif

/** 8 octet key, 8 octet key value pair */
typedef struct
{
  u64 key;   /**< the key */
  u64 value; /**< the value */
} clib_cuckoo_kv_8_8_t;

/** Decide if a clib_cuckoo_kv_8_8_t instance is free
    @param v- pointer to the (key,value) pair
*/
always_inline int
clib_cuckoo_kv_is_free_8_8 (const clib_cuckoo_kv_8_8_t * v)
{
  if (v->key == ~0ULL && v->value == ~0ULL)
    return 1;
  return 0;
}

always_inline void
clib_cuckoo_kv_set_free_8_8 (clib_cuckoo_kv_8_8_t * v)
{
  memset (v, 0xff, sizeof (*v));
}

/** Format a clib_cuckoo_kv_8_8_t instance
    @param s - u8 * vector under construction
    @param args (vararg) - the (key,value) pair to format
    @return s - the u8 * vector under construction
*/
always_inline u8 *
format_cuckoo_kvp_8_8 (u8 * s, va_list * args)
{
  clib_cuckoo_kv_8_8_t *v = va_arg (*args, clib_cuckoo_kv_8_8_t *);

  if (clib_cuckoo_kv_is_free_8_8 (v))
    {
      s = format (s, " -- empty -- ", v->key, v->value);
    }
  else
    {
      s = format (s, "key %llu value %llu", v->key, v->value);
    }
  return s;
}

always_inline u64
clib_cuckoo_hash_8_8 (clib_cuckoo_kv_8_8_t * v)
{
#if defined(clib_crc32c_uses_intrinsics) && !defined (__i386__)
  return crc32_u64 (0, v->key);
#else
  return clib_xxhash (v->key);
#endif
}

/** Compare two clib_cuckoo_kv_8_8_t instances
    @param a - first key
    @param b - second key
*/
always_inline int
clib_cuckoo_key_compare_8_8 (u64 a, u64 b)
{
  return a == b;
}

#if 0
#undef __included_cuckoo_template_h__
#include <vppinfra/cuckoo_template.h>
#endif

#endif /* __included_cuckoo_8_8_h__ */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
l_test_server", self.server_args, "vcl_test_client", self.client_uni_dir_nsock_test_args) class LDPThruHostStackIperf(VCLTestCase): """ LDP Thru Host Stack Iperf """ @classmethod def setUpClass(cls): super(LDPThruHostStackIperf, cls).setUpClass() @classmethod def tearDownClass(cls): super(LDPThruHostStackIperf, cls).tearDownClass() def setUp(self): super(LDPThruHostStackIperf, self).setUp() self.thru_host_stack_setup() self.client_iperf3_timeout = 20 self.client_iperf3_args = ["-4", "-t 2", "-c", self.loop0.local_ip4] self.server_iperf3_args = ["-4", "-s"] def tearDown(self): self.thru_host_stack_tear_down() super(LDPThruHostStackIperf, self).tearDown() def show_commands_at_teardown(self): self.logger.debug(self.vapi.cli("show session verbose 2")) self.logger.debug(self.vapi.cli("show app mq")) @unittest.skipUnless(_have_iperf3, "'%s' not found, Skipping.") def test_ldp_thru_host_stack_iperf3(self): """ run LDP thru host stack iperf3 test """ self.timeout = self.client_iperf3_timeout self.thru_host_stack_test(iperf3, self.server_iperf3_args, iperf3, self.client_iperf3_args) class LDPThruHostStackIperfUdp(VCLTestCase): """ LDP Thru Host Stack Iperf UDP """ @classmethod def setUpClass(cls): super(LDPThruHostStackIperfUdp, cls).setUpClass() @classmethod def tearDownClass(cls): super(LDPThruHostStackIperfUdp, cls).tearDownClass() def setUp(self): super(LDPThruHostStackIperfUdp, self).setUp() self.thru_host_stack_setup() self.client_iperf3_timeout = 20 self.client_iperf3_args = ["-4", "-t 2", "-u", "-l 1400", "-c", self.loop0.local_ip4] self.server_iperf3_args = ["-4", "-s"] def tearDown(self): self.thru_host_stack_tear_down() super(LDPThruHostStackIperfUdp, self).tearDown() def show_commands_at_teardown(self): self.logger.debug(self.vapi.cli("show session verbose 2")) self.logger.debug(self.vapi.cli("show app mq")) @unittest.skipUnless(_have_iperf3, "'%s' not found, Skipping.") def test_ldp_thru_host_stack_iperf3_udp(self): """ run LDP thru host stack iperf3 UDP test """ self.timeout = self.client_iperf3_timeout self.thru_host_stack_test(iperf3, self.server_iperf3_args, iperf3, self.client_iperf3_args) class LDPIpv6CutThruTestCase(VCLTestCase): """ LDP IPv6 Cut Thru Tests """ @classmethod def setUpClass(cls): super(LDPIpv6CutThruTestCase, cls).setUpClass() @classmethod def tearDownClass(cls): super(LDPIpv6CutThruTestCase, cls).tearDownClass() def show_commands_at_teardown(self): self.logger.debug(self.vapi.cli("show session verbose 2")) self.logger.debug(self.vapi.cli("show app mq")) def setUp(self): super(LDPIpv6CutThruTestCase, self).setUp() self.cut_thru_setup() self.client_iperf3_timeout = 20 self.client_uni_dir_nsock_timeout = 20 self.client_bi_dir_nsock_timeout = 20 self.client_ipv6_echo_test_args = ["-6", "-E", self.echo_phrase, "-X", self.server_ipv6_addr, self.server_port] self.client_ipv6_iperf3_args = ["-6", "-t 2", "-c", self.server_ipv6_addr] self.server_ipv6_iperf3_args = ["-6", "-s"] self.client_ipv6_uni_dir_nsock_test_args = ["-N", "1000", "-U", "-X", "-6", "-I", "2", self.server_ipv6_addr, self.server_port] self.client_ipv6_bi_dir_nsock_test_args = ["-N", "1000", "-B", "-X", "-6", "-I", "2", self.server_ipv6_addr, self.server_port] def tearDown(self): super(LDPIpv6CutThruTestCase, self).tearDown() self.cut_thru_tear_down() @unittest.skipUnless(config.extended, "part of extended tests") def test_ldp_ipv6_cut_thru_echo(self): """ run LDP IPv6 cut thru echo test """ self.cut_thru_test("sock_test_server", self.server_ipv6_args, "sock_test_client", self.client_ipv6_echo_test_args) @unittest.skipUnless(_have_iperf3, "'%s' not found, Skipping.") def test_ldp_ipv6_cut_thru_iperf3(self): """ run LDP IPv6 cut thru iperf3 test """ self.timeout = self.client_iperf3_timeout self.cut_thru_test(iperf3, self.server_ipv6_iperf3_args, iperf3, self.client_ipv6_iperf3_args) @unittest.skipUnless(config.extended, "part of extended tests") def test_ldp_ipv6_cut_thru_uni_dir_nsock(self): """ run LDP IPv6 cut thru uni-directional (multiple sockets) test """ self.timeout = self.client_uni_dir_nsock_timeout self.cut_thru_test("sock_test_server", self.server_ipv6_args, "sock_test_client", self.client_ipv6_uni_dir_nsock_test_args) @unittest.skipUnless(config.extended, "part of extended tests") @unittest.skip("sock test apps need to be improved") def test_ldp_ipv6_cut_thru_bi_dir_nsock(self): """ run LDP IPv6 cut thru bi-directional (multiple sockets) test """ self.timeout = self.client_bi_dir_nsock_timeout self.cut_thru_test("sock_test_server", self.server_ipv6_args, "sock_test_client", self.client_ipv6_bi_dir_nsock_test_args) class VCLIpv6CutThruTestCase(VCLTestCase): """ VCL IPv6 Cut Thru Tests """ @classmethod def setUpClass(cls): super(VCLIpv6CutThruTestCase, cls).setUpClass() @classmethod def tearDownClass(cls): super(VCLIpv6CutThruTestCase, cls).tearDownClass() def show_commands_at_teardown(self): self.logger.debug(self.vapi.cli("show session verbose 2")) self.logger.debug(self.vapi.cli("show app mq")) def setUp(self): super(VCLIpv6CutThruTestCase, self).setUp() self.cut_thru_setup() self.client_uni_dir_nsock_timeout = 20 self.client_bi_dir_nsock_timeout = 20 self.client_ipv6_echo_test_args = ["-6", "-E", self.echo_phrase, "-X", self.server_ipv6_addr, self.server_port] self.client_ipv6_uni_dir_nsock_test_args = ["-N", "1000", "-U", "-X", "-6", "-I", "2", self.server_ipv6_addr, self.server_port] self.client_ipv6_bi_dir_nsock_test_args = ["-N", "1000", "-B", "-X", "-6", "-I", "2", self.server_ipv6_addr, self.server_port] def tearDown(self): super(VCLIpv6CutThruTestCase, self).tearDown() self.cut_thru_tear_down() def show_commands_at_teardown(self): self.logger.debug(self.vapi.cli("show session verbose 2")) self.logger.debug(self.vapi.cli("show app mq")) def test_vcl_ipv6_cut_thru_echo(self): """ run VCL IPv6 cut thru echo test """ self.cut_thru_test("vcl_test_server", self.server_ipv6_args, "vcl_test_client", self.client_ipv6_echo_test_args) @unittest.skipUnless(config.extended, "part of extended tests") def test_vcl_ipv6_cut_thru_uni_dir_nsock(self): """ run VCL IPv6 cut thru uni-directional (multiple sockets) test """ self.timeout = self.client_uni_dir_nsock_timeout self.cut_thru_test("vcl_test_server", self.server_ipv6_args, "vcl_test_client", self.client_ipv6_uni_dir_nsock_test_args) @unittest.skipUnless(config.extended, "part of extended tests") def test_vcl_ipv6_cut_thru_bi_dir_nsock(self): """ run VCL IPv6 cut thru bi-directional (multiple sockets) test """ self.timeout = self.client_bi_dir_nsock_timeout self.cut_thru_test("vcl_test_server", self.server_ipv6_args, "vcl_test_client", self.client_ipv6_bi_dir_nsock_test_args) class VCLIpv6ThruHostStackEcho(VCLTestCase): """ VCL IPv6 Thru Host Stack Echo """ @classmethod def setUpClass(cls): super(VCLIpv6ThruHostStackEcho, cls).setUpClass() @classmethod def tearDownClass(cls): super(VCLIpv6ThruHostStackEcho, cls).tearDownClass() def setUp(self): super(VCLIpv6ThruHostStackEcho, self).setUp() self.thru_host_stack_ipv6_setup() self.client_ipv6_echo_test_args = ["-6", "-E", self.echo_phrase, "-X", self.loop0.local_ip6, self.server_port] def tearDown(self): self.thru_host_stack_ipv6_tear_down() super(VCLIpv6ThruHostStackEcho, self).tearDown() def test_vcl_ipv6_thru_host_stack_echo(self): """ run VCL IPv6 thru host stack echo test """ self.thru_host_stack_test("vcl_test_server", self.server_ipv6_args, "vcl_test_client", self.client_ipv6_echo_test_args) if __name__ == '__main__': unittest.main(testRunner=VppTestRunner)