#! /bin/bash # # socket_test.sh -- script to run socket tests. # script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" vpp_dir="$WS_ROOT/build-root/build-vpp-native/vpp/bin/" vpp_debug_dir="$WS_ROOT/build-root/build-vpp_debug-native/vpp/bin/" vpp_shm_dir="/dev/shm/" vpp_run_dir="/run/vpp" lib_dir="$WS_ROOT/build-root/install-vpp-native/vpp/lib/" lib_debug_dir="$WS_ROOT/build-root/install-vpp_debug-native/vpp/lib/" dpdk_devbind="$WS_ROOT/extras/vpp_config/scripts/dpdk-devbind.py" docker_vpp_dir="/vpp/" docker_app_dir="/vpp/" docker_lib_dir="/vpp-lib/" docker_os="ubuntu" vcl_ldpreload_lib="libvcl_ldpreload.so" user_gid="$(id -g)" vpp_app="vpp" sock_srvr_app="sock_test_server" sock_clnt_app="sock_test_client" sock_srvr_addr="127.0.0.1" sock_srvr_port="22000" iperf_srvr_app="iperf3 -V4d -s" iperf_clnt_app="iperf3 -V4d -c \$srvr_addr" gdb_in_emacs="gdb_in_emacs" vcl_config="vcl.conf" vcl_config_dir="$WS_ROOT/src/vcl/" docker_vcl_config_dir="/etc/vpp/" xterm_geom="100x60" bash_header="#! /bin/bash" tmp_cmdfile_prefix="/tmp/socket_test_cmd" cmd1_file="${tmp_cmdfile_prefix}1.$$" cmd2_file="${tmp_cmdfile_prefix}2.$$" cmd3_file="${tmp_cmdfile_prefix}3.$$" vpp_eth_name="enp0s8" tmp_vpp_exec_file="/tmp/vpp_config.$$" tmp_gdb_cmdfile_prefix="/tmp/gdb_cmdfile" def_gdb_cmdfile_prefix="$WS_ROOT/extras/gdb/gdb_cmdfile" tmp_gdb_cmdfile_vpp="${tmp_gdb_cmdfile_prefix}_vpp.$$" tmp_gdb_cmdfile_client="${tmp_gdb_cmdfile_prefix}_vcl_client.$$" tmp_gdb_cmdfile_server="${tmp_gdb_cmdfile_prefix}_vcl_server.$$" get_docker_server_ip4addr='srvr_addr=$(docker network inspect bridge | grep IPv4Address | awk -e '\''{print $2}'\'' | sed -e '\''s,/16,,'\'' -e '\''s,",,g'\'' -e '\''s/,//'\'')' #' single quote to fix the confused emacs colorizer. trap_signals="SIGINT SIGTERM EXIT" # Set default values for imported environment variables if they don't exist. # VPP_GDB_CMDFILE="${VPP_GDB_CMDFILE:-${def_gdb_cmdfile_prefix}.vpp}" VPPCOM_CLIENT_GDB_CMDFILE="${VPPCOM_CLIENT_GDB_CMDFILE:-${def_gdb_cmdfile_prefix}.vppcom_client}" VPPCOM_SERVER_GDB_CMDFILE="${VPPCOM_SERVER_GDB_CMDFILE:-${def_gdb_cmdfile_prefix}.vppcom_server}" usage() { cat < Server IP address. -P Server Port number. -E Run Echo test. -N Test Cfg: number of writes. -R Test Cfg: rx buffer size. -T Test Cfg: tx buffer size. -U Run Uni-directional test. -B Run Bi-directional test. -I Send data over multiple test sockets in parallel. -V Test Cfg: Verbose mode. -X Exit client/server after running test. Environment variables: VCL_CONFIG Pathname of vppcom configuration file. VPP_GDB_CMDFILE Pathname of gdb command file for vpp. VPPCOM_CLIENT_GDB_CMDFILE Pathname of gdb command file for client. VPPCOM_SERVER_GDB_CMDFILE Pathname of gdb command file for server. EOF exit 1 } declare -i emacs_vpp=0 declare -i emacs_client=0 declare -i emacs_server=0 declare -i gdb_vpp=0 declare -i gdb_client=0 declare -i gdb_server=0 declare -i perf_vpp=0 declare -i perf_client=0 declare -i perf_server=0 declare -i leave_tmp_files=0 declare -i bash_after_exit=0 declare -i iperf3=0 declare -i use_ipv6=0 while getopts ":hitlbcd6fn:m:e:g:p:E:I:N:P:R:S:T:UBVXDL" opt; do case $opt in h) usage ;; l) leave_tmp_files=1 ;; b) bash_after_exit=1 ;; i) iperf3=1 ;; 6) use_ipv6=1 sock_srvr_addr="::1" sock_clnt_options="$sock_clnt_options -$opt" sock_srvr_options="$sock_srvr_options -$opt" ;; f) full_thru_host_stack_vpp_cfg=1 ;; t) xterm_geom="180x40" use_tabs="true" ;; c) VCL_CONFIG="${vcl_config_dir}vcl_test.conf" ;; d) title_dbg="-DEBUG" vpp_dir=$vpp_debug_dir lib_dir=$lib_debug_dir ;; e) if [ $OPTARG = "a" ] || [ $OPTARG = "all" ] ; then emacs_client=1 emacs_server=1 emacs_vpp=1 elif [ $OPTARG = "c" ] || [ $OPTARG = "client" ] ; then emacs_client=1 elif [ $OPTARG = "s" ] || [ $OPTARG = "server" ] ; then emacs_server=1 elif [ $OPTARG = "v" ] || [ $OPTARG = "vpp" ] ; then emacs_vpp=1 else echo "ERROR: Option -e unknown argument \'$OPTARG\'" >&2 usage fi title_dbg="-DEBUG" vpp_dir=$vpp_debug_dir lib_dir=$lib_debug_dir ;; n) vpp_eth_name="$OPTARG" ;; m) if [ $OPTARG = "c" ] || [ $OPTARG = "client" ] ; then multi_host="client" elif [ $OPTARG = "s" ] || [ $OPTARG = "server" ] ; then multi_host="server" else echo "ERROR: Option -e unknown argument \'$OPTARG\'" >&2 usage fi ;; g) if [ $OPTARG = "a" ] || [ $OPTARG = "all" ] ; then gdb_client=1 gdb_server=1 gdb_vpp=1 elif [ $OPTARG = "c" ] || [ $OPTARG = "client" ] ; then gdb_client=1 elif [ $OPTARG = "s" ] || [ $OPTARG = "server" ] ; then gdb_server=1 elif [ $OPTARG = "v" ] || [ $OPTARG = "vpp" ] ; then gdb_vpp=1 else echo "ERROR: Option -g unknown argument \'$OPTARG\'" >&2 usage fi ;; p) if [ $OPTARG = "a" ] || [ $OPTARG = "all" ] ; then perf_client=1 perf_server=1 perf_vpp=1 elif [ $OPTARG = "c" ] || [ $OPTARG = "client" ] ; then perf_client=1 elif [ $OPTARG = "s" ] || [ $OPTARG = "server" ] ; then perf_server=1 elif [ $OPTARG = "v" ] || [ $OPTARG = "vpp" ] ; then perf_vpp=1 else echo "ERROR: Option -p unknown argument \'$OPTARG\'" >&2 usage fi echo "WARNING: -p options TBD" ;; S) sock_srvr_addr="$OPTARG" ;; P) sock_srvr_port="$OPTARG" ;; D|L) sock_clnt_options="$sock_clnt_options -$opt" sock_srvr_options="$sock_srvr_options -$opt" ;; E|I|N|R|T) sock_clnt_options="$sock_clnt_options -$opt \"$OPTARG\"" ;; U|B|V|X) sock_clnt_options="$sock_clnt_options -$opt" ;; \?) echo "ERROR: Invalid option: -$OPTARG" >&2 usage ;; :) echo "ERROR: Option -$OPTARG requires an argument." >&2 usage ;; esac done shift $(( $OPTIND-1 )) while ! [[ $run_test ]] && (( $# > 0 )) ; do case $1 in "nk" | "native-kernel") run_test="native_kernel" ;; "np" | "native-preload") run_test="native_preload" ;; "nv" | "native-vcl") sock_srvr_app="vcl_test_server" sock_clnt_app="vcl_test_client" run_test="native_vcl" ;; "dk" | "docker-kernel") run_test="docker_kernel" ;; "dp" | "docker-preload") run_test="docker_preload" ;; "dv" | "docker-vcl") sock_srvr_app="vcl_test_server" sock_clnt_app="vcl_test_client" run_test="docker_vcl" ;; *) echo "ERROR: Unknown option '$1'!" >&2 usage ;; esac shift done if [ -z "$VCL_DEBUG" ] ; then if [ "$title_dbg" = "-DEBUG" ] ; then VCL_DEBUG=1 else VCL_DEBUG=0 fi fi VCL_LDPRELOAD_LIB_DIR="${VCL_LDPRELOAD_LIB_DIR:-$lib_dir}" if [ -z "$WS_ROOT" ] ; then echo "ERROR: WS_ROOT environment variable not set!" >&2 echo " Please set WS_ROOT to VPP workspace root directory." >&2 exit 1 fi if [ ! -d $vpp_dir ] ; then if [ -z "$title_dbg" ] ; then (cd $WS_ROOT; make build-release) else (cd $WS_ROOT; make build) fi fi if [ ! -d $vpp_dir ] ; then echo "ERROR: Missing VPP$title_dbg bin directory!" >&2 echo " $vpp_dir" >&2 env_test_failed="true" fi if [[ $run_test =~ .*"_preload" ]] ; then if [ ! -d $lib_dir ] ; then echo "ERROR: Missing VPP$title_dbg lib directory!" >&2 echo " $lib_dir" >&2 elif [ ! -d $VCL_LDPRELOAD_LIB_DIR ] ; then echo "ERROR: Missing VCL LD_PRELOAD Library directory!" >&2 echo " $VCL_LDPRELOAD_LIB_DIR" >&2 env_test_failed="true" elif [ ! -f $VCL_LDPRELOAD_LIB_DIR/$vcl_ldpreload_lib ] ; then echo "ERROR: Missing VCL LD_PRELOAD library!" >&2 echo " $VCL_LDPRELOAD_LIB_DIR/$vcl_ldpreload_lib" >&2 env_test_failed="true" fi fi if [ ! -f $vpp_dir$vpp_app ] ; then echo "ERROR: Missing VPP$title_dbg Application!" >&2 echo " $vpp_dir$vpp_app" >&2 env_test_failed="true" fi if [ ! -f $vpp_dir$sock_srvr_app ] && [ ! $iperf3 -eq 1 ] ; then echo "ERROR: Missing SERVER$title_dbg Socket Server Application!" >&2 echo " $vpp_dir$sock_srvr_app" >&2 env_test_failed="true" fi if [ ! -f $vpp_dir$sock_clnt_app ] && [ ! $iperf3 -eq 1 ] ; then echo "ERROR: Missing CLIENT$title_dbg Socket Client Application!" >&2 echo " $vpp_dir$sock_clnt_app" >&2 env_test_failed="true" fi if [[ $run_test =~ "docker_".* ]] ; then if [ $emacs_client -eq 1 ] || [ $emacs_server -eq 1 ] || [ $gdb_client -eq 1 ] || [ $gdb_server -eq 1 ] ; then echo "WARNING: gdb is not currently supported in docker." echo " Ignoring client/server gdb options." emacs_client=0 emacs_server=0 gdb_client=0 gdb_server=0 fi fi if [[ $run_test =~ .*"_vcl" ]] && [ $iperf3 -eq 1 ] ; then echo "ERROR: Invalid option 'i' for test $run_test!" echo " iperf3 is not compiled with the VCL library." env_test_failed="true" fi if [ -n "$multi_host"] && [ ! -f "$dpdk_devbind" ] ; then echo "ERROR: Can't find dpdk-devbind.py!" echo " Run \"cd \$WS_ROOT; make install-ext-deps\" to install it." echo env_test_failed="true" fi if [ -n "$full_thru_host_stack_vpp_cfg" ] && [ -n "$multi_host" ] ; then echo "ERROR: Invalid options, cannot specify both \"-f\" and \"-m $multi_host\"!" echo env_test_failed="true" fi if [ -n "$env_test_failed" ] ; then exit 1 fi if [ -f "$VCL_CONFIG" ] ; then vcl_config="$(basename $VCL_CONFIG)" vcl_config_dir="$(dirname $VCL_CONFIG)/" api_prefix="$(egrep -s '^\s*api-prefix \w+' $VCL_CONFIG | tail -1 | awk -e '{print $2}')" if [ -n "$api_prefix" ] ; then api_segment=" api-segment { gid $user_gid prefix $api_prefix }" fi fi if [ -n "$VCL_APP_NAMESPACE_ID" ] && [ -n "$VCL_APP_NAMESPACE_SECRET" ] ; then namespace_id="$VCL_APP_NAMESPACE_ID" namespace_secret="$VCL_APP_NAMESPACE_SECRET" fi if [ -z "$api_segment" ] ; then api_segment=" api-segment { gid $user_gid }" fi vpp_args="unix { interactive full-coredump coredump-size unlimited exec $tmp_vpp_exec_file}${api_segment}" if [ $iperf3 -eq 1 ] ; then app_dir="$(dirname $(which iperf3))/" srvr_app=$iperf_srvr_app clnt_app=$iperf_clnt_app if [[ $run_test =~ "docker_".* ]] ; then unset -v app_dir sock_srvr_port=5201 docker_app_dir="networkstatic/" unset -v docker_os fi else app_dir="$vpp_dir" srvr_app="$sock_srvr_app${sock_srvr_options} $sock_srvr_port" clnt_app="$sock_clnt_app${sock_clnt_options} \$srvr_addr $sock_srvr_port" fi verify_no_vpp() { local grep_for_vpp="ps -eaf|grep -v grep|grep \"bin/vpp\"" if [ -n "$api_prefix" ] ; then grep_for_vpp="$grep_for_vpp|grep \"prefix $api_prefix\"" fi local running_vpp="$(eval $grep_for_vpp)" if [ -n "$running_vpp" ] ; then echo "ERROR: Please kill the following vpp instance(s):" echo echo $running_vpp echo exit 1 fi clean_devshm="$vpp_shm_dir*db $vpp_shm_dir*global_vm $vpp_shm_dir*vpe-api $vpp_shm_dir[0-9]*-[0-9]* $vpp_shm_dir*:segment[0-9]*" sudo rm -f $clean_devshm devshm_files="$(ls -l $clean_devshm 2>/dev/null | grep $(whoami))" if [ "$devshm_files" != "" ] ; then echo "ERROR: Please remove the following $vpp_shm_dir files:" for file in "$devshm_files" ; do echo " $file" done exit 1 fi if [ ! -d "$vpp_run_dir" ] ; then sudo mkdir $vpp_run_dir sudo chown root:$USER $vpp_run_dir fi if [ $use_ipv6 -eq 0 ] && [ -n "$full_thru_host_stack_vpp_cfg" ] ; then sock_srvr_table=0 sock_srvr_addr=172.16.1.1 sock_client_table=1 sock_client_addr=172.16.2.1 client_namespace_id="1" client_namespace_secret="5678" server_namespace_id="0" server_namespace_secret="1234" cat <> $tmp_vpp_exec_file session enable create loop inter create loop inter set inter state loop0 up set inter ip table loop0 $sock_srvr_table set inter ip address loop0 $sock_srvr_addr/24 set inter state loop1 up set inter
/*
 *------------------------------------------------------------------
 * 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.
 *------------------------------------------------------------------
 */

#include <vlib/vlib.h>
#include <vnet/plugin/plugin.h>
#include <vnet/crypto/crypto.h>
#include <x86intrin.h>
#include <crypto_ia32/crypto_ia32.h>
#include <crypto_ia32/aesni.h>

#if __GNUC__ > 4  && !__clang__ && CLIB_DEBUG == 0
#pragma GCC optimize ("O3")
#endif

typedef struct
{
  __m128i encrypt_key[15];
  __m128i decrypt_key[15];
} aes_cbc_key_data_t;

static_always_inline void
aes_cbc_dec (__m128i * k, u8 * src, u8 * dst, u8 * iv, int count,
	     aesni_key_size_t rounds)
{
  __m128i r0, r1, r2, r3, c0, c1, c2, c3, f;
  int i;

  f = _mm_loadu_si128 ((__m128i *) iv);

  while (count >= 64)
    {
      _mm_prefetch (src + 128, _MM_HINT_T0);
      _mm_prefetch (dst + 128, _MM_HINT_T0);

      c0 = _mm_loadu_si128 (((__m128i *) src + 0));
      c1 = _mm_loadu_si128 (((__m128i *) src + 1));
      c2 = _mm_loadu_si128 (((__m128i *) src + 2));
      c3 = _mm_loadu_si128 (((__m128i *) src + 3));

      r0 = c0 ^ k[0];
      r1 = c1 ^ k[0];
      r2 = c2 ^ k[0];
      r3 = c3 ^ k[0];

      for (i = 1; i < rounds; i++)
	{
	  r0 = _mm_aesdec_si128 (r0, k[i]);
	  r1 = _mm_aesdec_si128 (r1, k[i]);
	  r2 = _mm_aesdec_si128 (r2, k[i]);
	  r3 = _mm_aesdec_si128 (r3, k[i]);
	}

      r0 = _mm_aesdeclast_si128 (r0, k[i]);
      r1 = _mm_aesdeclast_si128 (r1, k[i]);
      r2 = _mm_aesdeclast_si128 (r2, k[i]);
      r3 = _mm_aesdeclast_si128 (r3, k[i]);

      _mm_storeu_si128 ((__m128i *) dst + 0, r0 ^ f);
      _mm_storeu_si128 ((__m128i *) dst + 1, r1 ^ c0);
      _mm_storeu_si128 ((__m128i *) dst + 2, r2 ^ c1);
      _mm_storeu_si128 ((__m128i *) dst + 3, r3 ^ c2);

      f = c3;

      count -= 64;
      src += 64;
      dst += 64;
    }

  while (count > 0)
    {
      c0 = _mm_loadu_si128 (((__m128i *) src));
      r0 = c0 ^ k[0];
      for (i = 1; i < rounds; i++)
	r0 = _mm_aesdec_si128 (r0, k[i]);
      r0 = _mm_aesdeclast_si128 (r0, k[i]);
      _mm_storeu_si128 ((__m128i *) dst, r0 ^ f);
      f = c0;
      count -= 16;
      src += 16;
      dst += 16;
    }
}

static_always_inline u32
aesni_ops_enc_aes_cbc (vlib_main_t * vm, vnet_crypto_op_t * ops[],
		       u32 n_ops, aesni_key_size_t ks