From: Balasubramanian Manoharan <[email protected]>

This 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
        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 <[email protected]>
---
 test/validation/Makefile.am                        |   8 +-
 .../classification/odp_classification_basic.c      | 176 +++++
 .../classification/odp_classification_tests.c      | 815 +++++++++++++++++++++
 .../classification/odp_classification_testsuites.h |  38 +
 test/validation/odp_classification.c               |  19 +
 5 files changed, 1054 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/Makefile.am b/test/validation/Makefile.am
index 400d758..50ba638 100644
--- a/test/validation/Makefile.am
+++ b/test/validation/Makefile.am
@@ -6,11 +6,12 @@ AM_LDFLAGS += -static
 TESTS_ENVIRONMENT = ODP_PLATFORM=${with_platform}
 
 if ODP_CUNIT_ENABLED
-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}
-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
 endif
 
 dist_odp_init_SOURCES = odp_init.c
@@ -31,3 +32,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..46c289e
--- /dev/null
+++ b/test/validation/classification/odp_classification_basic.c
@@ -0,0 +1,176 @@
+#include "odp_classification_testsuites.h"
+#include <odph_eth.h>
+#include <odph_ip.h>
+#include <odph_udp.h>
+#include <string.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..1f97035
--- /dev/null
+++ b/test/validation/classification/odp_classification_tests.c
@@ -0,0 +1,815 @@
+/* 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>
+#include <string.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 *)(&ethhdr->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;
+       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, &param);
+       if (ODP_BUFFER_POOL_INVALID == pool) {
+               fprintf(stderr, "Packet pool creation failed.\n");
+               return -1;
+       }
+
+       odp_queue_param_t qparam;
+       char queuename[ODP_QUEUE_NAME_LEN];
+       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)
+{
+       size_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 < CLS_L2_QOS_MAX; i++) {
+               qparam.sched.prio = ODP_SCHED_PRIO_LOWEST - i;
+               sprintf(cosname, "%s_%d", "L2_Cos", i);
+               cos_tbl[i] = odp_cos_create(cosname);
+               cos_list[CLS_L2_QOS_0 + i] = cos_tbl[i];
+               /* TODO */
+               if (cos_tbl[i] == ODP_COS_INVALID)
+                       break;
+               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;
+       }
+       retval = odp_cos_with_l2_priority(pktio_loop, num_qos,
+                       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 *)(&ethhdr->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..5c44e81
--- /dev/null
+++ b/test/validation/classification/odp_classification_testsuites.h
@@ -0,0 +1,38 @@
+/* Copyright (c) 2014, 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..cf66e3f
--- /dev/null
+++ b/test/validation/odp_classification.c
@@ -0,0 +1,19 @@
+/* Copyright (c) 2014, 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
[email protected]
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to