#!/usr/bin/env python """ Vpp VCL tests """ import unittest import os import subprocess import signal from framework import VppTestCase, VppTestRunner, running_extended_tests, \ Worker from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath, DpoProto class VCLAppWorker(Worker): """ VCL Test Application Worker """ def __init__(self, build_dir, appname, args, logger, env={}): vcl_lib_dir = "%s/vpp/lib" % build_dir if "iperf" in appname: app = appname env.update({'LD_PRELOAD': "%s/libvcl_ldpreload.so" % vcl_lib_dir}) elif "sock" in appname: app = "%s/vpp/bin/%s" % (build_dir, appname) env.update({'LD_PRELOAD': "%s/libvcl_ldpreload.so" % vcl_lib_dir}) else: app = "%s/vpp/bin/%s" % (build_dir, appname) self.args = [app] + args super(VCLAppWorker, self).__init__(self.args, logger, env) class VCLTestCase(VppTestCase): """ VCL Test Class """ @classmethod def setUpClass(cls): super(VCLTestCase, cls).setUpClass() @classmethod def tearDownClass(cls): super(VCLTestCase, cls).tearDownClass() def setUp(self): var = "VPP_BUILD_DIR" self.build_dir = os.getenv(var, None) if self.build_dir is None: raise Exception("Environment variable `%s' not set" % var) self.vppDebug = 'vpp_debug' in self.build_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 if os.path.isfile("/tmp/ldp_server_af_unix_socket"): os.remove("/tmp/ldp_server_af_unix_socket") super(VCLTestCase, self).setUp() def cut_thru_setup(self): self.vapi.session_enable_disable(is_enabled=1) def cut_thru_tear_down(self): self.vapi.session_enable_disable(is_enabled=0) def cut_thru_test(self, server_app, server_args, client_app, client_args): self.env = {'VCL_API_PREFIX': self.shm_prefix, 'VCL_APP_SCOPE_LOCAL': "true"} worker_server = VCLAppWorker(self.build_dir, server_app, server_args, self.logger, self.env) worker_server.start() self.sleep(self.pre_test_sleep) worker_client = VCLAppWorker(self.build_dir, client_app, client_args, self.logger, self.env) 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_enabled=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=b"1", secret=1234, sw_if_index=self.loop0.sw_if_index) self.vapi.app_namespace_add_del(namespace_id=b"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_enabled=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=b"1", secret=1234, sw_if_index=self.loop0.sw_if_index) self.vapi.app_namespace_add_del(namespace_id=b"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, proto=DpoProto.DPO_PROTO_IP6)], table_id=1, is_ip6=1) ip_t10 = VppIpRoute(self, self.loop0.local_ip6, 128, [VppRoutePath("::0", 0xffffffff, nh_table_id=1, proto=DpoProto.DPO_PROTO_IP6)], table_id=2, is_ip6=1) 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_enabled=0) def thru_host_stack_test(self, server_app, server_args, client_app, client_args): self.env = {'VCL_API_PREFIX': self.shm_prefix, 'VCL_APP_SCOPE_GLOBAL': "true", 'VCL_APP_NAMESPACE_ID': "1", 'VCL_APP_NAMESPACE_SECRET': "1234"} worker_server = VCLAppWorker(self.build_dir, server_app, server_args, self.logger, self.env) worker_server.start() self.sleep(self.pre_test_sleep) self.env.update({'VCL_APP_NAMESPACE_ID': "2", 'VCL_APP_NAMESPACE_SECRET': "5678"}) worker_client = VCLAppWorker(self.build_dir, client_app, client_args, self.logger, self.env) 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 validateResults(self, worker_client, worker_server, timeout): if os.path.isdir('/proc/{}'.format(worker_server.process.pid)): self.logger.info("Killing server worker process (pid %d)" % worker_server.process.pid) os.killpg(os.getpgid(worker_server.process.pid), signal.SIGTERM) worker_server.join() self.logger.info("Client worker result is `%s'" % worker_client.result) error = False if worker_client.result is None: try: error = True self.logger.error( "Timeout: %ss! Killing client worker process (pid %d)" % (timeout, worker_client.process.pid)) os.killpg(os.getpgid(worker_client.process.pid), signal.SIGKILL) worker_client.join() except OSError: self.logger.debug( "Couldn't kill client worker process") raise if error: raise Exception( "Timeout! Client worker did not finish in %ss" % timeout) self.assert_equal(worker_client.result, 0, "Binary test return code") class LDPCutThruTestCase(VCLTestCase): """ LDP Cut Thru Tests """ @classmethod def setUpClass(cls): super(LDPCutThruTestCase, cls).setUpClass() @classmethod def tearDownClass(cls): super(LDPCutThruTestCase, cls).tearDownClass() def setUp(self): super(LDPCutThruTestCase, self).setUp() self.cut_thru_setup() self.client_echo_test_args = ["-E", self.echo_phrase, "-X", self.server_addr, self.server_port] self.client_iperf3_timeout = 20 self.client_iperf3_args = ["-V4d", "-t 2", "-c", self.server_addr] self.server_iperf3_args = ["-V4d", "-s"] self.client_uni_dir_nsock_timeout = 20 self.client_uni_dir_nsock_test_args = ["-N", "1000", "-U", "-X", "-I", "2", self.server_addr, self.server_port] self.client_bi_dir_nsock_timeout = 20 self.client_bi_dir_nsock_test_args = ["-N", "1000", "-B", "-X", "-I", "2", self.server_addr, self.server_port] def tearDown(self): super(LDPCutThruTestCase, self).tearDown() self.cut_thru_tear_down() def show_commands_at_teardown(self): self.logger.debug(self.vapi.cli("show session verbose 2")) @unittest.skipUnless(running_extended_tests, "part of extended tests") def test_ldp_cut_thru_echo(self): """ run LDP cut thru echo test """ self.cut_thru_test("sock_test_server", self.server_args, "sock_test_client", self.client_echo_test_args) def test_ldp_cut_thru_iperf3(self): """ run LDP cut thru iperf3 test """ try: subprocess.check_output(['iperf3', '-v']) except subprocess.CalledProcessError: self.logger.error( "WARNING: Subprocess returned non-0 running 'iperf3 -v") self.logger.error(" 'test_ldp_cut_thru_iperf3' not run!") return except OSError as e: self.logger.error( "WARNING: Subprocess returned with OS error (%s) %s\n" " 'iperf3' is likely not installed,", e.errno, e.strerror) self.logger.error(" 'test_ldp_cut_thru_iperf3' not run!") return except Exception: self.logger.exception( "Subprocess returned non-0 running 'iperf3 -v") self.timeout = self.client_iperf3_timeout self.cut_thru_test("iperf3", self.server_iperf3_args, "iperf3", self.client_iperf3_args) @unittest.skipUnless(running_extended_tests, "part of extended tests") def test_ldp_cut_thru_uni_dir_nsock(self): """ run LDP cut thru uni-directional (multiple sockets) test """ self.timeout = self.client_uni_dir_nsock_timeout self.cut_thru_test("sock_test_server", self.server_args, "sock_test_client", self.client_uni_dir_nsock_test_args) @unittest.skipUnless(running_extended_tests, "part of extended tests") def test_ldp_cut_thru_bi_dir_nsock(self): """ run LDP cut thru bi-directional (multiple sockets) test """ self.timeout = self.client_bi_dir_nsock_timeout self.cut_thru_test("sock_test_server", self.server_args, "sock_test_client", self.client_bi_dir_nsock_test_args) class VCLCutThruTestCase(VCLTestCase): """ VCL Cut Thru Tests """ @classmethod def setUpClass(cls): super(VCLCutThruTestCase, cls).setUpClass() @classmethod def tearDownClass(cls): super(VCLCutThruTestCase, cls).tearDownClass() def setUp(self): super(VCLCutThruTestCase, self).setUp() self.cut_thru_setup() self.client_echo_test_args = ["-E", self.echo_phrase, "-X", self.server_addr, self.server_port] self.client_uni_dir_nsock_timeout = 20 self.client_uni_dir_nsock_test_args = ["-N", "1000", "-U", "-X", "-I", "2", self.server_addr, self.server_port] self.client_bi_dir_nsock_timeout = 20 self.client_bi_dir_nsock_test_args = ["-N", "1000", "-B", "-X", "-I", "2", self.server_addr, self.server_port] def tearDown(self): super(VCLCutThruTestCase, self).tearDown() def show_commands_at_teardown(self): self.logger.debug(self.vapi.cli("show session verbose 2")) def test_vcl_cut_thru_echo(self): """ run VCL cut thru echo test """ self.cut_thru_test("vcl_test_server", self.server_args, "vcl_test_client", self.client_echo_test_args) def test_vcl_cut_thru_uni_dir_nsock(self): """ run VCL cut thru uni-directional (multiple sockets) test """ self.timeout = self.client_uni_dir_nsock_timeout self.cut_thru_test("vcl_test_server", self.server_args, "vcl_test_client", self.client_uni_dir_nsock_test_args) def test_vcl_cut_thru_bi_dir_nsock(self): """ run VCL cut thru bi-directional (multiple sockets) test """ self.timeout = self.client_bi_dir_nsock_timeout self.cut_thru_test("vcl_test_server", self.server_args, "vcl_test_client", self.client_bi_dir_nsock_test_args) class VCLThruHostStackEcho(VCLTestCase): """ VCL Thru Host Stack Echo """ @classmethod def setUpClass(cls): super(VCLThruHostStackEcho, cls).setUpClass() @classmethod def tearDownClass(cls): super(VCLThruHostStackEcho, cls).tearDownClass() def setUp(self): super(VCLThruHostStackEcho, self).setUp() self.thru_host_stack_setup() self.client_bi_dir_nsock_timeout = 20 self.client_bi_dir_nsock_test_args = ["-N", "1000", "-B", "-X", "-I", "2", self.loop0.local_ip4, self.server_port] self.client_echo_test_args = ["-E", self.echo_phrase, "-X", self.loop0.local_ip4, self.server_port] def tearDown(self): self.thru_host_stack_tear_down() super(VCLThruHostStackEcho, self).tearDown() def show_commands_at_teardown(self): self.logger.debug(self.vapi.cli("show app server")) self.logger.debug(self.vapi.cli("show session verbose")) class VCLThruHostStackTLS(VCLTestCase): """ VCL Thru Host Stack TLS """ @classmethod def setUpClass(cls): super(VCLThruHostStackTLS, cls).setUpClass() @classmethod def tearDownClass(cls): super(VCLThruHostStackTLS, cls).tearDownClass() def setUp(self): super(VCLThruHostStackTLS, self).set
/*
 * ah_encrypt.c : IPSec AH encrypt node
 *
 * Copyright (c) 2015 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.
 */

#include <vnet/vnet.h>
#include <vnet/api_errno.h>
#include <vnet/ip/ip.h>

#include <vnet/ipsec/ipsec.h>
#include <vnet/ipsec/esp.h>
#include <vnet/ipsec/ah.h>

#define foreach_ah_encrypt_next                   \
_(DROP, "error-drop")                              \
_(IP4_LOOKUP, "ip4-lookup")                        \
_(IP6_LOOKUP, "ip6-lookup")                        \
_(INTERFACE_OUTPUT, "interface-output")

#define _(v, s) AH_ENCRYPT_NEXT_##v,
typedef enum
{
  foreach_ah_encrypt_next
#undef _
    AH_ENCRYPT_N_NEXT,
} ah_encrypt_next_t;

#define foreach_ah_encrypt_error                   \
 _(RX_PKTS, "AH pkts received")                    \
 _(SEQ_CYCLED, "sequence number cycled")


typedef enum
{
#define _(sym,str) AH_ENCRYPT_ERROR_##sym,
  foreach_ah_encrypt_error
#undef _
    AH_ENCRYPT_N_ERROR,
} ah_encrypt_error_t;

static char *ah_encrypt_error_strings[] = {
#define _(sym,string) string,
  foreach_ah_encrypt_error
#undef _
};

vlib_node_registration_t ah_encrypt_node;

typedef struct
{
  u32 spi;
  u32 seq;
  ipsec_integ_alg_t integ_alg;
} ah_encrypt_trace_t;

/* packet trace format function */
static u8 *
format_ah_encrypt_trace (u8 * s, va_list * args)
{
  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
  ah_encrypt_trace_t *t = va_arg (*args, ah_encrypt_trace_t *);

  s = format (s, "ah: spi %u seq %u integrity %U",
	      t->spi, t->seq, format_ipsec_integ_alg, t->integ_alg);
  return s;
}

static uword
ah_encrypt_node_fn (vlib_main_t * vm,
		    vlib_node_runtime_t * node, vlib_frame_t * from_frame)
{
  u32 n_left_from, *from, *to_next = 0, next_index;
  int icv_size = 0;
  from = vlib_frame_vector_args (from_frame);
  n_left_from = from_frame->n_vectors;
  ipsec_main_t *im = &ipsec_main;
  ipsec_proto_main_t *em = &ipsec_proto_main;
  next_index = node->cached_next_index;

  while (n_left_from > 0)
    {
      u32 n_left_to_next;

      vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);

      while (n_left_from > 0 && n_left_to_next > 0)
	{
	  u32 i_bi0, next0;
	  vlib_buffer_t *i_b0 = 0;
	  u32 sa_index0;
	  ipsec_sa_t *sa0;
	  ip4_and_ah_header_t *ih0, *oh0 = 0;
	  ip6_and_ah_header_t *ih6_0, *oh6_0 = 0;
	  u8 is_ipv6;
	  u8 ip_hdr_size;
	  u8 next_hdr_type;
	  u8 transport_mode = 0;
	  u8 tos = 0;
	  u8 ttl = 0;

	  i_bi0 = from[0];
	  from += 1;
	  n_left_from -= 1;
	  n_left_to_next -= 1