Message ID | 1422031471-30427-2-git-send-email-bala.manoharan@linaro.org |
---|---|
State | Accepted |
Commit | ac2ed396a463cb5c7fd0ec06bb42c4bb49015b94 |
Headers | show |
On 23 January 2015 at 11:44, <bala.manoharan@linaro.org> wrote: > From: Balasubramanian Manoharan <bala.manoharan@linaro.org> > Classification validation consists of two suites > * classification basic > This suite tests the basic classification APIs for creation and > deletion of various PMRs and CoS. > > * classification test > This suite tests behavious of different CoS once they are linked > behavious -> behaviors Maybe we can change that on commit. > to the pktio. This suite sends packets with different PMR TERM > values > across a loopback interface and tests the assigned CoS. > > Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org> > Reviewed-by: Mike Holmes <mike.holmes@linaro.org> > --- > v2: Incorporates review comments from Mike > > test/validation/.gitignore | 1 + > test/validation/Makefile.am | 8 +- > .../classification/odp_classification_basic.c | 178 +++++ > .../classification/odp_classification_tests.c | 816 > +++++++++++++++++++++ > .../classification/odp_classification_testsuites.h | 38 + > test/validation/odp_classification.c | 19 + > 6 files changed, 1058 insertions(+), 2 deletions(-) > create mode 100644 > test/validation/classification/odp_classification_basic.c > create mode 100644 > test/validation/classification/odp_classification_tests.c > create mode 100644 > test/validation/classification/odp_classification_testsuites.h > create mode 100644 test/validation/odp_classification.c > > diff --git a/test/validation/.gitignore b/test/validation/.gitignore > index a1d4d15..4a1ccb4 100644 > --- a/test/validation/.gitignore > +++ b/test/validation/.gitignore > @@ -3,6 +3,7 @@ > odp_init > odp_queue > odp_crypto > +odp_classification > odp_schedule > odp_shm > odp_system > diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am > index 0f5799c..c0e14cb 100644 > --- a/test/validation/Makefile.am > +++ b/test/validation/Makefile.am > @@ -6,13 +6,14 @@ AM_LDFLAGS += -static > TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform} > > if test_vald > -TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule odp_pktio_run > odp_buffer odp_system odp_timer odp_time odp_synchronizers > +TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule odp_pktio_run > odp_buffer odp_system odp_timer odp_time odp_synchronizers > odp_classification > check_PROGRAMS = ${bin_PROGRAMS} > endif > > -bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule > odp_pktio odp_buffer odp_system odp_timer odp_time odp_synchronizers > +bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule > odp_pktio odp_buffer odp_system odp_timer odp_time odp_synchronizers > odp_classification > odp_crypto_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/crypto > odp_buffer_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/buffer > +odp_classification_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/classification > > dist_odp_init_SOURCES = odp_init.c > dist_odp_pktio_SOURCES = odp_pktio.c common/odp_cunit_common.c > @@ -32,3 +33,6 @@ dist_odp_timer_SOURCES = odp_timer.c > common/odp_cunit_common.c > dist_odp_time_SOURCES = odp_time.c common/odp_cunit_common.c > dist_odp_synchronizers_SOURCES = odp_synchronizers.c \ > common/odp_cunit_common.c > +dist_odp_classification_SOURCES = > classification/odp_classification_tests.c \ > + classification/odp_classification_basic.c \ > + odp_classification.c > common/odp_cunit_common.c > diff --git a/test/validation/classification/odp_classification_basic.c > b/test/validation/classification/odp_classification_basic.c > new file mode 100644 > index 0000000..844b66e > --- /dev/null > +++ b/test/validation/classification/odp_classification_basic.c > @@ -0,0 +1,178 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include "odp_classification_testsuites.h" > + > +#define PMR_SET_NUM 5 > + > +static void classification_create_cos(void) > +{ > + odp_cos_t cos; > + char name[ODP_COS_NAME_LEN]; > + sprintf(name, "ClassOfService"); > + cos = odp_cos_create(name); > + CU_ASSERT_FATAL(cos != ODP_COS_INVALID); > + odp_cos_destroy(cos); > +} > + > +static void classification_destroy_cos(void) > +{ > + odp_cos_t cos; > + char name[ODP_COS_NAME_LEN]; > + int retval; > + sprintf(name, "ClassOfService"); > + cos = odp_cos_create(name); > + CU_ASSERT_FATAL(cos != ODP_COS_INVALID); > + retval = odp_cos_destroy(cos); > + CU_ASSERT(retval == 0); > + retval = odp_cos_destroy(ODP_COS_INVALID); > + CU_ASSERT(retval < 0); > +} > + > +static void classification_create_pmr_match(void) > +{ > + odp_pmr_t pmr; > + uint16_t val; > + uint16_t mask; > + val = 1024; > + mask = 0xffff; > + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, > sizeof(val)); > + CU_ASSERT(pmr != ODP_PMR_INVAL); > + odp_pmr_destroy(pmr); > +} > + > +static void classification_create_pmr_range(void) > +{ > + odp_pmr_t pmr; > + uint16_t val1; > + uint16_t val2; > + val1 = 1024; > + val2 = 2048; > + pmr = odp_pmr_create_range(ODP_PMR_TCP_SPORT, &val1, > + &val2, sizeof(val1)); > + CU_ASSERT(pmr != ODP_PMR_INVAL); > + odp_pmr_destroy(pmr); > +} > + > +static void classification_destroy_pmr(void) > +{ > + odp_pmr_t pmr; > + uint16_t val; > + uint16_t mask; > + int retval; > + val = 1024; > + mask = 0xffff; > + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, > sizeof(val)); > + retval = odp_pmr_destroy(pmr); > + CU_ASSERT(retval == 0); > + retval = odp_pmr_destroy(ODP_PMR_INVAL); > + retval = odp_pmr_destroy(ODP_PMR_INVAL); > + CU_ASSERT(retval < 0); > +} > + > +static void classification_cos_set_queue(void) > +{ > + int retval; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + odp_queue_param_t qparam; > + odp_queue_t queue_cos; > + odp_cos_t cos_queue; > + sprintf(cosname, "CoSQueue"); > + cos_queue = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_queue != ODP_COS_INVALID); > + > + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "QueueCoS"); > + > + queue_cos = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, &qparam); > + retval = odp_cos_set_queue(cos_queue, queue_cos); > + CU_ASSERT(retval == 0); > + odp_cos_destroy(cos_queue); > + odp_queue_destroy(queue_cos); > +} > + > +static void classification_cos_set_drop(void) > +{ > + int retval; > + char cosname[ODP_COS_NAME_LEN]; > + sprintf(cosname, "CoSDrop"); > + odp_cos_t cos_drop; > + cos_drop = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_drop != ODP_COS_INVALID); > + > + retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_POOL); > + CU_ASSERT(retval == 0); > + retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_NEVER); > + CU_ASSERT(retval == 0); > + odp_cos_destroy(cos_drop); > +} > + > +static void classification_pmr_match_set_create(void) > +{ > + odp_pmr_set_t pmr_set; > + int retval; > + odp_pmr_match_t pmr_terms[PMR_SET_NUM]; > + uint16_t val = 1024; > + uint16_t mask = 0xffff; > + int i; > + for (i = 0; i < PMR_SET_NUM; i++) { > + pmr_terms[i].match_type = ODP_PMR_MASK; > + pmr_terms[i].mask.term = ODP_PMR_TCP_DPORT; > + pmr_terms[i].mask.val = &val; > + pmr_terms[i].mask.mask = &mask; > + pmr_terms[i].mask.val_sz = sizeof(val); > + } > + > + retval = odp_pmr_match_set_create(PMR_SET_NUM, pmr_terms, > &pmr_set); > + CU_ASSERT(retval > 0); > + > + retval = odp_pmr_match_set_destroy(pmr_set); > + CU_ASSERT(retval == 0); > +} > + > +static void classification_pmr_match_set_destroy(void) > +{ > + odp_pmr_set_t pmr_set; > + int retval; > + odp_pmr_match_t pmr_terms[PMR_SET_NUM]; > + uint16_t val = 1024; > + uint16_t mask = 0xffff; > + int i; > + > + retval = odp_pmr_match_set_destroy(ODP_PMR_INVAL); > + CU_ASSERT(retval < 0); > + > + for (i = 0; i < PMR_SET_NUM; i++) { > + pmr_terms[i].match_type = ODP_PMR_MASK; > + pmr_terms[i].mask.term = ODP_PMR_TCP_DPORT; > + pmr_terms[i].mask.val = &val; > + pmr_terms[i].mask.mask = &mask; > + pmr_terms[i].mask.val_sz = sizeof(val); > + } > + > + retval = odp_pmr_match_set_create(PMR_SET_NUM, pmr_terms, > &pmr_set); > + CU_ASSERT(retval > 0); > + > + retval = odp_pmr_match_set_destroy(pmr_set); > + CU_ASSERT(retval == 0); > +} > + > +CU_TestInfo classification_basic[] = { > + _CU_TEST_INFO(classification_create_cos), > + _CU_TEST_INFO(classification_destroy_cos), > + _CU_TEST_INFO(classification_create_pmr_match), > + _CU_TEST_INFO(classification_create_pmr_range), > + _CU_TEST_INFO(classification_destroy_pmr), > + _CU_TEST_INFO(classification_cos_set_queue), > + _CU_TEST_INFO(classification_cos_set_drop), > + _CU_TEST_INFO(classification_pmr_match_set_create), > + _CU_TEST_INFO(classification_pmr_match_set_destroy), > + CU_TEST_INFO_NULL, > +}; > diff --git a/test/validation/classification/odp_classification_tests.c > b/test/validation/classification/odp_classification_tests.c > new file mode 100644 > index 0000000..778172c > --- /dev/null > +++ b/test/validation/classification/odp_classification_tests.c > @@ -0,0 +1,816 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include "odp_classification_testsuites.h" > +#include <odph_eth.h> > +#include <odph_ip.h> > +#include <odph_udp.h> > + > +#define SHM_PKT_NUM_BUFS 32 > +#define SHM_PKT_BUF_SIZE 1024 > + > +/* Config values for Default CoS */ > +#define TEST_DEFAULT 1 > +#define CLS_DEFAULT 0 > +#define CLS_DEFAULT_SADDR "10.0.0.1/32" > +#define CLS_DEFAULT_DADDR "10.0.0.100/32" > +#define CLS_DEFAULT_SPORT 1024 > +#define CLS_DEFAULT_DPORT 2048 > + > +/* Config values for Error CoS */ > +#define TEST_ERROR 1 > +#define CLS_ERROR 1 > + > +/* Config values for PMR_CHAIN */ > +#define TEST_PMR_CHAIN 1 > +#define CLS_PMR_CHAIN_SRC 2 > +#define CLS_PMR_CHAIN_DST 3 > +#define CLS_PMR_CHAIN_SADDR "10.0.0.5/32" > +#define CLS_PMR_CHAIN_SPORT 3000 > + > +/* Config values for PMR */ > +#define TEST_PMR 1 > +#define CLS_PMR 4 > +#define CLS_PMR_SPORT 4000 > + > +/* Config values for PMR SET */ > +#define TEST_PMR_SET 1 > +#define CLS_PMR_SET 5 > +#define CLS_PMR_SET_SADDR "10.0.0.6/32" > +#define CLS_PMR_SET_SPORT 5000 > + > +/* Config values for CoS L2 Priority */ > +#define TEST_L2_QOS 1 > +#define CLS_L2_QOS_0 6 > +#define CLS_L2_QOS_MAX 5 > + > +#define CLS_ENTRIES (CLS_L2_QOS_0 + CLS_L2_QOS_MAX) > + > +/* Test Packet values */ > +#define DATA_MAGIC 0x01020304 > +#define TEST_SEQ_INVALID ((uint32_t)~0) > + > +static odp_cos_t cos_list[CLS_ENTRIES]; > +static odp_pmr_t pmr_list[CLS_ENTRIES]; > +static odp_queue_t queue_list[CLS_ENTRIES]; > +static odp_pmr_set_t pmr_set; > + > +static odp_buffer_pool_t pool_default; > +static odp_pktio_t pktio_loop; > + > +/** sequence number of IP packets */ > +odp_atomic_u32_t seq; > + > +typedef struct cls_test_packet { > + uint32be_t magic; > + uint32be_t seq; > +} cls_test_packet_t; > + > +static inline > +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t > *mask) > +{ > + int b[4]; > + int qualifier = 32; > + int converted; > + > + if (strchr(ipaddress, '/')) { > + converted = sscanf(ipaddress, "%d.%d.%d.%d/%d", > + &b[3], &b[2], &b[1], &b[0], > + &qualifier); > + if (5 != converted) > + return -1; > + } else { > + converted = sscanf(ipaddress, "%d.%d.%d.%d", > + &b[3], &b[2], &b[1], &b[0]); > + if (4 != converted) > + return -1; > + } > + > + if ((b[0] > 255) || (b[1] > 255) || (b[2] > 255) || (b[3] > 255)) > + return -1; > + if (!qualifier || (qualifier > 32)) > + return -1; > + > + *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24; > + if (mask) > + *mask = ~(0xFFFFFFFF & ((1ULL << (32 - qualifier)) - 1)); > + > + return 0; > +} > + > +static inline > +void enqueue_loop_interface(odp_packet_t pkt) > +{ > + odp_queue_t defqueue = odp_pktio_outq_getdef(pktio_loop); > + odp_queue_enq(defqueue, odp_packet_to_buffer(pkt)); > +} > + > +static inline > +odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns) > +{ > + odp_buffer_t buf; > + odp_packet_t pkt; > + buf = odp_schedule(queue, ns); > + pkt = odp_packet_from_buffer(buf); > + return pkt; > +} > + > +static int cls_pkt_set_seq(odp_packet_t pkt) > +{ > + static uint32_t seq; > + cls_test_packet_t data; > + uint32_t offset; > + > + data.magic = DATA_MAGIC; > + data.seq = ++seq; > + > + offset = odp_packet_l4_offset(pkt); > + CU_ASSERT_FATAL(offset != 0); > + > + odp_packet_copydata_in(pkt, offset + ODPH_UDPHDR_LEN, > + sizeof(data), &data); > + > + return 0; > +} > + > +static uint32_t cls_pkt_get_seq(odp_packet_t pkt) > +{ > + uint32_t offset; > + cls_test_packet_t data; > + > + offset = odp_packet_l4_offset(pkt); > + if (offset) { > + odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN, > + sizeof(data), &data); > + > + if (data.magic == DATA_MAGIC) > + return data.seq; > + } > + > + return TEST_SEQ_INVALID; > +} > +odp_packet_t create_packet(bool vlan) > +{ > + uint32_t seqno; > + odph_ethhdr_t *ethhdr; > + odph_udphdr_t *udp; > + odph_ipv4hdr_t *ip; > + uint8_t payload_len; > + char src_mac[ODPH_ETHADDR_LEN] = {0}; > + char dst_mac[ODPH_ETHADDR_LEN] = {0}; > + uint32_t addr = 0; > + uint32_t mask; > + int offset; > + odp_packet_t pkt; > + int packet_len = 0; > + > + payload_len = sizeof(cls_test_packet_t); > + packet_len += ODPH_ETHHDR_LEN; > + packet_len += ODPH_IPV4HDR_LEN; > + packet_len += ODPH_UDPHDR_LEN; > + packet_len += payload_len; > + > + if (vlan) > + packet_len += ODPH_VLANHDR_LEN; > + > + pkt = odp_packet_alloc(pool_default, packet_len); > + CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); > + > + /* Ethernet Header */ > + offset = 0; > + odp_packet_l2_offset_set(pkt, offset); > + ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); > + memcpy(ethhdr->src.addr, src_mac, ODPH_ETHADDR_LEN); > + memcpy(ethhdr->dst.addr, dst_mac, ODPH_ETHADDR_LEN); > + offset += sizeof(odph_ethhdr_t); > + if (vlan) { > + /* Default vlan header */ > + uint8_t *parseptr; > + odph_vlanhdr_t *vlan = (odph_vlanhdr_t *)(ðhdr->type); > + parseptr = (uint8_t *)vlan; > + vlan->tci = odp_cpu_to_be_16(0); > + vlan->tpid = odp_cpu_to_be_16(ODPH_ETHTYPE_VLAN); > + offset += sizeof(odph_vlanhdr_t); > + parseptr += sizeof(odph_vlanhdr_t); > + uint16be_t *type = (uint16be_t *)parseptr; > + *type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); > + } else { > + ethhdr->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); > + } > + > + odp_packet_l3_offset_set(pkt, offset); > + > + /* ipv4 */ > + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); > + > + parse_ipv4_string(CLS_DEFAULT_SADDR, &addr, &mask); > + ip->dst_addr = odp_cpu_to_be_32(addr); > + > + parse_ipv4_string(CLS_DEFAULT_DADDR, &addr, &mask); > + ip->src_addr = odp_cpu_to_be_32(addr); > + ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN; > + ip->tot_len = odp_cpu_to_be_16(ODPH_UDPHDR_LEN + payload_len + > + ODPH_IPV4HDR_LEN); > + ip->ttl = 128; > + ip->proto = ODPH_IPPROTO_UDP; > + seqno = odp_atomic_fetch_inc_u32(&seq); > + ip->id = odp_cpu_to_be_16(seqno); > + ip->chksum = 0; > + odph_ipv4_csum_update(pkt); > + offset += ODPH_IPV4HDR_LEN; > + > + /* udp */ > + odp_packet_l4_offset_set(pkt, offset); > + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); > + udp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT); > + udp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT); > + udp->length = odp_cpu_to_be_16(payload_len + ODPH_UDPHDR_LEN); > + udp->chksum = 0; > + > + /* set pkt sequence number */ > + cls_pkt_set_seq(pkt); > + > + return pkt; > +} > + > +int classification_tests_init(void) > +{ > + odp_buffer_pool_t pool; > + odp_buffer_pool_param_t param; > + odp_queue_t inq_def; > + odp_queue_param_t qparam; > + char queuename[ODP_QUEUE_NAME_LEN]; > + int i; > + > + param.buf_size = SHM_PKT_BUF_SIZE; > + param.num_bufs = SHM_PKT_NUM_BUFS; > + param.buf_type = ODP_BUFFER_TYPE_PACKET; > + param.buf_align = 0; > + pool = odp_buffer_pool_create("classification_pool", > + ODP_SHM_NULL, ¶m); > + if (ODP_BUFFER_POOL_INVALID == pool) { > + fprintf(stderr, "Packet pool creation failed.\n"); > + return -1; > + } > + > + pool_default = odp_buffer_pool_lookup("classification_pool"); > + if (pool_default == ODP_BUFFER_POOL_INVALID) > + goto error_pool_default; > + > + pktio_loop = odp_pktio_open("loop", pool_default); > + if (pktio_loop == ODP_PKTIO_INVALID) > + goto error_pktio_loop; > + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; > + qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; > + qparam.sched.group = ODP_SCHED_GROUP_DEFAULT; > + > + sprintf(queuename, "%s", "inq_loop"); > + inq_def = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_PKTIN, &qparam); > + odp_pktio_inq_setdef(pktio_loop, inq_def); > + > + for (i = 0; i < CLS_ENTRIES; i++) > + cos_list[i] = ODP_COS_INVALID; > + > + for (i = 0; i < CLS_ENTRIES; i++) > + pmr_list[i] = ODP_PMR_INVAL; > + > + for (i = 0; i < CLS_ENTRIES; i++) > + queue_list[i] = ODP_QUEUE_INVALID; > + > + return 0; > + > +error_pktio_loop: > + odp_buffer_pool_destroy(pool_default); > + > +error_pool_default: > + return -1; > +} > + > +int classification_tests_finalize(void) > +{ > + int i; > + if (0 > odp_pktio_close(pktio_loop)) > + return -1; > + > + if (0 != odp_buffer_pool_destroy(pool_default)) > + return -1; > + > + for (i = 0; i < CLS_ENTRIES; i++) > + odp_cos_destroy(cos_list[i]); > + > + for (i = 0; i < CLS_ENTRIES; i++) > + odp_pmr_destroy(pmr_list[i]); > + > + for (i = 0; i < CLS_ENTRIES; i++) > + odp_queue_destroy(queue_list[i]); > + return 0; > +} > + > +void configure_cls_pmr_chain(void) > +{ > + /* PKTIO --> PMR_SRC(SRC IP ADDR) --> PMR_DST (TCP SPORT) */ > + > + /* Packet matching only the SRC IP ADDR should be delivered > + in queue[CLS_PMR_CHAIN_SRC] and a packet matching both SRC IP ADDR > and > + TCP SPORT should be delivered to queue[CLS_PMR_CHAIN_DST] */ > + > + uint16_t val; > + uint16_t maskport; > + int retval; > + char cosname[ODP_QUEUE_NAME_LEN]; > + odp_queue_param_t qparam; > + char queuename[ODP_QUEUE_NAME_LEN]; > + uint32_t addr; > + uint32_t mask; > + > + sprintf(cosname, "SrcCos"); > + cos_list[CLS_PMR_CHAIN_SRC] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_SRC] != ODP_COS_INVALID) > + > + qparam.sched.prio = ODP_SCHED_PRIO_NORMAL; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "SrcQueue"); > + > + queue_list[CLS_PMR_CHAIN_SRC] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + > + CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_SRC] != > ODP_QUEUE_INVALID); > + retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_SRC], > + queue_list[CLS_PMR_CHAIN_SRC]); > + CU_ASSERT(retval == 0); > + > + sprintf(cosname, "DstCos"); > + cos_list[CLS_PMR_CHAIN_DST] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_DST] != ODP_COS_INVALID); > + > + qparam.sched.prio = ODP_SCHED_PRIO_NORMAL; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "DstQueue"); > + > + queue_list[CLS_PMR_CHAIN_DST] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_DST] != > ODP_QUEUE_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_DST], > + queue_list[CLS_PMR_CHAIN_DST]); > + > + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); > + pmr_list[CLS_PMR_CHAIN_SRC] = > odp_pmr_create_match(ODP_PMR_SIP_ADDR, > + &addr, &mask, > + sizeof(addr)); > + CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_SRC] != ODP_PMR_INVAL); > + > + val = CLS_PMR_CHAIN_SPORT; > + maskport = 0xffff; > + pmr_list[CLS_PMR_CHAIN_DST] = > odp_pmr_create_match(ODP_PMR_UDP_SPORT, > + &val, &maskport, > + sizeof(val)); > + CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_DST] != ODP_PMR_INVAL); > + > + retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR_CHAIN_SRC], pktio_loop, > + cos_list[CLS_PMR_CHAIN_SRC]); > + CU_ASSERT(retval == 0); > + > + retval = odp_cos_pmr_cos(pmr_list[CLS_PMR_CHAIN_DST], > + cos_list[CLS_PMR_CHAIN_SRC], > + cos_list[CLS_PMR_CHAIN_DST]); > + CU_ASSERT(retval == 0); > +} > + > +void test_cls_pmr_chain(void) > +{ > + odp_packet_t pkt; > + odph_ipv4hdr_t *ip; > + odph_udphdr_t *udp; > + odp_queue_t queue; > + uint32_t addr = 0; > + uint32_t mask; > + uint32_t seq; > + > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); > + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); > + ip->src_addr = odp_cpu_to_be_32(addr); > + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); > + udp->src_port = odp_cpu_to_be_16(CLS_PMR_CHAIN_SPORT); > + > + enqueue_loop_interface(pkt); > + > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + odp_packet_free(pkt); > + > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); > + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); > + ip->src_addr = odp_cpu_to_be_32(addr); > + > + enqueue_loop_interface(pkt); > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + > + CU_ASSERT(1 == odp_pmr_match_count(pmr_list[CLS_PMR_CHAIN_DST])); > + odp_packet_free(pkt); > +} > + > +void configure_pktio_default_cos(void) > +{ > + int retval; > + odp_queue_param_t qparam; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + > + sprintf(cosname, "DefaultCoS"); > + cos_list[CLS_DEFAULT] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_DEFAULT] != ODP_COS_INVALID); > + > + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "DefaultQueue"); > + queue_list[CLS_DEFAULT] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_DEFAULT] != ODP_QUEUE_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_DEFAULT], > + queue_list[CLS_DEFAULT]); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_default_cos_set(pktio_loop, > cos_list[CLS_DEFAULT]); > + CU_ASSERT(retval == 0); > +} > + > +void test_pktio_default_cos(void) > +{ > + odp_packet_t pkt; > + odp_queue_t queue; > + uint32_t seq; > + /* create a default packet */ > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + enqueue_loop_interface(pkt); > + > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + /* Default packet should be received in default queue */ > + CU_ASSERT(queue == queue_list[CLS_DEFAULT]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + > + odp_packet_free(pkt); > +} > + > +void configure_pktio_error_cos(void) > +{ > + int retval; > + odp_queue_param_t qparam; > + char queuename[ODP_QUEUE_NAME_LEN]; > + char cosname[ODP_COS_NAME_LEN]; > + > + qparam.sched.prio = ODP_SCHED_PRIO_LOWEST; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "ErrorCos"); > + > + queue_list[CLS_ERROR] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_ERROR] != ODP_QUEUE_INVALID); > + > + sprintf(cosname, "%s", "ErrorCos"); > + cos_list[CLS_ERROR] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_ERROR] != ODP_COS_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_ERROR], > queue_list[CLS_ERROR]); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_error_cos_set(pktio_loop, cos_list[CLS_ERROR]); > + CU_ASSERT(retval == 0); > +} > + > +void test_pktio_error_cos(void) > +{ > + odp_queue_t queue; > + odp_packet_t pkt; > + > + /*Create an error packet */ > + pkt = create_packet(false); > + odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, > NULL); > + > + /* Incorrect IpV4 version */ > + ip->ver_ihl = 8 << 4 | ODPH_IPV4HDR_IHL_MIN; > + ip->chksum = 0; > + enqueue_loop_interface(pkt); > + > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + /* Error packet should be received in error queue */ > + CU_ASSERT(queue == queue_list[CLS_ERROR]); > + odp_packet_free(pkt); > +} > + > +static void classification_pktio_set_skip(void) > +{ > + int retval; > + size_t offset = 5; > + retval = odp_pktio_skip_set(pktio_loop, offset); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_skip_set(ODP_PKTIO_INVALID, offset); > + CU_ASSERT(retval < 0); > +} > + > +static void classification_pktio_set_headroom(void) > +{ > + size_t headroom; > + int retval; > + headroom = 5; > + retval = odp_pktio_headroom_set(pktio_loop, headroom); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_headroom_set(ODP_PKTIO_INVALID, headroom); > + CU_ASSERT(retval < 0); > +} > + > +void configure_cos_with_l2_priority(void) > +{ > + uint8_t num_qos = CLS_L2_QOS_MAX; > + odp_cos_t cos_tbl[CLS_L2_QOS_MAX]; > + odp_queue_t queue_tbl[CLS_L2_QOS_MAX]; > + uint8_t qos_tbl[CLS_L2_QOS_MAX]; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + int retval; > + int i; > + odp_queue_param_t qparam; > + > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + for (i = 0; i < num_qos; i++) { > + qparam.sched.prio = ODP_SCHED_PRIO_LOWEST - i; > + sprintf(cosname, "%s_%d", "L2_Cos", i); > + cos_tbl[i] = odp_cos_create(cosname); > + if (cos_tbl[i] == ODP_COS_INVALID) > + break; > + > + cos_list[CLS_L2_QOS_0 + i] = cos_tbl[i]; > + sprintf(queuename, "%s_%d", "L2_Queue", i); > + queue_tbl[i] = odp_queue_create(queuename, > ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_tbl[i] != ODP_QUEUE_INVALID); > + queue_list[CLS_L2_QOS_0 + i] = queue_tbl[i]; > + retval = odp_cos_set_queue(cos_tbl[i], queue_tbl[i]); > + CU_ASSERT(retval == 0); > + qos_tbl[i] = i; > + } > + /* count 'i' is passed instead of num_qos to handle the rare > scenario > + if the odp_cos_create() failed in the middle*/ > + retval = odp_cos_with_l2_priority(pktio_loop, i, qos_tbl, cos_tbl); > + CU_ASSERT(retval == 0); > +} > + > +void test_cos_with_l2_priority(void) > +{ > + odp_packet_t pkt; > + odph_ethhdr_t *ethhdr; > + odph_vlanhdr_t *vlan; > + odp_queue_t queue; > + uint32_t seq; > + > + uint8_t i; > + for (i = 0; i < CLS_L2_QOS_MAX; i++) { > + pkt = create_packet(true); > + seq = cls_pkt_get_seq(pkt); > + ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); > + vlan = (odph_vlanhdr_t *)(ðhdr->type); > + vlan->tci = odp_cpu_to_be_16(i << 13); > + enqueue_loop_interface(pkt); > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + odp_packet_free(pkt); > + } > +} > + > +void configure_pmr_cos(void) > +{ > + uint16_t val; > + uint16_t mask; > + int retval; > + val = CLS_PMR_SPORT; > + mask = 0xffff; > + odp_queue_param_t qparam; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + > + pmr_list[CLS_PMR] = odp_pmr_create_match(ODP_PMR_UDP_SPORT, &val, > + &mask, sizeof(val)); > + CU_ASSERT(pmr_list[CLS_PMR] != ODP_PMR_INVAL); > + > + sprintf(cosname, "PMR_CoS"); > + cos_list[CLS_PMR] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_PMR] != ODP_COS_INVALID); > + > + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "PMR_CoS"); > + > + queue_list[CLS_PMR] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_PMR] != ODP_QUEUE_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_PMR], > + queue_list[CLS_PMR]); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR], pktio_loop, > + cos_list[CLS_PMR]); > + CU_ASSERT(retval == 0); > +} > + > +void test_pmr_cos(void) > +{ > + odp_packet_t pkt; > + odph_udphdr_t *udp; > + odp_queue_t queue; > + uint32_t seq; > + > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); > + udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT); > + enqueue_loop_interface(pkt); > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_PMR]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + CU_ASSERT(1 == odp_pmr_match_count(pmr_list[CLS_PMR])); > + odp_packet_free(pkt); > +} > + > +void configure_pktio_pmr_match_set_cos(void) > +{ > + int retval; > + odp_pmr_match_t pmr_terms[2]; > + uint16_t val; > + uint16_t maskport; > + int num_terms = 2; /* one pmr for each L3 and L4 */ > + odp_queue_param_t qparam; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + uint32_t addr = 0; > + uint32_t mask; > + > + parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); > + pmr_terms[0].match_type = ODP_PMR_MASK; > + pmr_terms[0].mask.term = ODP_PMR_SIP_ADDR; > + pmr_terms[0].mask.val = &addr; > + pmr_terms[0].mask.mask = &mask; > + pmr_terms[0].mask.val_sz = sizeof(addr); > + > + > + val = CLS_PMR_SET_SPORT; > + maskport = 0xffff; > + pmr_terms[1].match_type = ODP_PMR_MASK; > + pmr_terms[1].mask.term = ODP_PMR_UDP_SPORT; > + pmr_terms[1].mask.val = &val; > + pmr_terms[1].mask.mask = &maskport; > + pmr_terms[1].mask.val_sz = sizeof(val); > + > + retval = odp_pmr_match_set_create(num_terms, pmr_terms, &pmr_set); > + CU_ASSERT(retval > 0); > + > + sprintf(cosname, "cos_pmr_set"); > + cos_list[CLS_PMR_SET] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_PMR_SET] != ODP_COS_INVALID) > + > + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "cos_pmr_set_queue"); > + > + queue_list[CLS_PMR_SET] = odp_queue_create(queuename, > + > ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_PMR_SET] != ODP_QUEUE_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_PMR_SET], > + queue_list[CLS_PMR_SET]); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_pmr_match_set_cos(pmr_set, pktio_loop, > + cos_list[CLS_PMR_SET]); > + CU_ASSERT(retval == 0); > +} > + > +void test_pktio_pmr_match_set_cos(void) > +{ > + uint32_t addr = 0; > + uint32_t mask; > + odph_ipv4hdr_t *ip; > + odph_udphdr_t *udp; > + odp_packet_t pkt; > + odp_queue_t queue; > + uint32_t seq; > + > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); > + parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); > + ip->src_addr = odp_cpu_to_be_32(addr); > + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); > + udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT); > + enqueue_loop_interface(pkt); > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_PMR_SET]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + odp_packet_free(pkt); > +} > + > +static void classification_pmr_match_count(void) > +{ > + odp_pmr_t pmr; > + uint16_t val; > + uint16_t mask; > + val = 1024; > + mask = 0xffff; > + int retval; > + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, > sizeof(val)); > + CU_ASSERT(pmr != ODP_PMR_INVAL); > + > + retval = odp_pmr_match_count(pmr); > + CU_ASSERT(retval == 0); > + > + odp_pmr_destroy(pmr); > +} > + > +static void classification_pmr_terms_avail(void) > +{ > + int retval; > + /* Since this API called at the start of the suite the return value > + should be greater than 0 */ > + retval = odp_pmr_terms_avail(); > + CU_ASSERT(retval > 0); > +} > + > +static void classification_pmr_terms_cap(void) > +{ > + unsigned long long retval; > + /* Need to check different values for different platforms */ > + retval = odp_pmr_terms_cap(); > + CU_ASSERT(retval | (1 << ODP_PMR_IPPROTO)); > +} > + > +static void classification_pktio_configure(void) > +{ > + /* Configure the Different CoS for the pktio interface */ > + if (TEST_DEFAULT) > + configure_pktio_default_cos(); > + if (TEST_ERROR) > + configure_pktio_error_cos(); > + if (TEST_PMR_CHAIN) > + configure_cls_pmr_chain(); > + if (TEST_L2_QOS) > + configure_cos_with_l2_priority(); > + if (TEST_PMR) > + configure_pmr_cos(); > + if (TEST_PMR_SET) > + configure_pktio_pmr_match_set_cos(); > +} > +static void classification_pktio_test(void) > +{ > + /* Test Different CoS on the pktio interface */ > + if (TEST_DEFAULT) > + test_pktio_default_cos(); > + if (TEST_ERROR) > + test_pktio_error_cos(); > + if (TEST_PMR_CHAIN) > + test_cls_pmr_chain(); > + if (TEST_L2_QOS) > + test_cos_with_l2_priority(); > + if (TEST_PMR) > + test_pmr_cos(); > + if (TEST_PMR_SET) > + test_pktio_pmr_match_set_cos(); > +} > + > +CU_TestInfo classification_tests[] = { > + _CU_TEST_INFO(classification_pmr_terms_avail), > + _CU_TEST_INFO(classification_pktio_set_skip), > + _CU_TEST_INFO(classification_pktio_set_headroom), > + _CU_TEST_INFO(classification_pmr_terms_cap), > + _CU_TEST_INFO(classification_pktio_configure), > + _CU_TEST_INFO(classification_pktio_test), > + _CU_TEST_INFO(classification_pmr_match_count), > + CU_TEST_INFO_NULL, > +}; > diff --git > a/test/validation/classification/odp_classification_testsuites.h > b/test/validation/classification/odp_classification_testsuites.h > new file mode 100644 > index 0000000..0ac5eda > --- /dev/null > +++ b/test/validation/classification/odp_classification_testsuites.h > @@ -0,0 +1,38 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef ODP_CLASSIFICATION_TESTSUITES_H_ > +#define ODP_CLASSIFICATION_TESTSUITES_H_ > + > +#include <odp.h> > +#include <CUnit/CUnit.h> > +#include <CUnit/Basic.h> > + > +/* Helper macro for CU_TestInfo initialization */ > +#define _CU_TEST_INFO(test_func) {#test_func, test_func} > + > +extern CU_TestInfo classification_tests[]; > +extern CU_TestInfo classification_basic[]; > + > +extern int classification_tests_init(void); > +extern int classification_tests_finalize(void); > + > +odp_packet_t create_packet(bool vlan); > +void configure_pktio_default_cos(void); > +void test_pktio_default_cos(void); > +void configure_pktio_error_cos(void); > +void test_pktio_error_cos(void); > +void configure_cls_pmr_chain(void); > +void test_cls_pmr_chain(void); > +void configure_cos_with_l2_priority(void); > +void test_cos_with_l2_priority(void); > +void configure_pmr_cos(void); > +void test_pmr_cos(void); > +void configure_pktio_pmr_match_set_cos(void); > +void test_pktio_pmr_match_set_cos(void); > + > + > +#endif /* ODP_BUFFER_TESTSUITES_H_ */ > diff --git a/test/validation/odp_classification.c > b/test/validation/odp_classification.c > new file mode 100644 > index 0000000..b501015 > --- /dev/null > +++ b/test/validation/odp_classification.c > @@ -0,0 +1,19 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include "odp_classification_testsuites.h" > + > +CU_SuiteInfo odp_testsuites[] = { > + { .pName = "classification basic", > + .pTests = classification_basic, > + }, > + { .pName = "classification tests", > + .pTests = classification_tests, > + .pInitFunc = classification_tests_init, > + .pCleanupFunc = classification_tests_finalize, > + }, > + CU_SUITE_INFO_NULL, > +}; > -- > 2.0.1.472.g6f92e5f > > > _______________________________________________ > lng-odp mailing list > lng-odp@lists.linaro.org > http://lists.linaro.org/mailman/listinfo/lng-odp >
arm compiler needs additional castings classification/odp_classification_tests.c: In function 'create_packet': classification/odp_classification_tests.c:198:22: error: cast increases required alignment of target type [-Werror=cast-align] uint16be_t *type = (uint16be_t *)parseptr; If you don't mind I can add cast to void * while merge. - uint16be_t *type = (uint16be_t *)parseptr; + uint16be_t *type = (uint16be_t *)(void *)parseptr; Maxim. On 01/23/2015 10:16 PM, Mike Holmes wrote: > > > On 23 January 2015 at 11:44, <bala.manoharan@linaro.org > <mailto:bala.manoharan@linaro.org>> wrote: > > From: Balasubramanian Manoharan <bala.manoharan@linaro.org > <mailto:bala.manoharan@linaro.org>> > > > Classification validation consists of two suites > * classification basic > This suite tests the basic classification APIs for > creation and > deletion of various PMRs and CoS. > > * classification test > This suite tests behavious of different CoS once they are > linked > > > behavious -> behaviors Maybe we can change that on commit. > > to the pktio. This suite sends packets with different PMR > TERM values > across a loopback interface and tests the assigned CoS. > > Signed-off-by: Balasubramanian Manoharan > <bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org>> > > > Reviewed-by: Mike Holmes <mike.holmes@linaro.org > <mailto:mike.holmes@linaro.org>> > > --- > v2: Incorporates review comments from Mike > > test/validation/.gitignore | 1 + > test/validation/Makefile.am | 8 +- > .../classification/odp_classification_basic.c | 178 +++++ > .../classification/odp_classification_tests.c | 816 > +++++++++++++++++++++ > .../classification/odp_classification_testsuites.h | 38 + > test/validation/odp_classification.c | 19 + > 6 files changed, 1058 insertions(+), 2 deletions(-) > create mode 100644 > test/validation/classification/odp_classification_basic.c > create mode 100644 > test/validation/classification/odp_classification_tests.c > create mode 100644 > test/validation/classification/odp_classification_testsuites.h > create mode 100644 test/validation/odp_classification.c > > diff --git a/test/validation/.gitignore b/test/validation/.gitignore > index a1d4d15..4a1ccb4 100644 > --- a/test/validation/.gitignore > +++ b/test/validation/.gitignore > @@ -3,6 +3,7 @@ > odp_init > odp_queue > odp_crypto > +odp_classification > odp_schedule > odp_shm > odp_system > diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am > index 0f5799c..c0e14cb 100644 > --- a/test/validation/Makefile.am > +++ b/test/validation/Makefile.am > @@ -6,13 +6,14 @@ AM_LDFLAGS += -static > TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform} > > if test_vald > -TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule > odp_pktio_run odp_buffer odp_system odp_timer odp_time > odp_synchronizers > +TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule > odp_pktio_run odp_buffer odp_system odp_timer odp_time > odp_synchronizers odp_classification > check_PROGRAMS = ${bin_PROGRAMS} > endif > > -bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule > odp_pktio odp_buffer odp_system odp_timer odp_time odp_synchronizers > +bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule > odp_pktio odp_buffer odp_system odp_timer odp_time > odp_synchronizers odp_classification > odp_crypto_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/crypto > odp_buffer_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/buffer > +odp_classification_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/classification > > dist_odp_init_SOURCES = odp_init.c > dist_odp_pktio_SOURCES = odp_pktio.c common/odp_cunit_common.c > @@ -32,3 +33,6 @@ dist_odp_timer_SOURCES = odp_timer.c > common/odp_cunit_common.c > dist_odp_time_SOURCES = odp_time.c common/odp_cunit_common.c > dist_odp_synchronizers_SOURCES = odp_synchronizers.c \ > common/odp_cunit_common.c > +dist_odp_classification_SOURCES = > classification/odp_classification_tests.c \ > + classification/odp_classification_basic.c \ > + odp_classification.c > common/odp_cunit_common.c > diff --git > a/test/validation/classification/odp_classification_basic.c > b/test/validation/classification/odp_classification_basic.c > new file mode 100644 > index 0000000..844b66e > --- /dev/null > +++ b/test/validation/classification/odp_classification_basic.c > @@ -0,0 +1,178 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include "odp_classification_testsuites.h" > + > +#define PMR_SET_NUM 5 > + > +static void classification_create_cos(void) > +{ > + odp_cos_t cos; > + char name[ODP_COS_NAME_LEN]; > + sprintf(name, "ClassOfService"); > + cos = odp_cos_create(name); > + CU_ASSERT_FATAL(cos != ODP_COS_INVALID); > + odp_cos_destroy(cos); > +} > + > +static void classification_destroy_cos(void) > +{ > + odp_cos_t cos; > + char name[ODP_COS_NAME_LEN]; > + int retval; > + sprintf(name, "ClassOfService"); > + cos = odp_cos_create(name); > + CU_ASSERT_FATAL(cos != ODP_COS_INVALID); > + retval = odp_cos_destroy(cos); > + CU_ASSERT(retval == 0); > + retval = odp_cos_destroy(ODP_COS_INVALID); > + CU_ASSERT(retval < 0); > +} > + > +static void classification_create_pmr_match(void) > +{ > + odp_pmr_t pmr; > + uint16_t val; > + uint16_t mask; > + val = 1024; > + mask = 0xffff; > + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, > sizeof(val)); > + CU_ASSERT(pmr != ODP_PMR_INVAL); > + odp_pmr_destroy(pmr); > +} > + > +static void classification_create_pmr_range(void) > +{ > + odp_pmr_t pmr; > + uint16_t val1; > + uint16_t val2; > + val1 = 1024; > + val2 = 2048; > + pmr = odp_pmr_create_range(ODP_PMR_TCP_SPORT, &val1, > + &val2, sizeof(val1)); > + CU_ASSERT(pmr != ODP_PMR_INVAL); > + odp_pmr_destroy(pmr); > +} > + > +static void classification_destroy_pmr(void) > +{ > + odp_pmr_t pmr; > + uint16_t val; > + uint16_t mask; > + int retval; > + val = 1024; > + mask = 0xffff; > + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, > sizeof(val)); > + retval = odp_pmr_destroy(pmr); > + CU_ASSERT(retval == 0); > + retval = odp_pmr_destroy(ODP_PMR_INVAL); > + retval = odp_pmr_destroy(ODP_PMR_INVAL); > + CU_ASSERT(retval < 0); > +} > + > +static void classification_cos_set_queue(void) > +{ > + int retval; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + odp_queue_param_t qparam; > + odp_queue_t queue_cos; > + odp_cos_t cos_queue; > + sprintf(cosname, "CoSQueue"); > + cos_queue = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_queue != ODP_COS_INVALID); > + > + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "QueueCoS"); > + > + queue_cos = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, &qparam); > + retval = odp_cos_set_queue(cos_queue, queue_cos); > + CU_ASSERT(retval == 0); > + odp_cos_destroy(cos_queue); > + odp_queue_destroy(queue_cos); > +} > + > +static void classification_cos_set_drop(void) > +{ > + int retval; > + char cosname[ODP_COS_NAME_LEN]; > + sprintf(cosname, "CoSDrop"); > + odp_cos_t cos_drop; > + cos_drop = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_drop != ODP_COS_INVALID); > + > + retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_POOL); > + CU_ASSERT(retval == 0); > + retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_NEVER); > + CU_ASSERT(retval == 0); > + odp_cos_destroy(cos_drop); > +} > + > +static void classification_pmr_match_set_create(void) > +{ > + odp_pmr_set_t pmr_set; > + int retval; > + odp_pmr_match_t pmr_terms[PMR_SET_NUM]; > + uint16_t val = 1024; > + uint16_t mask = 0xffff; > + int i; > + for (i = 0; i < PMR_SET_NUM; i++) { > + pmr_terms[i].match_type = ODP_PMR_MASK; > + pmr_terms[i].mask.term = ODP_PMR_TCP_DPORT; > + pmr_terms[i].mask.val = &val; > + pmr_terms[i].mask.mask = &mask; > + pmr_terms[i].mask.val_sz = sizeof(val); > + } > + > + retval = odp_pmr_match_set_create(PMR_SET_NUM, pmr_terms, > &pmr_set); > + CU_ASSERT(retval > 0); > + > + retval = odp_pmr_match_set_destroy(pmr_set); > + CU_ASSERT(retval == 0); > +} > + > +static void classification_pmr_match_set_destroy(void) > +{ > + odp_pmr_set_t pmr_set; > + int retval; > + odp_pmr_match_t pmr_terms[PMR_SET_NUM]; > + uint16_t val = 1024; > + uint16_t mask = 0xffff; > + int i; > + > + retval = odp_pmr_match_set_destroy(ODP_PMR_INVAL); > + CU_ASSERT(retval < 0); > + > + for (i = 0; i < PMR_SET_NUM; i++) { > + pmr_terms[i].match_type = ODP_PMR_MASK; > + pmr_terms[i].mask.term = ODP_PMR_TCP_DPORT; > + pmr_terms[i].mask.val = &val; > + pmr_terms[i].mask.mask = &mask; > + pmr_terms[i].mask.val_sz = sizeof(val); > + } > + > + retval = odp_pmr_match_set_create(PMR_SET_NUM, pmr_terms, > &pmr_set); > + CU_ASSERT(retval > 0); > + > + retval = odp_pmr_match_set_destroy(pmr_set); > + CU_ASSERT(retval == 0); > +} > + > +CU_TestInfo classification_basic[] = { > + _CU_TEST_INFO(classification_create_cos), > + _CU_TEST_INFO(classification_destroy_cos), > + _CU_TEST_INFO(classification_create_pmr_match), > + _CU_TEST_INFO(classification_create_pmr_range), > + _CU_TEST_INFO(classification_destroy_pmr), > + _CU_TEST_INFO(classification_cos_set_queue), > + _CU_TEST_INFO(classification_cos_set_drop), > + _CU_TEST_INFO(classification_pmr_match_set_create), > + _CU_TEST_INFO(classification_pmr_match_set_destroy), > + CU_TEST_INFO_NULL, > +}; > diff --git > a/test/validation/classification/odp_classification_tests.c > b/test/validation/classification/odp_classification_tests.c > new file mode 100644 > index 0000000..778172c > --- /dev/null > +++ b/test/validation/classification/odp_classification_tests.c > @@ -0,0 +1,816 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include "odp_classification_testsuites.h" > +#include <odph_eth.h> > +#include <odph_ip.h> > +#include <odph_udp.h> > + > +#define SHM_PKT_NUM_BUFS 32 > +#define SHM_PKT_BUF_SIZE 1024 > + > +/* Config values for Default CoS */ > +#define TEST_DEFAULT 1 > +#define CLS_DEFAULT 0 > +#define CLS_DEFAULT_SADDR "10.0.0.1/32 <http://10.0.0.1/32>" > +#define CLS_DEFAULT_DADDR "10.0.0.100/32 <http://10.0.0.100/32>" > +#define CLS_DEFAULT_SPORT 1024 > +#define CLS_DEFAULT_DPORT 2048 > + > +/* Config values for Error CoS */ > +#define TEST_ERROR 1 > +#define CLS_ERROR 1 > + > +/* Config values for PMR_CHAIN */ > +#define TEST_PMR_CHAIN 1 > +#define CLS_PMR_CHAIN_SRC 2 > +#define CLS_PMR_CHAIN_DST 3 > +#define CLS_PMR_CHAIN_SADDR "10.0.0.5/32 <http://10.0.0.5/32>" > +#define CLS_PMR_CHAIN_SPORT 3000 > + > +/* Config values for PMR */ > +#define TEST_PMR 1 > +#define CLS_PMR 4 > +#define CLS_PMR_SPORT 4000 > + > +/* Config values for PMR SET */ > +#define TEST_PMR_SET 1 > +#define CLS_PMR_SET 5 > +#define CLS_PMR_SET_SADDR "10.0.0.6/32 <http://10.0.0.6/32>" > +#define CLS_PMR_SET_SPORT 5000 > + > +/* Config values for CoS L2 Priority */ > +#define TEST_L2_QOS 1 > +#define CLS_L2_QOS_0 6 > +#define CLS_L2_QOS_MAX 5 > + > +#define CLS_ENTRIES (CLS_L2_QOS_0 + CLS_L2_QOS_MAX) > + > +/* Test Packet values */ > +#define DATA_MAGIC 0x01020304 > +#define TEST_SEQ_INVALID ((uint32_t)~0) > + > +static odp_cos_t cos_list[CLS_ENTRIES]; > +static odp_pmr_t pmr_list[CLS_ENTRIES]; > +static odp_queue_t queue_list[CLS_ENTRIES]; > +static odp_pmr_set_t pmr_set; > + > +static odp_buffer_pool_t pool_default; > +static odp_pktio_t pktio_loop; > + > +/** sequence number of IP packets */ > +odp_atomic_u32_t seq; > + > +typedef struct cls_test_packet { > + uint32be_t magic; > + uint32be_t seq; > +} cls_test_packet_t; > + > +static inline > +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, > uint32_t *mask) > +{ > + int b[4]; > + int qualifier = 32; > + int converted; > + > + if (strchr(ipaddress, '/')) { > + converted = sscanf(ipaddress, "%d.%d.%d.%d/%d", > + &b[3], &b[2], &b[1], &b[0], > + &qualifier); > + if (5 != converted) > + return -1; > + } else { > + converted = sscanf(ipaddress, "%d.%d.%d.%d", > + &b[3], &b[2], &b[1], &b[0]); > + if (4 != converted) > + return -1; > + } > + > + if ((b[0] > 255) || (b[1] > 255) || (b[2] > 255) || (b[3] > > 255)) > + return -1; > + if (!qualifier || (qualifier > 32)) > + return -1; > + > + *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24; > + if (mask) > + *mask = ~(0xFFFFFFFF & ((1ULL << (32 - qualifier)) > - 1)); > + > + return 0; > +} > + > +static inline > +void enqueue_loop_interface(odp_packet_t pkt) > +{ > + odp_queue_t defqueue = odp_pktio_outq_getdef(pktio_loop); > + odp_queue_enq(defqueue, odp_packet_to_buffer(pkt)); > +} > + > +static inline > +odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns) > +{ > + odp_buffer_t buf; > + odp_packet_t pkt; > + buf = odp_schedule(queue, ns); > + pkt = odp_packet_from_buffer(buf); > + return pkt; > +} > + > +static int cls_pkt_set_seq(odp_packet_t pkt) > +{ > + static uint32_t seq; > + cls_test_packet_t data; > + uint32_t offset; > + > + data.magic = DATA_MAGIC; > + data.seq = ++seq; > + > + offset = odp_packet_l4_offset(pkt); > + CU_ASSERT_FATAL(offset != 0); > + > + odp_packet_copydata_in(pkt, offset + ODPH_UDPHDR_LEN, > + sizeof(data), &data); > + > + return 0; > +} > + > +static uint32_t cls_pkt_get_seq(odp_packet_t pkt) > +{ > + uint32_t offset; > + cls_test_packet_t data; > + > + offset = odp_packet_l4_offset(pkt); > + if (offset) { > + odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN, > + sizeof(data), &data); > + > + if (data.magic == DATA_MAGIC) > + return data.seq; > + } > + > + return TEST_SEQ_INVALID; > +} > +odp_packet_t create_packet(bool vlan) > +{ > + uint32_t seqno; > + odph_ethhdr_t *ethhdr; > + odph_udphdr_t *udp; > + odph_ipv4hdr_t *ip; > + uint8_t payload_len; > + char src_mac[ODPH_ETHADDR_LEN] = {0}; > + char dst_mac[ODPH_ETHADDR_LEN] = {0}; > + uint32_t addr = 0; > + uint32_t mask; > + int offset; > + odp_packet_t pkt; > + int packet_len = 0; > + > + payload_len = sizeof(cls_test_packet_t); > + packet_len += ODPH_ETHHDR_LEN; > + packet_len += ODPH_IPV4HDR_LEN; > + packet_len += ODPH_UDPHDR_LEN; > + packet_len += payload_len; > + > + if (vlan) > + packet_len += ODPH_VLANHDR_LEN; > + > + pkt = odp_packet_alloc(pool_default, packet_len); > + CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); > + > + /* Ethernet Header */ > + offset = 0; > + odp_packet_l2_offset_set(pkt, offset); > + ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); > + memcpy(ethhdr->src.addr, src_mac, ODPH_ETHADDR_LEN); > + memcpy(ethhdr->dst.addr, dst_mac, ODPH_ETHADDR_LEN); > + offset += sizeof(odph_ethhdr_t); > + if (vlan) { > + /* Default vlan header */ > + uint8_t *parseptr; > + odph_vlanhdr_t *vlan = (odph_vlanhdr_t > *)(ðhdr->type); > + parseptr = (uint8_t *)vlan; > + vlan->tci = odp_cpu_to_be_16(0); > + vlan->tpid = odp_cpu_to_be_16(ODPH_ETHTYPE_VLAN); > + offset += sizeof(odph_vlanhdr_t); > + parseptr += sizeof(odph_vlanhdr_t); > + uint16be_t *type = (uint16be_t *)parseptr; > + *type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); > + } else { > + ethhdr->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); > + } > + > + odp_packet_l3_offset_set(pkt, offset); > + > + /* ipv4 */ > + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); > + > + parse_ipv4_string(CLS_DEFAULT_SADDR, &addr, &mask); > + ip->dst_addr = odp_cpu_to_be_32(addr); > + > + parse_ipv4_string(CLS_DEFAULT_DADDR, &addr, &mask); > + ip->src_addr = odp_cpu_to_be_32(addr); > + ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN; > + ip->tot_len = odp_cpu_to_be_16(ODPH_UDPHDR_LEN + payload_len + > + ODPH_IPV4HDR_LEN); > + ip->ttl = 128; > + ip->proto = ODPH_IPPROTO_UDP; > + seqno = odp_atomic_fetch_inc_u32(&seq); > + ip->id = odp_cpu_to_be_16(seqno); > + ip->chksum = 0; > + odph_ipv4_csum_update(pkt); > + offset += ODPH_IPV4HDR_LEN; > + > + /* udp */ > + odp_packet_l4_offset_set(pkt, offset); > + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); > + udp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT); > + udp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT); > + udp->length = odp_cpu_to_be_16(payload_len + ODPH_UDPHDR_LEN); > + udp->chksum = 0; > + > + /* set pkt sequence number */ > + cls_pkt_set_seq(pkt); > + > + return pkt; > +} > + > +int classification_tests_init(void) > +{ > + odp_buffer_pool_t pool; > + odp_buffer_pool_param_t param; > + odp_queue_t inq_def; > + odp_queue_param_t qparam; > + char queuename[ODP_QUEUE_NAME_LEN]; > + int i; > + > + param.buf_size = SHM_PKT_BUF_SIZE; > + param.num_bufs = SHM_PKT_NUM_BUFS; > + param.buf_type = ODP_BUFFER_TYPE_PACKET; > + param.buf_align = 0; > + pool = odp_buffer_pool_create("classification_pool", > + ODP_SHM_NULL, ¶m); > + if (ODP_BUFFER_POOL_INVALID == pool) { > + fprintf(stderr, "Packet pool creation failed.\n"); > + return -1; > + } > + > + pool_default = odp_buffer_pool_lookup("classification_pool"); > + if (pool_default == ODP_BUFFER_POOL_INVALID) > + goto error_pool_default; > + > + pktio_loop = odp_pktio_open("loop", pool_default); > + if (pktio_loop == ODP_PKTIO_INVALID) > + goto error_pktio_loop; > + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; > + qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; > + qparam.sched.group = ODP_SCHED_GROUP_DEFAULT; > + > + sprintf(queuename, "%s", "inq_loop"); > + inq_def = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_PKTIN, &qparam); > + odp_pktio_inq_setdef(pktio_loop, inq_def); > + > + for (i = 0; i < CLS_ENTRIES; i++) > + cos_list[i] = ODP_COS_INVALID; > + > + for (i = 0; i < CLS_ENTRIES; i++) > + pmr_list[i] = ODP_PMR_INVAL; > + > + for (i = 0; i < CLS_ENTRIES; i++) > + queue_list[i] = ODP_QUEUE_INVALID; > + > + return 0; > + > +error_pktio_loop: > + odp_buffer_pool_destroy(pool_default); > + > +error_pool_default: > + return -1; > +} > + > +int classification_tests_finalize(void) > +{ > + int i; > + if (0 > odp_pktio_close(pktio_loop)) > + return -1; > + > + if (0 != odp_buffer_pool_destroy(pool_default)) > + return -1; > + > + for (i = 0; i < CLS_ENTRIES; i++) > + odp_cos_destroy(cos_list[i]); > + > + for (i = 0; i < CLS_ENTRIES; i++) > + odp_pmr_destroy(pmr_list[i]); > + > + for (i = 0; i < CLS_ENTRIES; i++) > + odp_queue_destroy(queue_list[i]); > + return 0; > +} > + > +void configure_cls_pmr_chain(void) > +{ > + /* PKTIO --> PMR_SRC(SRC IP ADDR) --> PMR_DST (TCP SPORT) */ > + > + /* Packet matching only the SRC IP ADDR should be delivered > + in queue[CLS_PMR_CHAIN_SRC] and a packet matching both SRC > IP ADDR and > + TCP SPORT should be delivered to queue[CLS_PMR_CHAIN_DST] */ > + > + uint16_t val; > + uint16_t maskport; > + int retval; > + char cosname[ODP_QUEUE_NAME_LEN]; > + odp_queue_param_t qparam; > + char queuename[ODP_QUEUE_NAME_LEN]; > + uint32_t addr; > + uint32_t mask; > + > + sprintf(cosname, "SrcCos"); > + cos_list[CLS_PMR_CHAIN_SRC] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_SRC] != > ODP_COS_INVALID) > + > + qparam.sched.prio = ODP_SCHED_PRIO_NORMAL; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "SrcQueue"); > + > + queue_list[CLS_PMR_CHAIN_SRC] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + > + CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_SRC] != > ODP_QUEUE_INVALID); > + retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_SRC], > + queue_list[CLS_PMR_CHAIN_SRC]); > + CU_ASSERT(retval == 0); > + > + sprintf(cosname, "DstCos"); > + cos_list[CLS_PMR_CHAIN_DST] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_DST] != > ODP_COS_INVALID); > + > + qparam.sched.prio = ODP_SCHED_PRIO_NORMAL; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "DstQueue"); > + > + queue_list[CLS_PMR_CHAIN_DST] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_DST] != > ODP_QUEUE_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_DST], > + queue_list[CLS_PMR_CHAIN_DST]); > + > + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); > + pmr_list[CLS_PMR_CHAIN_SRC] = > odp_pmr_create_match(ODP_PMR_SIP_ADDR, > + &addr, &mask, > + sizeof(addr)); > + CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_SRC] != ODP_PMR_INVAL); > + > + val = CLS_PMR_CHAIN_SPORT; > + maskport = 0xffff; > + pmr_list[CLS_PMR_CHAIN_DST] = > odp_pmr_create_match(ODP_PMR_UDP_SPORT, > + &val, &maskport, > + sizeof(val)); > + CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_DST] != ODP_PMR_INVAL); > + > + retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR_CHAIN_SRC], > pktio_loop, > + cos_list[CLS_PMR_CHAIN_SRC]); > + CU_ASSERT(retval == 0); > + > + retval = odp_cos_pmr_cos(pmr_list[CLS_PMR_CHAIN_DST], > + cos_list[CLS_PMR_CHAIN_SRC], > + cos_list[CLS_PMR_CHAIN_DST]); > + CU_ASSERT(retval == 0); > +} > + > +void test_cls_pmr_chain(void) > +{ > + odp_packet_t pkt; > + odph_ipv4hdr_t *ip; > + odph_udphdr_t *udp; > + odp_queue_t queue; > + uint32_t addr = 0; > + uint32_t mask; > + uint32_t seq; > + > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); > + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); > + ip->src_addr = odp_cpu_to_be_32(addr); > + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); > + udp->src_port = odp_cpu_to_be_16(CLS_PMR_CHAIN_SPORT); > + > + enqueue_loop_interface(pkt); > + > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + odp_packet_free(pkt); > + > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); > + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); > + ip->src_addr = odp_cpu_to_be_32(addr); > + > + enqueue_loop_interface(pkt); > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + > + CU_ASSERT(1 == > odp_pmr_match_count(pmr_list[CLS_PMR_CHAIN_DST])); > + odp_packet_free(pkt); > +} > + > +void configure_pktio_default_cos(void) > +{ > + int retval; > + odp_queue_param_t qparam; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + > + sprintf(cosname, "DefaultCoS"); > + cos_list[CLS_DEFAULT] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_DEFAULT] != ODP_COS_INVALID); > + > + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "DefaultQueue"); > + queue_list[CLS_DEFAULT] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_DEFAULT] != ODP_QUEUE_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_DEFAULT], > + queue_list[CLS_DEFAULT]); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_default_cos_set(pktio_loop, > cos_list[CLS_DEFAULT]); > + CU_ASSERT(retval == 0); > +} > + > +void test_pktio_default_cos(void) > +{ > + odp_packet_t pkt; > + odp_queue_t queue; > + uint32_t seq; > + /* create a default packet */ > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + enqueue_loop_interface(pkt); > + > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + /* Default packet should be received in default queue */ > + CU_ASSERT(queue == queue_list[CLS_DEFAULT]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + > + odp_packet_free(pkt); > +} > + > +void configure_pktio_error_cos(void) > +{ > + int retval; > + odp_queue_param_t qparam; > + char queuename[ODP_QUEUE_NAME_LEN]; > + char cosname[ODP_COS_NAME_LEN]; > + > + qparam.sched.prio = ODP_SCHED_PRIO_LOWEST; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "ErrorCos"); > + > + queue_list[CLS_ERROR] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_ERROR] != ODP_QUEUE_INVALID); > + > + sprintf(cosname, "%s", "ErrorCos"); > + cos_list[CLS_ERROR] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_ERROR] != ODP_COS_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_ERROR], > queue_list[CLS_ERROR]); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_error_cos_set(pktio_loop, > cos_list[CLS_ERROR]); > + CU_ASSERT(retval == 0); > +} > + > +void test_pktio_error_cos(void) > +{ > + odp_queue_t queue; > + odp_packet_t pkt; > + > + /*Create an error packet */ > + pkt = create_packet(false); > + odph_ipv4hdr_t *ip = (odph_ipv4hdr_t > *)odp_packet_l3_ptr(pkt, NULL); > + > + /* Incorrect IpV4 version */ > + ip->ver_ihl = 8 << 4 | ODPH_IPV4HDR_IHL_MIN; > + ip->chksum = 0; > + enqueue_loop_interface(pkt); > + > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + /* Error packet should be received in error queue */ > + CU_ASSERT(queue == queue_list[CLS_ERROR]); > + odp_packet_free(pkt); > +} > + > +static void classification_pktio_set_skip(void) > +{ > + int retval; > + size_t offset = 5; > + retval = odp_pktio_skip_set(pktio_loop, offset); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_skip_set(ODP_PKTIO_INVALID, offset); > + CU_ASSERT(retval < 0); > +} > + > +static void classification_pktio_set_headroom(void) > +{ > + size_t headroom; > + int retval; > + headroom = 5; > + retval = odp_pktio_headroom_set(pktio_loop, headroom); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_headroom_set(ODP_PKTIO_INVALID, headroom); > + CU_ASSERT(retval < 0); > +} > + > +void configure_cos_with_l2_priority(void) > +{ > + uint8_t num_qos = CLS_L2_QOS_MAX; > + odp_cos_t cos_tbl[CLS_L2_QOS_MAX]; > + odp_queue_t queue_tbl[CLS_L2_QOS_MAX]; > + uint8_t qos_tbl[CLS_L2_QOS_MAX]; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + int retval; > + int i; > + odp_queue_param_t qparam; > + > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + for (i = 0; i < num_qos; i++) { > + qparam.sched.prio = ODP_SCHED_PRIO_LOWEST - i; > + sprintf(cosname, "%s_%d", "L2_Cos", i); > + cos_tbl[i] = odp_cos_create(cosname); > + if (cos_tbl[i] == ODP_COS_INVALID) > + break; > + > + cos_list[CLS_L2_QOS_0 + i] = cos_tbl[i]; > + sprintf(queuename, "%s_%d", "L2_Queue", i); > + queue_tbl[i] = odp_queue_create(queuename, > ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_tbl[i] != ODP_QUEUE_INVALID); > + queue_list[CLS_L2_QOS_0 + i] = queue_tbl[i]; > + retval = odp_cos_set_queue(cos_tbl[i], queue_tbl[i]); > + CU_ASSERT(retval == 0); > + qos_tbl[i] = i; > + } > + /* count 'i' is passed instead of num_qos to handle the > rare scenario > + if the odp_cos_create() failed in the middle*/ > + retval = odp_cos_with_l2_priority(pktio_loop, i, qos_tbl, > cos_tbl); > + CU_ASSERT(retval == 0); > +} > + > +void test_cos_with_l2_priority(void) > +{ > + odp_packet_t pkt; > + odph_ethhdr_t *ethhdr; > + odph_vlanhdr_t *vlan; > + odp_queue_t queue; > + uint32_t seq; > + > + uint8_t i; > + for (i = 0; i < CLS_L2_QOS_MAX; i++) { > + pkt = create_packet(true); > + seq = cls_pkt_get_seq(pkt); > + ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, > NULL); > + vlan = (odph_vlanhdr_t *)(ðhdr->type); > + vlan->tci = odp_cpu_to_be_16(i << 13); > + enqueue_loop_interface(pkt); > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + odp_packet_free(pkt); > + } > +} > + > +void configure_pmr_cos(void) > +{ > + uint16_t val; > + uint16_t mask; > + int retval; > + val = CLS_PMR_SPORT; > + mask = 0xffff; > + odp_queue_param_t qparam; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + > + pmr_list[CLS_PMR] = > odp_pmr_create_match(ODP_PMR_UDP_SPORT, &val, > + &mask, sizeof(val)); > + CU_ASSERT(pmr_list[CLS_PMR] != ODP_PMR_INVAL); > + > + sprintf(cosname, "PMR_CoS"); > + cos_list[CLS_PMR] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_PMR] != ODP_COS_INVALID); > + > + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "PMR_CoS"); > + > + queue_list[CLS_PMR] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_PMR] != ODP_QUEUE_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_PMR], > + queue_list[CLS_PMR]); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR], pktio_loop, > + cos_list[CLS_PMR]); > + CU_ASSERT(retval == 0); > +} > + > +void test_pmr_cos(void) > +{ > + odp_packet_t pkt; > + odph_udphdr_t *udp; > + odp_queue_t queue; > + uint32_t seq; > + > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); > + udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT); > + enqueue_loop_interface(pkt); > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_PMR]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + CU_ASSERT(1 == odp_pmr_match_count(pmr_list[CLS_PMR])); > + odp_packet_free(pkt); > +} > + > +void configure_pktio_pmr_match_set_cos(void) > +{ > + int retval; > + odp_pmr_match_t pmr_terms[2]; > + uint16_t val; > + uint16_t maskport; > + int num_terms = 2; /* one pmr for each L3 and L4 */ > + odp_queue_param_t qparam; > + char cosname[ODP_COS_NAME_LEN]; > + char queuename[ODP_QUEUE_NAME_LEN]; > + uint32_t addr = 0; > + uint32_t mask; > + > + parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); > + pmr_terms[0].match_type = ODP_PMR_MASK; > + pmr_terms[0].mask.term = ODP_PMR_SIP_ADDR; > + pmr_terms[0].mask.val = &addr; > + pmr_terms[0].mask.mask = &mask; > + pmr_terms[0].mask.val_sz = sizeof(addr); > + > + > + val = CLS_PMR_SET_SPORT; > + maskport = 0xffff; > + pmr_terms[1].match_type = ODP_PMR_MASK; > + pmr_terms[1].mask.term = ODP_PMR_UDP_SPORT; > + pmr_terms[1].mask.val = &val; > + pmr_terms[1].mask.mask = &maskport; > + pmr_terms[1].mask.val_sz = sizeof(val); > + > + retval = odp_pmr_match_set_create(num_terms, pmr_terms, > &pmr_set); > + CU_ASSERT(retval > 0); > + > + sprintf(cosname, "cos_pmr_set"); > + cos_list[CLS_PMR_SET] = odp_cos_create(cosname); > + CU_ASSERT_FATAL(cos_list[CLS_PMR_SET] != ODP_COS_INVALID) > + > + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; > + qparam.sched.sync = ODP_SCHED_SYNC_NONE; > + qparam.sched.group = ODP_SCHED_GROUP_ALL; > + sprintf(queuename, "%s", "cos_pmr_set_queue"); > + > + queue_list[CLS_PMR_SET] = odp_queue_create(queuename, > + ODP_QUEUE_TYPE_SCHED, > + &qparam); > + CU_ASSERT_FATAL(queue_list[CLS_PMR_SET] != ODP_QUEUE_INVALID); > + > + retval = odp_cos_set_queue(cos_list[CLS_PMR_SET], > + queue_list[CLS_PMR_SET]); > + CU_ASSERT(retval == 0); > + > + retval = odp_pktio_pmr_match_set_cos(pmr_set, pktio_loop, > + cos_list[CLS_PMR_SET]); > + CU_ASSERT(retval == 0); > +} > + > +void test_pktio_pmr_match_set_cos(void) > +{ > + uint32_t addr = 0; > + uint32_t mask; > + odph_ipv4hdr_t *ip; > + odph_udphdr_t *udp; > + odp_packet_t pkt; > + odp_queue_t queue; > + uint32_t seq; > + > + pkt = create_packet(false); > + seq = cls_pkt_get_seq(pkt); > + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); > + parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); > + ip->src_addr = odp_cpu_to_be_32(addr); > + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); > + udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT); > + enqueue_loop_interface(pkt); > + pkt = receive_packet(&queue, ODP_TIME_SEC); > + CU_ASSERT(queue == queue_list[CLS_PMR_SET]); > + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); > + odp_packet_free(pkt); > +} > + > +static void classification_pmr_match_count(void) > +{ > + odp_pmr_t pmr; > + uint16_t val; > + uint16_t mask; > + val = 1024; > + mask = 0xffff; > + int retval; > + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, > sizeof(val)); > + CU_ASSERT(pmr != ODP_PMR_INVAL); > + > + retval = odp_pmr_match_count(pmr); > + CU_ASSERT(retval == 0); > + > + odp_pmr_destroy(pmr); > +} > + > +static void classification_pmr_terms_avail(void) > +{ > + int retval; > + /* Since this API called at the start of the suite the > return value > + should be greater than 0 */ > + retval = odp_pmr_terms_avail(); > + CU_ASSERT(retval > 0); > +} > + > +static void classification_pmr_terms_cap(void) > +{ > + unsigned long long retval; > + /* Need to check different values for different platforms */ > + retval = odp_pmr_terms_cap(); > + CU_ASSERT(retval | (1 << ODP_PMR_IPPROTO)); > +} > + > +static void classification_pktio_configure(void) > +{ > + /* Configure the Different CoS for the pktio interface */ > + if (TEST_DEFAULT) > + configure_pktio_default_cos(); > + if (TEST_ERROR) > + configure_pktio_error_cos(); > + if (TEST_PMR_CHAIN) > + configure_cls_pmr_chain(); > + if (TEST_L2_QOS) > + configure_cos_with_l2_priority(); > + if (TEST_PMR) > + configure_pmr_cos(); > + if (TEST_PMR_SET) > + configure_pktio_pmr_match_set_cos(); > +} > +static void classification_pktio_test(void) > +{ > + /* Test Different CoS on the pktio interface */ > + if (TEST_DEFAULT) > + test_pktio_default_cos(); > + if (TEST_ERROR) > + test_pktio_error_cos(); > + if (TEST_PMR_CHAIN) > + test_cls_pmr_chain(); > + if (TEST_L2_QOS) > + test_cos_with_l2_priority(); > + if (TEST_PMR) > + test_pmr_cos(); > + if (TEST_PMR_SET) > + test_pktio_pmr_match_set_cos(); > +} > + > +CU_TestInfo classification_tests[] = { > + _CU_TEST_INFO(classification_pmr_terms_avail), > + _CU_TEST_INFO(classification_pktio_set_skip), > + _CU_TEST_INFO(classification_pktio_set_headroom), > + _CU_TEST_INFO(classification_pmr_terms_cap), > + _CU_TEST_INFO(classification_pktio_configure), > + _CU_TEST_INFO(classification_pktio_test), > + _CU_TEST_INFO(classification_pmr_match_count), > + CU_TEST_INFO_NULL, > +}; > diff --git > a/test/validation/classification/odp_classification_testsuites.h > b/test/validation/classification/odp_classification_testsuites.h > new file mode 100644 > index 0000000..0ac5eda > --- /dev/null > +++ b/test/validation/classification/odp_classification_testsuites.h > @@ -0,0 +1,38 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#ifndef ODP_CLASSIFICATION_TESTSUITES_H_ > +#define ODP_CLASSIFICATION_TESTSUITES_H_ > + > +#include <odp.h> > +#include <CUnit/CUnit.h> > +#include <CUnit/Basic.h> > + > +/* Helper macro for CU_TestInfo initialization */ > +#define _CU_TEST_INFO(test_func) {#test_func, test_func} > + > +extern CU_TestInfo classification_tests[]; > +extern CU_TestInfo classification_basic[]; > + > +extern int classification_tests_init(void); > +extern int classification_tests_finalize(void); > + > +odp_packet_t create_packet(bool vlan); > +void configure_pktio_default_cos(void); > +void test_pktio_default_cos(void); > +void configure_pktio_error_cos(void); > +void test_pktio_error_cos(void); > +void configure_cls_pmr_chain(void); > +void test_cls_pmr_chain(void); > +void configure_cos_with_l2_priority(void); > +void test_cos_with_l2_priority(void); > +void configure_pmr_cos(void); > +void test_pmr_cos(void); > +void configure_pktio_pmr_match_set_cos(void); > +void test_pktio_pmr_match_set_cos(void); > + > + > +#endif /* ODP_BUFFER_TESTSUITES_H_ */ > diff --git a/test/validation/odp_classification.c > b/test/validation/odp_classification.c > new file mode 100644 > index 0000000..b501015 > --- /dev/null > +++ b/test/validation/odp_classification.c > @@ -0,0 +1,19 @@ > +/* Copyright (c) 2015, Linaro Limited > + * All rights reserved. > + * > + * SPDX-License-Identifier: BSD-3-Clause > + */ > + > +#include "odp_classification_testsuites.h" > + > +CU_SuiteInfo odp_testsuites[] = { > + { .pName = "classification basic", > + .pTests = classification_basic, > + }, > + { .pName = "classification tests", > + .pTests = classification_tests, > + .pInitFunc = classification_tests_init, > + .pCleanupFunc = classification_tests_finalize, > + }, > + CU_SUITE_INFO_NULL, > +}; > -- > 2.0.1.472.g6f92e5f > > > _______________________________________________ > lng-odp mailing list > lng-odp@lists.linaro.org <mailto:lng-odp@lists.linaro.org> > http://lists.linaro.org/mailman/listinfo/lng-odp > > > > > -- > *Mike Holmes* > Linaro Sr Technical Manager > LNG - ODP > > > _______________________________________________ > lng-odp mailing list > lng-odp@lists.linaro.org > http://lists.linaro.org/mailman/listinfo/lng-odp
On 26/01/15 8:47 pm, Maxim Uvarov wrote: > arm compiler needs additional castings > > classification/odp_classification_tests.c: In function 'create_packet': > classification/odp_classification_tests.c:198:22: error: cast > increases required alignment of target type [-Werror=cast-align] > uint16be_t *type = (uint16be_t *)parseptr; > > If you don't mind I can add cast to void * while merge. Sure, you can add the cast to void * during merge. Thanks, Bala > > - uint16be_t *type = (uint16be_t *)parseptr; > + uint16be_t *type = (uint16be_t *)(void *)parseptr; > > > Maxim. > > On 01/23/2015 10:16 PM, Mike Holmes wrote: >> >> >> On 23 January 2015 at 11:44, <bala.manoharan@linaro.org >> <mailto:bala.manoharan@linaro.org>> wrote: >> >> From: Balasubramanian Manoharan <bala.manoharan@linaro.org >> <mailto:bala.manoharan@linaro.org>> >> >> Classification validation consists of two suites >> * classification basic >> This suite tests the basic classification APIs for >> creation and >> deletion of various PMRs and CoS. >> >> * classification test >> This suite tests behavious of different CoS once they are >> linked >> >> >> behavious -> behaviors Maybe we can change that on commit. >> >> to the pktio. This suite sends packets with different PMR >> TERM values >> across a loopback interface and tests the assigned CoS. >> >> Signed-off-by: Balasubramanian Manoharan >> <bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org>> >> >> >> Reviewed-by: Mike Holmes <mike.holmes@linaro.org >> <mailto:mike.holmes@linaro.org>> >> >> --- >> v2: Incorporates review comments from Mike >> >> test/validation/.gitignore | 1 + >> test/validation/Makefile.am | 8 +- >> .../classification/odp_classification_basic.c | 178 +++++ >> .../classification/odp_classification_tests.c | 816 >> +++++++++++++++++++++ >> .../classification/odp_classification_testsuites.h | 38 + >> test/validation/odp_classification.c | 19 + >> 6 files changed, 1058 insertions(+), 2 deletions(-) >> create mode 100644 >> test/validation/classification/odp_classification_basic.c >> create mode 100644 >> test/validation/classification/odp_classification_tests.c >> create mode 100644 >> test/validation/classification/odp_classification_testsuites.h >> create mode 100644 test/validation/odp_classification.c >> >> diff --git a/test/validation/.gitignore b/test/validation/.gitignore >> index a1d4d15..4a1ccb4 100644 >> --- a/test/validation/.gitignore >> +++ b/test/validation/.gitignore >> @@ -3,6 +3,7 @@ >> odp_init >> odp_queue >> odp_crypto >> +odp_classification >> odp_schedule >> odp_shm >> odp_system >> diff --git a/test/validation/Makefile.am >> b/test/validation/Makefile.am >> index 0f5799c..c0e14cb 100644 >> --- a/test/validation/Makefile.am >> +++ b/test/validation/Makefile.am >> @@ -6,13 +6,14 @@ AM_LDFLAGS += -static >> TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform} >> >> if test_vald >> -TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule >> odp_pktio_run odp_buffer odp_system odp_timer odp_time >> odp_synchronizers >> +TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule >> odp_pktio_run odp_buffer odp_system odp_timer odp_time >> odp_synchronizers odp_classification >> check_PROGRAMS = ${bin_PROGRAMS} >> endif >> >> -bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule >> odp_pktio odp_buffer odp_system odp_timer odp_time odp_synchronizers >> +bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule >> odp_pktio odp_buffer odp_system odp_timer odp_time >> odp_synchronizers odp_classification >> odp_crypto_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/crypto >> odp_buffer_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/buffer >> +odp_classification_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/classification >> >> dist_odp_init_SOURCES = odp_init.c >> dist_odp_pktio_SOURCES = odp_pktio.c common/odp_cunit_common.c >> @@ -32,3 +33,6 @@ dist_odp_timer_SOURCES = odp_timer.c >> common/odp_cunit_common.c >> dist_odp_time_SOURCES = odp_time.c common/odp_cunit_common.c >> dist_odp_synchronizers_SOURCES = odp_synchronizers.c \ >> common/odp_cunit_common.c >> +dist_odp_classification_SOURCES = >> classification/odp_classification_tests.c \ >> + classification/odp_classification_basic.c \ >> + odp_classification.c >> common/odp_cunit_common.c >> diff --git >> a/test/validation/classification/odp_classification_basic.c >> b/test/validation/classification/odp_classification_basic.c >> new file mode 100644 >> index 0000000..844b66e >> --- /dev/null >> +++ b/test/validation/classification/odp_classification_basic.c >> @@ -0,0 +1,178 @@ >> +/* Copyright (c) 2015, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include "odp_classification_testsuites.h" >> + >> +#define PMR_SET_NUM 5 >> + >> +static void classification_create_cos(void) >> +{ >> + odp_cos_t cos; >> + char name[ODP_COS_NAME_LEN]; >> + sprintf(name, "ClassOfService"); >> + cos = odp_cos_create(name); >> + CU_ASSERT_FATAL(cos != ODP_COS_INVALID); >> + odp_cos_destroy(cos); >> +} >> + >> +static void classification_destroy_cos(void) >> +{ >> + odp_cos_t cos; >> + char name[ODP_COS_NAME_LEN]; >> + int retval; >> + sprintf(name, "ClassOfService"); >> + cos = odp_cos_create(name); >> + CU_ASSERT_FATAL(cos != ODP_COS_INVALID); >> + retval = odp_cos_destroy(cos); >> + CU_ASSERT(retval == 0); >> + retval = odp_cos_destroy(ODP_COS_INVALID); >> + CU_ASSERT(retval < 0); >> +} >> + >> +static void classification_create_pmr_match(void) >> +{ >> + odp_pmr_t pmr; >> + uint16_t val; >> + uint16_t mask; >> + val = 1024; >> + mask = 0xffff; >> + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, >> sizeof(val)); >> + CU_ASSERT(pmr != ODP_PMR_INVAL); >> + odp_pmr_destroy(pmr); >> +} >> + >> +static void classification_create_pmr_range(void) >> +{ >> + odp_pmr_t pmr; >> + uint16_t val1; >> + uint16_t val2; >> + val1 = 1024; >> + val2 = 2048; >> + pmr = odp_pmr_create_range(ODP_PMR_TCP_SPORT, &val1, >> + &val2, sizeof(val1)); >> + CU_ASSERT(pmr != ODP_PMR_INVAL); >> + odp_pmr_destroy(pmr); >> +} >> + >> +static void classification_destroy_pmr(void) >> +{ >> + odp_pmr_t pmr; >> + uint16_t val; >> + uint16_t mask; >> + int retval; >> + val = 1024; >> + mask = 0xffff; >> + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, >> sizeof(val)); >> + retval = odp_pmr_destroy(pmr); >> + CU_ASSERT(retval == 0); >> + retval = odp_pmr_destroy(ODP_PMR_INVAL); >> + retval = odp_pmr_destroy(ODP_PMR_INVAL); >> + CU_ASSERT(retval < 0); >> +} >> + >> +static void classification_cos_set_queue(void) >> +{ >> + int retval; >> + char cosname[ODP_COS_NAME_LEN]; >> + char queuename[ODP_QUEUE_NAME_LEN]; >> + odp_queue_param_t qparam; >> + odp_queue_t queue_cos; >> + odp_cos_t cos_queue; >> + sprintf(cosname, "CoSQueue"); >> + cos_queue = odp_cos_create(cosname); >> + CU_ASSERT_FATAL(cos_queue != ODP_COS_INVALID); >> + >> + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; >> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >> + sprintf(queuename, "%s", "QueueCoS"); >> + >> + queue_cos = odp_queue_create(queuename, >> + ODP_QUEUE_TYPE_SCHED, &qparam); >> + retval = odp_cos_set_queue(cos_queue, queue_cos); >> + CU_ASSERT(retval == 0); >> + odp_cos_destroy(cos_queue); >> + odp_queue_destroy(queue_cos); >> +} >> + >> +static void classification_cos_set_drop(void) >> +{ >> + int retval; >> + char cosname[ODP_COS_NAME_LEN]; >> + sprintf(cosname, "CoSDrop"); >> + odp_cos_t cos_drop; >> + cos_drop = odp_cos_create(cosname); >> + CU_ASSERT_FATAL(cos_drop != ODP_COS_INVALID); >> + >> + retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_POOL); >> + CU_ASSERT(retval == 0); >> + retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_NEVER); >> + CU_ASSERT(retval == 0); >> + odp_cos_destroy(cos_drop); >> +} >> + >> +static void classification_pmr_match_set_create(void) >> +{ >> + odp_pmr_set_t pmr_set; >> + int retval; >> + odp_pmr_match_t pmr_terms[PMR_SET_NUM]; >> + uint16_t val = 1024; >> + uint16_t mask = 0xffff; >> + int i; >> + for (i = 0; i < PMR_SET_NUM; i++) { >> + pmr_terms[i].match_type = ODP_PMR_MASK; >> + pmr_terms[i].mask.term = ODP_PMR_TCP_DPORT; >> + pmr_terms[i].mask.val = &val; >> + pmr_terms[i].mask.mask = &mask; >> + pmr_terms[i].mask.val_sz = sizeof(val); >> + } >> + >> + retval = odp_pmr_match_set_create(PMR_SET_NUM, pmr_terms, >> &pmr_set); >> + CU_ASSERT(retval > 0); >> + >> + retval = odp_pmr_match_set_destroy(pmr_set); >> + CU_ASSERT(retval == 0); >> +} >> + >> +static void classification_pmr_match_set_destroy(void) >> +{ >> + odp_pmr_set_t pmr_set; >> + int retval; >> + odp_pmr_match_t pmr_terms[PMR_SET_NUM]; >> + uint16_t val = 1024; >> + uint16_t mask = 0xffff; >> + int i; >> + >> + retval = odp_pmr_match_set_destroy(ODP_PMR_INVAL); >> + CU_ASSERT(retval < 0); >> + >> + for (i = 0; i < PMR_SET_NUM; i++) { >> + pmr_terms[i].match_type = ODP_PMR_MASK; >> + pmr_terms[i].mask.term = ODP_PMR_TCP_DPORT; >> + pmr_terms[i].mask.val = &val; >> + pmr_terms[i].mask.mask = &mask; >> + pmr_terms[i].mask.val_sz = sizeof(val); >> + } >> + >> + retval = odp_pmr_match_set_create(PMR_SET_NUM, pmr_terms, >> &pmr_set); >> + CU_ASSERT(retval > 0); >> + >> + retval = odp_pmr_match_set_destroy(pmr_set); >> + CU_ASSERT(retval == 0); >> +} >> + >> +CU_TestInfo classification_basic[] = { >> + _CU_TEST_INFO(classification_create_cos), >> + _CU_TEST_INFO(classification_destroy_cos), >> + _CU_TEST_INFO(classification_create_pmr_match), >> + _CU_TEST_INFO(classification_create_pmr_range), >> + _CU_TEST_INFO(classification_destroy_pmr), >> + _CU_TEST_INFO(classification_cos_set_queue), >> + _CU_TEST_INFO(classification_cos_set_drop), >> + _CU_TEST_INFO(classification_pmr_match_set_create), >> + _CU_TEST_INFO(classification_pmr_match_set_destroy), >> + CU_TEST_INFO_NULL, >> +}; >> diff --git >> a/test/validation/classification/odp_classification_tests.c >> b/test/validation/classification/odp_classification_tests.c >> new file mode 100644 >> index 0000000..778172c >> --- /dev/null >> +++ b/test/validation/classification/odp_classification_tests.c >> @@ -0,0 +1,816 @@ >> +/* Copyright (c) 2015, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include "odp_classification_testsuites.h" >> +#include <odph_eth.h> >> +#include <odph_ip.h> >> +#include <odph_udp.h> >> + >> +#define SHM_PKT_NUM_BUFS 32 >> +#define SHM_PKT_BUF_SIZE 1024 >> + >> +/* Config values for Default CoS */ >> +#define TEST_DEFAULT 1 >> +#define CLS_DEFAULT 0 >> +#define CLS_DEFAULT_SADDR "10.0.0.1/32 <http://10.0.0.1/32>" >> +#define CLS_DEFAULT_DADDR "10.0.0.100/32 >> <http://10.0.0.100/32>" >> +#define CLS_DEFAULT_SPORT 1024 >> +#define CLS_DEFAULT_DPORT 2048 >> + >> +/* Config values for Error CoS */ >> +#define TEST_ERROR 1 >> +#define CLS_ERROR 1 >> + >> +/* Config values for PMR_CHAIN */ >> +#define TEST_PMR_CHAIN 1 >> +#define CLS_PMR_CHAIN_SRC 2 >> +#define CLS_PMR_CHAIN_DST 3 >> +#define CLS_PMR_CHAIN_SADDR "10.0.0.5/32 <http://10.0.0.5/32>" >> +#define CLS_PMR_CHAIN_SPORT 3000 >> + >> +/* Config values for PMR */ >> +#define TEST_PMR 1 >> +#define CLS_PMR 4 >> +#define CLS_PMR_SPORT 4000 >> + >> +/* Config values for PMR SET */ >> +#define TEST_PMR_SET 1 >> +#define CLS_PMR_SET 5 >> +#define CLS_PMR_SET_SADDR "10.0.0.6/32 <http://10.0.0.6/32>" >> +#define CLS_PMR_SET_SPORT 5000 >> + >> +/* Config values for CoS L2 Priority */ >> +#define TEST_L2_QOS 1 >> +#define CLS_L2_QOS_0 6 >> +#define CLS_L2_QOS_MAX 5 >> + >> +#define CLS_ENTRIES (CLS_L2_QOS_0 + CLS_L2_QOS_MAX) >> + >> +/* Test Packet values */ >> +#define DATA_MAGIC 0x01020304 >> +#define TEST_SEQ_INVALID ((uint32_t)~0) >> + >> +static odp_cos_t cos_list[CLS_ENTRIES]; >> +static odp_pmr_t pmr_list[CLS_ENTRIES]; >> +static odp_queue_t queue_list[CLS_ENTRIES]; >> +static odp_pmr_set_t pmr_set; >> + >> +static odp_buffer_pool_t pool_default; >> +static odp_pktio_t pktio_loop; >> + >> +/** sequence number of IP packets */ >> +odp_atomic_u32_t seq; >> + >> +typedef struct cls_test_packet { >> + uint32be_t magic; >> + uint32be_t seq; >> +} cls_test_packet_t; >> + >> +static inline >> +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, >> uint32_t *mask) >> +{ >> + int b[4]; >> + int qualifier = 32; >> + int converted; >> + >> + if (strchr(ipaddress, '/')) { >> + converted = sscanf(ipaddress, "%d.%d.%d.%d/%d", >> + &b[3], &b[2], &b[1], &b[0], >> + &qualifier); >> + if (5 != converted) >> + return -1; >> + } else { >> + converted = sscanf(ipaddress, "%d.%d.%d.%d", >> + &b[3], &b[2], &b[1], &b[0]); >> + if (4 != converted) >> + return -1; >> + } >> + >> + if ((b[0] > 255) || (b[1] > 255) || (b[2] > 255) || (b[3] >> > 255)) >> + return -1; >> + if (!qualifier || (qualifier > 32)) >> + return -1; >> + >> + *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24; >> + if (mask) >> + *mask = ~(0xFFFFFFFF & ((1ULL << (32 - qualifier)) >> - 1)); >> + >> + return 0; >> +} >> + >> +static inline >> +void enqueue_loop_interface(odp_packet_t pkt) >> +{ >> + odp_queue_t defqueue = odp_pktio_outq_getdef(pktio_loop); >> + odp_queue_enq(defqueue, odp_packet_to_buffer(pkt)); >> +} >> + >> +static inline >> +odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns) >> +{ >> + odp_buffer_t buf; >> + odp_packet_t pkt; >> + buf = odp_schedule(queue, ns); >> + pkt = odp_packet_from_buffer(buf); >> + return pkt; >> +} >> + >> +static int cls_pkt_set_seq(odp_packet_t pkt) >> +{ >> + static uint32_t seq; >> + cls_test_packet_t data; >> + uint32_t offset; >> + >> + data.magic = DATA_MAGIC; >> + data.seq = ++seq; >> + >> + offset = odp_packet_l4_offset(pkt); >> + CU_ASSERT_FATAL(offset != 0); >> + >> + odp_packet_copydata_in(pkt, offset + ODPH_UDPHDR_LEN, >> + sizeof(data), &data); >> + >> + return 0; >> +} >> + >> +static uint32_t cls_pkt_get_seq(odp_packet_t pkt) >> +{ >> + uint32_t offset; >> + cls_test_packet_t data; >> + >> + offset = odp_packet_l4_offset(pkt); >> + if (offset) { >> + odp_packet_copydata_out(pkt, offset + >> ODPH_UDPHDR_LEN, >> + sizeof(data), &data); >> + >> + if (data.magic == DATA_MAGIC) >> + return data.seq; >> + } >> + >> + return TEST_SEQ_INVALID; >> +} >> +odp_packet_t create_packet(bool vlan) >> +{ >> + uint32_t seqno; >> + odph_ethhdr_t *ethhdr; >> + odph_udphdr_t *udp; >> + odph_ipv4hdr_t *ip; >> + uint8_t payload_len; >> + char src_mac[ODPH_ETHADDR_LEN] = {0}; >> + char dst_mac[ODPH_ETHADDR_LEN] = {0}; >> + uint32_t addr = 0; >> + uint32_t mask; >> + int offset; >> + odp_packet_t pkt; >> + int packet_len = 0; >> + >> + payload_len = sizeof(cls_test_packet_t); >> + packet_len += ODPH_ETHHDR_LEN; >> + packet_len += ODPH_IPV4HDR_LEN; >> + packet_len += ODPH_UDPHDR_LEN; >> + packet_len += payload_len; >> + >> + if (vlan) >> + packet_len += ODPH_VLANHDR_LEN; >> + >> + pkt = odp_packet_alloc(pool_default, packet_len); >> + CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); >> + >> + /* Ethernet Header */ >> + offset = 0; >> + odp_packet_l2_offset_set(pkt, offset); >> + ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); >> + memcpy(ethhdr->src.addr, src_mac, ODPH_ETHADDR_LEN); >> + memcpy(ethhdr->dst.addr, dst_mac, ODPH_ETHADDR_LEN); >> + offset += sizeof(odph_ethhdr_t); >> + if (vlan) { >> + /* Default vlan header */ >> + uint8_t *parseptr; >> + odph_vlanhdr_t *vlan = (odph_vlanhdr_t >> *)(ðhdr->type); >> + parseptr = (uint8_t *)vlan; >> + vlan->tci = odp_cpu_to_be_16(0); >> + vlan->tpid = odp_cpu_to_be_16(ODPH_ETHTYPE_VLAN); >> + offset += sizeof(odph_vlanhdr_t); >> + parseptr += sizeof(odph_vlanhdr_t); >> + uint16be_t *type = (uint16be_t *)parseptr; >> + *type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); >> + } else { >> + ethhdr->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); >> + } >> + >> + odp_packet_l3_offset_set(pkt, offset); >> + >> + /* ipv4 */ >> + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); >> + >> + parse_ipv4_string(CLS_DEFAULT_SADDR, &addr, &mask); >> + ip->dst_addr = odp_cpu_to_be_32(addr); >> + >> + parse_ipv4_string(CLS_DEFAULT_DADDR, &addr, &mask); >> + ip->src_addr = odp_cpu_to_be_32(addr); >> + ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN; >> + ip->tot_len = odp_cpu_to_be_16(ODPH_UDPHDR_LEN + >> payload_len + >> + ODPH_IPV4HDR_LEN); >> + ip->ttl = 128; >> + ip->proto = ODPH_IPPROTO_UDP; >> + seqno = odp_atomic_fetch_inc_u32(&seq); >> + ip->id = odp_cpu_to_be_16(seqno); >> + ip->chksum = 0; >> + odph_ipv4_csum_update(pkt); >> + offset += ODPH_IPV4HDR_LEN; >> + >> + /* udp */ >> + odp_packet_l4_offset_set(pkt, offset); >> + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); >> + udp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT); >> + udp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT); >> + udp->length = odp_cpu_to_be_16(payload_len + >> ODPH_UDPHDR_LEN); >> + udp->chksum = 0; >> + >> + /* set pkt sequence number */ >> + cls_pkt_set_seq(pkt); >> + >> + return pkt; >> +} >> + >> +int classification_tests_init(void) >> +{ >> + odp_buffer_pool_t pool; >> + odp_buffer_pool_param_t param; >> + odp_queue_t inq_def; >> + odp_queue_param_t qparam; >> + char queuename[ODP_QUEUE_NAME_LEN]; >> + int i; >> + >> + param.buf_size = SHM_PKT_BUF_SIZE; >> + param.num_bufs = SHM_PKT_NUM_BUFS; >> + param.buf_type = ODP_BUFFER_TYPE_PACKET; >> + param.buf_align = 0; >> + pool = odp_buffer_pool_create("classification_pool", >> + ODP_SHM_NULL, ¶m); >> + if (ODP_BUFFER_POOL_INVALID == pool) { >> + fprintf(stderr, "Packet pool creation failed.\n"); >> + return -1; >> + } >> + >> + pool_default = >> odp_buffer_pool_lookup("classification_pool"); >> + if (pool_default == ODP_BUFFER_POOL_INVALID) >> + goto error_pool_default; >> + >> + pktio_loop = odp_pktio_open("loop", pool_default); >> + if (pktio_loop == ODP_PKTIO_INVALID) >> + goto error_pktio_loop; >> + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; >> + qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; >> + qparam.sched.group = ODP_SCHED_GROUP_DEFAULT; >> + >> + sprintf(queuename, "%s", "inq_loop"); >> + inq_def = odp_queue_create(queuename, >> + ODP_QUEUE_TYPE_PKTIN, &qparam); >> + odp_pktio_inq_setdef(pktio_loop, inq_def); >> + >> + for (i = 0; i < CLS_ENTRIES; i++) >> + cos_list[i] = ODP_COS_INVALID; >> + >> + for (i = 0; i < CLS_ENTRIES; i++) >> + pmr_list[i] = ODP_PMR_INVAL; >> + >> + for (i = 0; i < CLS_ENTRIES; i++) >> + queue_list[i] = ODP_QUEUE_INVALID; >> + >> + return 0; >> + >> +error_pktio_loop: >> + odp_buffer_pool_destroy(pool_default); >> + >> +error_pool_default: >> + return -1; >> +} >> + >> +int classification_tests_finalize(void) >> +{ >> + int i; >> + if (0 > odp_pktio_close(pktio_loop)) >> + return -1; >> + >> + if (0 != odp_buffer_pool_destroy(pool_default)) >> + return -1; >> + >> + for (i = 0; i < CLS_ENTRIES; i++) >> + odp_cos_destroy(cos_list[i]); >> + >> + for (i = 0; i < CLS_ENTRIES; i++) >> + odp_pmr_destroy(pmr_list[i]); >> + >> + for (i = 0; i < CLS_ENTRIES; i++) >> + odp_queue_destroy(queue_list[i]); >> + return 0; >> +} >> + >> +void configure_cls_pmr_chain(void) >> +{ >> + /* PKTIO --> PMR_SRC(SRC IP ADDR) --> PMR_DST (TCP SPORT) */ >> + >> + /* Packet matching only the SRC IP ADDR should be delivered >> + in queue[CLS_PMR_CHAIN_SRC] and a packet matching both SRC >> IP ADDR and >> + TCP SPORT should be delivered to queue[CLS_PMR_CHAIN_DST] */ >> + >> + uint16_t val; >> + uint16_t maskport; >> + int retval; >> + char cosname[ODP_QUEUE_NAME_LEN]; >> + odp_queue_param_t qparam; >> + char queuename[ODP_QUEUE_NAME_LEN]; >> + uint32_t addr; >> + uint32_t mask; >> + >> + sprintf(cosname, "SrcCos"); >> + cos_list[CLS_PMR_CHAIN_SRC] = odp_cos_create(cosname); >> + CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_SRC] != >> ODP_COS_INVALID) >> + >> + qparam.sched.prio = ODP_SCHED_PRIO_NORMAL; >> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >> + sprintf(queuename, "%s", "SrcQueue"); >> + >> + queue_list[CLS_PMR_CHAIN_SRC] = odp_queue_create(queuename, >> + ODP_QUEUE_TYPE_SCHED, >> + &qparam); >> + >> + CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_SRC] != >> ODP_QUEUE_INVALID); >> + retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_SRC], >> + queue_list[CLS_PMR_CHAIN_SRC]); >> + CU_ASSERT(retval == 0); >> + >> + sprintf(cosname, "DstCos"); >> + cos_list[CLS_PMR_CHAIN_DST] = odp_cos_create(cosname); >> + CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_DST] != >> ODP_COS_INVALID); >> + >> + qparam.sched.prio = ODP_SCHED_PRIO_NORMAL; >> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >> + sprintf(queuename, "%s", "DstQueue"); >> + >> + queue_list[CLS_PMR_CHAIN_DST] = odp_queue_create(queuename, >> + ODP_QUEUE_TYPE_SCHED, >> + &qparam); >> + CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_DST] != >> ODP_QUEUE_INVALID); >> + >> + retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_DST], >> + queue_list[CLS_PMR_CHAIN_DST]); >> + >> + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); >> + pmr_list[CLS_PMR_CHAIN_SRC] = >> odp_pmr_create_match(ODP_PMR_SIP_ADDR, >> + &addr, &mask, >> + sizeof(addr)); >> + CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_SRC] != >> ODP_PMR_INVAL); >> + >> + val = CLS_PMR_CHAIN_SPORT; >> + maskport = 0xffff; >> + pmr_list[CLS_PMR_CHAIN_DST] = >> odp_pmr_create_match(ODP_PMR_UDP_SPORT, >> + &val, &maskport, >> + sizeof(val)); >> + CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_DST] != >> ODP_PMR_INVAL); >> + >> + retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR_CHAIN_SRC], >> pktio_loop, >> + cos_list[CLS_PMR_CHAIN_SRC]); >> + CU_ASSERT(retval == 0); >> + >> + retval = odp_cos_pmr_cos(pmr_list[CLS_PMR_CHAIN_DST], >> + cos_list[CLS_PMR_CHAIN_SRC], >> + cos_list[CLS_PMR_CHAIN_DST]); >> + CU_ASSERT(retval == 0); >> +} >> + >> +void test_cls_pmr_chain(void) >> +{ >> + odp_packet_t pkt; >> + odph_ipv4hdr_t *ip; >> + odph_udphdr_t *udp; >> + odp_queue_t queue; >> + uint32_t addr = 0; >> + uint32_t mask; >> + uint32_t seq; >> + >> + pkt = create_packet(false); >> + seq = cls_pkt_get_seq(pkt); >> + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); >> + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); >> + ip->src_addr = odp_cpu_to_be_32(addr); >> + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); >> + udp->src_port = odp_cpu_to_be_16(CLS_PMR_CHAIN_SPORT); >> + >> + enqueue_loop_interface(pkt); >> + >> + pkt = receive_packet(&queue, ODP_TIME_SEC); >> + CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]); >> + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); >> + odp_packet_free(pkt); >> + >> + pkt = create_packet(false); >> + seq = cls_pkt_get_seq(pkt); >> + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); >> + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); >> + ip->src_addr = odp_cpu_to_be_32(addr); >> + >> + enqueue_loop_interface(pkt); >> + pkt = receive_packet(&queue, ODP_TIME_SEC); >> + CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]); >> + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); >> + >> + CU_ASSERT(1 == >> odp_pmr_match_count(pmr_list[CLS_PMR_CHAIN_DST])); >> + odp_packet_free(pkt); >> +} >> + >> +void configure_pktio_default_cos(void) >> +{ >> + int retval; >> + odp_queue_param_t qparam; >> + char cosname[ODP_COS_NAME_LEN]; >> + char queuename[ODP_QUEUE_NAME_LEN]; >> + >> + sprintf(cosname, "DefaultCoS"); >> + cos_list[CLS_DEFAULT] = odp_cos_create(cosname); >> + CU_ASSERT_FATAL(cos_list[CLS_DEFAULT] != ODP_COS_INVALID); >> + >> + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; >> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >> + sprintf(queuename, "%s", "DefaultQueue"); >> + queue_list[CLS_DEFAULT] = odp_queue_create(queuename, >> + ODP_QUEUE_TYPE_SCHED, &qparam); >> + CU_ASSERT_FATAL(queue_list[CLS_DEFAULT] != >> ODP_QUEUE_INVALID); >> + >> + retval = odp_cos_set_queue(cos_list[CLS_DEFAULT], >> + queue_list[CLS_DEFAULT]); >> + CU_ASSERT(retval == 0); >> + >> + retval = odp_pktio_default_cos_set(pktio_loop, >> cos_list[CLS_DEFAULT]); >> + CU_ASSERT(retval == 0); >> +} >> + >> +void test_pktio_default_cos(void) >> +{ >> + odp_packet_t pkt; >> + odp_queue_t queue; >> + uint32_t seq; >> + /* create a default packet */ >> + pkt = create_packet(false); >> + seq = cls_pkt_get_seq(pkt); >> + enqueue_loop_interface(pkt); >> + >> + pkt = receive_packet(&queue, ODP_TIME_SEC); >> + /* Default packet should be received in default queue */ >> + CU_ASSERT(queue == queue_list[CLS_DEFAULT]); >> + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); >> + >> + odp_packet_free(pkt); >> +} >> + >> +void configure_pktio_error_cos(void) >> +{ >> + int retval; >> + odp_queue_param_t qparam; >> + char queuename[ODP_QUEUE_NAME_LEN]; >> + char cosname[ODP_COS_NAME_LEN]; >> + >> + qparam.sched.prio = ODP_SCHED_PRIO_LOWEST; >> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >> + sprintf(queuename, "%s", "ErrorCos"); >> + >> + queue_list[CLS_ERROR] = odp_queue_create(queuename, >> + ODP_QUEUE_TYPE_SCHED, >> + &qparam); >> + CU_ASSERT_FATAL(queue_list[CLS_ERROR] != ODP_QUEUE_INVALID); >> + >> + sprintf(cosname, "%s", "ErrorCos"); >> + cos_list[CLS_ERROR] = odp_cos_create(cosname); >> + CU_ASSERT_FATAL(cos_list[CLS_ERROR] != ODP_COS_INVALID); >> + >> + retval = odp_cos_set_queue(cos_list[CLS_ERROR], >> queue_list[CLS_ERROR]); >> + CU_ASSERT(retval == 0); >> + >> + retval = odp_pktio_error_cos_set(pktio_loop, >> cos_list[CLS_ERROR]); >> + CU_ASSERT(retval == 0); >> +} >> + >> +void test_pktio_error_cos(void) >> +{ >> + odp_queue_t queue; >> + odp_packet_t pkt; >> + >> + /*Create an error packet */ >> + pkt = create_packet(false); >> + odph_ipv4hdr_t *ip = (odph_ipv4hdr_t >> *)odp_packet_l3_ptr(pkt, NULL); >> + >> + /* Incorrect IpV4 version */ >> + ip->ver_ihl = 8 << 4 | ODPH_IPV4HDR_IHL_MIN; >> + ip->chksum = 0; >> + enqueue_loop_interface(pkt); >> + >> + pkt = receive_packet(&queue, ODP_TIME_SEC); >> + /* Error packet should be received in error queue */ >> + CU_ASSERT(queue == queue_list[CLS_ERROR]); >> + odp_packet_free(pkt); >> +} >> + >> +static void classification_pktio_set_skip(void) >> +{ >> + int retval; >> + size_t offset = 5; >> + retval = odp_pktio_skip_set(pktio_loop, offset); >> + CU_ASSERT(retval == 0); >> + >> + retval = odp_pktio_skip_set(ODP_PKTIO_INVALID, offset); >> + CU_ASSERT(retval < 0); >> +} >> + >> +static void classification_pktio_set_headroom(void) >> +{ >> + size_t headroom; >> + int retval; >> + headroom = 5; >> + retval = odp_pktio_headroom_set(pktio_loop, headroom); >> + CU_ASSERT(retval == 0); >> + >> + retval = odp_pktio_headroom_set(ODP_PKTIO_INVALID, >> headroom); >> + CU_ASSERT(retval < 0); >> +} >> + >> +void configure_cos_with_l2_priority(void) >> +{ >> + uint8_t num_qos = CLS_L2_QOS_MAX; >> + odp_cos_t cos_tbl[CLS_L2_QOS_MAX]; >> + odp_queue_t queue_tbl[CLS_L2_QOS_MAX]; >> + uint8_t qos_tbl[CLS_L2_QOS_MAX]; >> + char cosname[ODP_COS_NAME_LEN]; >> + char queuename[ODP_QUEUE_NAME_LEN]; >> + int retval; >> + int i; >> + odp_queue_param_t qparam; >> + >> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >> + for (i = 0; i < num_qos; i++) { >> + qparam.sched.prio = ODP_SCHED_PRIO_LOWEST - i; >> + sprintf(cosname, "%s_%d", "L2_Cos", i); >> + cos_tbl[i] = odp_cos_create(cosname); >> + if (cos_tbl[i] == ODP_COS_INVALID) >> + break; >> + >> + cos_list[CLS_L2_QOS_0 + i] = cos_tbl[i]; >> + sprintf(queuename, "%s_%d", "L2_Queue", i); >> + queue_tbl[i] = odp_queue_create(queuename, >> ODP_QUEUE_TYPE_SCHED, >> + &qparam); >> + CU_ASSERT_FATAL(queue_tbl[i] != ODP_QUEUE_INVALID); >> + queue_list[CLS_L2_QOS_0 + i] = queue_tbl[i]; >> + retval = odp_cos_set_queue(cos_tbl[i], >> queue_tbl[i]); >> + CU_ASSERT(retval == 0); >> + qos_tbl[i] = i; >> + } >> + /* count 'i' is passed instead of num_qos to handle the >> rare scenario >> + if the odp_cos_create() failed in the middle*/ >> + retval = odp_cos_with_l2_priority(pktio_loop, i, qos_tbl, >> cos_tbl); >> + CU_ASSERT(retval == 0); >> +} >> + >> +void test_cos_with_l2_priority(void) >> +{ >> + odp_packet_t pkt; >> + odph_ethhdr_t *ethhdr; >> + odph_vlanhdr_t *vlan; >> + odp_queue_t queue; >> + uint32_t seq; >> + >> + uint8_t i; >> + for (i = 0; i < CLS_L2_QOS_MAX; i++) { >> + pkt = create_packet(true); >> + seq = cls_pkt_get_seq(pkt); >> + ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, >> NULL); >> + vlan = (odph_vlanhdr_t *)(ðhdr->type); >> + vlan->tci = odp_cpu_to_be_16(i << 13); >> + enqueue_loop_interface(pkt); >> + pkt = receive_packet(&queue, ODP_TIME_SEC); >> + CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]); >> + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); >> + odp_packet_free(pkt); >> + } >> +} >> + >> +void configure_pmr_cos(void) >> +{ >> + uint16_t val; >> + uint16_t mask; >> + int retval; >> + val = CLS_PMR_SPORT; >> + mask = 0xffff; >> + odp_queue_param_t qparam; >> + char cosname[ODP_COS_NAME_LEN]; >> + char queuename[ODP_QUEUE_NAME_LEN]; >> + >> + pmr_list[CLS_PMR] = >> odp_pmr_create_match(ODP_PMR_UDP_SPORT, &val, >> + &mask, sizeof(val)); >> + CU_ASSERT(pmr_list[CLS_PMR] != ODP_PMR_INVAL); >> + >> + sprintf(cosname, "PMR_CoS"); >> + cos_list[CLS_PMR] = odp_cos_create(cosname); >> + CU_ASSERT_FATAL(cos_list[CLS_PMR] != ODP_COS_INVALID); >> + >> + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; >> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >> + sprintf(queuename, "%s", "PMR_CoS"); >> + >> + queue_list[CLS_PMR] = odp_queue_create(queuename, >> + ODP_QUEUE_TYPE_SCHED, >> + &qparam); >> + CU_ASSERT_FATAL(queue_list[CLS_PMR] != ODP_QUEUE_INVALID); >> + >> + retval = odp_cos_set_queue(cos_list[CLS_PMR], >> + queue_list[CLS_PMR]); >> + CU_ASSERT(retval == 0); >> + >> + retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR], pktio_loop, >> + cos_list[CLS_PMR]); >> + CU_ASSERT(retval == 0); >> +} >> + >> +void test_pmr_cos(void) >> +{ >> + odp_packet_t pkt; >> + odph_udphdr_t *udp; >> + odp_queue_t queue; >> + uint32_t seq; >> + >> + pkt = create_packet(false); >> + seq = cls_pkt_get_seq(pkt); >> + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); >> + udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT); >> + enqueue_loop_interface(pkt); >> + pkt = receive_packet(&queue, ODP_TIME_SEC); >> + CU_ASSERT(queue == queue_list[CLS_PMR]); >> + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); >> + CU_ASSERT(1 == odp_pmr_match_count(pmr_list[CLS_PMR])); >> + odp_packet_free(pkt); >> +} >> + >> +void configure_pktio_pmr_match_set_cos(void) >> +{ >> + int retval; >> + odp_pmr_match_t pmr_terms[2]; >> + uint16_t val; >> + uint16_t maskport; >> + int num_terms = 2; /* one pmr for each L3 and L4 */ >> + odp_queue_param_t qparam; >> + char cosname[ODP_COS_NAME_LEN]; >> + char queuename[ODP_QUEUE_NAME_LEN]; >> + uint32_t addr = 0; >> + uint32_t mask; >> + >> + parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); >> + pmr_terms[0].match_type = ODP_PMR_MASK; >> + pmr_terms[0].mask.term = ODP_PMR_SIP_ADDR; >> + pmr_terms[0].mask.val = &addr; >> + pmr_terms[0].mask.mask = &mask; >> + pmr_terms[0].mask.val_sz = sizeof(addr); >> + >> + >> + val = CLS_PMR_SET_SPORT; >> + maskport = 0xffff; >> + pmr_terms[1].match_type = ODP_PMR_MASK; >> + pmr_terms[1].mask.term = ODP_PMR_UDP_SPORT; >> + pmr_terms[1].mask.val = &val; >> + pmr_terms[1].mask.mask = &maskport; >> + pmr_terms[1].mask.val_sz = sizeof(val); >> + >> + retval = odp_pmr_match_set_create(num_terms, pmr_terms, >> &pmr_set); >> + CU_ASSERT(retval > 0); >> + >> + sprintf(cosname, "cos_pmr_set"); >> + cos_list[CLS_PMR_SET] = odp_cos_create(cosname); >> + CU_ASSERT_FATAL(cos_list[CLS_PMR_SET] != ODP_COS_INVALID) >> + >> + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; >> + qparam.sched.sync = ODP_SCHED_SYNC_NONE; >> + qparam.sched.group = ODP_SCHED_GROUP_ALL; >> + sprintf(queuename, "%s", "cos_pmr_set_queue"); >> + >> + queue_list[CLS_PMR_SET] = odp_queue_create(queuename, >> + ODP_QUEUE_TYPE_SCHED, >> + &qparam); >> + CU_ASSERT_FATAL(queue_list[CLS_PMR_SET] != >> ODP_QUEUE_INVALID); >> + >> + retval = odp_cos_set_queue(cos_list[CLS_PMR_SET], >> + queue_list[CLS_PMR_SET]); >> + CU_ASSERT(retval == 0); >> + >> + retval = odp_pktio_pmr_match_set_cos(pmr_set, pktio_loop, >> + cos_list[CLS_PMR_SET]); >> + CU_ASSERT(retval == 0); >> +} >> + >> +void test_pktio_pmr_match_set_cos(void) >> +{ >> + uint32_t addr = 0; >> + uint32_t mask; >> + odph_ipv4hdr_t *ip; >> + odph_udphdr_t *udp; >> + odp_packet_t pkt; >> + odp_queue_t queue; >> + uint32_t seq; >> + >> + pkt = create_packet(false); >> + seq = cls_pkt_get_seq(pkt); >> + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); >> + parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); >> + ip->src_addr = odp_cpu_to_be_32(addr); >> + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); >> + udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT); >> + enqueue_loop_interface(pkt); >> + pkt = receive_packet(&queue, ODP_TIME_SEC); >> + CU_ASSERT(queue == queue_list[CLS_PMR_SET]); >> + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); >> + odp_packet_free(pkt); >> +} >> + >> +static void classification_pmr_match_count(void) >> +{ >> + odp_pmr_t pmr; >> + uint16_t val; >> + uint16_t mask; >> + val = 1024; >> + mask = 0xffff; >> + int retval; >> + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, >> sizeof(val)); >> + CU_ASSERT(pmr != ODP_PMR_INVAL); >> + >> + retval = odp_pmr_match_count(pmr); >> + CU_ASSERT(retval == 0); >> + >> + odp_pmr_destroy(pmr); >> +} >> + >> +static void classification_pmr_terms_avail(void) >> +{ >> + int retval; >> + /* Since this API called at the start of the suite the >> return value >> + should be greater than 0 */ >> + retval = odp_pmr_terms_avail(); >> + CU_ASSERT(retval > 0); >> +} >> + >> +static void classification_pmr_terms_cap(void) >> +{ >> + unsigned long long retval; >> + /* Need to check different values for different platforms */ >> + retval = odp_pmr_terms_cap(); >> + CU_ASSERT(retval | (1 << ODP_PMR_IPPROTO)); >> +} >> + >> +static void classification_pktio_configure(void) >> +{ >> + /* Configure the Different CoS for the pktio interface */ >> + if (TEST_DEFAULT) >> + configure_pktio_default_cos(); >> + if (TEST_ERROR) >> + configure_pktio_error_cos(); >> + if (TEST_PMR_CHAIN) >> + configure_cls_pmr_chain(); >> + if (TEST_L2_QOS) >> + configure_cos_with_l2_priority(); >> + if (TEST_PMR) >> + configure_pmr_cos(); >> + if (TEST_PMR_SET) >> + configure_pktio_pmr_match_set_cos(); >> +} >> +static void classification_pktio_test(void) >> +{ >> + /* Test Different CoS on the pktio interface */ >> + if (TEST_DEFAULT) >> + test_pktio_default_cos(); >> + if (TEST_ERROR) >> + test_pktio_error_cos(); >> + if (TEST_PMR_CHAIN) >> + test_cls_pmr_chain(); >> + if (TEST_L2_QOS) >> + test_cos_with_l2_priority(); >> + if (TEST_PMR) >> + test_pmr_cos(); >> + if (TEST_PMR_SET) >> + test_pktio_pmr_match_set_cos(); >> +} >> + >> +CU_TestInfo classification_tests[] = { >> + _CU_TEST_INFO(classification_pmr_terms_avail), >> + _CU_TEST_INFO(classification_pktio_set_skip), >> + _CU_TEST_INFO(classification_pktio_set_headroom), >> + _CU_TEST_INFO(classification_pmr_terms_cap), >> + _CU_TEST_INFO(classification_pktio_configure), >> + _CU_TEST_INFO(classification_pktio_test), >> + _CU_TEST_INFO(classification_pmr_match_count), >> + CU_TEST_INFO_NULL, >> +}; >> diff --git >> a/test/validation/classification/odp_classification_testsuites.h >> b/test/validation/classification/odp_classification_testsuites.h >> new file mode 100644 >> index 0000000..0ac5eda >> --- /dev/null >> +++ b/test/validation/classification/odp_classification_testsuites.h >> @@ -0,0 +1,38 @@ >> +/* Copyright (c) 2015, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#ifndef ODP_CLASSIFICATION_TESTSUITES_H_ >> +#define ODP_CLASSIFICATION_TESTSUITES_H_ >> + >> +#include <odp.h> >> +#include <CUnit/CUnit.h> >> +#include <CUnit/Basic.h> >> + >> +/* Helper macro for CU_TestInfo initialization */ >> +#define _CU_TEST_INFO(test_func) {#test_func, test_func} >> + >> +extern CU_TestInfo classification_tests[]; >> +extern CU_TestInfo classification_basic[]; >> + >> +extern int classification_tests_init(void); >> +extern int classification_tests_finalize(void); >> + >> +odp_packet_t create_packet(bool vlan); >> +void configure_pktio_default_cos(void); >> +void test_pktio_default_cos(void); >> +void configure_pktio_error_cos(void); >> +void test_pktio_error_cos(void); >> +void configure_cls_pmr_chain(void); >> +void test_cls_pmr_chain(void); >> +void configure_cos_with_l2_priority(void); >> +void test_cos_with_l2_priority(void); >> +void configure_pmr_cos(void); >> +void test_pmr_cos(void); >> +void configure_pktio_pmr_match_set_cos(void); >> +void test_pktio_pmr_match_set_cos(void); >> + >> + >> +#endif /* ODP_BUFFER_TESTSUITES_H_ */ >> diff --git a/test/validation/odp_classification.c >> b/test/validation/odp_classification.c >> new file mode 100644 >> index 0000000..b501015 >> --- /dev/null >> +++ b/test/validation/odp_classification.c >> @@ -0,0 +1,19 @@ >> +/* Copyright (c) 2015, Linaro Limited >> + * All rights reserved. >> + * >> + * SPDX-License-Identifier: BSD-3-Clause >> + */ >> + >> +#include "odp_classification_testsuites.h" >> + >> +CU_SuiteInfo odp_testsuites[] = { >> + { .pName = "classification basic", >> + .pTests = classification_basic, >> + }, >> + { .pName = "classification tests", >> + .pTests = classification_tests, >> + .pInitFunc = classification_tests_init, >> + .pCleanupFunc = >> classification_tests_finalize, >> + }, >> + CU_SUITE_INFO_NULL, >> +}; >> -- >> 2.0.1.472.g6f92e5f >> >> >> _______________________________________________ >> lng-odp mailing list >> lng-odp@lists.linaro.org <mailto:lng-odp@lists.linaro.org> >> http://lists.linaro.org/mailman/listinfo/lng-odp >> >> >> >> >> -- >> *Mike Holmes* >> Linaro Sr Technical Manager >> LNG - ODP >> >> >> _______________________________________________ >> lng-odp mailing list >> lng-odp@lists.linaro.org >> http://lists.linaro.org/mailman/listinfo/lng-odp > > > _______________________________________________ > lng-odp mailing list > lng-odp@lists.linaro.org > http://lists.linaro.org/mailman/listinfo/lng-odp
diff --git a/test/validation/.gitignore b/test/validation/.gitignore index a1d4d15..4a1ccb4 100644 --- a/test/validation/.gitignore +++ b/test/validation/.gitignore @@ -3,6 +3,7 @@ odp_init odp_queue odp_crypto +odp_classification odp_schedule odp_shm odp_system diff --git a/test/validation/Makefile.am b/test/validation/Makefile.am index 0f5799c..c0e14cb 100644 --- a/test/validation/Makefile.am +++ b/test/validation/Makefile.am @@ -6,13 +6,14 @@ AM_LDFLAGS += -static TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform} if test_vald -TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule odp_pktio_run odp_buffer odp_system odp_timer odp_time odp_synchronizers +TESTS = odp_init odp_queue odp_crypto odp_shm odp_schedule odp_pktio_run odp_buffer odp_system odp_timer odp_time odp_synchronizers odp_classification check_PROGRAMS = ${bin_PROGRAMS} endif -bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule odp_pktio odp_buffer odp_system odp_timer odp_time odp_synchronizers +bin_PROGRAMS = odp_init odp_queue odp_crypto odp_shm odp_schedule odp_pktio odp_buffer odp_system odp_timer odp_time odp_synchronizers odp_classification odp_crypto_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/crypto odp_buffer_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/buffer +odp_classification_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/classification dist_odp_init_SOURCES = odp_init.c dist_odp_pktio_SOURCES = odp_pktio.c common/odp_cunit_common.c @@ -32,3 +33,6 @@ dist_odp_timer_SOURCES = odp_timer.c common/odp_cunit_common.c dist_odp_time_SOURCES = odp_time.c common/odp_cunit_common.c dist_odp_synchronizers_SOURCES = odp_synchronizers.c \ common/odp_cunit_common.c +dist_odp_classification_SOURCES = classification/odp_classification_tests.c \ + classification/odp_classification_basic.c \ + odp_classification.c common/odp_cunit_common.c diff --git a/test/validation/classification/odp_classification_basic.c b/test/validation/classification/odp_classification_basic.c new file mode 100644 index 0000000..844b66e --- /dev/null +++ b/test/validation/classification/odp_classification_basic.c @@ -0,0 +1,178 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "odp_classification_testsuites.h" + +#define PMR_SET_NUM 5 + +static void classification_create_cos(void) +{ + odp_cos_t cos; + char name[ODP_COS_NAME_LEN]; + sprintf(name, "ClassOfService"); + cos = odp_cos_create(name); + CU_ASSERT_FATAL(cos != ODP_COS_INVALID); + odp_cos_destroy(cos); +} + +static void classification_destroy_cos(void) +{ + odp_cos_t cos; + char name[ODP_COS_NAME_LEN]; + int retval; + sprintf(name, "ClassOfService"); + cos = odp_cos_create(name); + CU_ASSERT_FATAL(cos != ODP_COS_INVALID); + retval = odp_cos_destroy(cos); + CU_ASSERT(retval == 0); + retval = odp_cos_destroy(ODP_COS_INVALID); + CU_ASSERT(retval < 0); +} + +static void classification_create_pmr_match(void) +{ + odp_pmr_t pmr; + uint16_t val; + uint16_t mask; + val = 1024; + mask = 0xffff; + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, sizeof(val)); + CU_ASSERT(pmr != ODP_PMR_INVAL); + odp_pmr_destroy(pmr); +} + +static void classification_create_pmr_range(void) +{ + odp_pmr_t pmr; + uint16_t val1; + uint16_t val2; + val1 = 1024; + val2 = 2048; + pmr = odp_pmr_create_range(ODP_PMR_TCP_SPORT, &val1, + &val2, sizeof(val1)); + CU_ASSERT(pmr != ODP_PMR_INVAL); + odp_pmr_destroy(pmr); +} + +static void classification_destroy_pmr(void) +{ + odp_pmr_t pmr; + uint16_t val; + uint16_t mask; + int retval; + val = 1024; + mask = 0xffff; + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, sizeof(val)); + retval = odp_pmr_destroy(pmr); + CU_ASSERT(retval == 0); + retval = odp_pmr_destroy(ODP_PMR_INVAL); + retval = odp_pmr_destroy(ODP_PMR_INVAL); + CU_ASSERT(retval < 0); +} + +static void classification_cos_set_queue(void) +{ + int retval; + char cosname[ODP_COS_NAME_LEN]; + char queuename[ODP_QUEUE_NAME_LEN]; + odp_queue_param_t qparam; + odp_queue_t queue_cos; + odp_cos_t cos_queue; + sprintf(cosname, "CoSQueue"); + cos_queue = odp_cos_create(cosname); + CU_ASSERT_FATAL(cos_queue != ODP_COS_INVALID); + + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; + qparam.sched.sync = ODP_SCHED_SYNC_NONE; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + sprintf(queuename, "%s", "QueueCoS"); + + queue_cos = odp_queue_create(queuename, + ODP_QUEUE_TYPE_SCHED, &qparam); + retval = odp_cos_set_queue(cos_queue, queue_cos); + CU_ASSERT(retval == 0); + odp_cos_destroy(cos_queue); + odp_queue_destroy(queue_cos); +} + +static void classification_cos_set_drop(void) +{ + int retval; + char cosname[ODP_COS_NAME_LEN]; + sprintf(cosname, "CoSDrop"); + odp_cos_t cos_drop; + cos_drop = odp_cos_create(cosname); + CU_ASSERT_FATAL(cos_drop != ODP_COS_INVALID); + + retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_POOL); + CU_ASSERT(retval == 0); + retval = odp_cos_set_drop(cos_drop, ODP_COS_DROP_NEVER); + CU_ASSERT(retval == 0); + odp_cos_destroy(cos_drop); +} + +static void classification_pmr_match_set_create(void) +{ + odp_pmr_set_t pmr_set; + int retval; + odp_pmr_match_t pmr_terms[PMR_SET_NUM]; + uint16_t val = 1024; + uint16_t mask = 0xffff; + int i; + for (i = 0; i < PMR_SET_NUM; i++) { + pmr_terms[i].match_type = ODP_PMR_MASK; + pmr_terms[i].mask.term = ODP_PMR_TCP_DPORT; + pmr_terms[i].mask.val = &val; + pmr_terms[i].mask.mask = &mask; + pmr_terms[i].mask.val_sz = sizeof(val); + } + + retval = odp_pmr_match_set_create(PMR_SET_NUM, pmr_terms, &pmr_set); + CU_ASSERT(retval > 0); + + retval = odp_pmr_match_set_destroy(pmr_set); + CU_ASSERT(retval == 0); +} + +static void classification_pmr_match_set_destroy(void) +{ + odp_pmr_set_t pmr_set; + int retval; + odp_pmr_match_t pmr_terms[PMR_SET_NUM]; + uint16_t val = 1024; + uint16_t mask = 0xffff; + int i; + + retval = odp_pmr_match_set_destroy(ODP_PMR_INVAL); + CU_ASSERT(retval < 0); + + for (i = 0; i < PMR_SET_NUM; i++) { + pmr_terms[i].match_type = ODP_PMR_MASK; + pmr_terms[i].mask.term = ODP_PMR_TCP_DPORT; + pmr_terms[i].mask.val = &val; + pmr_terms[i].mask.mask = &mask; + pmr_terms[i].mask.val_sz = sizeof(val); + } + + retval = odp_pmr_match_set_create(PMR_SET_NUM, pmr_terms, &pmr_set); + CU_ASSERT(retval > 0); + + retval = odp_pmr_match_set_destroy(pmr_set); + CU_ASSERT(retval == 0); +} + +CU_TestInfo classification_basic[] = { + _CU_TEST_INFO(classification_create_cos), + _CU_TEST_INFO(classification_destroy_cos), + _CU_TEST_INFO(classification_create_pmr_match), + _CU_TEST_INFO(classification_create_pmr_range), + _CU_TEST_INFO(classification_destroy_pmr), + _CU_TEST_INFO(classification_cos_set_queue), + _CU_TEST_INFO(classification_cos_set_drop), + _CU_TEST_INFO(classification_pmr_match_set_create), + _CU_TEST_INFO(classification_pmr_match_set_destroy), + CU_TEST_INFO_NULL, +}; diff --git a/test/validation/classification/odp_classification_tests.c b/test/validation/classification/odp_classification_tests.c new file mode 100644 index 0000000..778172c --- /dev/null +++ b/test/validation/classification/odp_classification_tests.c @@ -0,0 +1,816 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "odp_classification_testsuites.h" +#include <odph_eth.h> +#include <odph_ip.h> +#include <odph_udp.h> + +#define SHM_PKT_NUM_BUFS 32 +#define SHM_PKT_BUF_SIZE 1024 + +/* Config values for Default CoS */ +#define TEST_DEFAULT 1 +#define CLS_DEFAULT 0 +#define CLS_DEFAULT_SADDR "10.0.0.1/32" +#define CLS_DEFAULT_DADDR "10.0.0.100/32" +#define CLS_DEFAULT_SPORT 1024 +#define CLS_DEFAULT_DPORT 2048 + +/* Config values for Error CoS */ +#define TEST_ERROR 1 +#define CLS_ERROR 1 + +/* Config values for PMR_CHAIN */ +#define TEST_PMR_CHAIN 1 +#define CLS_PMR_CHAIN_SRC 2 +#define CLS_PMR_CHAIN_DST 3 +#define CLS_PMR_CHAIN_SADDR "10.0.0.5/32" +#define CLS_PMR_CHAIN_SPORT 3000 + +/* Config values for PMR */ +#define TEST_PMR 1 +#define CLS_PMR 4 +#define CLS_PMR_SPORT 4000 + +/* Config values for PMR SET */ +#define TEST_PMR_SET 1 +#define CLS_PMR_SET 5 +#define CLS_PMR_SET_SADDR "10.0.0.6/32" +#define CLS_PMR_SET_SPORT 5000 + +/* Config values for CoS L2 Priority */ +#define TEST_L2_QOS 1 +#define CLS_L2_QOS_0 6 +#define CLS_L2_QOS_MAX 5 + +#define CLS_ENTRIES (CLS_L2_QOS_0 + CLS_L2_QOS_MAX) + +/* Test Packet values */ +#define DATA_MAGIC 0x01020304 +#define TEST_SEQ_INVALID ((uint32_t)~0) + +static odp_cos_t cos_list[CLS_ENTRIES]; +static odp_pmr_t pmr_list[CLS_ENTRIES]; +static odp_queue_t queue_list[CLS_ENTRIES]; +static odp_pmr_set_t pmr_set; + +static odp_buffer_pool_t pool_default; +static odp_pktio_t pktio_loop; + +/** sequence number of IP packets */ +odp_atomic_u32_t seq; + +typedef struct cls_test_packet { + uint32be_t magic; + uint32be_t seq; +} cls_test_packet_t; + +static inline +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask) +{ + int b[4]; + int qualifier = 32; + int converted; + + if (strchr(ipaddress, '/')) { + converted = sscanf(ipaddress, "%d.%d.%d.%d/%d", + &b[3], &b[2], &b[1], &b[0], + &qualifier); + if (5 != converted) + return -1; + } else { + converted = sscanf(ipaddress, "%d.%d.%d.%d", + &b[3], &b[2], &b[1], &b[0]); + if (4 != converted) + return -1; + } + + if ((b[0] > 255) || (b[1] > 255) || (b[2] > 255) || (b[3] > 255)) + return -1; + if (!qualifier || (qualifier > 32)) + return -1; + + *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24; + if (mask) + *mask = ~(0xFFFFFFFF & ((1ULL << (32 - qualifier)) - 1)); + + return 0; +} + +static inline +void enqueue_loop_interface(odp_packet_t pkt) +{ + odp_queue_t defqueue = odp_pktio_outq_getdef(pktio_loop); + odp_queue_enq(defqueue, odp_packet_to_buffer(pkt)); +} + +static inline +odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns) +{ + odp_buffer_t buf; + odp_packet_t pkt; + buf = odp_schedule(queue, ns); + pkt = odp_packet_from_buffer(buf); + return pkt; +} + +static int cls_pkt_set_seq(odp_packet_t pkt) +{ + static uint32_t seq; + cls_test_packet_t data; + uint32_t offset; + + data.magic = DATA_MAGIC; + data.seq = ++seq; + + offset = odp_packet_l4_offset(pkt); + CU_ASSERT_FATAL(offset != 0); + + odp_packet_copydata_in(pkt, offset + ODPH_UDPHDR_LEN, + sizeof(data), &data); + + return 0; +} + +static uint32_t cls_pkt_get_seq(odp_packet_t pkt) +{ + uint32_t offset; + cls_test_packet_t data; + + offset = odp_packet_l4_offset(pkt); + if (offset) { + odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN, + sizeof(data), &data); + + if (data.magic == DATA_MAGIC) + return data.seq; + } + + return TEST_SEQ_INVALID; +} +odp_packet_t create_packet(bool vlan) +{ + uint32_t seqno; + odph_ethhdr_t *ethhdr; + odph_udphdr_t *udp; + odph_ipv4hdr_t *ip; + uint8_t payload_len; + char src_mac[ODPH_ETHADDR_LEN] = {0}; + char dst_mac[ODPH_ETHADDR_LEN] = {0}; + uint32_t addr = 0; + uint32_t mask; + int offset; + odp_packet_t pkt; + int packet_len = 0; + + payload_len = sizeof(cls_test_packet_t); + packet_len += ODPH_ETHHDR_LEN; + packet_len += ODPH_IPV4HDR_LEN; + packet_len += ODPH_UDPHDR_LEN; + packet_len += payload_len; + + if (vlan) + packet_len += ODPH_VLANHDR_LEN; + + pkt = odp_packet_alloc(pool_default, packet_len); + CU_ASSERT_FATAL(pkt != ODP_PACKET_INVALID); + + /* Ethernet Header */ + offset = 0; + odp_packet_l2_offset_set(pkt, offset); + ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); + memcpy(ethhdr->src.addr, src_mac, ODPH_ETHADDR_LEN); + memcpy(ethhdr->dst.addr, dst_mac, ODPH_ETHADDR_LEN); + offset += sizeof(odph_ethhdr_t); + if (vlan) { + /* Default vlan header */ + uint8_t *parseptr; + odph_vlanhdr_t *vlan = (odph_vlanhdr_t *)(ðhdr->type); + parseptr = (uint8_t *)vlan; + vlan->tci = odp_cpu_to_be_16(0); + vlan->tpid = odp_cpu_to_be_16(ODPH_ETHTYPE_VLAN); + offset += sizeof(odph_vlanhdr_t); + parseptr += sizeof(odph_vlanhdr_t); + uint16be_t *type = (uint16be_t *)parseptr; + *type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); + } else { + ethhdr->type = odp_cpu_to_be_16(ODPH_ETHTYPE_IPV4); + } + + odp_packet_l3_offset_set(pkt, offset); + + /* ipv4 */ + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); + + parse_ipv4_string(CLS_DEFAULT_SADDR, &addr, &mask); + ip->dst_addr = odp_cpu_to_be_32(addr); + + parse_ipv4_string(CLS_DEFAULT_DADDR, &addr, &mask); + ip->src_addr = odp_cpu_to_be_32(addr); + ip->ver_ihl = ODPH_IPV4 << 4 | ODPH_IPV4HDR_IHL_MIN; + ip->tot_len = odp_cpu_to_be_16(ODPH_UDPHDR_LEN + payload_len + + ODPH_IPV4HDR_LEN); + ip->ttl = 128; + ip->proto = ODPH_IPPROTO_UDP; + seqno = odp_atomic_fetch_inc_u32(&seq); + ip->id = odp_cpu_to_be_16(seqno); + ip->chksum = 0; + odph_ipv4_csum_update(pkt); + offset += ODPH_IPV4HDR_LEN; + + /* udp */ + odp_packet_l4_offset_set(pkt, offset); + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); + udp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT); + udp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT); + udp->length = odp_cpu_to_be_16(payload_len + ODPH_UDPHDR_LEN); + udp->chksum = 0; + + /* set pkt sequence number */ + cls_pkt_set_seq(pkt); + + return pkt; +} + +int classification_tests_init(void) +{ + odp_buffer_pool_t pool; + odp_buffer_pool_param_t param; + odp_queue_t inq_def; + odp_queue_param_t qparam; + char queuename[ODP_QUEUE_NAME_LEN]; + int i; + + param.buf_size = SHM_PKT_BUF_SIZE; + param.num_bufs = SHM_PKT_NUM_BUFS; + param.buf_type = ODP_BUFFER_TYPE_PACKET; + param.buf_align = 0; + pool = odp_buffer_pool_create("classification_pool", + ODP_SHM_NULL, ¶m); + if (ODP_BUFFER_POOL_INVALID == pool) { + fprintf(stderr, "Packet pool creation failed.\n"); + return -1; + } + + pool_default = odp_buffer_pool_lookup("classification_pool"); + if (pool_default == ODP_BUFFER_POOL_INVALID) + goto error_pool_default; + + pktio_loop = odp_pktio_open("loop", pool_default); + if (pktio_loop == ODP_PKTIO_INVALID) + goto error_pktio_loop; + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; + qparam.sched.sync = ODP_SCHED_SYNC_ATOMIC; + qparam.sched.group = ODP_SCHED_GROUP_DEFAULT; + + sprintf(queuename, "%s", "inq_loop"); + inq_def = odp_queue_create(queuename, + ODP_QUEUE_TYPE_PKTIN, &qparam); + odp_pktio_inq_setdef(pktio_loop, inq_def); + + for (i = 0; i < CLS_ENTRIES; i++) + cos_list[i] = ODP_COS_INVALID; + + for (i = 0; i < CLS_ENTRIES; i++) + pmr_list[i] = ODP_PMR_INVAL; + + for (i = 0; i < CLS_ENTRIES; i++) + queue_list[i] = ODP_QUEUE_INVALID; + + return 0; + +error_pktio_loop: + odp_buffer_pool_destroy(pool_default); + +error_pool_default: + return -1; +} + +int classification_tests_finalize(void) +{ + int i; + if (0 > odp_pktio_close(pktio_loop)) + return -1; + + if (0 != odp_buffer_pool_destroy(pool_default)) + return -1; + + for (i = 0; i < CLS_ENTRIES; i++) + odp_cos_destroy(cos_list[i]); + + for (i = 0; i < CLS_ENTRIES; i++) + odp_pmr_destroy(pmr_list[i]); + + for (i = 0; i < CLS_ENTRIES; i++) + odp_queue_destroy(queue_list[i]); + return 0; +} + +void configure_cls_pmr_chain(void) +{ + /* PKTIO --> PMR_SRC(SRC IP ADDR) --> PMR_DST (TCP SPORT) */ + + /* Packet matching only the SRC IP ADDR should be delivered + in queue[CLS_PMR_CHAIN_SRC] and a packet matching both SRC IP ADDR and + TCP SPORT should be delivered to queue[CLS_PMR_CHAIN_DST] */ + + uint16_t val; + uint16_t maskport; + int retval; + char cosname[ODP_QUEUE_NAME_LEN]; + odp_queue_param_t qparam; + char queuename[ODP_QUEUE_NAME_LEN]; + uint32_t addr; + uint32_t mask; + + sprintf(cosname, "SrcCos"); + cos_list[CLS_PMR_CHAIN_SRC] = odp_cos_create(cosname); + CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_SRC] != ODP_COS_INVALID) + + qparam.sched.prio = ODP_SCHED_PRIO_NORMAL; + qparam.sched.sync = ODP_SCHED_SYNC_NONE; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + sprintf(queuename, "%s", "SrcQueue"); + + queue_list[CLS_PMR_CHAIN_SRC] = odp_queue_create(queuename, + ODP_QUEUE_TYPE_SCHED, + &qparam); + + CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_SRC] != ODP_QUEUE_INVALID); + retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_SRC], + queue_list[CLS_PMR_CHAIN_SRC]); + CU_ASSERT(retval == 0); + + sprintf(cosname, "DstCos"); + cos_list[CLS_PMR_CHAIN_DST] = odp_cos_create(cosname); + CU_ASSERT_FATAL(cos_list[CLS_PMR_CHAIN_DST] != ODP_COS_INVALID); + + qparam.sched.prio = ODP_SCHED_PRIO_NORMAL; + qparam.sched.sync = ODP_SCHED_SYNC_NONE; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + sprintf(queuename, "%s", "DstQueue"); + + queue_list[CLS_PMR_CHAIN_DST] = odp_queue_create(queuename, + ODP_QUEUE_TYPE_SCHED, + &qparam); + CU_ASSERT_FATAL(queue_list[CLS_PMR_CHAIN_DST] != ODP_QUEUE_INVALID); + + retval = odp_cos_set_queue(cos_list[CLS_PMR_CHAIN_DST], + queue_list[CLS_PMR_CHAIN_DST]); + + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); + pmr_list[CLS_PMR_CHAIN_SRC] = odp_pmr_create_match(ODP_PMR_SIP_ADDR, + &addr, &mask, + sizeof(addr)); + CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_SRC] != ODP_PMR_INVAL); + + val = CLS_PMR_CHAIN_SPORT; + maskport = 0xffff; + pmr_list[CLS_PMR_CHAIN_DST] = odp_pmr_create_match(ODP_PMR_UDP_SPORT, + &val, &maskport, + sizeof(val)); + CU_ASSERT_FATAL(pmr_list[CLS_PMR_CHAIN_DST] != ODP_PMR_INVAL); + + retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR_CHAIN_SRC], pktio_loop, + cos_list[CLS_PMR_CHAIN_SRC]); + CU_ASSERT(retval == 0); + + retval = odp_cos_pmr_cos(pmr_list[CLS_PMR_CHAIN_DST], + cos_list[CLS_PMR_CHAIN_SRC], + cos_list[CLS_PMR_CHAIN_DST]); + CU_ASSERT(retval == 0); +} + +void test_cls_pmr_chain(void) +{ + odp_packet_t pkt; + odph_ipv4hdr_t *ip; + odph_udphdr_t *udp; + odp_queue_t queue; + uint32_t addr = 0; + uint32_t mask; + uint32_t seq; + + pkt = create_packet(false); + seq = cls_pkt_get_seq(pkt); + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); + ip->src_addr = odp_cpu_to_be_32(addr); + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); + udp->src_port = odp_cpu_to_be_16(CLS_PMR_CHAIN_SPORT); + + enqueue_loop_interface(pkt); + + pkt = receive_packet(&queue, ODP_TIME_SEC); + CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_DST]); + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); + odp_packet_free(pkt); + + pkt = create_packet(false); + seq = cls_pkt_get_seq(pkt); + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); + parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask); + ip->src_addr = odp_cpu_to_be_32(addr); + + enqueue_loop_interface(pkt); + pkt = receive_packet(&queue, ODP_TIME_SEC); + CU_ASSERT(queue == queue_list[CLS_PMR_CHAIN_SRC]); + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); + + CU_ASSERT(1 == odp_pmr_match_count(pmr_list[CLS_PMR_CHAIN_DST])); + odp_packet_free(pkt); +} + +void configure_pktio_default_cos(void) +{ + int retval; + odp_queue_param_t qparam; + char cosname[ODP_COS_NAME_LEN]; + char queuename[ODP_QUEUE_NAME_LEN]; + + sprintf(cosname, "DefaultCoS"); + cos_list[CLS_DEFAULT] = odp_cos_create(cosname); + CU_ASSERT_FATAL(cos_list[CLS_DEFAULT] != ODP_COS_INVALID); + + qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT; + qparam.sched.sync = ODP_SCHED_SYNC_NONE; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + sprintf(queuename, "%s", "DefaultQueue"); + queue_list[CLS_DEFAULT] = odp_queue_create(queuename, + ODP_QUEUE_TYPE_SCHED, &qparam); + CU_ASSERT_FATAL(queue_list[CLS_DEFAULT] != ODP_QUEUE_INVALID); + + retval = odp_cos_set_queue(cos_list[CLS_DEFAULT], + queue_list[CLS_DEFAULT]); + CU_ASSERT(retval == 0); + + retval = odp_pktio_default_cos_set(pktio_loop, cos_list[CLS_DEFAULT]); + CU_ASSERT(retval == 0); +} + +void test_pktio_default_cos(void) +{ + odp_packet_t pkt; + odp_queue_t queue; + uint32_t seq; + /* create a default packet */ + pkt = create_packet(false); + seq = cls_pkt_get_seq(pkt); + enqueue_loop_interface(pkt); + + pkt = receive_packet(&queue, ODP_TIME_SEC); + /* Default packet should be received in default queue */ + CU_ASSERT(queue == queue_list[CLS_DEFAULT]); + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); + + odp_packet_free(pkt); +} + +void configure_pktio_error_cos(void) +{ + int retval; + odp_queue_param_t qparam; + char queuename[ODP_QUEUE_NAME_LEN]; + char cosname[ODP_COS_NAME_LEN]; + + qparam.sched.prio = ODP_SCHED_PRIO_LOWEST; + qparam.sched.sync = ODP_SCHED_SYNC_NONE; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + sprintf(queuename, "%s", "ErrorCos"); + + queue_list[CLS_ERROR] = odp_queue_create(queuename, + ODP_QUEUE_TYPE_SCHED, + &qparam); + CU_ASSERT_FATAL(queue_list[CLS_ERROR] != ODP_QUEUE_INVALID); + + sprintf(cosname, "%s", "ErrorCos"); + cos_list[CLS_ERROR] = odp_cos_create(cosname); + CU_ASSERT_FATAL(cos_list[CLS_ERROR] != ODP_COS_INVALID); + + retval = odp_cos_set_queue(cos_list[CLS_ERROR], queue_list[CLS_ERROR]); + CU_ASSERT(retval == 0); + + retval = odp_pktio_error_cos_set(pktio_loop, cos_list[CLS_ERROR]); + CU_ASSERT(retval == 0); +} + +void test_pktio_error_cos(void) +{ + odp_queue_t queue; + odp_packet_t pkt; + + /*Create an error packet */ + pkt = create_packet(false); + odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); + + /* Incorrect IpV4 version */ + ip->ver_ihl = 8 << 4 | ODPH_IPV4HDR_IHL_MIN; + ip->chksum = 0; + enqueue_loop_interface(pkt); + + pkt = receive_packet(&queue, ODP_TIME_SEC); + /* Error packet should be received in error queue */ + CU_ASSERT(queue == queue_list[CLS_ERROR]); + odp_packet_free(pkt); +} + +static void classification_pktio_set_skip(void) +{ + int retval; + size_t offset = 5; + retval = odp_pktio_skip_set(pktio_loop, offset); + CU_ASSERT(retval == 0); + + retval = odp_pktio_skip_set(ODP_PKTIO_INVALID, offset); + CU_ASSERT(retval < 0); +} + +static void classification_pktio_set_headroom(void) +{ + size_t headroom; + int retval; + headroom = 5; + retval = odp_pktio_headroom_set(pktio_loop, headroom); + CU_ASSERT(retval == 0); + + retval = odp_pktio_headroom_set(ODP_PKTIO_INVALID, headroom); + CU_ASSERT(retval < 0); +} + +void configure_cos_with_l2_priority(void) +{ + uint8_t num_qos = CLS_L2_QOS_MAX; + odp_cos_t cos_tbl[CLS_L2_QOS_MAX]; + odp_queue_t queue_tbl[CLS_L2_QOS_MAX]; + uint8_t qos_tbl[CLS_L2_QOS_MAX]; + char cosname[ODP_COS_NAME_LEN]; + char queuename[ODP_QUEUE_NAME_LEN]; + int retval; + int i; + odp_queue_param_t qparam; + + qparam.sched.sync = ODP_SCHED_SYNC_NONE; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + for (i = 0; i < num_qos; i++) { + qparam.sched.prio = ODP_SCHED_PRIO_LOWEST - i; + sprintf(cosname, "%s_%d", "L2_Cos", i); + cos_tbl[i] = odp_cos_create(cosname); + if (cos_tbl[i] == ODP_COS_INVALID) + break; + + cos_list[CLS_L2_QOS_0 + i] = cos_tbl[i]; + sprintf(queuename, "%s_%d", "L2_Queue", i); + queue_tbl[i] = odp_queue_create(queuename, ODP_QUEUE_TYPE_SCHED, + &qparam); + CU_ASSERT_FATAL(queue_tbl[i] != ODP_QUEUE_INVALID); + queue_list[CLS_L2_QOS_0 + i] = queue_tbl[i]; + retval = odp_cos_set_queue(cos_tbl[i], queue_tbl[i]); + CU_ASSERT(retval == 0); + qos_tbl[i] = i; + } + /* count 'i' is passed instead of num_qos to handle the rare scenario + if the odp_cos_create() failed in the middle*/ + retval = odp_cos_with_l2_priority(pktio_loop, i, qos_tbl, cos_tbl); + CU_ASSERT(retval == 0); +} + +void test_cos_with_l2_priority(void) +{ + odp_packet_t pkt; + odph_ethhdr_t *ethhdr; + odph_vlanhdr_t *vlan; + odp_queue_t queue; + uint32_t seq; + + uint8_t i; + for (i = 0; i < CLS_L2_QOS_MAX; i++) { + pkt = create_packet(true); + seq = cls_pkt_get_seq(pkt); + ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL); + vlan = (odph_vlanhdr_t *)(ðhdr->type); + vlan->tci = odp_cpu_to_be_16(i << 13); + enqueue_loop_interface(pkt); + pkt = receive_packet(&queue, ODP_TIME_SEC); + CU_ASSERT(queue == queue_list[CLS_L2_QOS_0 + i]); + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); + odp_packet_free(pkt); + } +} + +void configure_pmr_cos(void) +{ + uint16_t val; + uint16_t mask; + int retval; + val = CLS_PMR_SPORT; + mask = 0xffff; + odp_queue_param_t qparam; + char cosname[ODP_COS_NAME_LEN]; + char queuename[ODP_QUEUE_NAME_LEN]; + + pmr_list[CLS_PMR] = odp_pmr_create_match(ODP_PMR_UDP_SPORT, &val, + &mask, sizeof(val)); + CU_ASSERT(pmr_list[CLS_PMR] != ODP_PMR_INVAL); + + sprintf(cosname, "PMR_CoS"); + cos_list[CLS_PMR] = odp_cos_create(cosname); + CU_ASSERT_FATAL(cos_list[CLS_PMR] != ODP_COS_INVALID); + + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; + qparam.sched.sync = ODP_SCHED_SYNC_NONE; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + sprintf(queuename, "%s", "PMR_CoS"); + + queue_list[CLS_PMR] = odp_queue_create(queuename, + ODP_QUEUE_TYPE_SCHED, + &qparam); + CU_ASSERT_FATAL(queue_list[CLS_PMR] != ODP_QUEUE_INVALID); + + retval = odp_cos_set_queue(cos_list[CLS_PMR], + queue_list[CLS_PMR]); + CU_ASSERT(retval == 0); + + retval = odp_pktio_pmr_cos(pmr_list[CLS_PMR], pktio_loop, + cos_list[CLS_PMR]); + CU_ASSERT(retval == 0); +} + +void test_pmr_cos(void) +{ + odp_packet_t pkt; + odph_udphdr_t *udp; + odp_queue_t queue; + uint32_t seq; + + pkt = create_packet(false); + seq = cls_pkt_get_seq(pkt); + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); + udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT); + enqueue_loop_interface(pkt); + pkt = receive_packet(&queue, ODP_TIME_SEC); + CU_ASSERT(queue == queue_list[CLS_PMR]); + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); + CU_ASSERT(1 == odp_pmr_match_count(pmr_list[CLS_PMR])); + odp_packet_free(pkt); +} + +void configure_pktio_pmr_match_set_cos(void) +{ + int retval; + odp_pmr_match_t pmr_terms[2]; + uint16_t val; + uint16_t maskport; + int num_terms = 2; /* one pmr for each L3 and L4 */ + odp_queue_param_t qparam; + char cosname[ODP_COS_NAME_LEN]; + char queuename[ODP_QUEUE_NAME_LEN]; + uint32_t addr = 0; + uint32_t mask; + + parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); + pmr_terms[0].match_type = ODP_PMR_MASK; + pmr_terms[0].mask.term = ODP_PMR_SIP_ADDR; + pmr_terms[0].mask.val = &addr; + pmr_terms[0].mask.mask = &mask; + pmr_terms[0].mask.val_sz = sizeof(addr); + + + val = CLS_PMR_SET_SPORT; + maskport = 0xffff; + pmr_terms[1].match_type = ODP_PMR_MASK; + pmr_terms[1].mask.term = ODP_PMR_UDP_SPORT; + pmr_terms[1].mask.val = &val; + pmr_terms[1].mask.mask = &maskport; + pmr_terms[1].mask.val_sz = sizeof(val); + + retval = odp_pmr_match_set_create(num_terms, pmr_terms, &pmr_set); + CU_ASSERT(retval > 0); + + sprintf(cosname, "cos_pmr_set"); + cos_list[CLS_PMR_SET] = odp_cos_create(cosname); + CU_ASSERT_FATAL(cos_list[CLS_PMR_SET] != ODP_COS_INVALID) + + qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST; + qparam.sched.sync = ODP_SCHED_SYNC_NONE; + qparam.sched.group = ODP_SCHED_GROUP_ALL; + sprintf(queuename, "%s", "cos_pmr_set_queue"); + + queue_list[CLS_PMR_SET] = odp_queue_create(queuename, + ODP_QUEUE_TYPE_SCHED, + &qparam); + CU_ASSERT_FATAL(queue_list[CLS_PMR_SET] != ODP_QUEUE_INVALID); + + retval = odp_cos_set_queue(cos_list[CLS_PMR_SET], + queue_list[CLS_PMR_SET]); + CU_ASSERT(retval == 0); + + retval = odp_pktio_pmr_match_set_cos(pmr_set, pktio_loop, + cos_list[CLS_PMR_SET]); + CU_ASSERT(retval == 0); +} + +void test_pktio_pmr_match_set_cos(void) +{ + uint32_t addr = 0; + uint32_t mask; + odph_ipv4hdr_t *ip; + odph_udphdr_t *udp; + odp_packet_t pkt; + odp_queue_t queue; + uint32_t seq; + + pkt = create_packet(false); + seq = cls_pkt_get_seq(pkt); + ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL); + parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask); + ip->src_addr = odp_cpu_to_be_32(addr); + udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL); + udp->src_port = odp_cpu_to_be_16(CLS_PMR_SET_SPORT); + enqueue_loop_interface(pkt); + pkt = receive_packet(&queue, ODP_TIME_SEC); + CU_ASSERT(queue == queue_list[CLS_PMR_SET]); + CU_ASSERT(seq == cls_pkt_get_seq(pkt)); + odp_packet_free(pkt); +} + +static void classification_pmr_match_count(void) +{ + odp_pmr_t pmr; + uint16_t val; + uint16_t mask; + val = 1024; + mask = 0xffff; + int retval; + pmr = odp_pmr_create_match(ODP_PMR_TCP_SPORT, &val, &mask, sizeof(val)); + CU_ASSERT(pmr != ODP_PMR_INVAL); + + retval = odp_pmr_match_count(pmr); + CU_ASSERT(retval == 0); + + odp_pmr_destroy(pmr); +} + +static void classification_pmr_terms_avail(void) +{ + int retval; + /* Since this API called at the start of the suite the return value + should be greater than 0 */ + retval = odp_pmr_terms_avail(); + CU_ASSERT(retval > 0); +} + +static void classification_pmr_terms_cap(void) +{ + unsigned long long retval; + /* Need to check different values for different platforms */ + retval = odp_pmr_terms_cap(); + CU_ASSERT(retval | (1 << ODP_PMR_IPPROTO)); +} + +static void classification_pktio_configure(void) +{ + /* Configure the Different CoS for the pktio interface */ + if (TEST_DEFAULT) + configure_pktio_default_cos(); + if (TEST_ERROR) + configure_pktio_error_cos(); + if (TEST_PMR_CHAIN) + configure_cls_pmr_chain(); + if (TEST_L2_QOS) + configure_cos_with_l2_priority(); + if (TEST_PMR) + configure_pmr_cos(); + if (TEST_PMR_SET) + configure_pktio_pmr_match_set_cos(); +} +static void classification_pktio_test(void) +{ + /* Test Different CoS on the pktio interface */ + if (TEST_DEFAULT) + test_pktio_default_cos(); + if (TEST_ERROR) + test_pktio_error_cos(); + if (TEST_PMR_CHAIN) + test_cls_pmr_chain(); + if (TEST_L2_QOS) + test_cos_with_l2_priority(); + if (TEST_PMR) + test_pmr_cos(); + if (TEST_PMR_SET) + test_pktio_pmr_match_set_cos(); +} + +CU_TestInfo classification_tests[] = { + _CU_TEST_INFO(classification_pmr_terms_avail), + _CU_TEST_INFO(classification_pktio_set_skip), + _CU_TEST_INFO(classification_pktio_set_headroom), + _CU_TEST_INFO(classification_pmr_terms_cap), + _CU_TEST_INFO(classification_pktio_configure), + _CU_TEST_INFO(classification_pktio_test), + _CU_TEST_INFO(classification_pmr_match_count), + CU_TEST_INFO_NULL, +}; diff --git a/test/validation/classification/odp_classification_testsuites.h b/test/validation/classification/odp_classification_testsuites.h new file mode 100644 index 0000000..0ac5eda --- /dev/null +++ b/test/validation/classification/odp_classification_testsuites.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ODP_CLASSIFICATION_TESTSUITES_H_ +#define ODP_CLASSIFICATION_TESTSUITES_H_ + +#include <odp.h> +#include <CUnit/CUnit.h> +#include <CUnit/Basic.h> + +/* Helper macro for CU_TestInfo initialization */ +#define _CU_TEST_INFO(test_func) {#test_func, test_func} + +extern CU_TestInfo classification_tests[]; +extern CU_TestInfo classification_basic[]; + +extern int classification_tests_init(void); +extern int classification_tests_finalize(void); + +odp_packet_t create_packet(bool vlan); +void configure_pktio_default_cos(void); +void test_pktio_default_cos(void); +void configure_pktio_error_cos(void); +void test_pktio_error_cos(void); +void configure_cls_pmr_chain(void); +void test_cls_pmr_chain(void); +void configure_cos_with_l2_priority(void); +void test_cos_with_l2_priority(void); +void configure_pmr_cos(void); +void test_pmr_cos(void); +void configure_pktio_pmr_match_set_cos(void); +void test_pktio_pmr_match_set_cos(void); + + +#endif /* ODP_BUFFER_TESTSUITES_H_ */ diff --git a/test/validation/odp_classification.c b/test/validation/odp_classification.c new file mode 100644 index 0000000..b501015 --- /dev/null +++ b/test/validation/odp_classification.c @@ -0,0 +1,19 @@ +/* Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "odp_classification_testsuites.h" + +CU_SuiteInfo odp_testsuites[] = { + { .pName = "classification basic", + .pTests = classification_basic, + }, + { .pName = "classification tests", + .pTests = classification_tests, + .pInitFunc = classification_tests_init, + .pCleanupFunc = classification_tests_finalize, + }, + CU_SUITE_INFO_NULL, +};