Additional test suite is added to classification validation suite to test
individual PMRs. This suite will test the defined PMRs by configuring
pktio separately for every test case.

Signed-off-by: Balasubramanian Manoharan <bala.manoha...@linaro.org>
---
 helper/include/odp/helper/tcp.h                    |   4 +
 test/validation/classification/Makefile.am         |   2 +
 test/validation/classification/classification.c    |   5 +
 .../classification/odp_classification_common.c     | 200 +++++++
 .../classification/odp_classification_test_pmr.c   | 629 +++++++++++++++++++++
 .../classification/odp_classification_tests.c      | 116 +---
 .../classification/odp_classification_testsuites.h |   7 +
 7 files changed, 854 insertions(+), 109 deletions(-)
 create mode 100644 test/validation/classification/odp_classification_common.c
 create mode 100644 test/validation/classification/odp_classification_test_pmr.c

diff --git a/helper/include/odp/helper/tcp.h b/helper/include/odp/helper/tcp.h
index defe422..b52784d 100644
--- a/helper/include/odp/helper/tcp.h
+++ b/helper/include/odp/helper/tcp.h
@@ -26,6 +26,10 @@ extern "C" {
  *  @{
  */
 
+/** TCP header length (Minimum Header length without options)*/
+/** If options field is added to TCP header then the correct header value
+should be updated by the application */
+#define ODPH_TCPHDR_LEN 20
 
 /** TCP header */
 typedef struct ODP_PACKED {
diff --git a/test/validation/classification/Makefile.am 
b/test/validation/classification/Makefile.am
index ba468fa..050d5e6 100644
--- a/test/validation/classification/Makefile.am
+++ b/test/validation/classification/Makefile.am
@@ -3,6 +3,8 @@ include ../Makefile.inc
 noinst_LTLIBRARIES = libclassification.la
 libclassification_la_SOURCES = odp_classification_basic.c \
                               odp_classification_tests.c \
+                              odp_classification_test_pmr.c \
+                              odp_classification_common.c \
                               classification.c
 
 bin_PROGRAMS = classification_main$(EXEEXT)
diff --git a/test/validation/classification/classification.c 
b/test/validation/classification/classification.c
index 2582aaa..aec0655 100644
--- a/test/validation/classification/classification.c
+++ b/test/validation/classification/classification.c
@@ -18,6 +18,11 @@ static CU_SuiteInfo classification_suites[] = {
                        .pInitFunc = classification_suite_init,
                        .pCleanupFunc = classification_suite_term,
        },
+       { .pName = "classification pmr tests",
+                       .pTests = classification_test_pmr,
+                       .pInitFunc = classification_test_pmr_init,
+                       .pCleanupFunc = classification_test_pmr_term,
+       },
        CU_SUITE_INFO_NULL,
 };
 
diff --git a/test/validation/classification/odp_classification_common.c 
b/test/validation/classification/odp_classification_common.c
new file mode 100644
index 0000000..db994c6
--- /dev/null
+++ b/test/validation/classification/odp_classification_common.c
@@ -0,0 +1,200 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ */
+
+#include "odp_classification_testsuites.h"
+#include <odp_cunit_common.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+#include <odp/helper/udp.h>
+#include <odp/helper/tcp.h>
+
+#define SHM_PKT_NUM_BUFS        32
+#define SHM_PKT_BUF_SIZE        1024
+
+#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
+
+#define CLS_TEST_SPORT         4096
+#define CLS_TEST_DPORT         8192
+#define CLS_TEST_DADDR         "10.0.0.5/32"
+
+/* Test Packet values */
+#define DATA_MAGIC             0x01020304
+#define TEST_SEQ_INVALID       ((uint32_t)~0)
+
+/** 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 int cls_pkt_set_seq(odp_packet_t pkt, bool flag_udp)
+{
+       static uint32_t seq;
+       cls_test_packet_t data;
+       uint32_t offset;
+       int status;
+
+       data.magic = DATA_MAGIC;
+       data.seq = ++seq;
+
+       offset = odp_packet_l4_offset(pkt);
+       CU_ASSERT_FATAL(offset != 0);
+
+       if (flag_udp)
+               status = odp_packet_copydata_in(pkt, offset + ODPH_UDPHDR_LEN,
+                                               sizeof(data), &data);
+       else
+               status = odp_packet_copydata_in(pkt, offset + ODPH_TCPHDR_LEN,
+                                               sizeof(data), &data);
+
+       return status;
+}
+
+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;
+}
+
+odp_packet_t create_packet_tcp(odp_pool_t pool, bool vlan, bool flag_udp)
+{
+       uint32_t seqno;
+       odph_ethhdr_t *ethhdr;
+       odph_udphdr_t *udp;
+       odph_tcphdr_t *tcp;
+       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;
+       if (flag_udp)
+               packet_len += ODPH_UDPHDR_LEN;
+       else
+               packet_len += ODPH_TCPHDR_LEN;
+       packet_len += payload_len;
+
+       if (vlan)
+               packet_len += ODPH_VLANHDR_LEN;
+
+       pkt = odp_packet_alloc(pool, 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;
+
+               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 *)(void *)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;
+       if (flag_udp)
+               ip->tot_len = odp_cpu_to_be_16(ODPH_UDPHDR_LEN + payload_len +
+                                              ODPH_IPV4HDR_LEN);
+       else
+               ip->tot_len = odp_cpu_to_be_16(ODPH_TCPHDR_LEN + payload_len +
+                                              ODPH_IPV4HDR_LEN);
+
+       ip->ttl = 128;
+       if (flag_udp)
+               ip->proto = ODPH_IPPROTO_UDP;
+       else
+               ip->proto = ODPH_IPPROTO_TCP;
+
+       seqno = odp_atomic_fetch_inc_u32(&seq);
+       ip->id = odp_cpu_to_be_16(seqno);
+       ip->chksum = 0;
+       ip->chksum = odp_cpu_to_be_16(odph_ipv4_csum_update(pkt));
+       offset += ODPH_IPV4HDR_LEN;
+
+       /* udp */
+       if (flag_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;
+       } else {
+               odp_packet_l4_offset_set(pkt, offset);
+               tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+               tcp->src_port = odp_cpu_to_be_16(CLS_DEFAULT_SPORT);
+               tcp->dst_port = odp_cpu_to_be_16(CLS_DEFAULT_DPORT);
+               tcp->hl = ODPH_TCPHDR_LEN / 4;
+               /* TODO: checksum field has to be updated */
+               tcp->cksm = 0;
+       }
+
+       /* set pkt sequence number */
+       cls_pkt_set_seq(pkt, flag_udp);
+
+       return pkt;
+}
diff --git a/test/validation/classification/odp_classification_test_pmr.c 
b/test/validation/classification/odp_classification_test_pmr.c
new file mode 100644
index 0000000..c18beaf
--- /dev/null
+++ b/test/validation/classification/odp_classification_test_pmr.c
@@ -0,0 +1,629 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:    BSD-3-Clause
+ */
+
+#include "odp_classification_testsuites.h"
+#include <odp_cunit_common.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+#include <odp/helper/udp.h>
+#include <odp/helper/tcp.h>
+
+#define SHM_PKT_NUM_BUFS        32
+#define SHM_PKT_BUF_SIZE        1024
+
+#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
+
+#define CLS_TEST_SPORT         4096
+#define CLS_TEST_DPORT         8192
+#define CLS_TEST_DADDR         "10.0.0.5/32"
+
+/* Test Packet values */
+#define DATA_MAGIC             0x01020304
+#define TEST_SEQ_INVALID       ((uint32_t)~0)
+
+static odp_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_pktio_interface(odp_packet_t pkt, odp_pktio_t pktio)
+{
+       odp_event_t ev;
+       odp_queue_t defqueue = odp_pktio_outq_getdef(pktio);
+
+       ev = odp_packet_to_event(pkt);
+       CU_ASSERT(odp_queue_enq(defqueue, ev) == 0);
+}
+
+static inline
+void enqueue_loop_interface(odp_packet_t pkt)
+{
+       odp_event_t ev;
+       odp_queue_t defqueue = odp_pktio_outq_getdef(pktio_loop);
+
+       ev = odp_packet_to_event(pkt);
+       CU_ASSERT(odp_queue_enq(defqueue, ev) == 0);
+}
+
+static inline
+odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns)
+{
+       odp_event_t ev;
+
+       ev = odp_schedule(queue, ns);
+       return odp_packet_from_event(ev);
+}
+
+static inline
+odp_queue_t queue_create(char *queuename, bool sched)
+{
+       odp_queue_t queue;
+
+       if (sched) {
+               odp_queue_param_t qparam;
+
+               qparam.sched.prio = ODP_SCHED_PRIO_HIGHEST;
+               qparam.sched.sync = ODP_SCHED_SYNC_NONE;
+               qparam.sched.group = ODP_SCHED_GROUP_ALL;
+
+               queue = odp_queue_create(queuename,
+                                        ODP_QUEUE_TYPE_SCHED,
+                                        &qparam);
+       } else {
+               queue = odp_queue_create(queuename,
+                                        ODP_QUEUE_TYPE_POLL,
+                                        NULL);
+       }
+
+       return queue;
+}
+
+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;
+}
+
+static int destroy_inq(odp_pktio_t pktio)
+{
+       odp_queue_t inq;
+       odp_event_t ev;
+
+       inq = odp_pktio_inq_getdef(pktio);
+
+       if (inq == ODP_QUEUE_INVALID) {
+               CU_FAIL("attempting to destroy invalid inq");
+               return -1;
+       }
+
+       if (0 > odp_pktio_inq_remdef(pktio))
+               return -1;
+
+       while (1) {
+               ev = odp_schedule(NULL, ODP_SCHED_NO_WAIT);
+
+               if (ev != ODP_EVENT_INVALID)
+                       odp_buffer_free(odp_buffer_from_event(ev));
+               else
+                       break;
+       }
+
+       return odp_queue_destroy(inq);
+}
+
+int classification_test_pmr_init(void)
+{
+       odp_pool_t pool;
+       odp_pool_param_t param;
+
+       memset(&param, 0, sizeof(param));
+       param.pkt.seg_len = SHM_PKT_BUF_SIZE;
+       param.pkt.len     = SHM_PKT_BUF_SIZE;
+       param.pkt.num     = SHM_PKT_NUM_BUFS;
+       param.type        = ODP_POOL_PACKET;
+
+       pool = odp_pool_create("classification_pool", &param);
+       if (ODP_POOL_INVALID == pool) {
+               fprintf(stderr, "Packet pool creation failed.\n");
+               return -1;
+       }
+
+       pool_default = odp_pool_lookup("classification_pool");
+       if (pool_default == ODP_POOL_INVALID)
+               return -1;
+
+       odp_atomic_init_u32(&seq, 0);
+       return 0;
+}
+
+odp_pktio_t create_pktio(odp_queue_type_t q_type)
+{
+       odp_pktio_t pktio;
+       odp_pktio_param_t pktio_param;
+       odp_pool_t pool;
+       int ret;
+
+       pool = odp_pool_lookup("classification_pool");
+       if (pool == ODP_POOL_INVALID)
+               return ODP_PKTIO_INVALID;
+
+       if (q_type == ODP_QUEUE_TYPE_POLL)
+               pktio_param.in_mode = ODP_PKTIN_MODE_POLL;
+       else
+               pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
+
+       pktio = odp_pktio_open("loop", pool, &pktio_param);
+       if (pktio == ODP_PKTIO_INVALID) {
+               ret = odp_pool_destroy(pool);
+               if (ret)
+                       fprintf(stderr, "unable to destroy pool.\n");
+               return ODP_PKTIO_INVALID;
+       }
+
+       return pktio;
+}
+
+odp_queue_t create_default_inq(odp_pktio_t pktio, odp_queue_type_t qtype)
+{
+       odp_queue_param_t qparam;
+       odp_queue_t inq_def;
+       char inq_name[ODP_QUEUE_NAME_LEN];
+
+       qparam.sched.prio  = ODP_SCHED_PRIO_DEFAULT;
+       qparam.sched.sync  = ODP_SCHED_SYNC_ATOMIC;
+       qparam.sched.group = ODP_SCHED_GROUP_ALL;
+
+       snprintf(inq_name, sizeof(inq_name), "inq-pktio-%" PRIu64,
+                odp_pktio_to_u64(pktio));
+       inq_def = odp_queue_lookup(inq_name);
+       if (inq_def == ODP_QUEUE_INVALID)
+               inq_def = odp_queue_create(
+                               inq_name,
+                               ODP_QUEUE_TYPE_PKTIN,
+                               qtype == ODP_QUEUE_TYPE_POLL ? NULL : &qparam);
+
+       CU_ASSERT(inq_def != ODP_QUEUE_INVALID);
+
+       if (0 > odp_pktio_inq_setdef(pktio, inq_def))
+               return ODP_QUEUE_INVALID;
+
+       return inq_def;
+}
+
+int classification_test_pmr_term(void)
+{
+       int retcode = 0;
+
+       if (0 != odp_pool_destroy(pool_default)) {
+               fprintf(stderr, "pool_default destroy failed.\n");
+               retcode = -1;
+       }
+
+       return retcode;
+}
+
+static void classification_pmr_term_tcp_dport(void)
+{
+       odp_packet_t pkt;
+       odph_tcphdr_t *tcp;
+       uint32_t seq;
+       uint16_t val;
+       uint16_t mask;
+       int retval;
+       odp_pktio_t pktio;
+       odp_queue_t queue;
+       odp_queue_t retqueue;
+       odp_queue_t defqueue;
+       odp_pmr_t pmr;
+       odp_cos_t cos;
+       char cosname[ODP_QUEUE_NAME_LEN];
+       char queuename[ODP_QUEUE_NAME_LEN];
+
+       val = CLS_TEST_DPORT;
+       mask = 0xffff;
+
+       pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+       defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+       pmr = odp_pmr_create(ODP_PMR_TCP_DPORT, &val,
+                            &mask, sizeof(val));
+       CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+       sprintf(cosname, "tcp_dport");
+       cos = odp_cos_create(cosname);
+       CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+       sprintf(queuename, "%s", "tcp_dport");
+
+       queue = queue_create(queuename, true);
+       CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+       retval = odp_cos_set_queue(cos, queue);
+       CU_ASSERT(retval == 0);
+
+       retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+       CU_ASSERT(retval == 0);
+
+       pkt = create_packet_tcp(pool_default, false, false);
+       seq = cls_pkt_get_seq(pkt);
+
+       tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+       tcp->dst_port = odp_cpu_to_be_16(CLS_TEST_DPORT);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == queue);
+       odp_packet_free(pkt);
+
+       /* Other packets are delivered to default queue */
+       pkt = create_packet_tcp(pool_default, false, false);
+       seq = cls_pkt_get_seq(pkt);
+
+       tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+       tcp->dst_port = odp_cpu_to_be_16(CLS_TEST_DPORT + 1);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == defqueue);
+
+       odp_packet_free(pkt);
+       destroy_inq(pktio);
+       odp_queue_destroy(queue);
+       odp_pktio_close(pktio);
+}
+
+static void classification_pmr_term_tcp_sport(void)
+{
+       odp_packet_t pkt;
+       odph_tcphdr_t *tcp;
+       uint32_t seq;
+       uint16_t val;
+       uint16_t mask;
+       int retval;
+       odp_pktio_t pktio;
+       odp_queue_t queue;
+       odp_queue_t retqueue;
+       odp_queue_t defqueue;
+       odp_pmr_t pmr;
+       odp_cos_t cos;
+       char cosname[ODP_QUEUE_NAME_LEN];
+       char queuename[ODP_QUEUE_NAME_LEN];
+
+       val = CLS_TEST_SPORT;
+       mask = 0xffff;
+
+       pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+       defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+       pmr = odp_pmr_create(ODP_PMR_TCP_SPORT, &val,
+                            &mask, sizeof(val));
+       CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+       sprintf(cosname, "tcp_sport");
+       cos = odp_cos_create(cosname);
+       CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+       sprintf(queuename, "%s", "tcp_sport");
+
+       queue = queue_create(queuename, true);
+       CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+       retval = odp_cos_set_queue(cos, queue);
+       CU_ASSERT(retval == 0);
+
+       retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+       CU_ASSERT(retval == 0);
+
+       pkt = create_packet_tcp(pool_default, false, false);
+       seq = cls_pkt_get_seq(pkt);
+
+       tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+       tcp->src_port = odp_cpu_to_be_16(CLS_TEST_SPORT);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == queue);
+       odp_packet_free(pkt);
+
+       pkt = create_packet_tcp(pool_default, false, false);
+       seq = cls_pkt_get_seq(pkt);
+
+       tcp = (odph_tcphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+       tcp->src_port = odp_cpu_to_be_16(CLS_TEST_SPORT + 1);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == defqueue);
+
+       odp_packet_free(pkt);
+       destroy_inq(pktio);
+       odp_queue_destroy(queue);
+       odp_pktio_close(pktio);
+}
+
+static void classification_pmr_term_udp_dport(void)
+{
+       odp_packet_t pkt;
+       odph_udphdr_t *udp;
+       uint32_t seq;
+       uint16_t val;
+       uint16_t mask;
+       int retval;
+       odp_pktio_t pktio;
+       odp_queue_t queue;
+       odp_queue_t retqueue;
+       odp_queue_t defqueue;
+       odp_pmr_t pmr;
+       odp_cos_t cos;
+       char cosname[ODP_QUEUE_NAME_LEN];
+       char queuename[ODP_QUEUE_NAME_LEN];
+
+       val = CLS_TEST_DPORT;
+       mask = 0xffff;
+
+       pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+       defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+       pmr = odp_pmr_create(ODP_PMR_UDP_DPORT, &val,
+                            &mask, sizeof(val));
+       CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+       sprintf(cosname, "tcp_sport");
+       cos = odp_cos_create(cosname);
+       CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+       sprintf(queuename, "%s", "tcp_sport");
+
+       queue = queue_create(queuename, true);
+       CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+       retval = odp_cos_set_queue(cos, queue);
+       CU_ASSERT(retval == 0);
+
+       retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+       CU_ASSERT(retval == 0);
+
+       pkt = create_packet_tcp(pool_default, false, true);
+       seq = cls_pkt_get_seq(pkt);
+
+       udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+       udp->dst_port = odp_cpu_to_be_16(CLS_TEST_DPORT);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == queue);
+       odp_packet_free(pkt);
+
+       /* Other packets received in default queue */
+       pkt = create_packet_tcp(pool_default, false, true);
+       seq = cls_pkt_get_seq(pkt);
+
+       udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
+       udp->dst_port = odp_cpu_to_be_16(CLS_TEST_DPORT + 1);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == defqueue);
+
+       odp_packet_free(pkt);
+       destroy_inq(pktio);
+       odp_queue_destroy(queue);
+       odp_pktio_close(pktio);
+}
+
+static void classification_pmr_term_udp_sport(void)
+{
+       odp_packet_t pkt;
+       odph_udphdr_t *udp;
+       uint32_t seq;
+       uint16_t val;
+       uint16_t mask;
+       int retval;
+       odp_pktio_t pktio;
+       odp_queue_t queue;
+       odp_queue_t retqueue;
+       odp_queue_t defqueue;
+       odp_pmr_t pmr;
+       odp_cos_t cos;
+       char cosname[ODP_QUEUE_NAME_LEN];
+       char queuename[ODP_QUEUE_NAME_LEN];
+
+       val = CLS_TEST_SPORT;
+       mask = 0xffff;
+
+       pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+       defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+       pmr = odp_pmr_create(ODP_PMR_UDP_SPORT, &val,
+                            &mask, sizeof(val));
+       CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+       sprintf(cosname, "udp_sport");
+       cos = odp_cos_create(cosname);
+       CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+       sprintf(queuename, "%s", "udp_sport");
+
+       queue = queue_create(queuename, true);
+       CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+       retval = odp_cos_set_queue(cos, queue);
+       CU_ASSERT(retval == 0);
+
+       retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+       CU_ASSERT(retval == 0);
+
+       pkt = create_packet_tcp(pool_default, false, true);
+       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_TEST_SPORT);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == queue);
+       odp_packet_free(pkt);
+
+       pkt = create_packet_tcp(pool_default, false, true);
+       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_TEST_SPORT + 1);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == defqueue);
+       odp_packet_free(pkt);
+
+       destroy_inq(pktio);
+       odp_queue_destroy(queue);
+       odp_pktio_close(pktio);
+}
+
+static void classification_pmr_term_ipproto(void)
+{
+       odp_packet_t pkt;
+       uint32_t seq;
+       uint8_t val;
+       uint8_t mask;
+       int retval;
+       odp_pktio_t pktio;
+       odp_queue_t queue;
+       odp_queue_t retqueue;
+       odp_queue_t defqueue;
+       odp_pmr_t pmr;
+       odp_cos_t cos;
+       char cosname[ODP_QUEUE_NAME_LEN];
+       char queuename[ODP_QUEUE_NAME_LEN];
+
+       val = ODPH_IPPROTO_UDP;
+       mask = 0xff;
+
+       pktio = create_pktio(ODP_QUEUE_TYPE_SCHED);
+       defqueue = create_default_inq(pktio, ODP_QUEUE_TYPE_SCHED);
+
+       pmr = odp_pmr_create(ODP_PMR_IPPROTO, &val,
+                            &mask, sizeof(val));
+       CU_ASSERT(pmr != ODP_PMR_INVAL);
+
+       sprintf(cosname, "ipproto");
+       cos = odp_cos_create(cosname);
+       CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+       sprintf(queuename, "%s", "ipproto");
+
+       queue = queue_create(queuename, true);
+       CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID);
+
+       retval = odp_cos_set_queue(cos, queue);
+       CU_ASSERT(retval == 0);
+
+       retval = odp_pktio_pmr_cos(pmr, pktio, cos);
+       CU_ASSERT(retval == 0);
+
+       pkt = create_packet_tcp(pool_default, false, true);
+       seq = cls_pkt_get_seq(pkt);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == queue);
+       odp_packet_free(pkt);
+
+       /* Other packets delivered to default queue */
+       pkt = create_packet_tcp(pool_default, false, false);
+       seq = cls_pkt_get_seq(pkt);
+
+       enqueue_pktio_interface(pkt, pktio);
+
+       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+       CU_ASSERT(retqueue == defqueue);
+
+       odp_packet_free(pkt);
+       destroy_inq(pktio);
+       odp_queue_destroy(queue);
+       odp_pktio_close(pktio);
+}
+
+CU_TestInfo classification_test_pmr[] = {
+       _CU_TEST_INFO(classification_pmr_term_tcp_dport),
+       _CU_TEST_INFO(classification_pmr_term_tcp_sport),
+       _CU_TEST_INFO(classification_pmr_term_udp_dport),
+       _CU_TEST_INFO(classification_pmr_term_udp_sport),
+       _CU_TEST_INFO(classification_pmr_term_ipproto),
+       CU_TEST_INFO_NULL,
+};
diff --git a/test/validation/classification/odp_classification_tests.c 
b/test/validation/classification/odp_classification_tests.c
index ecf9db0..9de6637 100644
--- a/test/validation/classification/odp_classification_tests.c
+++ b/test/validation/classification/odp_classification_tests.c
@@ -122,25 +122,6 @@ odp_packet_t receive_packet(odp_queue_t *queue, uint64_t 
ns)
        return odp_packet_from_event(ev);
 }
 
-static int cls_pkt_set_seq(odp_packet_t pkt)
-{
-       static uint32_t seq;
-       cls_test_packet_t data;
-       uint32_t offset;
-       int status;
-
-       data.magic = DATA_MAGIC;
-       data.seq = ++seq;
-
-       offset = odp_packet_l4_offset(pkt);
-       CU_ASSERT_FATAL(offset != 0);
-
-       status = odp_packet_copydata_in(pkt, offset + ODPH_UDPHDR_LEN,
-                                       sizeof(data), &data);
-
-       return status;
-}
-
 static uint32_t cls_pkt_get_seq(odp_packet_t pkt)
 {
        uint32_t offset;
@@ -184,89 +165,6 @@ static int destroy_inq(odp_pktio_t pktio)
 
        return odp_queue_destroy(inq);
 }
-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 *)(void *)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;
-       ip->chksum = odp_cpu_to_be_16(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_suite_init(void)
 {
@@ -442,7 +340,7 @@ void test_cls_pmr_chain(void)
        uint32_t mask;
        uint32_t seq;
 
-       pkt = create_packet(false);
+       pkt = create_packet_tcp(pool_default, false, true);
        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);
@@ -460,7 +358,7 @@ void test_cls_pmr_chain(void)
        CU_ASSERT(seq == cls_pkt_get_seq(pkt));
        odp_packet_free(pkt);
 
-       pkt = create_packet(false);
+       pkt = create_packet_tcp(pool_default, false, true);
        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);
@@ -508,7 +406,7 @@ void test_pktio_default_cos(void)
        odp_queue_t queue;
        uint32_t seq;
        /* create a default packet */
-       pkt = create_packet(false);
+       pkt = create_packet_tcp(pool_default, false, true);
        seq = cls_pkt_get_seq(pkt);
        enqueue_loop_interface(pkt);
 
@@ -554,7 +452,7 @@ void test_pktio_error_cos(void)
        odp_packet_t pkt;
 
        /*Create an error packet */
-       pkt = create_packet(false);
+       pkt = create_packet_tcp(pool_default, false, true);
        odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 
        /* Incorrect IpV4 version */
@@ -648,7 +546,7 @@ void test_cos_with_l2_priority(void)
 
        uint8_t i;
        for (i = 0; i < CLS_L2_QOS_MAX; i++) {
-               pkt = create_packet(true);
+               pkt = create_packet_tcp(pool_default, true, true);
                seq = cls_pkt_get_seq(pkt);
                ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
                vlan = (odph_vlanhdr_t *)(&ethhdr->type);
@@ -706,7 +604,7 @@ void test_pmr_cos(void)
        odp_queue_t queue;
        uint32_t seq;
 
-       pkt = create_packet(false);
+       pkt = create_packet_tcp(pool_default, false, true);
        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);
@@ -780,7 +678,7 @@ void test_pktio_pmr_match_set_cos(void)
        odp_queue_t queue;
        uint32_t seq;
 
-       pkt = create_packet(false);
+       pkt = create_packet_tcp(pool_default, false, true);
        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);
diff --git a/test/validation/classification/odp_classification_testsuites.h 
b/test/validation/classification/odp_classification_testsuites.h
index f603f30..be30ff0 100644
--- a/test/validation/classification/odp_classification_testsuites.h
+++ b/test/validation/classification/odp_classification_testsuites.h
@@ -16,11 +16,18 @@
 
 extern CU_TestInfo classification_suite[];
 extern CU_TestInfo classification_suite_basic[];
+extern CU_TestInfo classification_test_pmr[];
 
 int classification_suite_init(void);
 int classification_suite_term(void);
 
+int classification_test_pmr_term(void);
+int classification_test_pmr_init(void);
+
+odp_packet_t create_packet_tcp(odp_pool_t pool, bool vlan, bool udp);
 odp_packet_t create_packet(bool vlan);
+odp_pktio_t create_pktio(odp_queue_type_t q_type);
+odp_queue_t create_default_inq(odp_pktio_t pktio, odp_queue_type_t qtype);
 void configure_pktio_default_cos(void);
 void test_pktio_default_cos(void);
 void configure_pktio_error_cos(void);
-- 
1.9.1

_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to