app/test: packet framework unit tests
Unit tests for Packet Framework libraries. Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com> Tested-by: Waterman Cao <waterman.cao@intel.com> Acked-by: Pablo de Lara Guarch <pablo.de.lara.guarch@intel.com> Acked by: Ivan Boule <ivan.boule@6wind.com>
This commit is contained in:
parent
77a334675f
commit
5205954791
@ -52,6 +52,12 @@ SRCS-$(CONFIG_RTE_APP_TEST) += test_spinlock.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_memory.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_memzone.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_ring.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_table.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_table_pipeline.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_table_tables.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_table_ports.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_table_combined.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_table_acl.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_ring_perf.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_rwlock.c
|
||||
SRCS-$(CONFIG_RTE_APP_TEST) += test_timer.c
|
||||
|
@ -151,6 +151,8 @@ static void cmd_autotest_parsed(void *parsed_result,
|
||||
ret = test_cycles();
|
||||
if (!strcmp(res->autotest, "ring_autotest"))
|
||||
ret = test_ring();
|
||||
if (!strcmp(res->autotest, "table_autotest"))
|
||||
ret = test_table();
|
||||
if (!strcmp(res->autotest, "ring_perf_autotest"))
|
||||
ret = test_ring_perf();
|
||||
if (!strcmp(res->autotest, "timer_autotest"))
|
||||
@ -230,7 +232,7 @@ cmdline_parse_token_string_t cmd_autotest_autotest =
|
||||
"red_autotest#meter_autotest#sched_autotest#"
|
||||
"memcpy_perf_autotest#kni_autotest#"
|
||||
"pm_autotest#ivshmem_autotest#"
|
||||
"devargs_autotest#"
|
||||
"devargs_autotest#table_autotest#"
|
||||
#ifdef RTE_LIBRTE_ACL
|
||||
"acl_autotest#"
|
||||
#endif
|
||||
|
@ -57,6 +57,7 @@ int test_cycles(void);
|
||||
int test_logs(void);
|
||||
int test_memzone(void);
|
||||
int test_ring(void);
|
||||
int test_table(void);
|
||||
int test_ring_perf(void);
|
||||
int test_mempool(void);
|
||||
int test_mempool_perf(void);
|
||||
|
220
app/test/test_table.c
Normal file
220
app/test/test_table.c
Normal file
@ -0,0 +1,220 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef RTE_LIBRTE_TABLE
|
||||
|
||||
#include "test.h"
|
||||
|
||||
int
|
||||
test_table(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_hexdump.h>
|
||||
#include <rte_string_fns.h>
|
||||
#include <string.h>
|
||||
#include "test.h"
|
||||
#include "test_table.h"
|
||||
#include "test_table_pipeline.h"
|
||||
#include "test_table_ports.h"
|
||||
#include "test_table_tables.h"
|
||||
#include "test_table_combined.h"
|
||||
#include "test_table_acl.h"
|
||||
|
||||
/* Global variables */
|
||||
struct rte_pipeline *p;
|
||||
struct rte_ring *rings_rx[N_PORTS];
|
||||
struct rte_ring *rings_tx[N_PORTS];
|
||||
struct rte_mempool *pool = NULL;
|
||||
|
||||
uint32_t port_in_id[N_PORTS];
|
||||
uint32_t port_out_id[N_PORTS];
|
||||
uint32_t port_out_id_type[3];
|
||||
uint32_t table_id[N_PORTS*2];
|
||||
uint64_t override_hit_mask = 0xFFFFFFFF;
|
||||
uint64_t override_miss_mask = 0xFFFFFFFF;
|
||||
uint64_t non_reserved_actions_hit = 0;
|
||||
uint64_t non_reserved_actions_miss = 0;
|
||||
uint8_t connect_miss_action_to_port_out = 0;
|
||||
uint8_t connect_miss_action_to_table = 0;
|
||||
uint32_t table_entry_default_action = RTE_PIPELINE_ACTION_DROP;
|
||||
uint32_t table_entry_hit_action = RTE_PIPELINE_ACTION_PORT;
|
||||
uint32_t table_entry_miss_action = RTE_PIPELINE_ACTION_DROP;
|
||||
rte_pipeline_port_in_action_handler port_in_action = NULL;
|
||||
rte_pipeline_port_out_action_handler port_out_action = NULL;
|
||||
rte_pipeline_table_action_handler_hit action_handler_hit = NULL;
|
||||
rte_pipeline_table_action_handler_miss action_handler_miss = NULL;
|
||||
|
||||
/* Function prototypes */
|
||||
static void app_init_rings(void);
|
||||
static void app_init_mbuf_pools(void);
|
||||
|
||||
uint64_t pipeline_test_hash(void *key,
|
||||
__attribute__((unused)) uint32_t key_size,
|
||||
__attribute__((unused)) uint64_t seed)
|
||||
{
|
||||
uint32_t *k32 = (uint32_t *) key;
|
||||
uint32_t ip_dst = rte_be_to_cpu_32(k32[0]);
|
||||
uint64_t signature = ip_dst;
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
static void
|
||||
app_init_mbuf_pools(void)
|
||||
{
|
||||
/* Init the buffer pool */
|
||||
printf("Getting/Creating the mempool ...\n");
|
||||
pool = rte_mempool_lookup("mempool");
|
||||
if (!pool) {
|
||||
pool = rte_mempool_create(
|
||||
"mempool",
|
||||
POOL_SIZE,
|
||||
POOL_BUFFER_SIZE,
|
||||
POOL_CACHE_SIZE,
|
||||
sizeof(struct rte_pktmbuf_pool_private),
|
||||
rte_pktmbuf_pool_init, NULL,
|
||||
rte_pktmbuf_init, NULL,
|
||||
0,
|
||||
0);
|
||||
if (pool == NULL)
|
||||
rte_panic("Cannot create mbuf pool\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
app_init_rings(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
char name[32];
|
||||
|
||||
rte_snprintf(name, sizeof(name), "app_ring_rx_%u", i);
|
||||
rings_rx[i] = rte_ring_lookup(name);
|
||||
if (rings_rx[i] == NULL) {
|
||||
rings_rx[i] = rte_ring_create(
|
||||
name,
|
||||
RING_RX_SIZE,
|
||||
0,
|
||||
RING_F_SP_ENQ | RING_F_SC_DEQ);
|
||||
}
|
||||
if (rings_rx[i] == NULL)
|
||||
rte_panic("Cannot create RX ring %u\n", i);
|
||||
}
|
||||
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
char name[32];
|
||||
|
||||
rte_snprintf(name, sizeof(name), "app_ring_tx_%u", i);
|
||||
rings_tx[i] = rte_ring_lookup(name);
|
||||
if (rings_tx[i] == NULL) {
|
||||
rings_tx[i] = rte_ring_create(
|
||||
name,
|
||||
RING_TX_SIZE,
|
||||
0,
|
||||
RING_F_SP_ENQ | RING_F_SC_DEQ);
|
||||
}
|
||||
if (rings_tx[i] == NULL)
|
||||
rte_panic("Cannot create TX ring %u\n", i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
test_table(void)
|
||||
{
|
||||
int status, failures;
|
||||
unsigned i;
|
||||
|
||||
failures = 0;
|
||||
|
||||
app_init_rings();
|
||||
app_init_mbuf_pools();
|
||||
|
||||
printf("\n\n\n\n************Pipeline tests************\n");
|
||||
|
||||
if (test_table_pipeline() < 0)
|
||||
return -1;
|
||||
|
||||
printf("\n\n\n\n************Port tests************\n");
|
||||
for (i = 0; i < n_port_tests; i++) {
|
||||
status = port_tests[i]();
|
||||
if (status < 0) {
|
||||
printf("\nPort test number %d failed (%d).\n", i,
|
||||
status);
|
||||
failures++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n\n\n\n************Table tests************\n");
|
||||
for (i = 0; i < n_table_tests; i++) {
|
||||
status = table_tests[i]();
|
||||
if (status < 0) {
|
||||
printf("\nTable test number %d failed (%d).\n", i,
|
||||
status);
|
||||
failures++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n\n\n\n************Table tests************\n");
|
||||
for (i = 0; i < n_table_tests_combined; i++) {
|
||||
status = table_tests_combined[i]();
|
||||
if (status < 0) {
|
||||
printf("\nCombined table test number %d failed with "
|
||||
"reason number %d.\n", i, status);
|
||||
failures++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (failures)
|
||||
return -1;
|
||||
|
||||
#ifdef RTE_LIBRTE_ACL
|
||||
printf("\n\n\n\n************ACL tests************\n");
|
||||
if (test_table_ACL() < 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
204
app/test/test_table.h
Normal file
204
app/test/test_table.h
Normal file
@ -0,0 +1,204 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <rte_table_stub.h>
|
||||
#include <rte_table_lpm.h>
|
||||
#include <rte_table_lpm_ipv6.h>
|
||||
#include <rte_table_hash.h>
|
||||
#include <rte_table_array.h>
|
||||
#include <rte_pipeline.h>
|
||||
|
||||
#ifdef RTE_LIBRTE_ACL
|
||||
#include <rte_table_acl.h>
|
||||
#endif
|
||||
|
||||
#include <rte_port_ring.h>
|
||||
#include <rte_port_ethdev.h>
|
||||
#include <rte_port_source_sink.h>
|
||||
|
||||
#ifndef TEST_TABLE_H_
|
||||
#define TEST_TABLE_H_
|
||||
|
||||
#define RING_SIZE 4096
|
||||
#define MAX_BULK 32
|
||||
#define N 65536
|
||||
#define TIME_S 5
|
||||
#define TEST_RING_FULL_EMTPY_ITER 8
|
||||
#define N_PORTS 2
|
||||
#define N_PKTS 2
|
||||
#define N_PKTS_EXT 6
|
||||
#define RING_RX rings_rx[0]
|
||||
#define RING_RX_2 rings_rx[1]
|
||||
#define RING_TX rings_tx[0]
|
||||
#define RING_TX_2 rings_tx[1]
|
||||
#define PORT_RX_RING_SIZE 128
|
||||
#define PORT_TX_RING_SIZE 512
|
||||
#define RING_RX_SIZE 128
|
||||
#define RING_TX_SIZE 128
|
||||
#define POOL_BUFFER_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
|
||||
#define POOL_SIZE (32 * 1024)
|
||||
#define POOL_CACHE_SIZE 256
|
||||
#define BURST_SIZE 8
|
||||
#define WORKER_TYPE 1
|
||||
#define MAX_DUMMY_PORTS 2
|
||||
#define MP_NAME "dummy_port_mempool"
|
||||
#define MBUF_COUNT (8000 * MAX_DUMMY_PORTS)
|
||||
#define MBUF_SIZE (2048 + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM)
|
||||
#define MP_CACHE_SZ 256
|
||||
#define MP_SOCKET 0
|
||||
#define MP_FLAGS 0
|
||||
|
||||
/* Macros */
|
||||
#define RING_ENQUEUE(ring, value) do { \
|
||||
struct rte_mbuf *m; \
|
||||
uint32_t *k32, *signature; \
|
||||
uint8_t *key; \
|
||||
\
|
||||
m = rte_pktmbuf_alloc(pool); \
|
||||
if (m == NULL) \
|
||||
return -1; \
|
||||
signature = RTE_MBUF_METADATA_UINT32_PTR(m, 0); \
|
||||
key = RTE_MBUF_METADATA_UINT8_PTR(m, 32); \
|
||||
k32 = (uint32_t *) key; \
|
||||
k32[0] = (value); \
|
||||
*signature = pipeline_test_hash(key, 0, 0); \
|
||||
rte_ring_enqueue((ring), m); \
|
||||
} while (0)
|
||||
|
||||
#define RUN_PIPELINE(pipeline) do { \
|
||||
rte_pipeline_run((pipeline)); \
|
||||
rte_pipeline_flush((pipeline)); \
|
||||
} while (0)
|
||||
|
||||
#define VERIFY(var, value) do { \
|
||||
if ((var) != -(value)) \
|
||||
return var; \
|
||||
} while (0)
|
||||
|
||||
#define VERIFY_TRAFFIC(ring, sent, expected) do { \
|
||||
unsigned i, n = 0; \
|
||||
void *mbuf = NULL; \
|
||||
\
|
||||
for (i = 0; i < (sent); i++) { \
|
||||
if (!rte_ring_dequeue((ring), &mbuf)) { \
|
||||
if (mbuf == NULL) \
|
||||
continue; \
|
||||
n++; \
|
||||
rte_pktmbuf_free((struct rte_mbuf *)mbuf); \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
} \
|
||||
printf("Expected %d, got %d\n", expected, n); \
|
||||
if (n != (expected)) { \
|
||||
return -21; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Function definitions */
|
||||
int test_table(void);
|
||||
uint64_t pipeline_test_hash(
|
||||
void *key,
|
||||
__attribute__((unused)) uint32_t key_size,
|
||||
__attribute__((unused)) uint64_t seed);
|
||||
|
||||
/* Extern variables */
|
||||
extern struct rte_pipeline *p;
|
||||
extern struct rte_ring *rings_rx[N_PORTS];
|
||||
extern struct rte_ring *rings_tx[N_PORTS];
|
||||
extern struct rte_mempool *pool;
|
||||
extern uint32_t port_in_id[N_PORTS];
|
||||
extern uint32_t port_out_id[N_PORTS];
|
||||
extern uint32_t port_out_id_type[3];
|
||||
extern uint32_t table_id[N_PORTS*2];
|
||||
extern uint64_t override_hit_mask;
|
||||
extern uint64_t override_miss_mask;
|
||||
extern uint64_t non_reserved_actions_hit;
|
||||
extern uint64_t non_reserved_actions_miss;
|
||||
extern uint8_t connect_miss_action_to_port_out;
|
||||
extern uint8_t connect_miss_action_to_table;
|
||||
extern uint32_t table_entry_default_action;
|
||||
extern uint32_t table_entry_hit_action;
|
||||
extern uint32_t table_entry_miss_action;
|
||||
extern rte_pipeline_port_in_action_handler port_in_action;
|
||||
extern rte_pipeline_port_out_action_handler port_out_action;
|
||||
extern rte_pipeline_table_action_handler_hit action_handler_hit;
|
||||
extern rte_pipeline_table_action_handler_miss action_handler_miss;
|
||||
|
||||
/* Global data types */
|
||||
struct manage_ops {
|
||||
uint32_t op_id;
|
||||
void *op_data;
|
||||
int expected_result;
|
||||
};
|
||||
|
||||
/* Internal pipeline structures */
|
||||
struct rte_port_in {
|
||||
struct rte_port_in_ops ops;
|
||||
uint32_t burst_size;
|
||||
uint32_t table_id;
|
||||
void *h_port;
|
||||
};
|
||||
|
||||
struct rte_port_out {
|
||||
struct rte_port_out_ops ops;
|
||||
void *h_port;
|
||||
};
|
||||
|
||||
struct rte_table {
|
||||
struct rte_table_ops ops;
|
||||
rte_pipeline_table_action_handler_hit f_action;
|
||||
uint32_t table_next_id;
|
||||
uint32_t table_next_id_valid;
|
||||
uint8_t actions_lookup_miss[CACHE_LINE_SIZE];
|
||||
uint32_t action_data_size;
|
||||
void *h_table;
|
||||
};
|
||||
|
||||
#define RTE_PIPELINE_MAX_NAME_SZ 124
|
||||
|
||||
struct rte_pipeline {
|
||||
char name[RTE_PIPELINE_MAX_NAME_SZ];
|
||||
uint32_t socket_id;
|
||||
struct rte_port_in ports_in[16];
|
||||
struct rte_port_out ports_out[16];
|
||||
struct rte_table tables[64];
|
||||
uint32_t num_ports_in;
|
||||
uint32_t num_ports_out;
|
||||
uint32_t num_tables;
|
||||
struct rte_mbuf *pkts[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
struct rte_table_entry *actions[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
uint64_t mask_action[64];
|
||||
uint32_t mask_actions;
|
||||
};
|
||||
#endif
|
593
app/test/test_table_acl.c
Normal file
593
app/test/test_table_acl.c
Normal file
@ -0,0 +1,593 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef RTE_LIBRTE_ACL
|
||||
|
||||
#include <rte_hexdump.h>
|
||||
#include "test_table.h"
|
||||
#include "test_table_acl.h"
|
||||
|
||||
#define IPv4(a, b, c, d) ((uint32_t)(((a) & 0xff) << 24) | \
|
||||
(((b) & 0xff) << 16) | \
|
||||
(((c) & 0xff) << 8) | \
|
||||
((d) & 0xff))
|
||||
|
||||
static const char cb_port_delim[] = ":";
|
||||
|
||||
/*
|
||||
* Rule and trace formats definitions.
|
||||
**/
|
||||
|
||||
struct ipv4_5tuple {
|
||||
uint8_t proto;
|
||||
uint32_t ip_src;
|
||||
uint32_t ip_dst;
|
||||
uint16_t port_src;
|
||||
uint16_t port_dst;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROTO_FIELD_IPV4,
|
||||
SRC_FIELD_IPV4,
|
||||
DST_FIELD_IPV4,
|
||||
SRCP_FIELD_IPV4,
|
||||
DSTP_FIELD_IPV4,
|
||||
NUM_FIELDS_IPV4
|
||||
};
|
||||
|
||||
struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
|
||||
{
|
||||
.type = RTE_ACL_FIELD_TYPE_BITMASK,
|
||||
.size = sizeof(uint8_t),
|
||||
.field_index = PROTO_FIELD_IPV4,
|
||||
.input_index = PROTO_FIELD_IPV4,
|
||||
.offset = offsetof(struct ipv4_5tuple, proto),
|
||||
},
|
||||
{
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = SRC_FIELD_IPV4,
|
||||
.input_index = SRC_FIELD_IPV4,
|
||||
.offset = offsetof(struct ipv4_5tuple, ip_src),
|
||||
},
|
||||
{
|
||||
.type = RTE_ACL_FIELD_TYPE_MASK,
|
||||
.size = sizeof(uint32_t),
|
||||
.field_index = DST_FIELD_IPV4,
|
||||
.input_index = DST_FIELD_IPV4,
|
||||
.offset = offsetof(struct ipv4_5tuple, ip_dst),
|
||||
},
|
||||
{
|
||||
.type = RTE_ACL_FIELD_TYPE_RANGE,
|
||||
.size = sizeof(uint16_t),
|
||||
.field_index = SRCP_FIELD_IPV4,
|
||||
.input_index = SRCP_FIELD_IPV4,
|
||||
.offset = offsetof(struct ipv4_5tuple, port_src),
|
||||
},
|
||||
{
|
||||
.type = RTE_ACL_FIELD_TYPE_RANGE,
|
||||
.size = sizeof(uint16_t),
|
||||
.field_index = DSTP_FIELD_IPV4,
|
||||
.input_index = SRCP_FIELD_IPV4,
|
||||
.offset = offsetof(struct ipv4_5tuple, port_dst),
|
||||
},
|
||||
};
|
||||
|
||||
struct rte_table_acl_rule_add_params table_acl_IPv4_rule;
|
||||
|
||||
typedef int (*parse_5tuple)(char *text,
|
||||
struct rte_table_acl_rule_add_params *rule);
|
||||
|
||||
/*
|
||||
* The order of the fields in the rule string after the initial '@'
|
||||
*/
|
||||
enum {
|
||||
CB_FLD_SRC_ADDR,
|
||||
CB_FLD_DST_ADDR,
|
||||
CB_FLD_SRC_PORT_RANGE,
|
||||
CB_FLD_DST_PORT_RANGE,
|
||||
CB_FLD_PROTO,
|
||||
CB_FLD_NUM,
|
||||
};
|
||||
|
||||
|
||||
#define GET_CB_FIELD(in, fd, base, lim, dlm) \
|
||||
do { \
|
||||
unsigned long val; \
|
||||
char *end; \
|
||||
\
|
||||
errno = 0; \
|
||||
val = strtoul((in), &end, (base)); \
|
||||
if (errno != 0 || end[0] != (dlm) || val > (lim)) \
|
||||
return -EINVAL; \
|
||||
(fd) = (typeof(fd)) val; \
|
||||
(in) = end + 1; \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
|
||||
static int
|
||||
parse_ipv4_net(const char *in, uint32_t *addr, uint32_t *mask_len)
|
||||
{
|
||||
uint8_t a, b, c, d, m;
|
||||
|
||||
GET_CB_FIELD(in, a, 0, UINT8_MAX, '.');
|
||||
GET_CB_FIELD(in, b, 0, UINT8_MAX, '.');
|
||||
GET_CB_FIELD(in, c, 0, UINT8_MAX, '.');
|
||||
GET_CB_FIELD(in, d, 0, UINT8_MAX, '/');
|
||||
GET_CB_FIELD(in, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
|
||||
|
||||
addr[0] = IPv4(a, b, c, d);
|
||||
mask_len[0] = m;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_port_range(const char *in, uint16_t *port_low, uint16_t *port_high)
|
||||
{
|
||||
uint16_t a, b;
|
||||
|
||||
GET_CB_FIELD(in, a, 0, UINT16_MAX, ':');
|
||||
GET_CB_FIELD(in, b, 0, UINT16_MAX, 0);
|
||||
|
||||
port_low[0] = a;
|
||||
port_high[0] = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_cb_ipv4_rule(char *str, struct rte_table_acl_rule_add_params *v)
|
||||
{
|
||||
int i, rc;
|
||||
char *s, *sp, *in[CB_FLD_NUM];
|
||||
static const char *dlm = " \t\n";
|
||||
|
||||
/*
|
||||
** Skip leading '@'
|
||||
*/
|
||||
if (strchr(str, '@') != str)
|
||||
return -EINVAL;
|
||||
|
||||
s = str + 1;
|
||||
|
||||
/*
|
||||
* Populate the 'in' array with the location of each
|
||||
* field in the string we're parsing
|
||||
*/
|
||||
for (i = 0; i != DIM(in); i++) {
|
||||
in[i] = strtok_r(s, dlm, &sp);
|
||||
if (in[i] == NULL)
|
||||
return -EINVAL;
|
||||
s = NULL;
|
||||
}
|
||||
|
||||
/* Parse x.x.x.x/x */
|
||||
rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
|
||||
&v->field_value[SRC_FIELD_IPV4].value.u32,
|
||||
&v->field_value[SRC_FIELD_IPV4].mask_range.u32);
|
||||
if (rc != 0) {
|
||||
RTE_LOG(ERR, PIPELINE, "failed to read src address/mask: %s\n",
|
||||
in[CB_FLD_SRC_ADDR]);
|
||||
return rc;
|
||||
}
|
||||
|
||||
printf("V=%u, mask=%u\n", v->field_value[SRC_FIELD_IPV4].value.u32,
|
||||
v->field_value[SRC_FIELD_IPV4].mask_range.u32);
|
||||
|
||||
/* Parse x.x.x.x/x */
|
||||
rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
|
||||
&v->field_value[DST_FIELD_IPV4].value.u32,
|
||||
&v->field_value[DST_FIELD_IPV4].mask_range.u32);
|
||||
if (rc != 0) {
|
||||
RTE_LOG(ERR, PIPELINE, "failed to read dest address/mask: %s\n",
|
||||
in[CB_FLD_DST_ADDR]);
|
||||
return rc;
|
||||
}
|
||||
|
||||
printf("V=%u, mask=%u\n", v->field_value[DST_FIELD_IPV4].value.u32,
|
||||
v->field_value[DST_FIELD_IPV4].mask_range.u32);
|
||||
/* Parse n:n */
|
||||
rc = parse_port_range(in[CB_FLD_SRC_PORT_RANGE],
|
||||
&v->field_value[SRCP_FIELD_IPV4].value.u16,
|
||||
&v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
|
||||
if (rc != 0) {
|
||||
RTE_LOG(ERR, PIPELINE, "failed to read source port range: %s\n",
|
||||
in[CB_FLD_SRC_PORT_RANGE]);
|
||||
return rc;
|
||||
}
|
||||
|
||||
printf("V=%u, mask=%u\n", v->field_value[SRCP_FIELD_IPV4].value.u16,
|
||||
v->field_value[SRCP_FIELD_IPV4].mask_range.u16);
|
||||
/* Parse n:n */
|
||||
rc = parse_port_range(in[CB_FLD_DST_PORT_RANGE],
|
||||
&v->field_value[DSTP_FIELD_IPV4].value.u16,
|
||||
&v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
|
||||
if (rc != 0) {
|
||||
RTE_LOG(ERR, PIPELINE, "failed to read dest port range: %s\n",
|
||||
in[CB_FLD_DST_PORT_RANGE]);
|
||||
return rc;
|
||||
}
|
||||
|
||||
printf("V=%u, mask=%u\n", v->field_value[DSTP_FIELD_IPV4].value.u16,
|
||||
v->field_value[DSTP_FIELD_IPV4].mask_range.u16);
|
||||
/* parse 0/0xnn */
|
||||
GET_CB_FIELD(in[CB_FLD_PROTO],
|
||||
v->field_value[PROTO_FIELD_IPV4].value.u8,
|
||||
0, UINT8_MAX, '/');
|
||||
GET_CB_FIELD(in[CB_FLD_PROTO],
|
||||
v->field_value[PROTO_FIELD_IPV4].mask_range.u8,
|
||||
0, UINT8_MAX, 0);
|
||||
|
||||
printf("V=%u, mask=%u\n",
|
||||
(unsigned int)v->field_value[PROTO_FIELD_IPV4].value.u8,
|
||||
v->field_value[PROTO_FIELD_IPV4].mask_range.u8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The format for these rules DO NOT need the port ranges to be
|
||||
* separated by ' : ', just ':'. It's a lot more readable and
|
||||
* cleaner, IMO.
|
||||
*/
|
||||
char lines[][128] = {
|
||||
"@0.0.0.0/0 0.0.0.0/0 0:65535 0:65535 2/0xff", /* Protocol check */
|
||||
"@192.168.3.1/32 0.0.0.0/0 0:65535 0:65535 0/0", /* Src IP checl */
|
||||
"@0.0.0.0/0 10.4.4.1/32 0:65535 0:65535 0/0", /* dst IP check */
|
||||
"@0.0.0.0/0 0.0.0.0/0 105:105 0:65535 0/0", /* src port check */
|
||||
"@0.0.0.0/0 0.0.0.0/0 0:65535 206:206 0/0", /* dst port check */
|
||||
};
|
||||
|
||||
char line[128];
|
||||
|
||||
|
||||
static int
|
||||
setup_acl_pipeline(void)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
struct rte_pipeline_params pipeline_params = {
|
||||
.name = "PIPELINE",
|
||||
.socket_id = 0,
|
||||
};
|
||||
uint32_t n;
|
||||
struct rte_table_acl_rule_add_params rule_params;
|
||||
struct rte_pipeline_table_acl_rule_delete_params *delete_params;
|
||||
parse_5tuple parser;
|
||||
char acl_name[64];
|
||||
|
||||
/* Pipeline configuration */
|
||||
p = rte_pipeline_create(&pipeline_params);
|
||||
if (p == NULL) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Input port configuration */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
struct rte_port_ring_reader_params port_ring_params = {
|
||||
.ring = rings_rx[i],
|
||||
};
|
||||
|
||||
struct rte_pipeline_port_in_params port_params = {
|
||||
.ops = &rte_port_ring_reader_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.burst_size = BURST_SIZE,
|
||||
};
|
||||
|
||||
/* Put in action for some ports */
|
||||
if (i)
|
||||
port_params.f_action = port_in_action;
|
||||
|
||||
ret = rte_pipeline_port_in_create(p, &port_params,
|
||||
&port_in_id[i]);
|
||||
if (ret) {
|
||||
rte_panic("Unable to configure input port %d, ret:%d\n",
|
||||
i, ret);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* output Port configuration */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
struct rte_port_ring_writer_params port_ring_params = {
|
||||
.ring = rings_tx[i],
|
||||
.tx_burst_sz = BURST_SIZE,
|
||||
};
|
||||
|
||||
struct rte_pipeline_port_out_params port_params = {
|
||||
.ops = &rte_port_ring_writer_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
|
||||
if (rte_pipeline_port_out_create(p, &port_params,
|
||||
&port_out_id[i])) {
|
||||
rte_panic("Unable to configure output port %d\n", i);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Table configuration */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
struct rte_pipeline_table_params table_params;
|
||||
|
||||
/* Set up defaults for stub */
|
||||
table_params.ops = &rte_table_stub_ops;
|
||||
table_params.arg_create = NULL;
|
||||
table_params.f_action_hit = action_handler_hit;
|
||||
table_params.f_action_miss = NULL;
|
||||
table_params.action_data_size = 0;
|
||||
|
||||
RTE_LOG(INFO, PIPELINE, "miss_action=%x\n",
|
||||
table_entry_miss_action);
|
||||
|
||||
printf("RTE_ACL_RULE_SZ(%zu) = %zu\n", DIM(ipv4_defs),
|
||||
RTE_ACL_RULE_SZ(DIM(ipv4_defs)));
|
||||
|
||||
struct rte_table_acl_params acl_params;
|
||||
|
||||
acl_params.n_rules = 1 << 5;
|
||||
acl_params.n_rule_fields = DIM(ipv4_defs);
|
||||
rte_snprintf(acl_name, sizeof(acl_name), "ACL%d", i);
|
||||
acl_params.name = acl_name;
|
||||
memcpy(acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
|
||||
|
||||
table_params.ops = &rte_table_acl_ops;
|
||||
table_params.arg_create = &acl_params;
|
||||
|
||||
if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
|
||||
rte_panic("Unable to configure table %u\n", i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (connect_miss_action_to_table) {
|
||||
if (rte_pipeline_table_create(p, &table_params,
|
||||
&table_id[i+2])) {
|
||||
rte_panic("Unable to configure table %u\n", i);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
|
||||
table_id[i])) {
|
||||
rte_panic("Unable to connect input port %u to "
|
||||
"table %u\n",
|
||||
port_in_id[i], table_id[i]);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add entries to tables */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
struct rte_pipeline_table_entry table_entry = {
|
||||
.action = RTE_PIPELINE_ACTION_PORT,
|
||||
{.port_id = port_out_id[i^1]},
|
||||
};
|
||||
int key_found;
|
||||
struct rte_pipeline_table_entry *entry_ptr;
|
||||
|
||||
memset(&rule_params, 0, sizeof(rule_params));
|
||||
parser = parse_cb_ipv4_rule;
|
||||
|
||||
for (n = 1; n <= 5; n++) {
|
||||
rte_snprintf(line, sizeof(line), "%s", lines[n-1]);
|
||||
printf("PARSING [%s]\n", line);
|
||||
|
||||
ret = parser(line, &rule_params);
|
||||
if (ret != 0) {
|
||||
RTE_LOG(ERR, PIPELINE,
|
||||
"line %u: parse_cb_ipv4vlan_rule"
|
||||
" failed, error code: %d (%s)\n",
|
||||
n, ret, strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
|
||||
|
||||
ret = rte_pipeline_table_entry_add(p, table_id[i],
|
||||
&rule_params,
|
||||
&table_entry, &key_found, &entry_ptr);
|
||||
if (ret < 0) {
|
||||
rte_panic("Add entry to table %u failed (%d)\n",
|
||||
table_id[i], ret);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* delete a few rules */
|
||||
for (n = 2; n <= 3; n++) {
|
||||
rte_snprintf(line, sizeof(line), "%s", lines[n-1]);
|
||||
printf("PARSING [%s]\n", line);
|
||||
|
||||
ret = parser(line, &rule_params);
|
||||
if (ret != 0) {
|
||||
RTE_LOG(ERR, PIPELINE, "line %u: parse rule "
|
||||
" failed, error code: %d (%s)\n",
|
||||
n, ret, strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
delete_params = (struct
|
||||
rte_pipeline_table_acl_rule_delete_params *)
|
||||
&(rule_params.field_value[0]);
|
||||
ret = rte_pipeline_table_entry_delete(p, table_id[i],
|
||||
delete_params, &key_found, NULL);
|
||||
if (ret < 0) {
|
||||
rte_panic("Add entry to table %u failed (%d)\n",
|
||||
table_id[i], ret);
|
||||
goto fail;
|
||||
} else
|
||||
printf("Deleted Rule.\n");
|
||||
}
|
||||
|
||||
|
||||
/* Try to add duplicates */
|
||||
for (n = 1; n <= 5; n++) {
|
||||
rte_snprintf(line, sizeof(line), "%s", lines[n-1]);
|
||||
printf("PARSING [%s]\n", line);
|
||||
|
||||
ret = parser(line, &rule_params);
|
||||
if (ret != 0) {
|
||||
RTE_LOG(ERR, PIPELINE, "line %u: parse rule"
|
||||
" failed, error code: %d (%s)\n",
|
||||
n, ret, strerror(-ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
rule_params.priority = RTE_ACL_MAX_PRIORITY - n;
|
||||
|
||||
ret = rte_pipeline_table_entry_add(p, table_id[i],
|
||||
&rule_params,
|
||||
&table_entry, &key_found, &entry_ptr);
|
||||
if (ret < 0) {
|
||||
rte_panic("Add entry to table %u failed (%d)\n",
|
||||
table_id[i], ret);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable input ports */
|
||||
for (i = 0; i < N_PORTS ; i++)
|
||||
if (rte_pipeline_port_in_enable(p, port_in_id[i]))
|
||||
rte_panic("Unable to enable input port %u\n",
|
||||
port_in_id[i]);
|
||||
|
||||
/* Check pipeline consistency */
|
||||
if (rte_pipeline_check(p) < 0) {
|
||||
rte_panic("Pipeline consistency check failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
test_pipeline_single_filter(int expected_count)
|
||||
{
|
||||
int i, j, ret, tx_count;
|
||||
struct ipv4_5tuple five_tuple;
|
||||
|
||||
/* Allocate a few mbufs and manually insert into the rings. */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
struct rte_mbuf *mbuf;
|
||||
|
||||
mbuf = rte_pktmbuf_alloc(pool);
|
||||
memset(mbuf->pkt.data, 0x00,
|
||||
sizeof(struct ipv4_5tuple));
|
||||
|
||||
five_tuple.proto = j;
|
||||
five_tuple.ip_src = rte_bswap32(IPv4(192, 168, j, 1));
|
||||
five_tuple.ip_dst = rte_bswap32(IPv4(10, 4, j, 1));
|
||||
five_tuple.port_src = rte_bswap16(100 + j);
|
||||
five_tuple.port_dst = rte_bswap16(200 + j);
|
||||
|
||||
memcpy(mbuf->pkt.data, &five_tuple,
|
||||
sizeof(struct ipv4_5tuple));
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Enqueue onto ring %d\n",
|
||||
__func__, i);
|
||||
rte_ring_enqueue(rings_rx[i], mbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Run pipeline once */
|
||||
rte_pipeline_run(p);
|
||||
|
||||
rte_pipeline_flush(p);
|
||||
|
||||
tx_count = 0;
|
||||
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
void *objs[RING_TX_SIZE];
|
||||
struct rte_mbuf *mbuf;
|
||||
|
||||
ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10);
|
||||
if (ret <= 0) {
|
||||
printf("Got no objects from ring %d - error code %d\n",
|
||||
i, ret);
|
||||
} else {
|
||||
printf("Got %d object(s) from ring %d!\n", ret, i);
|
||||
for (j = 0; j < ret; j++) {
|
||||
mbuf = (struct rte_mbuf *)objs[j];
|
||||
rte_hexdump(stdout, "mbuf", mbuf->pkt.data, 64);
|
||||
rte_pktmbuf_free(mbuf);
|
||||
}
|
||||
tx_count += ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx_count != expected_count) {
|
||||
RTE_LOG(INFO, PIPELINE,
|
||||
"%s: Unexpected packets for ACL test, "
|
||||
"expected %d, got %d\n",
|
||||
__func__, expected_count, tx_count);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rte_pipeline_free(p);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
test_table_ACL(void)
|
||||
{
|
||||
|
||||
|
||||
override_hit_mask = 0xFF; /* All packets are a hit */
|
||||
|
||||
setup_acl_pipeline();
|
||||
if (test_pipeline_single_filter(10) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
35
app/test/test_table_acl.h
Normal file
35
app/test/test_table_acl.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Test prototypes */
|
||||
int test_table_ACL(void);
|
784
app/test/test_table_combined.c
Normal file
784
app/test/test_table_combined.c
Normal file
@ -0,0 +1,784 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef RTE_LIBRTE_TABLE
|
||||
#include <string.h>
|
||||
#include "test_table_combined.h"
|
||||
#include "test_table.h"
|
||||
#include <rte_table_lpm_ipv6.h>
|
||||
|
||||
#define MAX_TEST_KEYS 128
|
||||
#define N_PACKETS 50
|
||||
|
||||
enum check_table_result {
|
||||
CHECK_TABLE_OK,
|
||||
CHECK_TABLE_PORT_CONFIG,
|
||||
CHECK_TABLE_PORT_ENABLE,
|
||||
CHECK_TABLE_TABLE_CONFIG,
|
||||
CHECK_TABLE_ENTRY_ADD,
|
||||
CHECK_TABLE_DEFAULT_ENTRY_ADD,
|
||||
CHECK_TABLE_CONNECT,
|
||||
CHECK_TABLE_MANAGE_ERROR,
|
||||
CHECK_TABLE_CONSISTENCY,
|
||||
CHECK_TABLE_NO_TRAFFIC,
|
||||
CHECK_TABLE_INVALID_PARAMETER,
|
||||
};
|
||||
|
||||
struct table_packets {
|
||||
uint32_t hit_packet[MAX_TEST_KEYS];
|
||||
uint32_t miss_packet[MAX_TEST_KEYS];
|
||||
uint32_t n_hit_packets;
|
||||
uint32_t n_miss_packets;
|
||||
};
|
||||
|
||||
combined_table_test table_tests_combined[] = {
|
||||
test_table_lpm_combined,
|
||||
test_table_lpm_ipv6_combined,
|
||||
test_table_hash8lru,
|
||||
test_table_hash8ext,
|
||||
test_table_hash16lru,
|
||||
test_table_hash16ext,
|
||||
test_table_hash32lru,
|
||||
test_table_hash32ext,
|
||||
};
|
||||
|
||||
unsigned n_table_tests_combined = RTE_DIM(table_tests_combined);
|
||||
|
||||
/* Generic port tester function */
|
||||
static int
|
||||
test_table_type(struct rte_table_ops *table_ops, void *table_args,
|
||||
void *key, struct table_packets *table_packets,
|
||||
struct manage_ops *manage_ops, unsigned n_ops)
|
||||
{
|
||||
uint32_t ring_in_id, table_id, ring_out_id, ring_out_2_id;
|
||||
unsigned i;
|
||||
|
||||
RTE_SET_USED(manage_ops);
|
||||
RTE_SET_USED(n_ops);
|
||||
/* Create pipeline */
|
||||
struct rte_pipeline_params pipeline_params = {
|
||||
.name = "pipeline",
|
||||
.socket_id = 0,
|
||||
};
|
||||
|
||||
struct rte_pipeline *pipeline = rte_pipeline_create(&pipeline_params);
|
||||
|
||||
/* Create input ring */
|
||||
struct rte_port_ring_reader_params ring_params_rx = {
|
||||
.ring = RING_RX,
|
||||
};
|
||||
|
||||
struct rte_port_ring_writer_params ring_params_tx = {
|
||||
.ring = RING_RX,
|
||||
.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX,
|
||||
};
|
||||
|
||||
struct rte_pipeline_port_in_params ring_in_params = {
|
||||
.ops = &rte_port_ring_reader_ops,
|
||||
.arg_create = (void *)&ring_params_rx,
|
||||
.f_action = NULL,
|
||||
.burst_size = RTE_PORT_IN_BURST_SIZE_MAX,
|
||||
};
|
||||
|
||||
if (rte_pipeline_port_in_create(pipeline, &ring_in_params,
|
||||
&ring_in_id) != 0)
|
||||
return -CHECK_TABLE_PORT_CONFIG;
|
||||
|
||||
/* Create table */
|
||||
struct rte_pipeline_table_params table_params = {
|
||||
.ops = table_ops,
|
||||
.arg_create = table_args,
|
||||
.f_action_hit = NULL,
|
||||
.f_action_miss = NULL,
|
||||
.arg_ah = NULL,
|
||||
.action_data_size = 0,
|
||||
};
|
||||
|
||||
if (rte_pipeline_table_create(pipeline, &table_params, &table_id) != 0)
|
||||
return -CHECK_TABLE_TABLE_CONFIG;
|
||||
|
||||
/* Create output ports */
|
||||
ring_params_tx.ring = RING_TX;
|
||||
|
||||
struct rte_pipeline_port_out_params ring_out_params = {
|
||||
.ops = &rte_port_ring_writer_ops,
|
||||
.arg_create = (void *)&ring_params_tx,
|
||||
.f_action = NULL,
|
||||
};
|
||||
|
||||
if (rte_pipeline_port_out_create(pipeline, &ring_out_params,
|
||||
&ring_out_id) != 0)
|
||||
return -CHECK_TABLE_PORT_CONFIG;
|
||||
|
||||
ring_params_tx.ring = RING_TX_2;
|
||||
|
||||
if (rte_pipeline_port_out_create(pipeline, &ring_out_params,
|
||||
&ring_out_2_id) != 0)
|
||||
return -CHECK_TABLE_PORT_CONFIG;
|
||||
|
||||
/* Add entry to the table */
|
||||
struct rte_pipeline_table_entry default_entry = {
|
||||
.action = RTE_PIPELINE_ACTION_DROP,
|
||||
{.table_id = ring_out_id},
|
||||
};
|
||||
|
||||
struct rte_pipeline_table_entry table_entry = {
|
||||
.action = RTE_PIPELINE_ACTION_PORT,
|
||||
{.table_id = ring_out_id},
|
||||
};
|
||||
|
||||
struct rte_pipeline_table_entry *default_entry_ptr, *entry_ptr;
|
||||
|
||||
int key_found;
|
||||
|
||||
if (rte_pipeline_table_default_entry_add(pipeline, table_id,
|
||||
&default_entry, &default_entry_ptr) != 0)
|
||||
return -CHECK_TABLE_DEFAULT_ENTRY_ADD;
|
||||
|
||||
if (rte_pipeline_table_entry_add(pipeline, table_id,
|
||||
key ? key : &table_entry, &table_entry, &key_found,
|
||||
&entry_ptr) != 0)
|
||||
return -CHECK_TABLE_ENTRY_ADD;
|
||||
|
||||
/* Create connections and check consistency */
|
||||
if (rte_pipeline_port_in_connect_to_table(pipeline, ring_in_id,
|
||||
table_id) != 0)
|
||||
return -CHECK_TABLE_CONNECT;
|
||||
|
||||
if (rte_pipeline_port_in_enable(pipeline, ring_in_id) != 0)
|
||||
return -CHECK_TABLE_PORT_ENABLE;
|
||||
|
||||
if (rte_pipeline_check(pipeline) != 0)
|
||||
return -CHECK_TABLE_CONSISTENCY;
|
||||
|
||||
|
||||
|
||||
/* Flow test - All hits */
|
||||
if (table_packets->n_hit_packets) {
|
||||
for (i = 0; i < table_packets->n_hit_packets; i++)
|
||||
RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]);
|
||||
|
||||
RUN_PIPELINE(pipeline);
|
||||
|
||||
VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets,
|
||||
table_packets->n_hit_packets);
|
||||
}
|
||||
|
||||
/* Flow test - All misses */
|
||||
if (table_packets->n_miss_packets) {
|
||||
for (i = 0; i < table_packets->n_miss_packets; i++)
|
||||
RING_ENQUEUE(RING_RX, table_packets->miss_packet[i]);
|
||||
|
||||
RUN_PIPELINE(pipeline);
|
||||
|
||||
VERIFY_TRAFFIC(RING_TX, table_packets->n_miss_packets, 0);
|
||||
}
|
||||
|
||||
/* Flow test - Half hits, half misses */
|
||||
if (table_packets->n_hit_packets && table_packets->n_miss_packets) {
|
||||
for (i = 0; i < (table_packets->n_hit_packets) / 2; i++)
|
||||
RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]);
|
||||
|
||||
for (i = 0; i < (table_packets->n_miss_packets) / 2; i++)
|
||||
RING_ENQUEUE(RING_RX, table_packets->miss_packet[i]);
|
||||
|
||||
RUN_PIPELINE(pipeline);
|
||||
VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets,
|
||||
table_packets->n_hit_packets / 2);
|
||||
}
|
||||
|
||||
/* Flow test - Single packet */
|
||||
if (table_packets->n_hit_packets) {
|
||||
RING_ENQUEUE(RING_RX, table_packets->hit_packet[0]);
|
||||
RUN_PIPELINE(pipeline);
|
||||
VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets, 1);
|
||||
}
|
||||
if (table_packets->n_miss_packets) {
|
||||
RING_ENQUEUE(RING_RX, table_packets->miss_packet[0]);
|
||||
RUN_PIPELINE(pipeline);
|
||||
VERIFY_TRAFFIC(RING_TX, table_packets->n_miss_packets, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Change table entry action */
|
||||
printf("Change entry action\n");
|
||||
table_entry.table_id = ring_out_2_id;
|
||||
|
||||
if (rte_pipeline_table_default_entry_add(pipeline, table_id,
|
||||
&default_entry, &default_entry_ptr) != 0)
|
||||
return -CHECK_TABLE_ENTRY_ADD;
|
||||
|
||||
if (rte_pipeline_table_entry_add(pipeline, table_id,
|
||||
key ? key : &table_entry, &table_entry, &key_found,
|
||||
&entry_ptr) != 0)
|
||||
return -CHECK_TABLE_ENTRY_ADD;
|
||||
|
||||
/* Check that traffic destination has changed */
|
||||
if (table_packets->n_hit_packets) {
|
||||
for (i = 0; i < table_packets->n_hit_packets; i++)
|
||||
RING_ENQUEUE(RING_RX, table_packets->hit_packet[i]);
|
||||
|
||||
RUN_PIPELINE(pipeline);
|
||||
VERIFY_TRAFFIC(RING_TX, table_packets->n_hit_packets, 0);
|
||||
VERIFY_TRAFFIC(RING_TX_2, table_packets->n_hit_packets,
|
||||
table_packets->n_hit_packets);
|
||||
}
|
||||
|
||||
printf("delete entry\n");
|
||||
/* Delete table entry */
|
||||
rte_pipeline_table_entry_delete(pipeline, table_id,
|
||||
key ? key : &table_entry, &key_found, NULL);
|
||||
|
||||
rte_pipeline_free(pipeline);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table tests */
|
||||
int
|
||||
test_table_stub_combined(void)
|
||||
{
|
||||
int status, i;
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
for (i = 0; i < N_PACKETS; i++)
|
||||
table_packets.hit_packet[i] = i;
|
||||
|
||||
table_packets.n_hit_packets = N_PACKETS;
|
||||
table_packets.n_miss_packets = 0;
|
||||
|
||||
status = test_table_type(&rte_table_stub_ops, NULL, NULL,
|
||||
&table_packets, NULL, 1);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_lpm_combined(void)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
/* Traffic flow */
|
||||
struct rte_table_lpm_params lpm_params = {
|
||||
.n_rules = 1 << 16,
|
||||
.entry_unique_size = 8,
|
||||
.offset = 0,
|
||||
};
|
||||
|
||||
struct rte_table_lpm_key lpm_key = {
|
||||
.ip = 0xadadadad,
|
||||
.depth = 16,
|
||||
};
|
||||
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
|
||||
for (i = 0; i < N_PACKETS; i++)
|
||||
table_packets.hit_packet[i] = 0xadadadad;
|
||||
|
||||
for (i = 0; i < N_PACKETS; i++)
|
||||
table_packets.miss_packet[i] = 0xfefefefe;
|
||||
|
||||
table_packets.n_hit_packets = N_PACKETS;
|
||||
table_packets.n_miss_packets = N_PACKETS;
|
||||
|
||||
status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params,
|
||||
(void *)&lpm_key, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
/* Invalid parameters */
|
||||
lpm_params.n_rules = 0;
|
||||
|
||||
status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params,
|
||||
(void *)&lpm_key, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
lpm_params.n_rules = 1 << 24;
|
||||
lpm_key.depth = 0;
|
||||
|
||||
status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params,
|
||||
(void *)&lpm_key, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_ENTRY_ADD);
|
||||
|
||||
lpm_key.depth = 33;
|
||||
|
||||
status = test_table_type(&rte_table_lpm_ops, (void *)&lpm_params,
|
||||
(void *)&lpm_key, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_ENTRY_ADD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_lpm_ipv6_combined(void)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
/* Traffic flow */
|
||||
struct rte_table_lpm_ipv6_params lpm_ipv6_params = {
|
||||
.n_rules = 1 << 16,
|
||||
.number_tbl8s = 1 << 13,
|
||||
.entry_unique_size = 8,
|
||||
.offset = 32,
|
||||
};
|
||||
|
||||
struct rte_table_lpm_ipv6_key lpm_ipv6_key = {
|
||||
.depth = 16,
|
||||
};
|
||||
memset(lpm_ipv6_key.ip, 0xad, 16);
|
||||
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
for (i = 0; i < N_PACKETS; i++)
|
||||
table_packets.hit_packet[i] = 0xadadadad;
|
||||
|
||||
for (i = 0; i < N_PACKETS; i++)
|
||||
table_packets.miss_packet[i] = 0xadadadab;
|
||||
|
||||
table_packets.n_hit_packets = N_PACKETS;
|
||||
table_packets.n_miss_packets = N_PACKETS;
|
||||
|
||||
status = test_table_type(&rte_table_lpm_ipv6_ops,
|
||||
(void *)&lpm_ipv6_params,
|
||||
(void *)&lpm_ipv6_key, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
/* Invalid parameters */
|
||||
lpm_ipv6_params.n_rules = 0;
|
||||
|
||||
status = test_table_type(&rte_table_lpm_ipv6_ops,
|
||||
(void *)&lpm_ipv6_params,
|
||||
(void *)&lpm_ipv6_key, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
lpm_ipv6_params.n_rules = 1 << 24;
|
||||
lpm_ipv6_key.depth = 0;
|
||||
|
||||
status = test_table_type(&rte_table_lpm_ipv6_ops,
|
||||
(void *)&lpm_ipv6_params,
|
||||
(void *)&lpm_ipv6_key, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_ENTRY_ADD);
|
||||
|
||||
lpm_ipv6_key.depth = 129;
|
||||
status = test_table_type(&rte_table_lpm_ipv6_ops,
|
||||
(void *)&lpm_ipv6_params,
|
||||
(void *)&lpm_ipv6_key, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_ENTRY_ADD);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_hash8lru(void)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
/* Traffic flow */
|
||||
struct rte_table_hash_key8_lru_params key8lru_params = {
|
||||
.n_entries = 1<<24,
|
||||
.f_hash = pipeline_test_hash,
|
||||
.seed = 0,
|
||||
.signature_offset = 0,
|
||||
.key_offset = 32,
|
||||
};
|
||||
|
||||
uint8_t key8lru[8];
|
||||
uint32_t *k8lru = (uint32_t *) key8lru;
|
||||
|
||||
memset(key8lru, 0, sizeof(key8lru));
|
||||
k8lru[0] = 0xadadadad;
|
||||
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.hit_packet[i] = 0xadadadad;
|
||||
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.miss_packet[i] = 0xfefefefe;
|
||||
|
||||
table_packets.n_hit_packets = 50;
|
||||
table_packets.n_miss_packets = 50;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key8_lru_ops,
|
||||
(void *)&key8lru_params, (void *)key8lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
/* Invalid parameters */
|
||||
key8lru_params.n_entries = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key8_lru_ops,
|
||||
(void *)&key8lru_params, (void *)key8lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key8lru_params.n_entries = 1<<16;
|
||||
key8lru_params.f_hash = NULL;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key8_lru_ops,
|
||||
(void *)&key8lru_params, (void *)key8lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_hash16lru(void)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
/* Traffic flow */
|
||||
struct rte_table_hash_key16_lru_params key16lru_params = {
|
||||
.n_entries = 1<<16,
|
||||
.f_hash = pipeline_test_hash,
|
||||
.seed = 0,
|
||||
.signature_offset = 0,
|
||||
.key_offset = 32,
|
||||
};
|
||||
|
||||
uint8_t key16lru[16];
|
||||
uint32_t *k16lru = (uint32_t *) key16lru;
|
||||
|
||||
memset(key16lru, 0, sizeof(key16lru));
|
||||
k16lru[0] = 0xadadadad;
|
||||
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.hit_packet[i] = 0xadadadad;
|
||||
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.miss_packet[i] = 0xfefefefe;
|
||||
|
||||
table_packets.n_hit_packets = 50;
|
||||
table_packets.n_miss_packets = 50;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key16_lru_ops,
|
||||
(void *)&key16lru_params, (void *)key16lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
/* Invalid parameters */
|
||||
key16lru_params.n_entries = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key16_lru_ops,
|
||||
(void *)&key16lru_params, (void *)key16lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key16lru_params.n_entries = 1<<16;
|
||||
key16lru_params.f_hash = NULL;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key16_lru_ops,
|
||||
(void *)&key16lru_params, (void *)key16lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_hash32lru(void)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
/* Traffic flow */
|
||||
struct rte_table_hash_key32_lru_params key32lru_params = {
|
||||
.n_entries = 1<<16,
|
||||
.f_hash = pipeline_test_hash,
|
||||
.seed = 0,
|
||||
.signature_offset = 0,
|
||||
.key_offset = 32,
|
||||
};
|
||||
|
||||
uint8_t key32lru[32];
|
||||
uint32_t *k32lru = (uint32_t *) key32lru;
|
||||
|
||||
memset(key32lru, 0, sizeof(key32lru));
|
||||
k32lru[0] = 0xadadadad;
|
||||
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.hit_packet[i] = 0xadadadad;
|
||||
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.miss_packet[i] = 0xbdadadad;
|
||||
|
||||
table_packets.n_hit_packets = 50;
|
||||
table_packets.n_miss_packets = 50;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key32_lru_ops,
|
||||
(void *)&key32lru_params, (void *)key32lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
/* Invalid parameters */
|
||||
key32lru_params.n_entries = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key32_lru_ops,
|
||||
(void *)&key32lru_params, (void *)key32lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key32lru_params.n_entries = 1<<16;
|
||||
key32lru_params.f_hash = NULL;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key32_lru_ops,
|
||||
(void *)&key32lru_params, (void *)key32lru, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_hash8ext(void)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
/* Traffic flow */
|
||||
struct rte_table_hash_key8_ext_params key8ext_params = {
|
||||
.n_entries = 1<<16,
|
||||
.n_entries_ext = 1<<15,
|
||||
.f_hash = pipeline_test_hash,
|
||||
.seed = 0,
|
||||
.signature_offset = 0,
|
||||
.key_offset = 32,
|
||||
};
|
||||
|
||||
uint8_t key8ext[8];
|
||||
uint32_t *k8ext = (uint32_t *) key8ext;
|
||||
|
||||
memset(key8ext, 0, sizeof(key8ext));
|
||||
k8ext[0] = 0xadadadad;
|
||||
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.hit_packet[i] = 0xadadadad;
|
||||
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.miss_packet[i] = 0xbdadadad;
|
||||
|
||||
table_packets.n_hit_packets = 50;
|
||||
table_packets.n_miss_packets = 50;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key8_ext_ops,
|
||||
(void *)&key8ext_params, (void *)key8ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
/* Invalid parameters */
|
||||
key8ext_params.n_entries = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key8_ext_ops,
|
||||
(void *)&key8ext_params, (void *)key8ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key8ext_params.n_entries = 1<<16;
|
||||
key8ext_params.f_hash = NULL;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key8_ext_ops,
|
||||
(void *)&key8ext_params, (void *)key8ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key8ext_params.f_hash = pipeline_test_hash;
|
||||
key8ext_params.n_entries_ext = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key8_ext_ops,
|
||||
(void *)&key8ext_params, (void *)key8ext, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_hash16ext(void)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
/* Traffic flow */
|
||||
struct rte_table_hash_key16_ext_params key16ext_params = {
|
||||
.n_entries = 1<<16,
|
||||
.n_entries_ext = 1<<15,
|
||||
.f_hash = pipeline_test_hash,
|
||||
.seed = 0,
|
||||
.signature_offset = 0,
|
||||
.key_offset = 32,
|
||||
};
|
||||
|
||||
uint8_t key16ext[16];
|
||||
uint32_t *k16ext = (uint32_t *) key16ext;
|
||||
|
||||
memset(key16ext, 0, sizeof(key16ext));
|
||||
k16ext[0] = 0xadadadad;
|
||||
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.hit_packet[i] = 0xadadadad;
|
||||
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.miss_packet[i] = 0xbdadadad;
|
||||
|
||||
table_packets.n_hit_packets = 50;
|
||||
table_packets.n_miss_packets = 50;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key16_ext_ops,
|
||||
(void *)&key16ext_params, (void *)key16ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
/* Invalid parameters */
|
||||
key16ext_params.n_entries = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key16_ext_ops,
|
||||
(void *)&key16ext_params, (void *)key16ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key16ext_params.n_entries = 1<<16;
|
||||
key16ext_params.f_hash = NULL;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key16_ext_ops,
|
||||
(void *)&key16ext_params, (void *)key16ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key16ext_params.f_hash = pipeline_test_hash;
|
||||
key16ext_params.n_entries_ext = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key16_ext_ops,
|
||||
(void *)&key16ext_params, (void *)key16ext, &table_packets, NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_hash32ext(void)
|
||||
{
|
||||
int status, i;
|
||||
|
||||
/* Traffic flow */
|
||||
struct rte_table_hash_key32_ext_params key32ext_params = {
|
||||
.n_entries = 1<<16,
|
||||
.n_entries_ext = 1<<15,
|
||||
.f_hash = pipeline_test_hash,
|
||||
.seed = 0,
|
||||
.signature_offset = 0,
|
||||
.key_offset = 32,
|
||||
};
|
||||
|
||||
uint8_t key32ext[32];
|
||||
uint32_t *k32ext = (uint32_t *) key32ext;
|
||||
|
||||
memset(key32ext, 0, sizeof(key32ext));
|
||||
k32ext[0] = 0xadadadad;
|
||||
|
||||
struct table_packets table_packets;
|
||||
|
||||
printf("--------------\n");
|
||||
printf("RUNNING TEST - %s\n", __func__);
|
||||
printf("--------------\n");
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.hit_packet[i] = 0xadadadad;
|
||||
|
||||
for (i = 0; i < 50; i++)
|
||||
table_packets.miss_packet[i] = 0xbdadadad;
|
||||
|
||||
table_packets.n_hit_packets = 50;
|
||||
table_packets.n_miss_packets = 50;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key32_ext_ops,
|
||||
(void *)&key32ext_params, (void *)key32ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_OK);
|
||||
|
||||
/* Invalid parameters */
|
||||
key32ext_params.n_entries = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key32_ext_ops,
|
||||
(void *)&key32ext_params, (void *)key32ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key32ext_params.n_entries = 1<<16;
|
||||
key32ext_params.f_hash = NULL;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key32_ext_ops,
|
||||
(void *)&key32ext_params, (void *)key32ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
key32ext_params.f_hash = pipeline_test_hash;
|
||||
key32ext_params.n_entries_ext = 0;
|
||||
|
||||
status = test_table_type(&rte_table_hash_key32_ext_ops,
|
||||
(void *)&key32ext_params, (void *)key32ext, &table_packets,
|
||||
NULL, 0);
|
||||
VERIFY(status, CHECK_TABLE_TABLE_CONFIG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
55
app/test/test_table_combined.h
Normal file
55
app/test/test_table_combined.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Test prototypes */
|
||||
int test_table_stub_combined(void);
|
||||
int test_table_lpm_combined(void);
|
||||
int test_table_lpm_ipv6_combined(void);
|
||||
#ifdef RTE_LIBRTE_ACL
|
||||
int test_table_acl(void);
|
||||
#endif
|
||||
int test_table_hash8unoptimized(void);
|
||||
int test_table_hash8lru(void);
|
||||
int test_table_hash8ext(void);
|
||||
int test_table_hash16unoptimized(void);
|
||||
int test_table_hash16lru(void);
|
||||
int test_table_hash16ext(void);
|
||||
int test_table_hash32unoptimized(void);
|
||||
int test_table_hash32lru(void);
|
||||
int test_table_hash32ext(void);
|
||||
|
||||
/* Extern variables */
|
||||
typedef int (*combined_table_test)(void);
|
||||
|
||||
extern combined_table_test table_tests_combined[];
|
||||
extern unsigned n_table_tests_combined;
|
603
app/test/test_table_pipeline.c
Normal file
603
app/test/test_table_pipeline.c
Normal file
@ -0,0 +1,603 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RTE_LIBRTE_PIPELINE
|
||||
|
||||
#include "test.h"
|
||||
|
||||
#else
|
||||
|
||||
#include <string.h>
|
||||
#include <rte_pipeline.h>
|
||||
#include <rte_log.h>
|
||||
#include <inttypes.h>
|
||||
#include <rte_hexdump.h>
|
||||
#include "test_table.h"
|
||||
#include "test_table_pipeline.h"
|
||||
|
||||
#define RTE_CBUF_UINT8_PTR(cbuf, offset) \
|
||||
(&cbuf->data[offset])
|
||||
#define RTE_CBUF_UINT32_PTR(cbuf, offset) \
|
||||
(&cbuf->data32[offset/sizeof(uint32_t)])
|
||||
|
||||
#if 0
|
||||
|
||||
static rte_pipeline_port_out_action_handler port_action_0x00
|
||||
(struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg);
|
||||
static rte_pipeline_port_out_action_handler port_action_0xFF
|
||||
(struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg);
|
||||
static rte_pipeline_port_out_action_handler port_action_stub
|
||||
(struct rte_mbuf **pkts, uint32_t n, uint64_t *pkts_mask, void *arg);
|
||||
|
||||
|
||||
rte_pipeline_port_out_action_handler port_action_0x00(struct rte_mbuf **pkts,
|
||||
uint32_t n,
|
||||
uint64_t *pkts_mask,
|
||||
void *arg)
|
||||
{
|
||||
RTE_SET_USED(pkts);
|
||||
RTE_SET_USED(n);
|
||||
RTE_SET_USED(arg);
|
||||
printf("Port Action 0x00\n");
|
||||
*pkts_mask = 0x00;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rte_pipeline_port_out_action_handler port_action_0xFF(struct rte_mbuf **pkts,
|
||||
uint32_t n,
|
||||
uint64_t *pkts_mask,
|
||||
void *arg)
|
||||
{
|
||||
RTE_SET_USED(pkts);
|
||||
RTE_SET_USED(n);
|
||||
RTE_SET_USED(arg);
|
||||
printf("Port Action 0xFF\n");
|
||||
*pkts_mask = 0xFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rte_pipeline_port_out_action_handler port_action_stub(struct rte_mbuf **pkts,
|
||||
uint32_t n,
|
||||
uint64_t *pkts_mask,
|
||||
void *arg)
|
||||
{
|
||||
RTE_SET_USED(pkts);
|
||||
RTE_SET_USED(n);
|
||||
RTE_SET_USED(pkts_mask);
|
||||
RTE_SET_USED(arg);
|
||||
printf("Port Action stub\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
rte_pipeline_table_action_handler_hit
|
||||
table_action_0x00(struct rte_mbuf **pkts, uint64_t *pkts_mask,
|
||||
struct rte_pipeline_table_entry **actions, uint32_t action_mask);
|
||||
|
||||
rte_pipeline_table_action_handler_hit
|
||||
table_action_stub_hit(struct rte_mbuf **pkts, uint64_t *pkts_mask,
|
||||
struct rte_pipeline_table_entry **actions, uint32_t action_mask);
|
||||
|
||||
rte_pipeline_table_action_handler_miss
|
||||
table_action_stub_miss(struct rte_mbuf **pkts, uint64_t *pkts_mask,
|
||||
struct rte_pipeline_table_entry *action, uint32_t action_mask);
|
||||
|
||||
rte_pipeline_table_action_handler_hit
|
||||
table_action_0x00(__attribute__((unused)) struct rte_mbuf **pkts,
|
||||
uint64_t *pkts_mask,
|
||||
__attribute__((unused)) struct rte_pipeline_table_entry **actions,
|
||||
__attribute__((unused)) uint32_t action_mask)
|
||||
{
|
||||
printf("Table Action, setting pkts_mask to 0x00\n");
|
||||
*pkts_mask = 0x00;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rte_pipeline_table_action_handler_hit
|
||||
table_action_stub_hit(__attribute__((unused)) struct rte_mbuf **pkts,
|
||||
uint64_t *pkts_mask,
|
||||
__attribute__((unused)) struct rte_pipeline_table_entry **actions,
|
||||
__attribute__((unused)) uint32_t action_mask)
|
||||
{
|
||||
printf("STUB Table Action Hit - doing nothing\n");
|
||||
printf("STUB Table Action Hit - setting mask to 0x%"PRIx64"\n",
|
||||
override_hit_mask);
|
||||
*pkts_mask = override_hit_mask;
|
||||
return 0;
|
||||
}
|
||||
rte_pipeline_table_action_handler_miss
|
||||
table_action_stub_miss(__attribute__((unused)) struct rte_mbuf **pkts,
|
||||
uint64_t *pkts_mask,
|
||||
__attribute__((unused)) struct rte_pipeline_table_entry *action,
|
||||
__attribute__((unused)) uint32_t action_mask)
|
||||
{
|
||||
printf("STUB Table Action Miss - setting mask to 0x%"PRIx64"\n",
|
||||
override_miss_mask);
|
||||
*pkts_mask = override_miss_mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum e_test_type {
|
||||
e_TEST_STUB = 0,
|
||||
e_TEST_LPM,
|
||||
e_TEST_LPM6,
|
||||
e_TEST_HASH_LRU_8,
|
||||
e_TEST_HASH_LRU_16,
|
||||
e_TEST_HASH_LRU_32,
|
||||
e_TEST_HASH_EXT_8,
|
||||
e_TEST_HASH_EXT_16,
|
||||
e_TEST_HASH_EXT_32
|
||||
};
|
||||
|
||||
char pipeline_test_names[][64] = {
|
||||
"Stub",
|
||||
"LPM",
|
||||
"LPMv6",
|
||||
"8-bit LRU Hash",
|
||||
"16-bit LRU Hash",
|
||||
"32-bit LRU Hash",
|
||||
"16-bit Ext Hash",
|
||||
"8-bit Ext Hash",
|
||||
"32-bit Ext Hash",
|
||||
""
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
cleanup_pipeline(void)
|
||||
{
|
||||
|
||||
rte_pipeline_free(p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int check_pipeline_invalid_params(void);
|
||||
|
||||
static int
|
||||
check_pipeline_invalid_params(void)
|
||||
{
|
||||
struct rte_pipeline_params pipeline_params_1 = {
|
||||
.name = NULL,
|
||||
.socket_id = 0,
|
||||
};
|
||||
struct rte_pipeline_params pipeline_params_2 = {
|
||||
.name = "PIPELINE",
|
||||
.socket_id = -1,
|
||||
};
|
||||
struct rte_pipeline_params pipeline_params_3 = {
|
||||
.name = "PIPELINE",
|
||||
.socket_id = 127,
|
||||
};
|
||||
|
||||
p = rte_pipeline_create(NULL);
|
||||
if (p != NULL) {
|
||||
RTE_LOG(INFO, PIPELINE,
|
||||
"%s: configured pipeline with null params\n",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
p = rte_pipeline_create(&pipeline_params_1);
|
||||
if (p != NULL) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with NULL "
|
||||
"name\n", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
p = rte_pipeline_create(&pipeline_params_2);
|
||||
if (p != NULL) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with invalid "
|
||||
"socket\n", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
p = rte_pipeline_create(&pipeline_params_3);
|
||||
if (p != NULL) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Configure pipeline with invalid "
|
||||
"socket\n", __func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Check pipeline consistency */
|
||||
if (!rte_pipeline_check(p)) {
|
||||
rte_panic("Pipeline consistency reported as OK\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
setup_pipeline(int test_type)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
struct rte_pipeline_params pipeline_params = {
|
||||
.name = "PIPELINE",
|
||||
.socket_id = 0,
|
||||
};
|
||||
|
||||
RTE_LOG(INFO, PIPELINE, "%s: **** Setting up %s test\n",
|
||||
__func__, pipeline_test_names[test_type]);
|
||||
|
||||
/* Pipeline configuration */
|
||||
p = rte_pipeline_create(&pipeline_params);
|
||||
if (p == NULL) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = rte_pipeline_free(p);
|
||||
if (ret != 0) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Failed to free pipeline\n",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Pipeline configuration */
|
||||
p = rte_pipeline_create(&pipeline_params);
|
||||
if (p == NULL) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Failed to configure pipeline\n",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* Input port configuration */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
struct rte_port_ring_reader_params port_ring_params = {
|
||||
.ring = rings_rx[i],
|
||||
};
|
||||
|
||||
struct rte_pipeline_port_in_params port_params = {
|
||||
.ops = &rte_port_ring_reader_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.burst_size = BURST_SIZE,
|
||||
};
|
||||
|
||||
/* Put in action for some ports */
|
||||
if (i)
|
||||
port_params.f_action = NULL;
|
||||
|
||||
ret = rte_pipeline_port_in_create(p, &port_params,
|
||||
&port_in_id[i]);
|
||||
if (ret) {
|
||||
rte_panic("Unable to configure input port %d, ret:%d\n",
|
||||
i, ret);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* output Port configuration */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
struct rte_port_ring_writer_params port_ring_params = {
|
||||
.ring = rings_tx[i],
|
||||
.tx_burst_sz = BURST_SIZE,
|
||||
};
|
||||
|
||||
struct rte_pipeline_port_out_params port_params = {
|
||||
.ops = &rte_port_ring_writer_ops,
|
||||
.arg_create = (void *) &port_ring_params,
|
||||
.f_action = NULL,
|
||||
.arg_ah = NULL,
|
||||
};
|
||||
|
||||
if (i)
|
||||
port_params.f_action = port_out_action;
|
||||
|
||||
if (rte_pipeline_port_out_create(p, &port_params,
|
||||
&port_out_id[i])) {
|
||||
rte_panic("Unable to configure output port %d\n", i);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Table configuration */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
struct rte_pipeline_table_params table_params = {
|
||||
.ops = &rte_table_stub_ops,
|
||||
.arg_create = NULL,
|
||||
.f_action_hit = action_handler_hit,
|
||||
.f_action_miss = action_handler_miss,
|
||||
.action_data_size = 0,
|
||||
};
|
||||
|
||||
if (rte_pipeline_table_create(p, &table_params, &table_id[i])) {
|
||||
rte_panic("Unable to configure table %u\n", i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (connect_miss_action_to_table)
|
||||
if (rte_pipeline_table_create(p, &table_params,
|
||||
&table_id[i+2])) {
|
||||
rte_panic("Unable to configure table %u\n", i);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < N_PORTS; i++)
|
||||
if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i],
|
||||
table_id[i])) {
|
||||
rte_panic("Unable to connect input port %u to "
|
||||
"table %u\n", port_in_id[i], table_id[i]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Add entries to tables */
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
struct rte_pipeline_table_entry default_entry = {
|
||||
.action = (enum rte_pipeline_action)
|
||||
table_entry_default_action,
|
||||
{.port_id = port_out_id[i^1]},
|
||||
};
|
||||
struct rte_pipeline_table_entry *default_entry_ptr;
|
||||
|
||||
if (connect_miss_action_to_table) {
|
||||
printf("Setting first table to output to next table\n");
|
||||
default_entry.action = RTE_PIPELINE_ACTION_TABLE;
|
||||
default_entry.table_id = table_id[i+2];
|
||||
}
|
||||
|
||||
/* Add the default action for the table. */
|
||||
ret = rte_pipeline_table_default_entry_add(p, table_id[i],
|
||||
&default_entry, &default_entry_ptr);
|
||||
if (ret < 0) {
|
||||
rte_panic("Unable to add default entry to table %u "
|
||||
"code %d\n", table_id[i], ret);
|
||||
goto fail;
|
||||
} else
|
||||
printf("Added default entry to table id %d with "
|
||||
"action %x\n",
|
||||
table_id[i], default_entry.action);
|
||||
|
||||
if (connect_miss_action_to_table) {
|
||||
/* We create a second table so the first can pass
|
||||
traffic into it */
|
||||
struct rte_pipeline_table_entry default_entry = {
|
||||
.action = RTE_PIPELINE_ACTION_PORT,
|
||||
{.port_id = port_out_id[i^1]},
|
||||
};
|
||||
printf("Setting secont table to output to port\n");
|
||||
|
||||
/* Add the default action for the table. */
|
||||
ret = rte_pipeline_table_default_entry_add(p,
|
||||
table_id[i+2],
|
||||
&default_entry, &default_entry_ptr);
|
||||
if (ret < 0) {
|
||||
rte_panic("Unable to add default entry to "
|
||||
"table %u code %d\n",
|
||||
table_id[i], ret);
|
||||
goto fail;
|
||||
} else
|
||||
printf("Added default entry to table id %d "
|
||||
"with action %x\n",
|
||||
table_id[i], default_entry.action);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable input ports */
|
||||
for (i = 0; i < N_PORTS ; i++)
|
||||
if (rte_pipeline_port_in_enable(p, port_in_id[i]))
|
||||
rte_panic("Unable to enable input port %u\n",
|
||||
port_in_id[i]);
|
||||
|
||||
/* Check pipeline consistency */
|
||||
if (rte_pipeline_check(p) < 0) {
|
||||
rte_panic("Pipeline consistency check failed\n");
|
||||
goto fail;
|
||||
} else
|
||||
printf("Pipeline Consistency OK!\n");
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
test_pipeline_single_filter(int test_type, int expected_count)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int ret;
|
||||
int tx_count;
|
||||
|
||||
RTE_LOG(INFO, PIPELINE, "%s: **** Running %s test\n",
|
||||
__func__, pipeline_test_names[test_type]);
|
||||
/* Run pipeline once */
|
||||
rte_pipeline_run(p);
|
||||
|
||||
|
||||
ret = rte_pipeline_flush(NULL);
|
||||
if (ret != -EINVAL) {
|
||||
RTE_LOG(INFO, PIPELINE,
|
||||
"%s: No pipeline flush error NULL pipeline (%d)\n",
|
||||
__func__, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a few mbufs and manually insert into the rings. */
|
||||
for (i = 0; i < N_PORTS; i++)
|
||||
for (j = 0; j < N_PORTS; j++) {
|
||||
struct rte_mbuf *m;
|
||||
uint8_t *key;
|
||||
uint32_t *k32;
|
||||
|
||||
m = rte_pktmbuf_alloc(pool);
|
||||
if (m == NULL) {
|
||||
rte_panic("Failed to alloc mbuf from pool\n");
|
||||
return -1;
|
||||
}
|
||||
key = RTE_MBUF_METADATA_UINT8_PTR(m, 32);
|
||||
|
||||
k32 = (uint32_t *) key;
|
||||
k32[0] = 0xadadadad >> (j % 2);
|
||||
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Enqueue onto ring %d\n",
|
||||
__func__, i);
|
||||
rte_ring_enqueue(rings_rx[i], m);
|
||||
}
|
||||
|
||||
/* Run pipeline once */
|
||||
rte_pipeline_run(p);
|
||||
|
||||
/*
|
||||
* need to flush the pipeline, as there may be less hits than the burst
|
||||
size and they will not have been flushed to the tx rings. */
|
||||
rte_pipeline_flush(p);
|
||||
|
||||
/*
|
||||
* Now we'll see what we got back on the tx rings. We should see whatever
|
||||
* packets we had hits on that were destined for the output ports.
|
||||
*/
|
||||
tx_count = 0;
|
||||
|
||||
for (i = 0; i < N_PORTS; i++) {
|
||||
void *objs[RING_TX_SIZE];
|
||||
struct rte_mbuf *mbuf;
|
||||
|
||||
ret = rte_ring_sc_dequeue_burst(rings_tx[i], objs, 10);
|
||||
if (ret <= 0)
|
||||
printf("Got no objects from ring %d - error code %d\n",
|
||||
i, ret);
|
||||
else {
|
||||
printf("Got %d object(s) from ring %d!\n", ret, i);
|
||||
for (j = 0; j < ret; j++) {
|
||||
mbuf = (struct rte_mbuf *)objs[j];
|
||||
rte_hexdump(stdout, "Object:", mbuf->pkt.data,
|
||||
mbuf->pkt.data_len);
|
||||
rte_pktmbuf_free(mbuf);
|
||||
}
|
||||
tx_count += ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (tx_count != expected_count) {
|
||||
RTE_LOG(INFO, PIPELINE,
|
||||
"%s: Unexpected packets out for %s test, expected %d, "
|
||||
"got %d\n", __func__, pipeline_test_names[test_type],
|
||||
expected_count, tx_count);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cleanup_pipeline();
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
test_table_pipeline(void)
|
||||
{
|
||||
/* TEST - All packets dropped */
|
||||
action_handler_hit = NULL;
|
||||
action_handler_miss = NULL;
|
||||
table_entry_default_action = RTE_PIPELINE_ACTION_DROP;
|
||||
setup_pipeline(e_TEST_STUB);
|
||||
if (test_pipeline_single_filter(e_TEST_STUB, 0) < 0)
|
||||
return -1;
|
||||
|
||||
/* TEST - All packets passed through */
|
||||
table_entry_default_action = RTE_PIPELINE_ACTION_PORT;
|
||||
setup_pipeline(e_TEST_STUB);
|
||||
if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0)
|
||||
return -1;
|
||||
|
||||
/* TEST - one packet per port */
|
||||
action_handler_hit = NULL;
|
||||
action_handler_miss =
|
||||
(rte_pipeline_table_action_handler_miss) table_action_stub_miss;
|
||||
table_entry_default_action = RTE_PIPELINE_ACTION_PORT;
|
||||
override_miss_mask = 0x01; /* one packet per port */
|
||||
setup_pipeline(e_TEST_STUB);
|
||||
if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0)
|
||||
return -1;
|
||||
|
||||
/* TEST - one packet per port */
|
||||
override_miss_mask = 0x02; /*all per port */
|
||||
setup_pipeline(e_TEST_STUB);
|
||||
if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0)
|
||||
return -1;
|
||||
|
||||
/* TEST - all packets per port */
|
||||
override_miss_mask = 0x03; /*all per port */
|
||||
setup_pipeline(e_TEST_STUB);
|
||||
if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* This test will set up two tables in the pipeline. the first table
|
||||
* will forward to another table on miss, and the second table will
|
||||
* forward to port.
|
||||
*/
|
||||
connect_miss_action_to_table = 1;
|
||||
table_entry_default_action = RTE_PIPELINE_ACTION_TABLE;
|
||||
action_handler_hit = NULL; /* not for stub, hitmask always zero */
|
||||
action_handler_miss = NULL;
|
||||
setup_pipeline(e_TEST_STUB);
|
||||
if (test_pipeline_single_filter(e_TEST_STUB, 4) < 0)
|
||||
return -1;
|
||||
connect_miss_action_to_table = 0;
|
||||
|
||||
printf("TEST - two tables, hitmask override to 0x01\n");
|
||||
connect_miss_action_to_table = 1;
|
||||
action_handler_miss =
|
||||
(rte_pipeline_table_action_handler_miss)table_action_stub_miss;
|
||||
override_miss_mask = 0x01;
|
||||
setup_pipeline(e_TEST_STUB);
|
||||
if (test_pipeline_single_filter(e_TEST_STUB, 2) < 0)
|
||||
return -1;
|
||||
connect_miss_action_to_table = 0;
|
||||
|
||||
if (check_pipeline_invalid_params()) {
|
||||
RTE_LOG(INFO, PIPELINE, "%s: Check pipeline invalid params "
|
||||
"failed.\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
35
app/test/test_table_pipeline.h
Normal file
35
app/test/test_table_pipeline.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Test prototypes */
|
||||
int test_table_pipeline(void);
|
224
app/test/test_table_ports.c
Normal file
224
app/test/test_table_ports.c
Normal file
@ -0,0 +1,224 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef RTE_LIBRTE_TABLE
|
||||
|
||||
#include "test_table_ports.h"
|
||||
#include "test_table.h"
|
||||
|
||||
port_test port_tests[] = {
|
||||
test_port_ring_reader,
|
||||
test_port_ring_writer,
|
||||
};
|
||||
|
||||
unsigned n_port_tests = RTE_DIM(port_tests);
|
||||
|
||||
/* Port tests */
|
||||
int
|
||||
test_port_ring_reader(void)
|
||||
{
|
||||
int status, i;
|
||||
struct rte_port_ring_reader_params port_ring_reader_params;
|
||||
void *port;
|
||||
|
||||
/* Invalid params */
|
||||
port = rte_port_ring_reader_ops.f_create(NULL, 0);
|
||||
if (port != NULL)
|
||||
return -1;
|
||||
|
||||
status = rte_port_ring_reader_ops.f_free(port);
|
||||
if (status >= 0)
|
||||
return -2;
|
||||
|
||||
/* Create and free */
|
||||
port_ring_reader_params.ring = RING_RX;
|
||||
port = rte_port_ring_reader_ops.f_create(&port_ring_reader_params, 0);
|
||||
if (port == NULL)
|
||||
return -3;
|
||||
|
||||
status = rte_port_ring_reader_ops.f_free(port);
|
||||
if (status != 0)
|
||||
return -4;
|
||||
|
||||
/* -- Traffic RX -- */
|
||||
int expected_pkts, received_pkts;
|
||||
struct rte_mbuf *res_mbuf[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
void *mbuf[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
|
||||
port_ring_reader_params.ring = RING_RX;
|
||||
port = rte_port_ring_reader_ops.f_create(&port_ring_reader_params, 0);
|
||||
|
||||
/* Single packet */
|
||||
mbuf[0] = (void *)rte_pktmbuf_alloc(pool);
|
||||
|
||||
expected_pkts = rte_ring_sp_enqueue_burst(port_ring_reader_params.ring,
|
||||
mbuf, 1);
|
||||
received_pkts = rte_port_ring_reader_ops.f_rx(port, res_mbuf, 1);
|
||||
|
||||
if (received_pkts < expected_pkts)
|
||||
return -5;
|
||||
|
||||
rte_pktmbuf_free(res_mbuf[0]);
|
||||
|
||||
/* Multiple packets */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
mbuf[i] = rte_pktmbuf_alloc(pool);
|
||||
|
||||
expected_pkts = rte_ring_sp_enqueue_burst(port_ring_reader_params.ring,
|
||||
(void * const *) mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
|
||||
received_pkts = rte_port_ring_reader_ops.f_rx(port, res_mbuf,
|
||||
RTE_PORT_IN_BURST_SIZE_MAX);
|
||||
|
||||
if (received_pkts < expected_pkts)
|
||||
return -6;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(res_mbuf[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_port_ring_writer(void)
|
||||
{
|
||||
int status, i;
|
||||
struct rte_port_ring_writer_params port_ring_writer_params;
|
||||
void *port;
|
||||
|
||||
/* Invalid params */
|
||||
port = rte_port_ring_writer_ops.f_create(NULL, 0);
|
||||
if (port != NULL)
|
||||
return -1;
|
||||
|
||||
status = rte_port_ring_writer_ops.f_free(port);
|
||||
if (status >= 0)
|
||||
return -2;
|
||||
|
||||
port_ring_writer_params.ring = NULL;
|
||||
|
||||
port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0);
|
||||
if (port != NULL)
|
||||
return -3;
|
||||
|
||||
port_ring_writer_params.ring = RING_TX;
|
||||
port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX + 1;
|
||||
|
||||
port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0);
|
||||
if (port != NULL)
|
||||
return -4;
|
||||
|
||||
/* Create and free */
|
||||
port_ring_writer_params.ring = RING_TX;
|
||||
port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX;
|
||||
|
||||
port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0);
|
||||
if (port == NULL)
|
||||
return -5;
|
||||
|
||||
status = rte_port_ring_writer_ops.f_free(port);
|
||||
if (status != 0)
|
||||
return -6;
|
||||
|
||||
/* -- Traffic TX -- */
|
||||
int expected_pkts, received_pkts;
|
||||
struct rte_mbuf *mbuf[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
struct rte_mbuf *res_mbuf[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
|
||||
port_ring_writer_params.ring = RING_TX;
|
||||
port_ring_writer_params.tx_burst_sz = RTE_PORT_IN_BURST_SIZE_MAX;
|
||||
port = rte_port_ring_writer_ops.f_create(&port_ring_writer_params, 0);
|
||||
|
||||
/* Single packet */
|
||||
mbuf[0] = rte_pktmbuf_alloc(pool);
|
||||
|
||||
rte_port_ring_writer_ops.f_tx(port, mbuf[0]);
|
||||
rte_port_ring_writer_ops.f_flush(port);
|
||||
expected_pkts = 1;
|
||||
received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring,
|
||||
(void **)res_mbuf, port_ring_writer_params.tx_burst_sz);
|
||||
|
||||
if (received_pkts < expected_pkts)
|
||||
return -7;
|
||||
|
||||
rte_pktmbuf_free(res_mbuf[0]);
|
||||
|
||||
/* Multiple packets */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) {
|
||||
mbuf[i] = rte_pktmbuf_alloc(pool);
|
||||
rte_port_ring_writer_ops.f_tx(port, mbuf[i]);
|
||||
}
|
||||
|
||||
expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX;
|
||||
received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring,
|
||||
(void **)res_mbuf, port_ring_writer_params.tx_burst_sz);
|
||||
|
||||
if (received_pkts < expected_pkts)
|
||||
return -8;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(res_mbuf[i]);
|
||||
|
||||
/* TX Bulk */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
mbuf[i] = rte_pktmbuf_alloc(pool);
|
||||
rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)-1);
|
||||
|
||||
expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX;
|
||||
received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring,
|
||||
(void **)res_mbuf, port_ring_writer_params.tx_burst_sz);
|
||||
|
||||
if (received_pkts < expected_pkts)
|
||||
return -8;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(res_mbuf[i]);
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
mbuf[i] = rte_pktmbuf_alloc(pool);
|
||||
rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)-3);
|
||||
rte_port_ring_writer_ops.f_tx_bulk(port, mbuf, (uint64_t)2);
|
||||
|
||||
expected_pkts = RTE_PORT_IN_BURST_SIZE_MAX;
|
||||
received_pkts = rte_ring_sc_dequeue_burst(port_ring_writer_params.ring,
|
||||
(void **)res_mbuf, port_ring_writer_params.tx_burst_sz);
|
||||
|
||||
if (received_pkts < expected_pkts)
|
||||
return -9;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(res_mbuf[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
42
app/test/test_table_ports.h
Normal file
42
app/test/test_table_ports.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Test prototypes */
|
||||
int test_port_ring_reader(void);
|
||||
int test_port_ring_writer(void);
|
||||
|
||||
/* Extern variables */
|
||||
typedef int (*port_test)(void);
|
||||
|
||||
extern port_test port_tests[];
|
||||
extern unsigned n_port_tests;
|
907
app/test/test_table_tables.c
Normal file
907
app/test/test_table_tables.c
Normal file
@ -0,0 +1,907 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef RTE_LIBRTE_TABLE
|
||||
|
||||
#include <string.h>
|
||||
#include <rte_byteorder.h>
|
||||
#include <rte_table_lpm_ipv6.h>
|
||||
#include <rte_lru.h>
|
||||
#include <rte_cycles.h>
|
||||
#include "test_table_tables.h"
|
||||
#include "test_table.h"
|
||||
|
||||
table_test table_tests[] = {
|
||||
test_table_stub,
|
||||
test_table_array,
|
||||
test_table_lpm,
|
||||
test_table_lpm_ipv6,
|
||||
test_table_hash_lru,
|
||||
test_table_hash_ext,
|
||||
};
|
||||
|
||||
#define PREPARE_PACKET(mbuf, value) do { \
|
||||
uint32_t *k32, *signature; \
|
||||
uint8_t *key; \
|
||||
mbuf = rte_pktmbuf_alloc(pool); \
|
||||
signature = RTE_MBUF_METADATA_UINT32_PTR(mbuf, 0); \
|
||||
key = RTE_MBUF_METADATA_UINT8_PTR(mbuf, 32); \
|
||||
memset(key, 0, 32); \
|
||||
k32 = (uint32_t *) key; \
|
||||
k32[0] = (value); \
|
||||
*signature = pipeline_test_hash(key, 0, 0); \
|
||||
} while (0)
|
||||
|
||||
unsigned n_table_tests = RTE_DIM(table_tests);
|
||||
|
||||
/* Function prototypes */
|
||||
static int
|
||||
test_table_hash_lru_generic(struct rte_table_ops *ops);
|
||||
static int
|
||||
test_table_hash_ext_generic(struct rte_table_ops *ops);
|
||||
|
||||
struct rte_bucket_4_8 {
|
||||
/* Cache line 0 */
|
||||
uint64_t signature;
|
||||
uint64_t lru_list;
|
||||
struct rte_bucket_4_8 *next;
|
||||
uint64_t next_valid;
|
||||
uint64_t key[4];
|
||||
/* Cache line 1 */
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
#if RTE_TABLE_HASH_LRU_STRATEGY == 3
|
||||
uint64_t shuffles = 0xfffffffdfffbfff9ULL;
|
||||
#else
|
||||
uint64_t shuffles = 0x0003000200010000ULL;
|
||||
#endif
|
||||
|
||||
static int test_lru_update(void)
|
||||
{
|
||||
struct rte_bucket_4_8 b;
|
||||
struct rte_bucket_4_8 *bucket;
|
||||
uint32_t i;
|
||||
uint64_t pos;
|
||||
uint64_t iterations;
|
||||
uint64_t j;
|
||||
int poss;
|
||||
|
||||
printf("---------------------------\n");
|
||||
printf("Testing lru_update macro...\n");
|
||||
printf("---------------------------\n");
|
||||
bucket = &b;
|
||||
iterations = 10;
|
||||
#if RTE_TABLE_HASH_LRU_STRATEGY == 3
|
||||
bucket->lru_list = 0xFFFFFFFFFFFFFFFFULL;
|
||||
#else
|
||||
bucket->lru_list = 0x0000000100020003ULL;
|
||||
#endif
|
||||
poss = 0;
|
||||
for (j = 0; j < iterations; j++)
|
||||
for (i = 0; i < 9; i++) {
|
||||
uint32_t idx = i >> 1;
|
||||
lru_update(bucket, idx);
|
||||
pos = lru_pos(bucket);
|
||||
poss += pos;
|
||||
printf("%s: %d lru_list=%016"PRIx64", upd=%d, "
|
||||
"pos=%"PRIx64"\n",
|
||||
__func__, i, bucket->lru_list, i>>1, pos);
|
||||
}
|
||||
|
||||
if (bucket->lru_list != shuffles) {
|
||||
printf("%s: ERROR: %d lru_list=%016"PRIx64", expected %016"
|
||||
PRIx64"\n",
|
||||
__func__, i, bucket->lru_list, shuffles);
|
||||
return -1;
|
||||
}
|
||||
printf("%s: output checksum of results =%d\n",
|
||||
__func__, poss);
|
||||
#if 0
|
||||
if (poss != 126) {
|
||||
printf("%s: ERROR output checksum of results =%d expected %d\n",
|
||||
__func__, poss, 126);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
uint64_t sc_start = rte_rdtsc();
|
||||
iterations = 100000000;
|
||||
poss = 0;
|
||||
for (j = 0; j < iterations; j++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
lru_update(bucket, i);
|
||||
pos |= bucket->lru_list;
|
||||
}
|
||||
}
|
||||
uint64_t sc_end = rte_rdtsc();
|
||||
|
||||
printf("%s: output checksum of results =%llu\n",
|
||||
__func__, (long long unsigned int)pos);
|
||||
printf("%s: start=%016"PRIx64", end=%016"PRIx64"\n",
|
||||
__func__, sc_start, sc_end);
|
||||
printf("\nlru_update: %lu cycles per loop iteration.\n\n",
|
||||
(long unsigned int)((sc_end-sc_start)/(iterations*4)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Table tests */
|
||||
int
|
||||
test_table_stub(void)
|
||||
{
|
||||
int i;
|
||||
uint64_t expected_mask = 0, result_mask;
|
||||
struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
void *table;
|
||||
char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
|
||||
/* Create */
|
||||
table = rte_table_stub_ops.f_create(NULL, 0, 1);
|
||||
if (table == NULL)
|
||||
return -1;
|
||||
|
||||
/* Traffic flow */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
if (i % 2 == 0)
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadad);
|
||||
else
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadab);
|
||||
|
||||
expected_mask = 0;
|
||||
rte_table_stub_ops.f_lookup(table, mbufs, -1,
|
||||
&result_mask, (void **)entries);
|
||||
if (result_mask != expected_mask)
|
||||
return -2;
|
||||
|
||||
/* Free resources */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(mbufs[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_array(void)
|
||||
{
|
||||
int status, i;
|
||||
uint64_t result_mask;
|
||||
struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
void *table;
|
||||
char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
char entry1, entry2;
|
||||
void *entry_ptr;
|
||||
int key_found;
|
||||
|
||||
/* Create */
|
||||
struct rte_table_array_params array_params;
|
||||
|
||||
table = rte_table_array_ops.f_create(NULL, 0, 1);
|
||||
if (table != NULL)
|
||||
return -1;
|
||||
|
||||
array_params.n_entries = 0;
|
||||
|
||||
table = rte_table_array_ops.f_create(&array_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
array_params.n_entries = 7;
|
||||
|
||||
table = rte_table_array_ops.f_create(&array_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -3;
|
||||
|
||||
array_params.n_entries = 1 << 24;
|
||||
array_params.offset = 1;
|
||||
|
||||
table = rte_table_array_ops.f_create(&array_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -4;
|
||||
|
||||
array_params.offset = 32;
|
||||
|
||||
table = rte_table_array_ops.f_create(&array_params, 0, 1);
|
||||
if (table == NULL)
|
||||
return -5;
|
||||
|
||||
/* Free */
|
||||
status = rte_table_array_ops.f_free(table);
|
||||
if (status < 0)
|
||||
return -6;
|
||||
|
||||
status = rte_table_array_ops.f_free(NULL);
|
||||
if (status == 0)
|
||||
return -7;
|
||||
|
||||
/* Add */
|
||||
struct rte_table_array_key array_key_1 = {
|
||||
.pos = 10,
|
||||
};
|
||||
struct rte_table_array_key array_key_2 = {
|
||||
.pos = 20,
|
||||
};
|
||||
entry1 = 'A';
|
||||
entry2 = 'B';
|
||||
|
||||
table = rte_table_array_ops.f_create(&array_params, 0, 1);
|
||||
if (table == NULL)
|
||||
return -8;
|
||||
|
||||
status = rte_table_array_ops.f_add(NULL, (void *) &array_key_1, &entry1,
|
||||
&key_found, &entry_ptr);
|
||||
if (status == 0)
|
||||
return -9;
|
||||
|
||||
status = rte_table_array_ops.f_add(table, (void *) &array_key_1, NULL,
|
||||
&key_found, &entry_ptr);
|
||||
if (status == 0)
|
||||
return -10;
|
||||
|
||||
status = rte_table_array_ops.f_add(table, (void *) &array_key_1,
|
||||
&entry1, &key_found, &entry_ptr);
|
||||
if (status != 0)
|
||||
return -11;
|
||||
|
||||
/* Traffic flow */
|
||||
status = rte_table_array_ops.f_add(table, (void *) &array_key_2,
|
||||
&entry2, &key_found, &entry_ptr);
|
||||
if (status != 0)
|
||||
return -12;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
if (i % 2 == 0)
|
||||
PREPARE_PACKET(mbufs[i], 10);
|
||||
else
|
||||
PREPARE_PACKET(mbufs[i], 20);
|
||||
|
||||
rte_table_array_ops.f_lookup(table, mbufs, -1,
|
||||
&result_mask, (void **)entries);
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
if (i % 2 == 0 && *entries[i] != 'A')
|
||||
return -13;
|
||||
else
|
||||
if (i % 2 == 1 && *entries[i] != 'B')
|
||||
return -13;
|
||||
|
||||
/* Free resources */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(mbufs[i]);
|
||||
|
||||
status = rte_table_array_ops.f_free(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_lpm(void)
|
||||
{
|
||||
int status, i;
|
||||
uint64_t expected_mask = 0, result_mask;
|
||||
struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
void *table;
|
||||
char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
char entry;
|
||||
void *entry_ptr;
|
||||
int key_found;
|
||||
uint32_t entry_size = 1;
|
||||
|
||||
/* Create */
|
||||
struct rte_table_lpm_params lpm_params;
|
||||
|
||||
table = rte_table_lpm_ops.f_create(NULL, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -1;
|
||||
|
||||
lpm_params.n_rules = 0;
|
||||
|
||||
table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
lpm_params.n_rules = 1 << 24;
|
||||
lpm_params.offset = 1;
|
||||
|
||||
table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -3;
|
||||
|
||||
lpm_params.offset = 32;
|
||||
lpm_params.entry_unique_size = 0;
|
||||
|
||||
table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -4;
|
||||
|
||||
lpm_params.entry_unique_size = entry_size + 1;
|
||||
|
||||
table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -5;
|
||||
|
||||
lpm_params.entry_unique_size = entry_size;
|
||||
|
||||
table = rte_table_lpm_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table == NULL)
|
||||
return -6;
|
||||
|
||||
/* Free */
|
||||
status = rte_table_lpm_ops.f_free(table);
|
||||
if (status < 0)
|
||||
return -7;
|
||||
|
||||
status = rte_table_lpm_ops.f_free(NULL);
|
||||
if (status == 0)
|
||||
return -8;
|
||||
|
||||
/* Add */
|
||||
struct rte_table_lpm_key lpm_key;
|
||||
lpm_key.ip = 0xadadadad;
|
||||
|
||||
table = rte_table_lpm_ops.f_create(&lpm_params, 0, 1);
|
||||
if (table == NULL)
|
||||
return -9;
|
||||
|
||||
status = rte_table_lpm_ops.f_add(NULL, &lpm_key, &entry, &key_found,
|
||||
&entry_ptr);
|
||||
if (status == 0)
|
||||
return -10;
|
||||
|
||||
status = rte_table_lpm_ops.f_add(table, NULL, &entry, &key_found,
|
||||
&entry_ptr);
|
||||
if (status == 0)
|
||||
return -11;
|
||||
|
||||
status = rte_table_lpm_ops.f_add(table, &lpm_key, NULL, &key_found,
|
||||
&entry_ptr);
|
||||
if (status == 0)
|
||||
return -12;
|
||||
|
||||
lpm_key.depth = 0;
|
||||
status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
|
||||
&entry_ptr);
|
||||
if (status == 0)
|
||||
return -13;
|
||||
|
||||
lpm_key.depth = 33;
|
||||
status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
|
||||
&entry_ptr);
|
||||
if (status == 0)
|
||||
return -14;
|
||||
|
||||
lpm_key.depth = 16;
|
||||
status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
|
||||
&entry_ptr);
|
||||
if (status != 0)
|
||||
return -15;
|
||||
|
||||
/* Delete */
|
||||
status = rte_table_lpm_ops.f_delete(NULL, &lpm_key, &key_found, NULL);
|
||||
if (status == 0)
|
||||
return -16;
|
||||
|
||||
status = rte_table_lpm_ops.f_delete(table, NULL, &key_found, NULL);
|
||||
if (status == 0)
|
||||
return -17;
|
||||
|
||||
lpm_key.depth = 0;
|
||||
status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
|
||||
if (status == 0)
|
||||
return -18;
|
||||
|
||||
lpm_key.depth = 33;
|
||||
status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
|
||||
if (status == 0)
|
||||
return -19;
|
||||
|
||||
lpm_key.depth = 16;
|
||||
status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
|
||||
if (status != 0)
|
||||
return -20;
|
||||
|
||||
status = rte_table_lpm_ops.f_delete(table, &lpm_key, &key_found, NULL);
|
||||
if (status != 0)
|
||||
return -21;
|
||||
|
||||
/* Traffic flow */
|
||||
entry = 'A';
|
||||
status = rte_table_lpm_ops.f_add(table, &lpm_key, &entry, &key_found,
|
||||
&entry_ptr);
|
||||
if (status < 0)
|
||||
return -22;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
if (i % 2 == 0) {
|
||||
expected_mask |= (uint64_t)1 << i;
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadad);
|
||||
} else
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadab);
|
||||
|
||||
rte_table_lpm_ops.f_lookup(table, mbufs, -1,
|
||||
&result_mask, (void **)entries);
|
||||
if (result_mask != expected_mask)
|
||||
return -21;
|
||||
|
||||
/* Free resources */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(mbufs[i]);
|
||||
|
||||
status = rte_table_lpm_ops.f_free(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_lpm_ipv6(void)
|
||||
{
|
||||
int status, i;
|
||||
uint64_t expected_mask = 0, result_mask;
|
||||
struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
void *table;
|
||||
char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
char entry;
|
||||
void *entry_ptr;
|
||||
int key_found;
|
||||
uint32_t entry_size = 1;
|
||||
|
||||
/* Create */
|
||||
struct rte_table_lpm_ipv6_params lpm_params;
|
||||
|
||||
table = rte_table_lpm_ipv6_ops.f_create(NULL, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -1;
|
||||
|
||||
lpm_params.n_rules = 0;
|
||||
|
||||
table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
lpm_params.n_rules = 1 << 24;
|
||||
lpm_params.number_tbl8s = 0;
|
||||
table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
lpm_params.number_tbl8s = 1 << 21;
|
||||
lpm_params.entry_unique_size = 0;
|
||||
table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
lpm_params.entry_unique_size = entry_size + 1;
|
||||
table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
lpm_params.entry_unique_size = entry_size;
|
||||
lpm_params.offset = 32;
|
||||
|
||||
table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table == NULL)
|
||||
return -3;
|
||||
|
||||
/* Free */
|
||||
status = rte_table_lpm_ipv6_ops.f_free(table);
|
||||
if (status < 0)
|
||||
return -4;
|
||||
|
||||
status = rte_table_lpm_ipv6_ops.f_free(NULL);
|
||||
if (status == 0)
|
||||
return -5;
|
||||
|
||||
/* Add */
|
||||
struct rte_table_lpm_ipv6_key lpm_key;
|
||||
|
||||
lpm_key.ip[0] = 0xad;
|
||||
lpm_key.ip[1] = 0xad;
|
||||
lpm_key.ip[2] = 0xad;
|
||||
lpm_key.ip[3] = 0xad;
|
||||
|
||||
table = rte_table_lpm_ipv6_ops.f_create(&lpm_params, 0, entry_size);
|
||||
if (table == NULL)
|
||||
return -6;
|
||||
|
||||
status = rte_table_lpm_ipv6_ops.f_add(NULL, &lpm_key, &entry,
|
||||
&key_found, &entry_ptr);
|
||||
if (status == 0)
|
||||
return -7;
|
||||
|
||||
status = rte_table_lpm_ipv6_ops.f_add(table, NULL, &entry, &key_found,
|
||||
&entry_ptr);
|
||||
if (status == 0)
|
||||
return -8;
|
||||
|
||||
status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, NULL, &key_found,
|
||||
&entry_ptr);
|
||||
if (status == 0)
|
||||
return -9;
|
||||
|
||||
lpm_key.depth = 0;
|
||||
status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
|
||||
&key_found, &entry_ptr);
|
||||
if (status == 0)
|
||||
return -10;
|
||||
|
||||
lpm_key.depth = 129;
|
||||
status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
|
||||
&key_found, &entry_ptr);
|
||||
if (status == 0)
|
||||
return -11;
|
||||
|
||||
lpm_key.depth = 16;
|
||||
status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
|
||||
&key_found, &entry_ptr);
|
||||
if (status != 0)
|
||||
return -12;
|
||||
|
||||
/* Delete */
|
||||
status = rte_table_lpm_ipv6_ops.f_delete(NULL, &lpm_key, &key_found,
|
||||
NULL);
|
||||
if (status == 0)
|
||||
return -13;
|
||||
|
||||
status = rte_table_lpm_ipv6_ops.f_delete(table, NULL, &key_found, NULL);
|
||||
if (status == 0)
|
||||
return -14;
|
||||
|
||||
lpm_key.depth = 0;
|
||||
status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
|
||||
NULL);
|
||||
if (status == 0)
|
||||
return -15;
|
||||
|
||||
lpm_key.depth = 129;
|
||||
status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
|
||||
NULL);
|
||||
if (status == 0)
|
||||
return -16;
|
||||
|
||||
lpm_key.depth = 16;
|
||||
status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
|
||||
NULL);
|
||||
if (status != 0)
|
||||
return -17;
|
||||
|
||||
status = rte_table_lpm_ipv6_ops.f_delete(table, &lpm_key, &key_found,
|
||||
NULL);
|
||||
if (status != 0)
|
||||
return -18;
|
||||
|
||||
/* Traffic flow */
|
||||
entry = 'A';
|
||||
status = rte_table_lpm_ipv6_ops.f_add(table, &lpm_key, &entry,
|
||||
&key_found, &entry_ptr);
|
||||
if (status < 0)
|
||||
return -19;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
if (i % 2 == 0) {
|
||||
expected_mask |= (uint64_t)1 << i;
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadad);
|
||||
} else
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadab);
|
||||
|
||||
rte_table_lpm_ipv6_ops.f_lookup(table, mbufs, -1,
|
||||
&result_mask, (void **)entries);
|
||||
if (result_mask != expected_mask)
|
||||
return -20;
|
||||
|
||||
/* Free resources */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(mbufs[i]);
|
||||
|
||||
status = rte_table_lpm_ipv6_ops.f_free(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_table_hash_lru_generic(struct rte_table_ops *ops)
|
||||
{
|
||||
int status, i;
|
||||
uint64_t expected_mask = 0, result_mask;
|
||||
struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
void *table;
|
||||
char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
char entry;
|
||||
void *entry_ptr;
|
||||
int key_found;
|
||||
|
||||
/* Create */
|
||||
struct rte_table_hash_key8_lru_params hash_params;
|
||||
|
||||
hash_params.n_entries = 0;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -1;
|
||||
|
||||
hash_params.n_entries = 1 << 10;
|
||||
hash_params.signature_offset = 1;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
hash_params.signature_offset = 0;
|
||||
hash_params.key_offset = 1;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -3;
|
||||
|
||||
hash_params.key_offset = 32;
|
||||
hash_params.f_hash = NULL;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -4;
|
||||
|
||||
hash_params.f_hash = pipeline_test_hash;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table == NULL)
|
||||
return -5;
|
||||
|
||||
/* Free */
|
||||
status = ops->f_free(table);
|
||||
if (status < 0)
|
||||
return -6;
|
||||
|
||||
status = ops->f_free(NULL);
|
||||
if (status == 0)
|
||||
return -7;
|
||||
|
||||
/* Add */
|
||||
uint8_t key[32];
|
||||
uint32_t *k32 = (uint32_t *) &key;
|
||||
|
||||
memset(key, 0, 32);
|
||||
k32[0] = rte_be_to_cpu_32(0xadadadad);
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table == NULL)
|
||||
return -8;
|
||||
|
||||
entry = 'A';
|
||||
status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
|
||||
if (status != 0)
|
||||
return -9;
|
||||
|
||||
/* Delete */
|
||||
status = ops->f_delete(table, &key, &key_found, NULL);
|
||||
if (status != 0)
|
||||
return -10;
|
||||
|
||||
status = ops->f_delete(table, &key, &key_found, NULL);
|
||||
if (status != 0)
|
||||
return -11;
|
||||
|
||||
/* Traffic flow */
|
||||
entry = 'A';
|
||||
status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
|
||||
if (status < 0)
|
||||
return -12;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
if (i % 2 == 0) {
|
||||
expected_mask |= (uint64_t)1 << i;
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadad);
|
||||
} else
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadab);
|
||||
|
||||
ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
|
||||
if (result_mask != expected_mask)
|
||||
return -13;
|
||||
|
||||
/* Free resources */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(mbufs[i]);
|
||||
|
||||
status = ops->f_free(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
test_table_hash_ext_generic(struct rte_table_ops *ops)
|
||||
{
|
||||
int status, i;
|
||||
uint64_t expected_mask = 0, result_mask;
|
||||
struct rte_mbuf *mbufs[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
void *table;
|
||||
char *entries[RTE_PORT_IN_BURST_SIZE_MAX];
|
||||
char entry;
|
||||
int key_found;
|
||||
void *entry_ptr;
|
||||
|
||||
/* Create */
|
||||
struct rte_table_hash_key8_ext_params hash_params;
|
||||
|
||||
hash_params.n_entries = 0;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -1;
|
||||
|
||||
hash_params.n_entries = 1 << 10;
|
||||
hash_params.n_entries_ext = 0;
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
hash_params.n_entries_ext = 1 << 4;
|
||||
hash_params.signature_offset = 1;
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -2;
|
||||
|
||||
hash_params.signature_offset = 0;
|
||||
hash_params.key_offset = 1;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -3;
|
||||
|
||||
hash_params.key_offset = 32;
|
||||
hash_params.f_hash = NULL;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table != NULL)
|
||||
return -4;
|
||||
|
||||
hash_params.f_hash = pipeline_test_hash;
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table == NULL)
|
||||
return -5;
|
||||
|
||||
/* Free */
|
||||
status = ops->f_free(table);
|
||||
if (status < 0)
|
||||
return -6;
|
||||
|
||||
status = ops->f_free(NULL);
|
||||
if (status == 0)
|
||||
return -7;
|
||||
|
||||
/* Add */
|
||||
uint8_t key[32];
|
||||
uint32_t *k32 = (uint32_t *) &key;
|
||||
|
||||
memset(key, 0, 32);
|
||||
k32[0] = rte_be_to_cpu_32(0xadadadad);
|
||||
|
||||
table = ops->f_create(&hash_params, 0, 1);
|
||||
if (table == NULL)
|
||||
return -8;
|
||||
|
||||
entry = 'A';
|
||||
status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
|
||||
if (status != 0)
|
||||
return -9;
|
||||
|
||||
/* Delete */
|
||||
status = ops->f_delete(table, &key, &key_found, NULL);
|
||||
if (status != 0)
|
||||
return -10;
|
||||
|
||||
status = ops->f_delete(table, &key, &key_found, NULL);
|
||||
if (status != 0)
|
||||
return -11;
|
||||
|
||||
/* Traffic flow */
|
||||
entry = 'A';
|
||||
status = ops->f_add(table, &key, &entry, &key_found, &entry_ptr);
|
||||
if (status < 0)
|
||||
return -12;
|
||||
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
if (i % 2 == 0) {
|
||||
expected_mask |= (uint64_t)1 << i;
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadad);
|
||||
} else
|
||||
PREPARE_PACKET(mbufs[i], 0xadadadab);
|
||||
|
||||
ops->f_lookup(table, mbufs, -1, &result_mask, (void **)entries);
|
||||
if (result_mask != expected_mask)
|
||||
return -13;
|
||||
|
||||
/* Free resources */
|
||||
for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
|
||||
rte_pktmbuf_free(mbufs[i]);
|
||||
|
||||
status = ops->f_free(table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_hash_lru(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = test_table_hash_lru_generic(&rte_table_hash_key8_lru_ops);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = test_table_hash_lru_generic(
|
||||
&rte_table_hash_key8_lru_dosig_ops);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = test_table_hash_lru_generic(&rte_table_hash_key16_lru_ops);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = test_table_hash_lru_generic(&rte_table_hash_key32_lru_ops);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = test_lru_update();
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
test_table_hash_ext(void)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = test_table_hash_ext_generic(&rte_table_hash_key8_ext_ops);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = test_table_hash_ext_generic(
|
||||
&rte_table_hash_key8_ext_dosig_ops);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = test_table_hash_ext_generic(&rte_table_hash_key16_ext_ops);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = test_table_hash_ext_generic(&rte_table_hash_key32_ext_ops);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
50
app/test/test_table_tables.h
Normal file
50
app/test/test_table_tables.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Test prototypes */
|
||||
int test_table_lpm(void);
|
||||
int test_table_lpm_ipv6(void);
|
||||
int test_table_array(void);
|
||||
#ifdef RTE_LIBRTE_ACL
|
||||
int test_table_acl(void);
|
||||
#endif
|
||||
int test_table_hash_unoptimized(void);
|
||||
int test_table_hash_lru(void);
|
||||
int test_table_hash_ext(void);
|
||||
int test_table_stub(void);
|
||||
|
||||
/* Extern variables */
|
||||
typedef int (*table_test)(void);
|
||||
|
||||
extern table_test table_tests[];
|
||||
extern unsigned n_table_tests;
|
@ -39,6 +39,8 @@
|
||||
* Simple API to dump out memory in a special hex format.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user