diff mbox

[PATCHv3] linux-generic: add vlan insertion test

Message ID 1478113679-475-1-git-send-email-maxim.uvarov@linaro.org
State Superseded
Headers show

Commit Message

Maxim Uvarov Nov. 2, 2016, 7:07 p.m. UTC
linux-generic packet mmap has separate function to put back
vlan tags which stripped out by linux kernel. This test is
to add code coverage for this function with receiving vlan
traffic from veth device.

Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

---
 v3: - do not point from tests to examples. (Christophe)
     - use better naming.
     - steal code from l2fwd_simple istead of packet.

 I tested this code with printf added to vlan insersion function.

 Thanks,
 Maxim.

 test/linux-generic/Makefile.am                    |   4 +
 test/linux-generic/m4/configure.m4                |   1 +
 test/linux-generic/mmap_vlan_ins/.gitignore       |   2 +
 test/linux-generic/mmap_vlan_ins/Makefile.am      |  15 ++
 test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c  | 232 ++++++++++++++++++++++
 test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh |  79 ++++++++
 test/linux-generic/mmap_vlan_ins/pktio_env        | 120 +++++++++++
 test/linux-generic/mmap_vlan_ins/vlan.pcap        | Bin 0 -> 9728 bytes
 8 files changed, 453 insertions(+)
 create mode 100644 test/linux-generic/mmap_vlan_ins/.gitignore
 create mode 100644 test/linux-generic/mmap_vlan_ins/Makefile.am
 create mode 100644 test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c
 create mode 100755 test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh
 create mode 100644 test/linux-generic/mmap_vlan_ins/pktio_env
 create mode 100644 test/linux-generic/mmap_vlan_ins/vlan.pcap

diff --git a/test/linux-generic/mmap_vlan_ins/vlan.pcap b/test/linux-generic/mmap_vlan_ins/vlan.pcap
new file mode 100644
index 0000000000000000000000000000000000000000..106ccb682e51495b4025337518a0bce63c2c7681
GIT binary patch
literal 9728
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
H$A|v_$relS

literal 0
HcmV?d00001

-- 
2.7.1.250.gff4ea60

Comments

Mike Holmes Nov. 7, 2016, 5:40 p.m. UTC | #1
If you run as root this adds coverage bumping up from 18.5% function
coverage to 96.3%
However this test fails if you are not root, so it should skip rather than
fail just as we do with pktio_run_tap

......
Failed to open pktiop0p1
./mmap_vlan_ins/mmap_vlan_ins.sh: 71: kill: No such process

./mmap_vlan_ins/mmap_vlan_ins.sh: 72: kill: No such process

pktio: removing test interfaces pktiop0p1, pktiop1p0, pktiop2p3, pktiop3p2
check_for_root(): need to be root to setup VETH
FAIL mmap_vlan_ins/mmap_vlan_ins.sh (exit status: 1)





On 2 November 2016 at 15:07, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:

> linux-generic packet mmap has separate function to put back

> vlan tags which stripped out by linux kernel. This test is

> to add code coverage for this function with receiving vlan

> traffic from veth device.

>

> Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org>

> ---

>  v3: - do not point from tests to examples. (Christophe)

>      - use better naming.

>      - steal code from l2fwd_simple istead of packet.

>

>  I tested this code with printf added to vlan insersion function.

>

>  Thanks,

>  Maxim.

>

>  test/linux-generic/Makefile.am                    |   4 +

>  test/linux-generic/m4/configure.m4                |   1 +

>  test/linux-generic/mmap_vlan_ins/.gitignore       |   2 +

>  test/linux-generic/mmap_vlan_ins/Makefile.am      |  15 ++

>  test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c  | 232

> ++++++++++++++++++++++

>  test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh |  79 ++++++++

>  test/linux-generic/mmap_vlan_ins/pktio_env        | 120 +++++++++++

>  test/linux-generic/mmap_vlan_ins/vlan.pcap        | Bin 0 -> 9728 bytes

>  8 files changed, 453 insertions(+)

>  create mode 100644 test/linux-generic/mmap_vlan_ins/.gitignore

>  create mode 100644 test/linux-generic/mmap_vlan_ins/Makefile.am

>  create mode 100644 test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c

>  create mode 100755 test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh

>  create mode 100644 test/linux-generic/mmap_vlan_ins/pktio_env

>  create mode 100644 test/linux-generic/mmap_vlan_ins/vlan.pcap

>

> diff --git a/test/linux-generic/Makefile.am b/test/linux-generic/Makefile.

> am

> index 4660cf0..998ee56 100644

> --- a/test/linux-generic/Makefile.am

> +++ b/test/linux-generic/Makefile.am

> @@ -37,11 +37,15 @@ TESTS = validation/api/pktio/pktio_run.sh \

>

>  SUBDIRS += validation/api/pktio\

>            validation/api/shmem\

> +          mmap_vlan_ins\

>            pktio_ipc\

>            ring

>

>  if HAVE_PCAP

>  TESTS += validation/api/pktio/pktio_run_pcap.sh

> +

> +TESTS +=   mmap_vlan_ins/mmap_vlan_ins.sh

> +SUBDIRS += mmap_vlan_ins

>  endif

>  if netmap_support

>  TESTS += validation/api/pktio/pktio_run_netmap.sh

> diff --git a/test/linux-generic/m4/configure.m4 b/test/linux-generic/m4/

> configure.m4

> index 6b92201..8746dab 100644

> --- a/test/linux-generic/m4/configure.m4

> +++ b/test/linux-generic/m4/configure.m4

> @@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])

>  AC_CONFIG_FILES([test/linux-generic/Makefile

>                  test/linux-generic/validation/api/shmem/Makefile

>                  test/linux-generic/validation/api/pktio/Makefile

> +                test/linux-generic/mmap_vlan_ins/Makefile

>                  test/linux-generic/pktio_ipc/Makefile

>                  test/linux-generic/ring/Makefile

>                  test/linux-generic/performance/Makefile])

> diff --git a/test/linux-generic/mmap_vlan_ins/.gitignore

> b/test/linux-generic/mmap_vlan_ins/.gitignore

> new file mode 100644

> index 0000000..755fa2e

> --- /dev/null

> +++ b/test/linux-generic/mmap_vlan_ins/.gitignore

> @@ -0,0 +1,2 @@

> +*.pcap

> +plat_mmap_vlan_ins

> diff --git a/test/linux-generic/mmap_vlan_ins/Makefile.am

> b/test/linux-generic/mmap_vlan_ins/Makefile.am

> new file mode 100644

> index 0000000..2641556

> --- /dev/null

> +++ b/test/linux-generic/mmap_vlan_ins/Makefile.am

> @@ -0,0 +1,15 @@

> +include $(top_srcdir)/test/Makefile.inc

> +TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/validation

> +

> +dist_check_SCRIPTS = vlan.pcap \

> +                    mmap_vlan_ins.sh \

> +                    pktio_env

> +

> +test_SCRIPTS = $(dist_check_SCRIPTS)

> +

> +bin_PROGRAMS = plat_mmap_vlan_ins$(EXEEXT)

> +plat_mmap_vlan_ins_LDFLAGS = $(AM_LDFLAGS) -static

> +plat_mmap_vlan_ins_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example

> +

> +# Clonned from example odp_l2fwd simple

> +dist_plat_mmap_vlan_ins_SOURCES = mmap_vlan_ins.c

> diff --git a/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c

> b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c

> new file mode 100644

> index 0000000..0682d2d

> --- /dev/null

> +++ b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c

> @@ -0,0 +1,232 @@

> +/* Copyright (c) 2016, Linaro Limited

> + * All rights reserved.

> + *

> + * SPDX-License-Identifier:     BSD-3-Clause

> + */

> +

> +#include <stdlib.h>

> +#include <stdio.h>

> +#include <getopt.h>

> +#include <signal.h>

> +

> +#include <odp_api.h>

> +#include <odp/helper/linux.h>

> +#include <odp/helper/eth.h>

> +#include <odp/helper/ip.h>

> +

> +#define POOL_NUM_PKT 8192

> +#define POOL_SEG_LEN 1856

> +#define MAX_PKT_BURST 32

> +#define MAX_WORKERS 1

> +

> +static int exit_thr;

> +static int g_ret;

> +

> +struct {

> +       odp_pktio_t if0, if1;

> +       odp_pktin_queue_t if0in, if1in;

> +       odp_pktout_queue_t if0out, if1out;

> +       odph_ethaddr_t src, dst;

> +} global;

> +

> +static void sig_handler(int signo ODP_UNUSED)

> +{

> +       printf("sig_handler!\n");

> +       exit_thr = 1;

> +}

> +

> +static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,

> +                               odp_pktin_queue_t *pktin,

> +                               odp_pktout_queue_t *pktout)

> +{

> +       odp_pktio_param_t pktio_param;

> +       odp_pktin_queue_param_t in_queue_param;

> +       odp_pktout_queue_param_t out_queue_param;

> +       odp_pktio_t pktio;

> +

> +       odp_pktio_param_init(&pktio_param);

> +

> +       pktio = odp_pktio_open(name, pool, &pktio_param);

> +       if (pktio == ODP_PKTIO_INVALID) {

> +               printf("Failed to open %s\n", name);

> +               exit(1);

> +       }

> +

> +       odp_pktin_queue_param_init(&in_queue_param);

> +       odp_pktout_queue_param_init(&out_queue_param);

> +

> +       in_queue_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;

> +

> +       if (odp_pktin_queue_config(pktio, &in_queue_param)) {

> +               printf("Failed to config input queue for %s\n", name);

> +               exit(1);

> +       }

> +

> +       out_queue_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;

> +

> +       if (odp_pktout_queue_config(pktio, &out_queue_param)) {

> +               printf("Failed to config output queue for %s\n", name);

> +               exit(1);

> +       }

> +

> +       if (odp_pktin_queue(pktio, pktin, 1) != 1) {

> +               printf("pktin queue query failed for %s\n", name);

> +               exit(1);

> +       }

> +       if (odp_pktout_queue(pktio, pktout, 1) != 1) {

> +               printf("pktout queue query failed for %s\n", name);

> +               exit(1);

> +       }

> +       return pktio;

> +}

> +

> +static int run_worker(void *arg ODP_UNUSED)

> +{

> +       odp_packet_t pkt_tbl[MAX_PKT_BURST];

> +       int pkts, sent, tx_drops, i;

> +       int total_pkts = 0;

> +

> +       if (odp_pktio_start(global.if0)) {

> +               printf("unable to start input interface\n");

> +               exit(1);

> +       }

> +       printf("started input interface\n");

> +       if (odp_pktio_start(global.if1)) {

> +               printf("unable to start output interface\n");

> +               exit(1);

> +       }

> +       printf("started output interface\n");

> +       printf("started all\n");

> +

> +       while (!exit_thr) {

> +               pkts = odp_pktin_recv_tmo(global.if0in, pkt_tbl,

> MAX_PKT_BURST,

> +                                         ODP_PKTIN_NO_WAIT);

> +

> +               if (odp_unlikely(pkts <= 0))

> +                       continue;

> +               for (i = 0; i < pkts; i++) {

> +                       odp_packet_t pkt = pkt_tbl[i];

> +                       odph_ethhdr_t *eth;

> +

> +                       if (odp_unlikely(!odp_packet_has_eth(pkt))) {

> +                               printf("warning: packet has no eth

> header\n");

> +                               return 0;

> +                       }

> +                       eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt,

> NULL);

> +                       eth->src = global.src;

> +                       eth->dst = global.dst;

> +               }

> +               sent = odp_pktout_send(global.if1out, pkt_tbl, pkts);

> +               if (sent < 0)

> +                       sent = 0;

> +               total_pkts += sent;

> +               tx_drops = pkts - sent;

> +               if (odp_unlikely(tx_drops))

> +                       odp_packet_free_multi(&pkt_tbl[sent], tx_drops);

> +       }

> +

> +       if (total_pkts < 10)

> +               g_ret = -1;

> +

> +       return 0;

> +}

> +

> +int main(int argc, char **argv)

> +{

> +       odp_pool_t pool;

> +       odp_pool_param_t params;

> +       odp_cpumask_t cpumask;

> +       odph_odpthread_t thd[MAX_WORKERS];

> +       odp_instance_t instance;

> +       odph_odpthread_params_t thr_params;

> +       int opt;

> +       int long_index;

> +

> +       static const struct option longopts[] = { {NULL, 0, NULL, 0} };

> +       static const char *shortopts = "";

> +

> +       /* let helper collect its own arguments (e.g. --odph_proc) */

> +       odph_parse_options(argc, argv, shortopts, longopts);

> +

> +       /*

> +        * parse own options: currentely none, but this will move optind

> +        * to the first non-option argument. (in case there where helprt

> args)

> +        */

> +       opterr = 0; /* do not issue errors on helper options */

> +       while (1) {

> +               opt = getopt_long(argc, argv, shortopts, longopts,

> &long_index);

> +               if (-1 == opt)

> +                       break;  /* No more options */

> +       }

> +

> +       if (argc != optind + 4 ||

> +           odph_eth_addr_parse(&global.dst, argv[optind + 2]) != 0 ||

> +           odph_eth_addr_parse(&global.src, argv[optind + 3]) != 0) {

> +               printf("Usage: odp_l2fwd_simple eth0 eth1

> 01:02:03:04:05:06"

> +                      " 07:08:09:0a:0b:0c\n");

> +               printf("Where eth0 and eth1 are the used interfaces"

> +                      " (must have 2 of them)\n");

> +               printf("And the hexadecimal numbers are destination MAC

> address"

> +                      " and source MAC address\n");

> +               exit(1);

> +       }

> +

> +       if (odp_init_global(&instance, NULL, NULL)) {

> +               printf("Error: ODP global init failed.\n");

> +               exit(1);

> +       }

> +

> +       if (odp_init_local(instance, ODP_THREAD_CONTROL)) {

> +               printf("Error: ODP local init failed.\n");

> +               exit(1);

> +       }

> +

> +       /* Create packet pool */

> +       odp_pool_param_init(&params);

> +       params.pkt.seg_len = POOL_SEG_LEN;

> +       params.pkt.len     = POOL_SEG_LEN;

> +       params.pkt.num     = POOL_NUM_PKT;

> +       params.type        = ODP_POOL_PACKET;

> +

> +       pool = odp_pool_create("packet pool", &params);

> +

> +       if (pool == ODP_POOL_INVALID) {

> +               printf("Error: packet pool create failed.\n");

> +               exit(1);

> +       }

> +

> +       global.if0 = create_pktio(argv[optind], pool, &global.if0in,

> +

>  &global.if0out);

> +       global.if1 = create_pktio(argv[optind + 1], pool, &global.if1in,

> +

>  &global.if1out);

> +

> +       odp_cpumask_default_worker(&cpumask, MAX_WORKERS);

> +

> +       memset(&thr_params, 0, sizeof(thr_params));

> +       thr_params.start    = run_worker;

> +       thr_params.arg      = NULL;

> +       thr_params.thr_type = ODP_THREAD_WORKER;

> +       thr_params.instance = instance;

> +

> +       signal(SIGINT, sig_handler);

> +

> +       odph_odpthreads_create(thd, &cpumask, &thr_params);

> +       odph_odpthreads_join(thd);

> +

> +       if (odp_pool_destroy(pool)) {

> +               printf("Error: pool destroy\n");

> +               exit(EXIT_FAILURE);

> +       }

> +

> +       if (odp_term_local()) {

> +               printf("Error: term local\n");

> +               exit(EXIT_FAILURE);

> +       }

> +

> +       if (odp_term_global(instance)) {

> +               printf("Error: term global\n");

> +               exit(EXIT_FAILURE);

> +       }

> +

> +       return g_ret;

> +}

> diff --git a/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh

> b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh

> new file mode 100755

> index 0000000..476ab9b

> --- /dev/null

> +++ b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh

> @@ -0,0 +1,79 @@

> +#!/bin/sh

> +#

> +# Copyright (c) 2016, Linaro Limited

> +# All rights reserved.

> +#

> +# SPDX-License-Identifier:     BSD-3-Clause

> +#

> +

> +#

> +# This test is intend to test pkt_mmap_vlan_insert() feature for

> +# linux-generic packet mmap pktio.

> +#

> +#

> +

> +# directory where platform test sources are, including scripts

> +TEST_SRC_DIR=$(dirname $0)

> +

> +# exit codes expected by automake for skipped tests

> +TEST_SKIPPED=77

> +

> +# directories where binary can be found:

> +# -in the validation dir when running make check (intree or out of tree)

> +# -in the script directory, when running after 'make install', or

> +# -in the validation when running standalone intree.

> +# -in the current directory.

> +# running stand alone out of tree requires setting PATH

> +PATH=${TEST_DIR}/../mmap_vlan_ins:$PATH

> +PATH=`pwd`/mmap_vlan_ins:$PATH

> +PATH=$(dirname $0):$PATH

> +PATH=.:$PATH

> +

> +bin_path=$(which plat_mmap_vlan_ins${EXEEXT})

> +if [ -x "$bin_path" ] ; then

> +       echo "running with plat_mmap_vlan_ins: $bin_path"

> +else

> +       echo "cannot find plat_mmap_vlan_ins: please set you PATH for it."

> +       pwd

> +       exit 1

> +fi

> +

> +

> +# Use installed pktio env or for make check take it from platform

> directory

> +if [ -f "./pktio_env" ]; then

> +       . ./pktio_env

> +elif [ -f ${TEST_SRC_DIR}/pktio_env ]; then

> +       . ${TEST_SRC_DIR}/pktio_env

> +else

> +       echo "BUG: unable to find pktio_env!"

> +       echo "pktio_env has to be in current directory or"

> +       echo " in platform/\$ODP_PLATFORM/test."

> +       echo "ODP_PLATFORM=\"$ODP_PLATFORM\""

> +       exit 1

> +fi

> +

> +setup_pktio_env

> +

> +PCAP_IN=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`

> +echo "using PCAP_IN = ${PCAP_IN}"

> +PCAP_OUT=vlan_out.pcap

> +

> +# Listen on veth pipe and write to pcap Send pcap

> +plat_mmap_vlan_ins${EXEEXT} pktiop0p1 pcap:out=${PCAP_OUT} \

> +       00:02:03:04:05:06 00:08:09:0a:0b:0c &

> +P1=$!

> +# Send pcap file to veth interface

> +plat_mmap_vlan_ins${EXEEXT} pcap:in=${PCAP_IN} pktiop0p1 \

> +       01:02:03:04:05:06 01:08:09:0a:0b:0c &

> +P2=$!

> +

> +sleep 1

> +kill -s INT ${P1}

> +kill -s INT ${P2}

> +

> +ret=$?

> +rm -f ${PCAP_OUT}

> +

> +cleanup_pktio_env

> +

> +exit $ret

> diff --git a/test/linux-generic/mmap_vlan_ins/pktio_env

> b/test/linux-generic/mmap_vlan_ins/pktio_env

> new file mode 100644

> index 0000000..345b5bd

> --- /dev/null

> +++ b/test/linux-generic/mmap_vlan_ins/pktio_env

> @@ -0,0 +1,120 @@

> +#!/bin/sh

> +#

> +# Copyright (c) 2015, Linaro Limited

> +# All rights reserved.

> +#

> +# SPDX-License-Identifier:     BSD-3-Clause

> +#

> +# Test script wrapper for running ODP pktio apps on linux-generic.

> +#

> +# For linux-generic the default behavior is to create two pairs of

> +# virtual Ethernet interfaces and provide the names of these via

> +# environment variables to pktio apps, the interfaces will be removed

> +# before the script exits.

> +#

> +# Note that the creation of virtual Ethernet devices depends on having

> +# CONFIG_VETH enabled in the kernel, if not enabled the env setup will be

> skipped.

> +#

> +# Network set up

> +# IF0 <---> IF1

> +# IF2 <---> IF3

> +IF0=pktiop0p1

> +IF1=pktiop1p0

> +IF2=pktiop2p3

> +IF3=pktiop3p2

> +

> +if [ "$0" = "$BASH_SOURCE" ]; then

> +       echo "Error: Platform specific env file has to be sourced."

> +fi

> +

> +check_for_root()

> +{

> +       if [ "$(id -u)" != "0" ]; then

> +               echo "check_for_root(): need to be root to setup VETH"

> +               return 1

> +       fi

> +       return 0

> +}

> +

> +# wait for a network interface's operational state to be "up"

> +wait_for_iface_up()

> +{

> +       iface=$1

> +       cnt=0

> +

> +       while [ $cnt -lt 50 ]; do

> +               read operstate < /sys/class/net/$iface/operstate

> +

> +               if [ $? -ne 0 ]; then

> +                       break

> +               elif [ "$operstate" = "up" ]; then

> +                       return 0

> +               fi

> +

> +               sleep 0.1

> +               cnt=`expr $cnt + 1`

> +       done

> +

> +       return 1

> +}

> +

> +setup_pktio_env()

> +{

> +       echo "pktio: setting up test interfaces $IF0, $IF1, $IF2, $IF3."

> +

> +       check_for_root

> +       if [ $? -ne 0 ]; then

> +               return 1

> +       fi

> +

> +       for iface in $IF0 $IF1 $IF2 $IF3; do

> +               ip link show $iface 2> /dev/null

> +               if [ $? -eq 0 ]; then

> +                       echo "pktio: interface $iface already exist $?"

> +                       return 2

> +               fi

> +       done

> +

> +       if [ "$1" = "clean" ]; then

> +               trap cleanup_pktio_env EXIT

> +       fi

> +

> +       ip link add $IF0 type veth peer name $IF1

> +       if [ $? -ne 0 ]; then

> +               echo "pktio: error: unable to create veth pair"

> +               return 3

> +       fi

> +       ip link add $IF2 type veth peer name $IF3

> +       if [ $? -ne 0 ]; then

> +               echo "pktio: error: unable to create veth pair"

> +               return 4

> +       fi

> +

> +       for iface in $IF0 $IF1 $IF2 $IF3; do

> +               ip link set $iface mtu 9216 up

> +               ifconfig $iface -arp

> +       done

> +

> +       # check that the interface has come up before starting the test

> +       for iface in $IF0 $IF1 $IF2 $IF3; do

> +               wait_for_iface_up $iface

> +               if [ $? -ne 0 ]; then

> +                       echo "pktio: interface $iface failed to come up"

> +                       return 5

> +               fi

> +       done

> +}

> +

> +cleanup_pktio_env()

> +{

> +       echo "pktio: removing test interfaces $IF0, $IF1, $IF2, $IF3"

> +       check_for_root

> +       if [ $? -ne 0 ]; then

> +               return 1

> +       fi

> +

> +       for iface in $IF0 $IF1 $IF2 $IF3; do

> +               ip link del $iface 2> /dev/null

> +       done

> +       return 0

> +}

> diff --git a/test/linux-generic/mmap_vlan_ins/vlan.pcap

> b/test/linux-generic/mmap_vlan_ins/vlan.pcap

> new file mode 100644

> index 0000000000000000000000000000000000000000..

> 106ccb682e51495b4025337518a0bce63c2c7681

> GIT binary patch

> literal 9728

> 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

> H$A|v_$relS

>

> literal 0

> HcmV?d00001

>

> --

> 2.7.1.250.gff4ea60

>

>



-- 
Mike Holmes
Program Manager - Linaro Networking Group
Linaro.org <http://www.linaro.org/> *│ *Open source software for ARM SoCs
"Work should be fun and collaborative, the rest follows"
diff mbox

Patch

diff --git a/test/linux-generic/Makefile.am b/test/linux-generic/Makefile.am
index 4660cf0..998ee56 100644
--- a/test/linux-generic/Makefile.am
+++ b/test/linux-generic/Makefile.am
@@ -37,11 +37,15 @@  TESTS = validation/api/pktio/pktio_run.sh \
 
 SUBDIRS += validation/api/pktio\
 	   validation/api/shmem\
+	   mmap_vlan_ins\
 	   pktio_ipc\
 	   ring
 
 if HAVE_PCAP
 TESTS += validation/api/pktio/pktio_run_pcap.sh
+
+TESTS +=   mmap_vlan_ins/mmap_vlan_ins.sh
+SUBDIRS += mmap_vlan_ins
 endif
 if netmap_support
 TESTS += validation/api/pktio/pktio_run_netmap.sh
diff --git a/test/linux-generic/m4/configure.m4 b/test/linux-generic/m4/configure.m4
index 6b92201..8746dab 100644
--- a/test/linux-generic/m4/configure.m4
+++ b/test/linux-generic/m4/configure.m4
@@ -3,6 +3,7 @@  m4_include([test/linux-generic/m4/performance.m4])
 AC_CONFIG_FILES([test/linux-generic/Makefile
 		 test/linux-generic/validation/api/shmem/Makefile
 		 test/linux-generic/validation/api/pktio/Makefile
+		 test/linux-generic/mmap_vlan_ins/Makefile
 		 test/linux-generic/pktio_ipc/Makefile
 		 test/linux-generic/ring/Makefile
 		 test/linux-generic/performance/Makefile])
diff --git a/test/linux-generic/mmap_vlan_ins/.gitignore b/test/linux-generic/mmap_vlan_ins/.gitignore
new file mode 100644
index 0000000..755fa2e
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/.gitignore
@@ -0,0 +1,2 @@ 
+*.pcap
+plat_mmap_vlan_ins
diff --git a/test/linux-generic/mmap_vlan_ins/Makefile.am b/test/linux-generic/mmap_vlan_ins/Makefile.am
new file mode 100644
index 0000000..2641556
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/Makefile.am
@@ -0,0 +1,15 @@ 
+include $(top_srcdir)/test/Makefile.inc
+TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/validation
+
+dist_check_SCRIPTS = vlan.pcap \
+		     mmap_vlan_ins.sh \
+		     pktio_env
+
+test_SCRIPTS = $(dist_check_SCRIPTS)
+
+bin_PROGRAMS = plat_mmap_vlan_ins$(EXEEXT)
+plat_mmap_vlan_ins_LDFLAGS = $(AM_LDFLAGS) -static
+plat_mmap_vlan_ins_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example
+
+# Clonned from example odp_l2fwd simple
+dist_plat_mmap_vlan_ins_SOURCES = mmap_vlan_ins.c
diff --git a/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c
new file mode 100644
index 0000000..0682d2d
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c
@@ -0,0 +1,232 @@ 
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <signal.h>
+
+#include <odp_api.h>
+#include <odp/helper/linux.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+
+#define POOL_NUM_PKT 8192
+#define POOL_SEG_LEN 1856
+#define MAX_PKT_BURST 32
+#define MAX_WORKERS 1
+
+static int exit_thr;
+static int g_ret;
+
+struct {
+	odp_pktio_t if0, if1;
+	odp_pktin_queue_t if0in, if1in;
+	odp_pktout_queue_t if0out, if1out;
+	odph_ethaddr_t src, dst;
+} global;
+
+static void sig_handler(int signo ODP_UNUSED)
+{
+	printf("sig_handler!\n");
+	exit_thr = 1;
+}
+
+static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,
+				odp_pktin_queue_t *pktin,
+				odp_pktout_queue_t *pktout)
+{
+	odp_pktio_param_t pktio_param;
+	odp_pktin_queue_param_t in_queue_param;
+	odp_pktout_queue_param_t out_queue_param;
+	odp_pktio_t pktio;
+
+	odp_pktio_param_init(&pktio_param);
+
+	pktio = odp_pktio_open(name, pool, &pktio_param);
+	if (pktio == ODP_PKTIO_INVALID) {
+		printf("Failed to open %s\n", name);
+		exit(1);
+	}
+
+	odp_pktin_queue_param_init(&in_queue_param);
+	odp_pktout_queue_param_init(&out_queue_param);
+
+	in_queue_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;
+
+	if (odp_pktin_queue_config(pktio, &in_queue_param)) {
+		printf("Failed to config input queue for %s\n", name);
+		exit(1);
+	}
+
+	out_queue_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;
+
+	if (odp_pktout_queue_config(pktio, &out_queue_param)) {
+		printf("Failed to config output queue for %s\n", name);
+		exit(1);
+	}
+
+	if (odp_pktin_queue(pktio, pktin, 1) != 1) {
+		printf("pktin queue query failed for %s\n", name);
+		exit(1);
+	}
+	if (odp_pktout_queue(pktio, pktout, 1) != 1) {
+		printf("pktout queue query failed for %s\n", name);
+		exit(1);
+	}
+	return pktio;
+}
+
+static int run_worker(void *arg ODP_UNUSED)
+{
+	odp_packet_t pkt_tbl[MAX_PKT_BURST];
+	int pkts, sent, tx_drops, i;
+	int total_pkts = 0;
+
+	if (odp_pktio_start(global.if0)) {
+		printf("unable to start input interface\n");
+		exit(1);
+	}
+	printf("started input interface\n");
+	if (odp_pktio_start(global.if1)) {
+		printf("unable to start output interface\n");
+		exit(1);
+	}
+	printf("started output interface\n");
+	printf("started all\n");
+
+	while (!exit_thr) {
+		pkts = odp_pktin_recv_tmo(global.if0in, pkt_tbl, MAX_PKT_BURST,
+					  ODP_PKTIN_NO_WAIT);
+
+		if (odp_unlikely(pkts <= 0))
+			continue;
+		for (i = 0; i < pkts; i++) {
+			odp_packet_t pkt = pkt_tbl[i];
+			odph_ethhdr_t *eth;
+
+			if (odp_unlikely(!odp_packet_has_eth(pkt))) {
+				printf("warning: packet has no eth header\n");
+				return 0;
+			}
+			eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
+			eth->src = global.src;
+			eth->dst = global.dst;
+		}
+		sent = odp_pktout_send(global.if1out, pkt_tbl, pkts);
+		if (sent < 0)
+			sent = 0;
+		total_pkts += sent;
+		tx_drops = pkts - sent;
+		if (odp_unlikely(tx_drops))
+			odp_packet_free_multi(&pkt_tbl[sent], tx_drops);
+	}
+
+	if (total_pkts < 10)
+		g_ret = -1;
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	odp_pool_t pool;
+	odp_pool_param_t params;
+	odp_cpumask_t cpumask;
+	odph_odpthread_t thd[MAX_WORKERS];
+	odp_instance_t instance;
+	odph_odpthread_params_t thr_params;
+	int opt;
+	int long_index;
+
+	static const struct option longopts[] = { {NULL, 0, NULL, 0} };
+	static const char *shortopts = "";
+
+	/* let helper collect its own arguments (e.g. --odph_proc) */
+	odph_parse_options(argc, argv, shortopts, longopts);
+
+	/*
+	 * parse own options: currentely none, but this will move optind
+	 * to the first non-option argument. (in case there where helprt args)
+	 */
+	opterr = 0; /* do not issue errors on helper options */
+	while (1) {
+		opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
+		if (-1 == opt)
+			break;  /* No more options */
+	}
+
+	if (argc != optind + 4 ||
+	    odph_eth_addr_parse(&global.dst, argv[optind + 2]) != 0 ||
+	    odph_eth_addr_parse(&global.src, argv[optind + 3]) != 0) {
+		printf("Usage: odp_l2fwd_simple eth0 eth1 01:02:03:04:05:06"
+		       " 07:08:09:0a:0b:0c\n");
+		printf("Where eth0 and eth1 are the used interfaces"
+		       " (must have 2 of them)\n");
+		printf("And the hexadecimal numbers are destination MAC address"
+		       " and source MAC address\n");
+		exit(1);
+	}
+
+	if (odp_init_global(&instance, NULL, NULL)) {
+		printf("Error: ODP global init failed.\n");
+		exit(1);
+	}
+
+	if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
+		printf("Error: ODP local init failed.\n");
+		exit(1);
+	}
+
+	/* Create packet pool */
+	odp_pool_param_init(&params);
+	params.pkt.seg_len = POOL_SEG_LEN;
+	params.pkt.len     = POOL_SEG_LEN;
+	params.pkt.num     = POOL_NUM_PKT;
+	params.type        = ODP_POOL_PACKET;
+
+	pool = odp_pool_create("packet pool", &params);
+
+	if (pool == ODP_POOL_INVALID) {
+		printf("Error: packet pool create failed.\n");
+		exit(1);
+	}
+
+	global.if0 = create_pktio(argv[optind], pool, &global.if0in,
+								&global.if0out);
+	global.if1 = create_pktio(argv[optind + 1], pool, &global.if1in,
+								&global.if1out);
+
+	odp_cpumask_default_worker(&cpumask, MAX_WORKERS);
+
+	memset(&thr_params, 0, sizeof(thr_params));
+	thr_params.start    = run_worker;
+	thr_params.arg      = NULL;
+	thr_params.thr_type = ODP_THREAD_WORKER;
+	thr_params.instance = instance;
+
+	signal(SIGINT, sig_handler);
+
+	odph_odpthreads_create(thd, &cpumask, &thr_params);
+	odph_odpthreads_join(thd);
+
+	if (odp_pool_destroy(pool)) {
+		printf("Error: pool destroy\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (odp_term_local()) {
+		printf("Error: term local\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (odp_term_global(instance)) {
+		printf("Error: term global\n");
+		exit(EXIT_FAILURE);
+	}
+
+	return g_ret;
+}
diff --git a/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh
new file mode 100755
index 0000000..476ab9b
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh
@@ -0,0 +1,79 @@ 
+#!/bin/sh
+#
+# Copyright (c) 2016, Linaro Limited
+# All rights reserved.
+#
+# SPDX-License-Identifier:	BSD-3-Clause
+#
+
+#
+# This test is intend to test pkt_mmap_vlan_insert() feature for
+# linux-generic packet mmap pktio.
+#
+#
+
+# directory where platform test sources are, including scripts
+TEST_SRC_DIR=$(dirname $0)
+
+# exit codes expected by automake for skipped tests
+TEST_SKIPPED=77
+
+# directories where binary can be found:
+# -in the validation dir when running make check (intree or out of tree)
+# -in the script directory, when running after 'make install', or
+# -in the validation when running standalone intree.
+# -in the current directory.
+# running stand alone out of tree requires setting PATH
+PATH=${TEST_DIR}/../mmap_vlan_ins:$PATH
+PATH=`pwd`/mmap_vlan_ins:$PATH
+PATH=$(dirname $0):$PATH
+PATH=.:$PATH
+
+bin_path=$(which plat_mmap_vlan_ins${EXEEXT})
+if [ -x "$bin_path" ] ; then
+	echo "running with plat_mmap_vlan_ins: $bin_path"
+else
+	echo "cannot find plat_mmap_vlan_ins: please set you PATH for it."
+	pwd
+	exit 1
+fi
+
+
+# Use installed pktio env or for make check take it from platform directory
+if [ -f "./pktio_env" ]; then
+	. ./pktio_env
+elif [ -f ${TEST_SRC_DIR}/pktio_env ]; then
+	. ${TEST_SRC_DIR}/pktio_env
+else
+	echo "BUG: unable to find pktio_env!"
+	echo "pktio_env has to be in current directory or"
+	echo " in platform/\$ODP_PLATFORM/test."
+	echo "ODP_PLATFORM=\"$ODP_PLATFORM\""
+	exit 1
+fi
+
+setup_pktio_env
+
+PCAP_IN=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`
+echo "using PCAP_IN = ${PCAP_IN}"
+PCAP_OUT=vlan_out.pcap
+
+# Listen on veth pipe and write to pcap Send pcap
+plat_mmap_vlan_ins${EXEEXT} pktiop0p1 pcap:out=${PCAP_OUT} \
+	00:02:03:04:05:06 00:08:09:0a:0b:0c &
+P1=$!
+# Send pcap file to veth interface
+plat_mmap_vlan_ins${EXEEXT} pcap:in=${PCAP_IN} pktiop0p1 \
+	01:02:03:04:05:06 01:08:09:0a:0b:0c &
+P2=$!
+
+sleep 1
+kill -s INT ${P1}
+kill -s INT ${P2}
+
+ret=$?
+rm -f ${PCAP_OUT}
+
+cleanup_pktio_env
+
+exit $ret
diff --git a/test/linux-generic/mmap_vlan_ins/pktio_env b/test/linux-generic/mmap_vlan_ins/pktio_env
new file mode 100644
index 0000000..345b5bd
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/pktio_env
@@ -0,0 +1,120 @@ 
+#!/bin/sh
+#
+# Copyright (c) 2015, Linaro Limited
+# All rights reserved.
+#
+# SPDX-License-Identifier:	BSD-3-Clause
+#
+# Test script wrapper for running ODP pktio apps on linux-generic.
+#
+# For linux-generic the default behavior is to create two pairs of
+# virtual Ethernet interfaces and provide the names of these via
+# environment variables to pktio apps, the interfaces will be removed
+# before the script exits.
+#
+# Note that the creation of virtual Ethernet devices depends on having
+# CONFIG_VETH enabled in the kernel, if not enabled the env setup will be skipped.
+#
+# Network set up
+# IF0 <---> IF1
+# IF2 <---> IF3
+IF0=pktiop0p1
+IF1=pktiop1p0
+IF2=pktiop2p3
+IF3=pktiop3p2
+
+if [ "$0" = "$BASH_SOURCE" ]; then
+	echo "Error: Platform specific env file has to be sourced."
+fi
+
+check_for_root()
+{
+	if [ "$(id -u)" != "0" ]; then
+		echo "check_for_root(): need to be root to setup VETH"
+		return 1
+	fi
+	return 0
+}
+
+# wait for a network interface's operational state to be "up"
+wait_for_iface_up()
+{
+	iface=$1
+	cnt=0
+
+	while [ $cnt -lt 50 ]; do
+		read operstate < /sys/class/net/$iface/operstate
+
+		if [ $? -ne 0 ]; then
+			break
+		elif [ "$operstate" = "up" ]; then
+			return 0
+		fi
+
+		sleep 0.1
+		cnt=`expr $cnt + 1`
+	done
+
+	return 1
+}
+
+setup_pktio_env()
+{
+	echo "pktio: setting up test interfaces $IF0, $IF1, $IF2, $IF3."
+
+	check_for_root
+	if [ $? -ne 0 ]; then
+		return 1
+	fi
+
+	for iface in $IF0 $IF1 $IF2 $IF3; do
+		ip link show $iface 2> /dev/null
+		if [ $? -eq 0 ]; then
+			echo "pktio: interface $iface already exist $?"
+			return 2
+		fi
+	done
+
+	if [ "$1" = "clean" ]; then
+		trap cleanup_pktio_env EXIT
+	fi
+
+	ip link add $IF0 type veth peer name $IF1
+	if [ $? -ne 0 ]; then
+		echo "pktio: error: unable to create veth pair"
+		return 3
+	fi
+	ip link add $IF2 type veth peer name $IF3
+	if [ $? -ne 0 ]; then
+		echo "pktio: error: unable to create veth pair"
+		return 4
+	fi
+
+	for iface in $IF0 $IF1 $IF2 $IF3; do
+		ip link set $iface mtu 9216 up
+		ifconfig $iface -arp
+	done
+
+	# check that the interface has come up before starting the test
+	for iface in $IF0 $IF1 $IF2 $IF3; do
+		wait_for_iface_up $iface
+		if [ $? -ne 0 ]; then
+			echo "pktio: interface $iface failed to come up"
+			return 5
+		fi
+	done
+}
+
+cleanup_pktio_env()
+{
+	echo "pktio: removing test interfaces $IF0, $IF1, $IF2, $IF3"
+	check_for_root
+	if [ $? -ne 0 ]; then
+		return 1
+	fi
+
+	for iface in $IF0 $IF1 $IF2 $IF3; do
+		ip link del $iface 2> /dev/null
+	done
+	return 0
+}