From patchwork Fri Dec 19 11:46:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maxim Uvarov X-Patchwork-Id: 42486 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-wi0-f198.google.com (mail-wi0-f198.google.com [209.85.212.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 5EF5426C68 for ; Fri, 19 Dec 2014 11:47:13 +0000 (UTC) Received: by mail-wi0-f198.google.com with SMTP id r20sf597048wiv.1 for ; Fri, 19 Dec 2014 03:47:12 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:subject:precedence:list-id:list-unsubscribe:list-archive :list-post:list-help:list-subscribe:mime-version:content-type :content-transfer-encoding:errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=/puBmaYNq2GYkGgAgUv1EPzJJiVmuO8szw4SK3C4Jeo=; b=MwuO4H+aVEsPMq5Isz4n9kLlSoDcKRBbz0TfVJyZREqPmo5EpVnX+RGTZJweOprO82 EXO5p23oPmXOlWS0sYBxHj+fEPWvmDSdINzn66Hal8acOlc8Z09E93WfWizQT2ELLzfn +skoXBNvdnp/kkiKg1wDYmUmG0GiCKB5b0ntqlbrEqpxm4K9pLMht+yB8aTZjZ+ICX8a rKAzVF30dib+IpZKdQajg1p0eM+UwAaGloDSbihlW2DBl+7V3TKNcPmfefx0N8GRqMx2 KeWLC6xUSx0j8HkLBmcoOJQ9fRQv1IT9NWUwrGgD4Mjohyw9d3HFF30quD1t+ZvEwJBz TJRw== X-Gm-Message-State: ALoCoQmG6qjXH6OQj4J2J7975uf4evZqL94PQDPb2YYfsZGwwU1xMTesJaxi2gZ65feMOZc2gUb2 X-Received: by 10.180.105.97 with SMTP id gl1mr400100wib.7.1418989632623; Fri, 19 Dec 2014 03:47:12 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.203.162 with SMTP id kr2ls1248299lac.36.gmail; Fri, 19 Dec 2014 03:47:12 -0800 (PST) X-Received: by 10.152.204.9 with SMTP id ku9mr7368791lac.55.1418989632384; Fri, 19 Dec 2014 03:47:12 -0800 (PST) Received: from mail-lb0-f173.google.com (mail-lb0-f173.google.com. [209.85.217.173]) by mx.google.com with ESMTPS id k1si9767122lam.30.2014.12.19.03.47.12 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 19 Dec 2014 03:47:12 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.173 as permitted sender) client-ip=209.85.217.173; Received: by mail-lb0-f173.google.com with SMTP id z12so665027lbi.18 for ; Fri, 19 Dec 2014 03:47:12 -0800 (PST) X-Received: by 10.152.87.100 with SMTP id w4mr7377552laz.71.1418989632083; Fri, 19 Dec 2014 03:47:12 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.142.69 with SMTP id ru5csp241901lbb; Fri, 19 Dec 2014 03:47:10 -0800 (PST) X-Received: by 10.224.37.131 with SMTP id x3mr10459437qad.104.1418989629936; Fri, 19 Dec 2014 03:47:09 -0800 (PST) Received: from ip-10-35-177-41.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id dv7si11538277qcb.38.2014.12.19.03.47.09 (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 19 Dec 2014 03:47:09 -0800 (PST) Received-SPF: none (google.com: lng-odp-bounces@lists.linaro.org does not designate permitted sender hosts) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-35-177-41.ec2.internal) by ip-10-35-177-41.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1Y1w1T-0006hf-8h; Fri, 19 Dec 2014 11:47:07 +0000 Received: from mail-lb0-f176.google.com ([209.85.217.176]) by ip-10-35-177-41.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1Y1w1I-0006fY-Ep for lng-odp@lists.linaro.org; Fri, 19 Dec 2014 11:46:56 +0000 Received: by mail-lb0-f176.google.com with SMTP id p9so653621lbv.21 for ; Fri, 19 Dec 2014 03:46:50 -0800 (PST) X-Received: by 10.152.203.137 with SMTP id kq9mr7346759lac.51.1418989610767; Fri, 19 Dec 2014 03:46:50 -0800 (PST) Received: from localhost.localdomain ([188.92.105.210]) by mx.google.com with ESMTPSA id z4sm2474524laz.8.2014.12.19.03.46.49 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 19 Dec 2014 03:46:49 -0800 (PST) From: Maxim Uvarov To: lng-odp@lists.linaro.org Date: Fri, 19 Dec 2014 14:46:38 +0300 Message-Id: <1418989601-14300-2-git-send-email-maxim.uvarov@linaro.org> X-Mailer: git-send-email 1.8.5.1.163.gd7aced9 In-Reply-To: <1418989601-14300-1-git-send-email-maxim.uvarov@linaro.org> References: <1418989601-14300-1-git-send-email-maxim.uvarov@linaro.org> X-Topics: patch Subject: [lng-odp] [PATCHv7 1/4] validation: pktio: initial pktio tests X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , MIME-Version: 1.0 Errors-To: lng-odp-bounces@lists.linaro.org Sender: lng-odp-bounces@lists.linaro.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: maxim.uvarov@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.173 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Stuart Haslam This is primarily sunny day basic functional testing, all tests are single threaded. On platforms other than linux-generic testing will be performed using the "loop" interface by default. For linux-generic, since we don't have a working "loop" device, a wrapper script is run that attempts to create a pair of virtual Ethernet interfaces for testing. If creating the interfaces fails the test is skipped and "make check" reports it as such. Signed-off-by: Stuart Haslam Reviewed-by: Bill Fischofer Signed-off-by: Maxim Uvarov --- test/validation/.gitignore | 1 + test/validation/Makefile.am | 7 +- test/validation/odp_pktio.c | 501 ++++++++++++++++++++++++++++++++++++++++++ test/validation/odp_pktio_run | 132 +++++++++++ 4 files changed, 639 insertions(+), 2 deletions(-) create mode 100644 test/validation/odp_pktio.c create mode 100755 test/validation/odp_pktio_run diff --git a/test/validation/.gitignore b/test/validation/.gitignore index 32834ae..c727223 100644 --- a/test/validation/.gitignore +++ b/test/validation/.gitignore @@ -5,3 +5,4 @@ odp_queue odp_crypto odp_schedule odp_shm +odp_pktio diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am index a12fdfa..db24ef4 100644 --- a/test/validation/Makefile.am +++ b/test/validation/Makefile.am @@ -3,14 +3,17 @@ include $(top_srcdir)/test/Makefile.inc AM_CFLAGS += -I$(srcdir)/common AM_LDFLAGS += -static +AM_TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform} + if ODP_CUNIT_ENABLED -TESTS = ${bin_PROGRAMS} +TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule odp_pktio_run check_PROGRAMS = ${bin_PROGRAMS} -bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule +bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule odp_pktio odp_crypto_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/crypto endif dist_odp_init_SOURCES = odp_init.c +dist_odp_pktio_SOURCES = odp_pktio.c common/odp_cunit_common.c dist_odp_queue_SOURCES = odp_queue.c common/odp_cunit_common.c dist_odp_crypto_SOURCES = crypto/odp_crypto_test_async_inp.c \ crypto/odp_crypto_test_sync_inp.c \ diff --git a/test/validation/odp_pktio.c b/test/validation/odp_pktio.c new file mode 100644 index 0000000..f7dc80b --- /dev/null +++ b/test/validation/odp_pktio.c @@ -0,0 +1,501 @@ +/* Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + +#include +#include +#include + +#include + +#define PKT_BUF_NUM 32 +#define PKT_BUF_SIZE 1856 +#define MAX_NUM_IFACES 2 +#define TEST_SEQ_INVALID ((uint32_t)~0) +#define TEST_SEQ_MAGIC 0x92749451 + +/** interface names used for testing */ +static const char *iface_name[MAX_NUM_IFACES]; + +/** number of interfaces being used (1=loopback, 2=pair) */ +static int num_ifaces; + +/** local container for pktio attributes */ +typedef struct { + const char *name; + odp_pktio_t id; + odp_queue_t outq; + odp_queue_t inq; +} pktio_info_t; + +/** structure of test packet UDP payload */ +typedef struct { + uint32be_t magic; + uint32be_t seq; +} pkt_test_data_t; + +/** default packet pool */ +odp_buffer_pool_t default_pkt_pool = ODP_BUFFER_POOL_INVALID; + +/** sequence number of IP packets */ +odp_atomic_u32_t ip_seq; + +static void pktio_pkt_set_macs(odp_packet_t pkt, + pktio_info_t *src, pktio_info_t *dst) +{ + uint32_t len; + odph_ethhdr_t *eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, &len); + int ret; + + ret = odp_pktio_mac_addr(src->id, ð->src, sizeof(eth->src)); + CU_ASSERT(ret == ODPH_ETHADDR_LEN); + + ret = odp_pktio_mac_addr(dst->id, ð->dst, sizeof(eth->dst)); + CU_ASSERT(ret == ODPH_ETHADDR_LEN); +} + +static int pktio_pkt_set_seq(odp_packet_t pkt) +{ + static uint32_t tstseq; + size_t l4_off; + pkt_test_data_t data; + + data.magic = TEST_SEQ_MAGIC; + data.seq = tstseq; + + l4_off = odp_packet_l4_offset(pkt); + if (!l4_off) { + CU_FAIL("packet L4 offset not set"); + return -1; + } + + odp_packet_copydata_in(pkt, l4_off+ODPH_UDPHDR_LEN, + sizeof(data), &data); + + tstseq++; + + return 0; +} + +static uint32_t pktio_pkt_seq(odp_packet_t pkt) +{ + size_t l4_off; + pkt_test_data_t data; + + l4_off = odp_packet_l4_offset(pkt); + if (l4_off) { + odp_packet_copydata_out(pkt, l4_off+ODPH_UDPHDR_LEN, + sizeof(data), &data); + + if (data.magic == TEST_SEQ_MAGIC) + return data.seq; + } + + return TEST_SEQ_INVALID; +} + +static odp_packet_t pktio_create_packet(void) +{ + odp_packet_t pkt; + odph_ethhdr_t *eth; + odph_ipv4hdr_t *ip; + odph_udphdr_t *udp; + char *buf; + uint16_t seq; + size_t payload_len = sizeof(pkt_test_data_t); + uint8_t mac[ODPH_ETHADDR_LEN] = {0}; + + pkt = odp_packet_alloc(default_pkt_pool, payload_len + ODPH_UDPHDR_LEN + + ODPH_IPV4HDR_LEN + ODPH_ETHHDR_LEN); + if (pkt == ODP_PACKET_INVALID) { + CU_FAIL("failed to allocate packet buffer"); + return ODP_PACKET_INVALID; + } + buf = odp_packet_data(pkt); + + /* Ethernet */ + odp_packet_l2_offset_set(pkt, 0); + eth = (odph_ethhdr_t *)buf; + memcpy(eth->src.addr, mac, ODPH_ETHADDR_LEN); + memcpy(eth->dst.addr, mac, ODPH_ETHADDR_LEN); + eth->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); + + /* IP */ + odp_packet_l3_offset_set(pkt, ODPH_ETHHDR_LEN); + ip = (odph_ipv4hdr_t *)(buf + ODPH_ETHHDR_LEN); + ip->dst_addr = odp_cpu_to_be_32(0); + ip->src_addr = odp_cpu_to_be_32(0); + ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN; + ip->tot_len = odp_cpu_to_be_16(payload_len + ODPH_UDPHDR_LEN + + ODPH_IPV4HDR_LEN); + ip->ttl = 128; + ip->proto = ODPH_IPPROTO_UDP; + seq = odp_atomic_fetch_inc_u32(&ip_seq); + ip->id = odp_cpu_to_be_16(seq); + ip->chksum = 0; + odph_ipv4_csum_update(pkt); + + /* UDP */ + odp_packet_l4_offset_set(pkt, ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); + udp = (odph_udphdr_t *)(buf + ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); + udp->src_port = odp_cpu_to_be_16(0); + udp->dst_port = odp_cpu_to_be_16(0); + udp->length = odp_cpu_to_be_16(payload_len + ODPH_UDPHDR_LEN); + udp->chksum = 0; + + if (pktio_pkt_set_seq(pkt) != 0) { + odp_packet_free(pkt); + return ODP_PACKET_INVALID; + } + + return pkt; +} + +static int pktio_fixup_checksums(odp_packet_t pkt) +{ + odph_ipv4hdr_t *ip; + odph_udphdr_t *udp; + uint32_t len; + + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, &len); + + if (ip->proto != ODPH_IPPROTO_UDP) { + CU_FAIL("unexpected L4 protocol"); + return -1; + } + + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, &len); + + ip->chksum = 0; + odph_ipv4_csum_update(pkt); + udp->chksum = 0; + udp->chksum = odph_ipv4_udp_chksum(pkt); + + return 0; +} + +static int default_pool_create(void) +{ + odp_buffer_pool_param_t params; + + if (default_pkt_pool != ODP_BUFFER_POOL_INVALID) + return -1; + + params.buf_size = PKT_BUF_SIZE; + params.buf_align = 0; + params.num_bufs = PKT_BUF_NUM; + params.buf_type = ODP_BUFFER_TYPE_PACKET; + + default_pkt_pool = odp_buffer_pool_create("pkt_pool_default", + ODP_SHM_NULL, ¶ms); + if (default_pkt_pool == ODP_BUFFER_POOL_INVALID) + return -1; + + return 0; +} + +static odp_pktio_t create_pktio(const char *iface) +{ + odp_buffer_pool_t pool; + odp_pktio_t pktio; + char pool_name[ODP_BUFFER_POOL_NAME_LEN]; + odp_buffer_pool_param_t params; + + params.buf_size = PKT_BUF_SIZE; + params.buf_align = 0; + params.num_bufs = PKT_BUF_NUM; + params.buf_type = ODP_BUFFER_TYPE_PACKET; + + snprintf(pool_name, sizeof(pool_name), "pkt_pool_%s", iface); + pool = odp_buffer_pool_lookup(pool_name); + if (pool == ODP_BUFFER_POOL_INVALID) + pool = odp_buffer_pool_create(pool_name, ODP_SHM_NULL, ¶ms); + CU_ASSERT(pool != ODP_BUFFER_POOL_INVALID); + + pktio = odp_pktio_open(iface, pool); + CU_ASSERT(pktio != ODP_PKTIO_INVALID); + + return pktio; +} + +static int create_inq(odp_pktio_t pktio) +{ + odp_queue_param_t qparam; + odp_queue_t inq_def; + char inq_name[ODP_QUEUE_NAME_LEN]; + + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; + qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; + qparam.sched.group = ODP_SCHED_GROUP_DEFAULT; + + snprintf(inq_name, sizeof(inq_name), "inq-pktio-%d", pktio); + inq_def = odp_queue_lookup(inq_name); + if (inq_def == ODP_QUEUE_INVALID) + inq_def = odp_queue_create(inq_name, + ODP_QUEUE_TYPE_PKTIN, &qparam); + CU_ASSERT(inq_def != ODP_QUEUE_INVALID); + + return odp_pktio_inq_setdef(pktio, inq_def); +} + +static odp_buffer_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns) +{ + uint64_t start, now, diff; + odp_buffer_t buf; + + start = odp_time_cycles(); + + do { + buf = odp_queue_deq(queue); + if (buf != ODP_BUFFER_INVALID) + return buf; + now = odp_time_cycles(); + diff = odp_time_diff_cycles(start, now); + } while (odp_time_cycles_to_ns(diff) < ns); + + return ODP_BUFFER_INVALID; +} + +static odp_packet_t wait_for_packet(odp_queue_t queue, + uint32_t seq, uint64_t ns) +{ + uint64_t start, now, diff; + odp_buffer_t buf; + odp_packet_t pkt = ODP_PACKET_INVALID; + + start = odp_time_cycles(); + + do { + if (queue != ODP_QUEUE_INVALID) + buf = queue_deq_wait_time(queue, ns); + else + buf = odp_schedule(NULL, ns); + + if (buf != ODP_BUFFER_INVALID && + odp_buffer_type(buf) == ODP_BUFFER_TYPE_PACKET) { + pkt = odp_packet_from_buffer(buf); + if (pktio_pkt_seq(pkt) == seq) + return pkt; + } + + now = odp_time_cycles(); + diff = odp_time_diff_cycles(start, now); + } while (odp_time_cycles_to_ns(diff) < ns); + + CU_FAIL("failed to receive transmitted packet"); + + return ODP_PACKET_INVALID; +} + +static void pktio_txrx_multi(pktio_info_t *pktio_a, pktio_info_t *pktio_b, + int num_pkts) +{ + odp_packet_t tx_pkt[num_pkts]; + odp_buffer_t tx_buf[num_pkts]; + odp_packet_t rx_pkt; + uint32_t tx_seq[num_pkts]; + int i, ret; + + /* generate test packets to send */ + for (i = 0; i < num_pkts; ++i) { + tx_pkt[i] = pktio_create_packet(); + if (tx_pkt[i] == ODP_PACKET_INVALID) + break; + + tx_seq[i] = pktio_pkt_seq(tx_pkt[i]); + if (tx_seq[i] == TEST_SEQ_INVALID) + break; + + pktio_pkt_set_macs(tx_pkt[i], pktio_a, pktio_b); + if (pktio_fixup_checksums(tx_pkt[i]) != 0) + break; + + tx_buf[i] = odp_packet_to_buffer(tx_pkt[i]); + } + + if (i != num_pkts) { + CU_FAIL("failed to generate test packets"); + return; + } + + /* send packet(s) out */ + if (num_pkts == 1) + ret = odp_queue_enq(pktio_a->outq, tx_buf[0]); + else + ret = odp_queue_enq_multi(pktio_a->outq, tx_buf, num_pkts); + + if (ret != 0) { + CU_FAIL("failed to enqueue test packets"); + return; + } + + /* and wait for them to arrive back */ + for (i = 0; i < num_pkts; ++i) { + rx_pkt = wait_for_packet(pktio_b->inq, tx_seq[i], ODP_TIME_SEC); + + if (rx_pkt == ODP_PACKET_INVALID) + break; + CU_ASSERT(odp_packet_input(rx_pkt) == pktio_b->id); + CU_ASSERT(odp_packet_error(rx_pkt) == 0); + odp_packet_free(rx_pkt); + } + + CU_ASSERT(i == num_pkts); +} + +static void pktio_test_txrx(odp_queue_type_t q_type, int num_pkts) +{ + int ret, i, if_b; + pktio_info_t pktios[MAX_NUM_IFACES]; + pktio_info_t *io; + + /* create pktios and associate input/output queues */ + for (i = 0; i < num_ifaces; ++i) { + io = &pktios[i]; + + io->name = iface_name[i]; + io->id = create_pktio(iface_name[i]); + if (io->id == ODP_PKTIO_INVALID) { + CU_FAIL("failed to open iface"); + return; + } + create_inq(io->id); + io->outq = odp_pktio_outq_getdef(io->id); + if (q_type == ODP_QUEUE_TYPE_POLL) + io->inq = odp_pktio_inq_getdef(io->id); + else + io->inq = ODP_QUEUE_INVALID; + } + + /* if we have two interfaces then send through one and receive on + * another but if there's only one assume it's a loopback */ + if_b = (num_ifaces == 1) ? 0 : 1; + pktio_txrx_multi(&pktios[0], &pktios[if_b], num_pkts); + + for (i = 0; i < num_ifaces; ++i) { + ret = odp_pktio_close(pktios[i].id); + CU_ASSERT(ret == 0); + } +} + +static void test_odp_pktio_poll_queue(void) +{ + pktio_test_txrx(ODP_QUEUE_TYPE_POLL, 1); +} + +static void test_odp_pktio_poll_multi(void) +{ + pktio_test_txrx(ODP_QUEUE_TYPE_POLL, 4); +} + +static void test_odp_pktio_sched_queue(void) +{ + pktio_test_txrx(ODP_QUEUE_TYPE_SCHED, 1); +} + +static void test_odp_pktio_sched_multi(void) +{ + pktio_test_txrx(ODP_QUEUE_TYPE_SCHED, 4); +} + +static void test_odp_pktio_open(void) +{ + odp_pktio_t pktio; + int i; + + /* test the sequence open->close->open->close() */ + for (i = 0; i < 2; ++i) { + pktio = create_pktio(iface_name[0]); + CU_ASSERT(pktio != ODP_PKTIO_INVALID); + CU_ASSERT(odp_pktio_close(pktio) == 0); + } + + pktio = odp_pktio_open("nothere", default_pkt_pool); + CU_ASSERT(pktio == ODP_PKTIO_INVALID); +} + +static void test_odp_pktio_inq(void) +{ + odp_pktio_t pktio; + + pktio = create_pktio(iface_name[0]); + CU_ASSERT(pktio != ODP_PKTIO_INVALID); + + CU_ASSERT(create_inq(pktio) == 0); + + CU_ASSERT(odp_pktio_close(pktio) == 0); +} + +static void test_odp_pktio_outq(void) +{ + odp_queue_t testq; + + testq = odp_pktio_outq_getdef(ODP_PKTIO_INVALID); + CU_ASSERT(testq == ODP_QUEUE_INVALID); +} + +static void test_odp_pktio_close(void) +{ + int res; + + res = odp_pktio_close(ODP_PKTIO_INVALID); + CU_ASSERT_EQUAL(res, -1); +} + +static int init_pktio_suite(void) +{ + iface_name[0] = getenv("ODP_PKTIO_IF0"); + iface_name[1] = getenv("ODP_PKTIO_IF1"); + num_ifaces = 1; + + if (!iface_name[0]) { + printf("No interfaces specified, using default \"loop\".\n"); + iface_name[0] = "loop"; + } else if (!iface_name[1]) { + printf("Using loopback interface: %s\n", iface_name[0]); + } else { + num_ifaces = 2; + printf("Using paired interfaces: %s %s\n", + iface_name[0], iface_name[1]); + } + + if (default_pool_create() != 0) { + fprintf(stderr, "error: failed to create default pool\n"); + return -1; + } + + return 0; +} + +static int term_pktio_suite(void) +{ + if (odp_buffer_pool_destroy(default_pkt_pool) != 0) { + fprintf(stderr, "error: failed to destroy default pool\n"); + return -1; + } + + return 0; +} + +CU_TestInfo pktio_tests[] = { + {"pktio open", test_odp_pktio_open}, + {"pktio close", test_odp_pktio_close}, + {"pktio inq", test_odp_pktio_inq}, + {"pktio outq", test_odp_pktio_outq}, + {"pktio poll queues", test_odp_pktio_poll_queue}, + {"pktio poll multi", test_odp_pktio_poll_multi}, + {"pktio sched queues", test_odp_pktio_sched_queue}, + {"pktio sched multi", test_odp_pktio_sched_multi}, + CU_TEST_INFO_NULL +}; + +CU_SuiteInfo odp_testsuites[] = { + {"odp_pktio", + init_pktio_suite, term_pktio_suite, NULL, NULL, pktio_tests}, + CU_SUITE_INFO_NULL +}; diff --git a/test/validation/odp_pktio_run b/test/validation/odp_pktio_run new file mode 100755 index 0000000..d4d6b2c --- /dev/null +++ b/test/validation/odp_pktio_run @@ -0,0 +1,132 @@ +#!/bin/sh +# +# Test script wrapper for running ODP pktio tests on linux-generic. +# +# For platforms other than linux-generic this script does nothing other +# than running the odp_pktio binary, odp_pktio will then attempt to +# open and use the special device named "loop" for testing. +# +# For linux-generic the default behaviour is to create a pair of +# virtual Ethernet interfaces and provide the names of these via +# environment variables to odp_pktio, 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 test will be skipped. +# +# The evironment variable ODP_PLATFORM is used to determine the +# platform under test, when this script is invoked via 'make check' +# this variable is set automatically. +# +# It's also possible to split up the steps, which makes it easier when +# debugging, for example; +# +# export ODP_PLATFORM=linux-generic +# odp_pktio_run setup +# wireshark -i pktio-p0 -k & +# odp_pktio_run +# (repeat running test multiple times..) +# odp_pktio_run cleanup +# +TEST_DIR=$(dirname $0) +IF0=pktio-p0 +IF1=pktio-p1 + +# exit codes expected by automake for skipped tests +TEST_SKIPPED=77 + +setup_env1() +{ + ip link show $IF0 2> /dev/null + if [ $? = 0 ]; then + ip link show $IF1 2> /dev/null + if [ $? = 0 ]; then + echo "pktio: interfaces $IF0 and $IF1 already exist" + return + fi + fi + + echo "pktio: setting up test interfaces $IF0 and $IF1" + + if [ "$1" = "clean" ]; then + trap cleanup_env1 EXIT + fi + + ip link add $IF0 type veth peer name $IF1 + if [ $? != 0 ]; then + echo "pktio: error: unable to create veth pair" + exit $TEST_SKIPPED + fi + ip link set $IF0 up + ip link set $IF1 up + + # network needs a little time to come up + sleep 1 +} + +cleanup_env1() +{ + echo "pktio: removing test interfaces $IF0 and $IF1" + ip link del $IF0 2> /dev/null + ip link del $IF1 2> /dev/null +} + +run_test() +{ + local ret=0 + + # the linux-generic implementation uses environment variables to + # control which socket method is used, so try each combination to + # ensure decent coverage. + for distype in MMAP MMSG BASIC; do + unset ODP_PKTIO_DISABLE_SOCKET_${distype} + done + + for distype in SKIP MMAP MMSG; do + if [ "$disabletype" != "SKIP" ]; then + export ODP_PKTIO_DISABLE_SOCKET_${distype}=y + fi + $TEST_DIR/odp_pktio + if [ $? != 0 ]; then + ret=1 + fi + done + + if [ $ret != 0 ]; then + echo "!!! FAILED !!!" + fi + + exit $ret +} + +run() +{ + if [ "$ODP_PLATFORM" != "linux-generic" ]; then + echo "pktio: using 'loop' device" + $TEST_DIR/odp_pktio + exit $? + elif [ "$ODP_PKTIO_IF0" = "" ]; then + # no interfaces specified on linux-generic, use defaults + setup_env1 clean + export ODP_PKTIO_IF0=$IF0 + export ODP_PKTIO_IF1=$IF1 + fi + + run_test +} + +if [ "$ODP_PLATFORM" = "" ]; then + echo "pktio: error: ODP_PLATFORM must be defined" + # not skipped as this should never happen via "make check" + exit 1 +fi + +if [ "$(id -u)" != "0" ]; then + echo "pktio: error: must be run as root" + exit $TEST_SKIPPED +fi + +case "$1" in + setup) setup_env1 ;; + cleanup) cleanup_env1 ;; + *) run ;; +esac