diff mbox

[API-NEXT] validation: classification: added additional suite to test individual PMRs

Message ID 1438269634-5735-1-git-send-email-bala.manoharan@linaro.org
State New
Headers show

Commit Message

Balasubramanian Manoharan July 30, 2015, 3:20 p.m. UTC
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.manoharan@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

Comments

Christophe Milard July 31, 2015, 3:47 p.m. UTC | #1
I am sorry, as this is not well documented yet (I am currentely working on
the documentation), but this patch does not respect the naming convention
for test function, test-suite...

Possibly you started your work on this before my modification went in...

Anyway here follows the naming convention for testing:
(I regard this naming as important as all tests are now "libifized" -part
of a library-, and naming chaos would make this lib unusable)

Once, again sorry you hit this transition period...

Here follows the naming convention:

* Tests, i.e. functions which are used in CUNIT test suites are named:
   <Module>_test_*
* Test arrays, i.e. arrays of CU_TestInfo, listing the test functions
 belonging to a suite, are called:
   <Module>_suite[_*]
 where the possible suffix can be used if many suites are declared.
* CUNIT suite init and termination functions are called:
   <Module>_suite[_*]_init() and <Module>_suite[_*]_term()
 respectively.
* Suite arrays, i.e. arrays of CU_SuiteInfo used in executables are called:
   <Module>_suites[_*]
 where the possible suffix identifies the executable using it, if many.
* Main executable function(s), are called:
   <Module>_main[_*]
 where the possible suffix identifies the executable using it
* Init/term function for the whole executable are called:
   <Module>_init
   <Module>_term

All test tests have now been transformed to match this new naming, so you
should see this in classification tests as well on recent checkouts.

Thanks,

Christophe.

On 30 July 2015 at 17:20, Balasubramanian Manoharan <
bala.manoharan@linaro.org> wrote:

> 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.manoharan@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
>
Balasubramanian Manoharan July 31, 2015, 3:52 p.m. UTC | #2
Hi Christophe,

Thanks for pointing this out :) I had started this work before the naming
conventions were mandated.
I will follow the naming conventions followed here before my final patch is
out.

I will update these changes along with review comments I get ;)

Regards,
Bala

On 31 July 2015 at 21:17, Christophe Milard <christophe.milard@linaro.org>
wrote:

> I am sorry, as this is not well documented yet (I am currentely working on
> the documentation), but this patch does not respect the naming convention
> for test function, test-suite...
>
> Possibly you started your work on this before my modification went in...
>
> Anyway here follows the naming convention for testing:
> (I regard this naming as important as all tests are now "libifized" -part
> of a library-, and naming chaos would make this lib unusable)
>
> Once, again sorry you hit this transition period...
>
> Here follows the naming convention:
>
> * Tests, i.e. functions which are used in CUNIT test suites are named:
>    <Module>_test_*
> * Test arrays, i.e. arrays of CU_TestInfo, listing the test functions
>  belonging to a suite, are called:
>    <Module>_suite[_*]
>  where the possible suffix can be used if many suites are declared.
> * CUNIT suite init and termination functions are called:
>    <Module>_suite[_*]_init() and <Module>_suite[_*]_term()
>  respectively.
> * Suite arrays, i.e. arrays of CU_SuiteInfo used in executables are called:
>    <Module>_suites[_*]
>  where the possible suffix identifies the executable using it, if many.
> * Main executable function(s), are called:
>    <Module>_main[_*]
>  where the possible suffix identifies the executable using it
> * Init/term function for the whole executable are called:
>    <Module>_init
>    <Module>_term
>
> All test tests have now been transformed to match this new naming, so you
> should see this in classification tests as well on recent checkouts.
>
> Thanks,
>
> Christophe.
>
> On 30 July 2015 at 17:20, Balasubramanian Manoharan <
> bala.manoharan@linaro.org> wrote:
>
>> 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.manoharan@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
>>
>
>
Ivan Khoronzhuk Aug. 3, 2015, 12:22 p.m. UTC | #3
Hi, Bala

On 30.07.15 18:20, Balasubramanian Manoharan wrote:
> 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.manoharan@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);

pmr, cos destroy?

> +}
> +
> +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);

pmr, cos destroy?

> +}
> +
> +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);

Why cos and pmr are not destroyed here?

> +}
> +
> +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);

pmr, cos destroy?

> +}
> +
> +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);

pmr, cos destroy?

> +}
> +
> +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);
>

As I understand it's not complete list of PMRs to test within this
suite.

I thought it shoud use odp_pmr_terms_cap() before testing PMRs.
In my case sport for TCP and UDP is not supported.

Also, this question not for the tests. IPPROTO check, it's OK. But in
general, ODP_PMR_UDP/TCP_SPORT or ODP_PMR_UDP/TCP_DPORT is a combination
of two PMRs like: IPPROTO - PORT, (at least for my board), when
application creates connection ODP_PMR_UDP_SPORT, in real it creates
connection like ODP_PMR_IPPROTO (UDP) - ODP_PMR_UDP_SPORT (because
UDP/TCP check is done on l3). Just thought, becouse I have some hassle
with it...maybe there is some shortening in the API... because in this
case PMRset primitive should be used.

PS:
You patches are based on api-next, and I cannot check it w/o
modifications connected with odp_pktio_params_t.
I merged v1.2 tag and based on it.
Balasubramanian Manoharan Aug. 3, 2015, 1:26 p.m. UTC | #4
Hi,

On 3 August 2015 at 17:52, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

>
> Hi, Bala
>
> On 30.07.15 18:20, Balasubramanian Manoharan wrote:
>
>> 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.manoharan@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);
>>
>
> pmr, cos destroy?


Oops.. My mistake. pmr, cos should be destroyed after each test.
Will fix this for all the locations you have pointed below also.

>
>
>  +}
>> +
>> +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);
>>
>
> pmr, cos destroy?
>
>
>  +}
>> +
>> +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);
>>
>
> Why cos and pmr are not destroyed here?
>
>
>  +}
>> +
>> +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);
>>
>
> pmr, cos destroy?
>
>
>  +}
>> +
>> +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);
>>
>
> pmr, cos destroy?
>
>
>  +}
>> +
>> +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);
>>
>>
> As I understand it's not complete list of PMRs to test within this
> suite.
>
> I thought it shoud use odp_pmr_terms_cap() before testing PMRs.
> In my case sport for TCP and UDP is not supported.
>

I actually thought about that doing something like that before running the
suite. But then I though maybe it would be useful if a particular PMR term
fails when not supported by a platform so that the application can know
which terms are supported by this platform once this suite is run.

I am open for change if we want to run only the terms which is supported
per platform. We can add some configuration file which is tunable per
platform where you basically say yes to each Test Case you want to run in
regression.


>
> Also, this question not for the tests. IPPROTO check, it's OK. But in
> general, ODP_PMR_UDP/TCP_SPORT or ODP_PMR_UDP/TCP_DPORT is a combination
> of two PMRs like: IPPROTO - PORT, (at least for my board), when
> application creates connection ODP_PMR_UDP_SPORT, in real it creates
> connection like ODP_PMR_IPPROTO (UDP) - ODP_PMR_UDP_SPORT (because
> UDP/TCP check is done on l3). Just thought, becouse I have some hassle
> with it...maybe there is some shortening in the API... because in this
> case PMRset primitive should be used.
>

I understand your point but the reason for having terms UDP and UDP_SPORT
is for ease of use by application.
Lets says if you want to check only for UDP protocol or when you want to
classify a specific flow in a UDP protocol so that
the configuration is easier.


> PS:
> You patches are based on api-next, and I cannot check it w/o
> modifications connected with odp_pktio_params_t.
> I merged v1.2 tag and based on it.
>
>
> --

Regards,
> Ivan Khoronzhuk
>
Regards,
Bala
Ivan Khoronzhuk Aug. 3, 2015, 3:53 p.m. UTC | #5
As a proposition, we had talk some time ago about,
You moved packet creation to common classification file.
Maybe it's time to assign correct src/dst MAC address, taken from pktio?
In separate patch.
Balasubramanian Manoharan Aug. 3, 2015, 4:06 p.m. UTC | #6
On 3 August 2015 at 21:23, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> As a proposition, we had talk some time ago about,
> You moved packet creation to common classification file.
> Maybe it's time to assign correct src/dst MAC address, taken from pktio?
> In separate patch.


Yes. I agree we need to correct them.
A separate patch is better as it does not require much discussion.

Regards,
Bala

>
>
> --
> Regards,
> Ivan Khoronzhuk
>
Ivan Khoronzhuk Aug. 3, 2015, 4:14 p.m. UTC | #7
One more issue

On 30.07.15 18:20, Balasubramanian Manoharan wrote:
> 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.manoharan@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

................

> +
> +	/* 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 @@

...................

> +
> +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)

I think it should be moved to common file also.

> +{
> +	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);

what in case of TCP? Incorrect seq num?

> +
> +		if (data.magic == DATA_MAGIC)
> +			return data.seq;
> +	}
> +
> +	return TEST_SEQ_INVALID;
> +}
> +

.......
Balasubramanian Manoharan Aug. 3, 2015, 4:24 p.m. UTC | #8
On 3 August 2015 at 21:44, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> One more issue
>
> On 30.07.15 18:20, Balasubramanian Manoharan wrote:
>
>> 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.manoharan@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
>>
>
> ................
>
>  +
>> +       /* 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 @@
>>
>
> ...................
>
>
>  +
>> +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)
>>
>
> I think it should be moved to common file also.
>
>  +{
>> +       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);
>>
>
> what in case of TCP? Incorrect seq num?

Looks like a coding error. TCP should be added using a boolean flag.

Incorrect seq num is tested in the ASSERT function after receiving the
packet.
Seq num is used to check whether the received packet is the same which was
sent.

>
>
>  +
>> +               if (data.magic == DATA_MAGIC)
>> +                       return data.seq;
>> +       }
>> +
>> +       return TEST_SEQ_INVALID;
>> +}
>> +
>>
>
> .......
>
> --
> Regards,
> Ivan Khoronzhuk
>
Regards,
Bala
Mike Holmes Aug. 3, 2015, 4:27 p.m. UTC | #9
I don’t think this has to be API-NEXT, it does touch a helper but that is
not the API from odp/include

On 3 August 2015 at 12:24, Bala Manoharan <bala.manoharan@linaro.org> wrote:

>
>
> On 3 August 2015 at 21:44, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
> wrote:
>
>> One more issue
>>
>> On 30.07.15 18:20, Balasubramanian Manoharan wrote:
>>
>>> 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.manoharan@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
>>>
>>
>> ................
>>
>> +
>>> +       /* 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 @@
>>>
>>
>> ...................
>>
>>
>> +
>>> +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)
>>>
>>
>> I think it should be moved to common file also.
>>
>> +{
>>> +       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);
>>>
>>
>> what in case of TCP? Incorrect seq num?
>
> Looks like a coding error. TCP should be added using a boolean flag.
>
> Incorrect seq num is tested in the ASSERT function after receiving the
> packet.
> Seq num is used to check whether the received packet is the same which was
> sent.
>
>>
>>
>> +
>>> +               if (data.magic == DATA_MAGIC)
>>> +                       return data.seq;
>>> +       }
>>> +
>>> +       return TEST_SEQ_INVALID;
>>> +}
>>> +
>>>
>>
>> .......
>>
>> --
>> Regards,
>> Ivan Khoronzhuk
>>
> Regards,
> Bala
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
>
Ivan Khoronzhuk Aug. 3, 2015, 4:31 p.m. UTC | #10
On 03.08.15 19:24, Bala Manoharan wrote:
>
>
> On 3 August 2015 at 21:44, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>
>     One more issue
>
>     On 30.07.15 18:20, Balasubramanian Manoharan wrote:
>
>         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.manoharan@linaro.org <mailto:bala.manoharan@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
>         <http://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
>
>
>     ................
>
>         +
>         +       /* 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 @@
>
>
>     ...................
>
>
>         +
>         +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)
>
>
>     I think it should be moved to common file also.
>
>         +{
>         +       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);
>
>
>     what in case of TCP? Incorrect seq num?
>
> Looks like a coding error. TCP should be added using a boolean flag.
>
> Incorrect seq num is tested in the ASSERT function after receiving the
> packet.
> Seq num is used to check whether the received packet is the same which
> was sent.
>

That's not enough. You use the same "fail" function before and after.
It's not correct when you read it before sending and after sending.

It can be assigned 1 while packet creation.
Read before sending: ffff
Read after sending: ffff

No errors - it's the same.
But assigned 1, in fact that's error. And will not be caught.

PS:
  I propose also rename create_packet_tcp() to create_packet().
  It can create TCP and UDP packets.

>
>
>         +
>         +               if (data.magic == DATA_MAGIC)
>         +                       return data.seq;
>         +       }
>         +
>         +       return TEST_SEQ_INVALID;
>         +}
>         +
>
>
>     .......
>
>     --
>     Regards,
>     Ivan Khoronzhuk
>
> Regards,
> Bala
Balasubramanian Manoharan Aug. 3, 2015, 4:40 p.m. UTC | #11
On 3 August 2015 at 22:01, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

>
>
> On 03.08.15 19:24, Bala Manoharan wrote:
>
>>
>>
>> On 3 August 2015 at 21:44, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
>> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>>
>>     One more issue
>>
>>     On 30.07.15 18:20, Balasubramanian Manoharan wrote:
>>
>>         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.manoharan@linaro.org <mailto:bala.manoharan@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
>>         <http://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
>>
>>
>>     ................
>>
>>         +
>>         +       /* 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 @@
>>
>>
>>     ...................
>>
>>
>>         +
>>         +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)
>>
>>
>>     I think it should be moved to common file also.
>>
>>         +{
>>         +       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);
>>
>>
>>     what in case of TCP? Incorrect seq num?
>>
>> Looks like a coding error. TCP should be added using a boolean flag.
>>
>> Incorrect seq num is tested in the ASSERT function after receiving the
>> packet.
>> Seq num is used to check whether the received packet is the same which
>> was sent.
>>
>>
> That's not enough. You use the same "fail" function before and after.
> It's not correct when you read it before sending and after sending.
>
> It can be assigned 1 while packet creation.
> Read before sending: ffff
> Read after sending: ffff
>
> No errors - it's the same.
> But assigned 1, in fact that's error. And will not be caught.
>

I understand your point. seq number should be tested for !=  TEST_SEQ_INVALID
using a separate assert after receiving the packet.

>
> PS:
>  I propose also rename create_packet_tcp() to create_packet().
>  It can create TCP and UDP packets.


I wanted to make this change before sending the patch. Looks like I had
missed and sent the patch before.

Regards,
Bala

>
>
>
>>
>>         +
>>         +               if (data.magic == DATA_MAGIC)
>>         +                       return data.seq;
>>         +       }
>>         +
>>         +       return TEST_SEQ_INVALID;
>>         +}
>>         +
>>
>>
>>     .......
>>
>>     --
>>     Regards,
>>     Ivan Khoronzhuk
>>
>> Regards,
>> Bala
>>
>
> --
> Regards,
> Ivan Khoronzhuk
>
Ivan Khoronzhuk Aug. 3, 2015, 4:46 p.m. UTC | #12
Bala,

.......

>
>
>              what in case of TCP? Incorrect seq num?
>
>         Looks like a coding error. TCP should be added using a boolean flag.
>
>         Incorrect seq num is tested in the ASSERT function after
>         receiving the
>         packet.
>         Seq num is used to check whether the received packet is the same
>         which
>         was sent.
>
>
>     That's not enough. You use the same "fail" function before and after.
>     It's not correct when you read it before sending and after sending.
>
>     It can be assigned 1 while packet creation.
>     Read before sending: ffff
>     Read after sending: ffff
>
>     No errors - it's the same.
>     But assigned 1, in fact that's error. And will not be caught.
>
>
> I understand your point. seq number should be tested for !=
> TEST_SEQ_INVALID using a separate assert after receiving the packet.

Smth similar. But I'm not sure if it's needed at all.

I've better added check like seq_num < 20 to cover all seqnumbers that's 
not possible. (Maybe 20 or other num, but it shouldn't be
very big)

>
>
>     PS:
>       I propose also rename create_packet_tcp() to create_packet().
>       It can create TCP and UDP packets.
>
>
> I wanted to make this change before sending the patch. Looks like I had
> missed and sent the patch before.
>
> Regards,
> Bala
>
>
>
>
>
>                  +
>                  +               if (data.magic == DATA_MAGIC)
>                  +                       return data.seq;
>                  +       }
>                  +
>                  +       return TEST_SEQ_INVALID;
>                  +}
>                  +
>
>
>              .......
>
>              --
>              Regards,
>              Ivan Khoronzhuk
>
>         Regards,
>         Bala
>
>
>     --
>     Regards,
>     Ivan Khoronzhuk
>
>
Balasubramanian Manoharan Aug. 3, 2015, 4:51 p.m. UTC | #13
On 3 August 2015 at 22:16, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> Bala,
>
> .......
>
>
>>
>>              what in case of TCP? Incorrect seq num?
>>
>>         Looks like a coding error. TCP should be added using a boolean
>> flag.
>>
>>         Incorrect seq num is tested in the ASSERT function after
>>         receiving the
>>         packet.
>>         Seq num is used to check whether the received packet is the same
>>         which
>>         was sent.
>>
>>
>>     That's not enough. You use the same "fail" function before and after.
>>     It's not correct when you read it before sending and after sending.
>>
>>     It can be assigned 1 while packet creation.
>>     Read before sending: ffff
>>     Read after sending: ffff
>>
>>     No errors - it's the same.
>>     But assigned 1, in fact that's error. And will not be caught.
>>
>>
>> I understand your point. seq number should be tested for !=
>> TEST_SEQ_INVALID using a separate assert after receiving the packet.
>>
>
> Smth similar. But I'm not sure if it's needed at all.
>
> I've better added check like seq_num < 20 to cover all seqnumbers that's
> not possible. (Maybe 20 or other num, but it shouldn't be
> very big)


But seq_num is somthing you generate and add right? So why do u need to
check for multiple numbers?
we just need to know if the packet is the same which we sent through
scheduler/poll queue.
Do you return different numbers for different error case or something?

Regards,
Bala

>
>
>
>>
>>     PS:
>>       I propose also rename create_packet_tcp() to create_packet().
>>       It can create TCP and UDP packets.
>>
>>
>> I wanted to make this change before sending the patch. Looks like I had
>> missed and sent the patch before.
>>
>> Regards,
>> Bala
>>
>>
>>
>>
>>
>>                  +
>>                  +               if (data.magic == DATA_MAGIC)
>>                  +                       return data.seq;
>>                  +       }
>>                  +
>>                  +       return TEST_SEQ_INVALID;
>>                  +}
>>                  +
>>
>>
>>              .......
>>
>>              --
>>              Regards,
>>              Ivan Khoronzhuk
>>
>>         Regards,
>>         Bala
>>
>>
>>     --
>>     Regards,
>>     Ivan Khoronzhuk
>>
>>
>>
> --
> Regards,
> Ivan Khoronzhuk
>
Ivan Khoronzhuk Aug. 3, 2015, 5:03 p.m. UTC | #14
Bala,

On 03.08.15 19:51, Bala Manoharan wrote:
>
>
> On 3 August 2015 at 22:16, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>
>     Bala,
>
>     .......
>
>
>
>                       what in case of TCP? Incorrect seq num?
>
>                  Looks like a coding error. TCP should be added using a
>         boolean flag.
>
>                  Incorrect seq num is tested in the ASSERT function after
>                  receiving the
>                  packet.
>                  Seq num is used to check whether the received packet is
>         the same
>                  which
>                  was sent.
>
>
>              That's not enough. You use the same "fail" function before
>         and after.
>              It's not correct when you read it before sending and after
>         sending.
>
>              It can be assigned 1 while packet creation.
>              Read before sending: ffff
>              Read after sending: ffff
>
>              No errors - it's the same.
>              But assigned 1, in fact that's error. And will not be caught.
>
>
>         I understand your point. seq number should be tested for !=
>         TEST_SEQ_INVALID using a separate assert after receiving the packet.
>
>
>     Smth similar. But I'm not sure if it's needed at all.
>
>     I've better added check like seq_num < 20 to cover all seqnumbers
>     that's not possible. (Maybe 20 or other num, but it shouldn't be
>     very big)
>
>
> But seq_num is somthing you generate and add right? So why do u need to
> check for multiple numbers?
> we just need to know if the packet is the same which we sent through
> scheduler/poll queue.
> Do you return different numbers for different error case or something?
>

No. It just thought.
Maybe it's not correct place for such deep check of seqnum assigning.
I just wanted to point that when you use cls_pkt_set_seq() inside of
packet creation function it doesn't mean that this number is correctly
assigned in the packet.

When you compare set and rcv values, you should use real value, you've
set, not read. It's needed to exclude some strange errors.

Maybe it's not correct place for catching such king of errors.
But anyway, I'll better change it.

For instance:
What about to use following in each test:

cls_pkt_set_seq(pkt, ++seq_num);
rcv_pkt(pkt);
ASSERT(seq_num == cls_pkt_get_seq(pkt))

instead of:

seq_num = cls_pkt_get_seq(pkt);
rcv_pkt(pkt);
ASSERT(seq_num == cls_pkt_get_seq(pkt))


cls_pkt_get_seq(pkt) can always return the same value or etc.
You will never catch the error.

If you want to do it in packet creation function, then it's
better to check on range of real seqnums (that was my proposition).

> Regards,
> Bala
>
>
>
>
>
>              PS:
>                I propose also rename create_packet_tcp() to create_packet().
>                It can create TCP and UDP packets.
>
>
>         I wanted to make this change before sending the patch. Looks
>         like I had
>         missed and sent the patch before.
>
>         Regards,
>         Bala
>
>
>
>
>
>                           +
>                           +               if (data.magic == DATA_MAGIC)
>                           +                       return data.seq;
>                           +       }
>                           +
>                           +       return TEST_SEQ_INVALID;
>                           +}
>                           +
>
>
>                       .......
>
>                       --
>                       Regards,
>                       Ivan Khoronzhuk
>
>                  Regards,
>                  Bala
>
>
>              --
>              Regards,
>              Ivan Khoronzhuk
>
>
>
>     --
>     Regards,
>     Ivan Khoronzhuk
>
>
Balasubramanian Manoharan Aug. 3, 2015, 5:16 p.m. UTC | #15
Ivan,

On 3 August 2015 at 22:33, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> Bala,
>
> On 03.08.15 19:51, Bala Manoharan wrote:
>
>>
>>
>> On 3 August 2015 at 22:16, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
>> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>>
>>     Bala,
>>
>>     .......
>>
>>
>>
>>                       what in case of TCP? Incorrect seq num?
>>
>>                  Looks like a coding error. TCP should be added using a
>>         boolean flag.
>>
>>                  Incorrect seq num is tested in the ASSERT function after
>>                  receiving the
>>                  packet.
>>                  Seq num is used to check whether the received packet is
>>         the same
>>                  which
>>                  was sent.
>>
>>
>>              That's not enough. You use the same "fail" function before
>>         and after.
>>              It's not correct when you read it before sending and after
>>         sending.
>>
>>              It can be assigned 1 while packet creation.
>>              Read before sending: ffff
>>              Read after sending: ffff
>>
>>              No errors - it's the same.
>>              But assigned 1, in fact that's error. And will not be caught.
>>
>>
>>         I understand your point. seq number should be tested for !=
>>         TEST_SEQ_INVALID using a separate assert after receiving the
>> packet.
>>
>>
>>     Smth similar. But I'm not sure if it's needed at all.
>>
>>     I've better added check like seq_num < 20 to cover all seqnumbers
>>     that's not possible. (Maybe 20 or other num, but it shouldn't be
>>     very big)
>>
>>
>> But seq_num is somthing you generate and add right? So why do u need to
>> check for multiple numbers?
>> we just need to know if the packet is the same which we sent through
>> scheduler/poll queue.
>> Do you return different numbers for different error case or something?
>>
>>
> No. It just thought.
> Maybe it's not correct place for such deep check of seqnum assigning.
> I just wanted to point that when you use cls_pkt_set_seq() inside of
> packet creation function it doesn't mean that this number is correctly
> assigned in the packet.
>
> When you compare set and rcv values, you should use real value, you've
> set, not read. It's needed to exclude some strange errors.
>
> Maybe it's not correct place for catching such king of errors.
> But anyway, I'll better change it.
>
> For instance:
> What about to use following in each test:
>
> cls_pkt_set_seq(pkt, ++seq_num);
> rcv_pkt(pkt);
> ASSERT(seq_num == cls_pkt_get_seq(pkt))
>
> instead of:
>
> seq_num = cls_pkt_get_seq(pkt);
> rcv_pkt(pkt);
> ASSERT(seq_num == cls_pkt_get_seq(pkt))
>
>
> cls_pkt_get_seq(pkt) can always return the same value or etc.
> You will never catch the error.
>
> If you want to do it in packet creation function, then it's
> better to check on range of real seqnums (that was my proposition).


Actually the current code flow is something like,

pkt = create_pkt() // This call sets the seq num by calling
cls_pkt_set_seq()
seq = cls_pkt_get_seq(pkt);
enqueue_pkt();
pkt = recv_pkt();
ASSERT(seq == cls_pkt_get_seq(pkt))

I don't see much difference from what you have explained above.
Maybe I am missing something, we can have a quick discussion about this in
tomorrow meeting to sort out the differences.

Regards,
Bala

>
>
>  Regards,
>> Bala
>>
>>
>>
>>
>>
>>              PS:
>>                I propose also rename create_packet_tcp() to
>> create_packet().
>>                It can create TCP and UDP packets.
>>
>>
>>         I wanted to make this change before sending the patch. Looks
>>         like I had
>>         missed and sent the patch before.
>>
>>         Regards,
>>         Bala
>>
>>
>>
>>
>>
>>                           +
>>                           +               if (data.magic == DATA_MAGIC)
>>                           +                       return data.seq;
>>                           +       }
>>                           +
>>                           +       return TEST_SEQ_INVALID;
>>                           +}
>>                           +
>>
>>
>>                       .......
>>
>>                       --
>>                       Regards,
>>                       Ivan Khoronzhuk
>>
>>                  Regards,
>>                  Bala
>>
>>
>>              --
>>              Regards,
>>              Ivan Khoronzhuk
>>
>>
>>
>>     --
>>     Regards,
>>     Ivan Khoronzhuk
>>
>>
>>
> --
> Regards,
> Ivan Khoronzhuk
>
Ivan Khoronzhuk Aug. 3, 2015, 5:28 p.m. UTC | #16
Bala,

On 03.08.15 20:16, Bala Manoharan wrote:
> Ivan,
>
> On 3 August 2015 at 22:33, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>
>     Bala,
>
>     On 03.08.15 19:51, Bala Manoharan wrote:
>
>
>
>         On 3 August 2015 at 22:16, Ivan Khoronzhuk
>         <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>
>         <mailto:ivan.khoronzhuk@linaro.org
>         <mailto:ivan.khoronzhuk@linaro.org>>> wrote:
>
>              Bala,
>
>              .......
>
>
>
>                                what in case of TCP? Incorrect seq num?
>
>                           Looks like a coding error. TCP should be added
>         using a
>                  boolean flag.
>
>                           Incorrect seq num is tested in the ASSERT
>         function after
>                           receiving the
>                           packet.
>                           Seq num is used to check whether the received
>         packet is
>                  the same
>                           which
>                           was sent.
>
>
>                       That's not enough. You use the same "fail"
>         function before
>                  and after.
>                       It's not correct when you read it before sending
>         and after
>                  sending.
>
>                       It can be assigned 1 while packet creation.
>                       Read before sending: ffff
>                       Read after sending: ffff
>
>                       No errors - it's the same.
>                       But assigned 1, in fact that's error. And will not
>         be caught.
>
>
>                  I understand your point. seq number should be tested for !=
>                  TEST_SEQ_INVALID using a separate assert after
>         receiving the packet.
>
>
>              Smth similar. But I'm not sure if it's needed at all.
>
>              I've better added check like seq_num < 20 to cover all
>         seqnumbers
>              that's not possible. (Maybe 20 or other num, but it
>         shouldn't be
>              very big)
>
>
>         But seq_num is somthing you generate and add right? So why do u
>         need to
>         check for multiple numbers?
>         we just need to know if the packet is the same which we sent through
>         scheduler/poll queue.
>         Do you return different numbers for different error case or
>         something?
>
>
>     No. It just thought.
>     Maybe it's not correct place for such deep check of seqnum assigning.
>     I just wanted to point that when you use cls_pkt_set_seq() inside of
>     packet creation function it doesn't mean that this number is correctly
>     assigned in the packet.
>
>     When you compare set and rcv values, you should use real value, you've
>     set, not read. It's needed to exclude some strange errors.
>
>     Maybe it's not correct place for catching such king of errors.
>     But anyway, I'll better change it.
>
>     For instance:
>     What about to use following in each test:
>
>     cls_pkt_set_seq(pkt, ++seq_num);
>     rcv_pkt(pkt);
>     ASSERT(seq_num == cls_pkt_get_seq(pkt))
>
>     instead of:
>
>     seq_num = cls_pkt_get_seq(pkt);
>     rcv_pkt(pkt);
>     ASSERT(seq_num == cls_pkt_get_seq(pkt))
>
>
>     cls_pkt_get_seq(pkt) can always return the same value or etc.
>     You will never catch the error.
>
>     If you want to do it in packet creation function, then it's
>     better to check on range of real seqnums (that was my proposition).
>
>
> Actually the current code flow is something like,
>
> pkt = create_pkt() // This call sets the seq num by calling
I think it's not correct place to set seqnum

> cls_pkt_set_seq()
actually it's inside of create_pkt(), that's the problem

> seq = cls_pkt_get_seq(pkt);
I propose to assign seqnum here instead of
reading it with cls_pkt_get_seq().
So, here: cls_pkt_set_seq(pkt, ++seq);
It'll allow you to exclude errors with cls_pkt_get_seq()
(like it's currently present with TCP)

> enqueue_pkt();
> pkt = recv_pkt();
> ASSERT(seq == cls_pkt_get_seq(pkt))


>
> I don't see much difference from what you have explained above.

I see an error that is not caught. That's the difference.

> Maybe I am missing something, we can have a quick discussion about this
> in tomorrow meeting to sort out the differences.



>
> Regards,
> Bala
>
>
>
>         Regards,
>         Bala
>
>
>
>
>
>                       PS:
>                         I propose also rename create_packet_tcp() to
>         create_packet().
>                         It can create TCP and UDP packets.
>
>
>                  I wanted to make this change before sending the patch.
>         Looks
>                  like I had
>                  missed and sent the patch before.
>
>                  Regards,
>                  Bala
>
>
>
>
>
>                                    +
>                                    +               if (data.magic ==
>         DATA_MAGIC)
>                                    +                       return data.seq;
>                                    +       }
>                                    +
>                                    +       return TEST_SEQ_INVALID;
>                                    +}
>                                    +
>
>
>                                .......
>
>                                --
>                                Regards,
>                                Ivan Khoronzhuk
>
>                           Regards,
>                           Bala
>
>
>                       --
>                       Regards,
>                       Ivan Khoronzhuk
>
>
>
>              --
>              Regards,
>              Ivan Khoronzhuk
>
>
>
>     --
>     Regards,
>     Ivan Khoronzhuk
>
>
Balasubramanian Manoharan Aug. 3, 2015, 5:49 p.m. UTC | #17
Ivan,

On 3 August 2015 at 22:58, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> Bala,
>
> On 03.08.15 20:16, Bala Manoharan wrote:
>
>> Ivan,
>>
>> On 3 August 2015 at 22:33, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
>> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>>
>>     Bala,
>>
>>     On 03.08.15 19:51, Bala Manoharan wrote:
>>
>>
>>
>>         On 3 August 2015 at 22:16, Ivan Khoronzhuk
>>         <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>
>>         <mailto:ivan.khoronzhuk@linaro.org
>>
>>         <mailto:ivan.khoronzhuk@linaro.org>>> wrote:
>>
>>              Bala,
>>
>>              .......
>>
>>
>>
>>                                what in case of TCP? Incorrect seq num?
>>
>>                           Looks like a coding error. TCP should be added
>>         using a
>>                  boolean flag.
>>
>>                           Incorrect seq num is tested in the ASSERT
>>         function after
>>                           receiving the
>>                           packet.
>>                           Seq num is used to check whether the received
>>         packet is
>>                  the same
>>                           which
>>                           was sent.
>>
>>
>>                       That's not enough. You use the same "fail"
>>         function before
>>                  and after.
>>                       It's not correct when you read it before sending
>>         and after
>>                  sending.
>>
>>                       It can be assigned 1 while packet creation.
>>                       Read before sending: ffff
>>                       Read after sending: ffff
>>
>>                       No errors - it's the same.
>>                       But assigned 1, in fact that's error. And will not
>>         be caught.
>>
>>
>>                  I understand your point. seq number should be tested for
>> !=
>>                  TEST_SEQ_INVALID using a separate assert after
>>         receiving the packet.
>>
>>
>>              Smth similar. But I'm not sure if it's needed at all.
>>
>>              I've better added check like seq_num < 20 to cover all
>>         seqnumbers
>>              that's not possible. (Maybe 20 or other num, but it
>>         shouldn't be
>>              very big)
>>
>>
>>         But seq_num is somthing you generate and add right? So why do u
>>         need to
>>         check for multiple numbers?
>>         we just need to know if the packet is the same which we sent
>> through
>>         scheduler/poll queue.
>>         Do you return different numbers for different error case or
>>         something?
>>
>>
>>     No. It just thought.
>>     Maybe it's not correct place for such deep check of seqnum assigning.
>>     I just wanted to point that when you use cls_pkt_set_seq() inside of
>>     packet creation function it doesn't mean that this number is correctly
>>     assigned in the packet.
>>
>>     When you compare set and rcv values, you should use real value, you've
>>     set, not read. It's needed to exclude some strange errors.
>>
>>     Maybe it's not correct place for catching such king of errors.
>>     But anyway, I'll better change it.
>>
>>     For instance:
>>     What about to use following in each test:
>>
>>     cls_pkt_set_seq(pkt, ++seq_num);
>>     rcv_pkt(pkt);
>>     ASSERT(seq_num == cls_pkt_get_seq(pkt))
>>
>>     instead of:
>>
>>     seq_num = cls_pkt_get_seq(pkt);
>>     rcv_pkt(pkt);
>>     ASSERT(seq_num == cls_pkt_get_seq(pkt))
>>
>>
>>     cls_pkt_get_seq(pkt) can always return the same value or etc.
>>     You will never catch the error.
>>
>>     If you want to do it in packet creation function, then it's
>>     better to check on range of real seqnums (that was my proposition).
>>
>>
>> Actually the current code flow is something like,
>>
>> pkt = create_pkt() // This call sets the seq num by calling
>>
> I think it's not correct place to set seqnum
>

I tend to disagree since we are creating a packet and we should be able to
add most of the parameters in this single call.

>
>  cls_pkt_set_seq()
>>
> actually it's inside of create_pkt(), that's the problem
>
>  seq = cls_pkt_get_seq(pkt);
>>
> I propose to assign seqnum here instead of
> reading it with cls_pkt_get_seq().
> So, here: cls_pkt_set_seq(pkt, ++seq);
> It'll allow you to exclude errors with cls_pkt_get_seq()
> (like it's currently present with TCP)


>
>  enqueue_pkt();
>> pkt = recv_pkt();
>> ASSERT(seq == cls_pkt_get_seq(pkt))
>>
>
>
>
>> I don't see much difference from what you have explained above.
>>
>
> I see an error that is not caught. That's the difference.


This TCP error is a valid one but the return value of cls_pkt_get_seq() API
could be tested to better point the error.
In this case it would have shown the error before sending the packet in the
enqueue function after the create packet itself.

Regards,
Bala

>
>
>  Maybe I am missing something, we can have a quick discussion about this
>> in tomorrow meeting to sort out the differences.
>>
>
>
>
>
>> Regards,
>> Bala
>>
>>
>>
>>         Regards,
>>         Bala
>>
>>
>>
>>
>>
>>                       PS:
>>                         I propose also rename create_packet_tcp() to
>>         create_packet().
>>                         It can create TCP and UDP packets.
>>
>>
>>                  I wanted to make this change before sending the patch.
>>         Looks
>>                  like I had
>>                  missed and sent the patch before.
>>
>>                  Regards,
>>                  Bala
>>
>>
>>
>>
>>
>>                                    +
>>                                    +               if (data.magic ==
>>         DATA_MAGIC)
>>                                    +                       return
>> data.seq;
>>                                    +       }
>>                                    +
>>                                    +       return TEST_SEQ_INVALID;
>>                                    +}
>>                                    +
>>
>>
>>                                .......
>>
>>                                --
>>                                Regards,
>>                                Ivan Khoronzhuk
>>
>>                           Regards,
>>                           Bala
>>
>>
>>                       --
>>                       Regards,
>>                       Ivan Khoronzhuk
>>
>>
>>
>>              --
>>              Regards,
>>              Ivan Khoronzhuk
>>
>>
>>
>>     --
>>     Regards,
>>     Ivan Khoronzhuk
>>
>>
>>
> --
> Regards,
> Ivan Khoronzhuk
>

Regards,
Bala
Ivan Khoronzhuk Aug. 3, 2015, 6:01 p.m. UTC | #18
Bala,

On 03.08.15 20:49, Bala Manoharan wrote:
> Ivan,
>
> On 3 August 2015 at 22:58, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>
>     Bala,
>
>     On 03.08.15 20:16, Bala Manoharan wrote:
>
>         Ivan,
>
>         On 3 August 2015 at 22:33, Ivan Khoronzhuk
>         <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>
>         <mailto:ivan.khoronzhuk@linaro.org
>         <mailto:ivan.khoronzhuk@linaro.org>>> wrote:
>
>              Bala,
>
>              On 03.08.15 19:51, Bala Manoharan wrote:
>
>
>
>                  On 3 August 2015 at 22:16, Ivan Khoronzhuk
>                  <ivan.khoronzhuk@linaro.org
>         <mailto:ivan.khoronzhuk@linaro.org>
>         <mailto:ivan.khoronzhuk@linaro.org
>         <mailto:ivan.khoronzhuk@linaro.org>>
>                  <mailto:ivan.khoronzhuk@linaro.org
>         <mailto:ivan.khoronzhuk@linaro.org>
>
>                  <mailto:ivan.khoronzhuk@linaro.org
>         <mailto:ivan.khoronzhuk@linaro.org>>>> wrote:
>
>                       Bala,
>
>                       .......
>
>
>
>                                         what in case of TCP? Incorrect
>         seq num?
>
>                                    Looks like a coding error. TCP should
>         be added
>                  using a
>                           boolean flag.
>
>                                    Incorrect seq num is tested in the ASSERT
>                  function after
>                                    receiving the
>                                    packet.
>                                    Seq num is used to check whether the
>         received
>                  packet is
>                           the same
>                                    which
>                                    was sent.
>
>
>                                That's not enough. You use the same "fail"
>                  function before
>                           and after.
>                                It's not correct when you read it before
>         sending
>                  and after
>                           sending.
>
>                                It can be assigned 1 while packet creation.
>                                Read before sending: ffff
>                                Read after sending: ffff
>
>                                No errors - it's the same.
>                                But assigned 1, in fact that's error. And
>         will not
>                  be caught.
>
>
>                           I understand your point. seq number should be
>         tested for !=
>                           TEST_SEQ_INVALID using a separate assert after
>                  receiving the packet.
>
>
>                       Smth similar. But I'm not sure if it's needed at all.
>
>                       I've better added check like seq_num < 20 to cover all
>                  seqnumbers
>                       that's not possible. (Maybe 20 or other num, but it
>                  shouldn't be
>                       very big)
>
>
>                  But seq_num is somthing you generate and add right? So
>         why do u
>                  need to
>                  check for multiple numbers?
>                  we just need to know if the packet is the same which we
>         sent through
>                  scheduler/poll queue.
>                  Do you return different numbers for different error case or
>                  something?
>
>
>              No. It just thought.
>              Maybe it's not correct place for such deep check of seqnum
>         assigning.
>              I just wanted to point that when you use cls_pkt_set_seq()
>         inside of
>              packet creation function it doesn't mean that this number
>         is correctly
>              assigned in the packet.
>
>              When you compare set and rcv values, you should use real
>         value, you've
>              set, not read. It's needed to exclude some strange errors.
>
>              Maybe it's not correct place for catching such king of errors.
>              But anyway, I'll better change it.
>
>              For instance:
>              What about to use following in each test:
>
>              cls_pkt_set_seq(pkt, ++seq_num);
>              rcv_pkt(pkt);
>              ASSERT(seq_num == cls_pkt_get_seq(pkt))
>
>              instead of:
>
>              seq_num = cls_pkt_get_seq(pkt);
>              rcv_pkt(pkt);
>              ASSERT(seq_num == cls_pkt_get_seq(pkt))
>
>
>              cls_pkt_get_seq(pkt) can always return the same value or etc.
>              You will never catch the error.
>
>              If you want to do it in packet creation function, then it's
>              better to check on range of real seqnums (that was my
>         proposition).
>
>
>         Actually the current code flow is something like,
>
>         pkt = create_pkt() // This call sets the seq num by calling
>
>     I think it's not correct place to set seqnum
>
>
> I tend to disagree since we are creating a packet and we should be able
> to add most of the parameters in this single call.

As you wish,
But you tend to pass test successfully in case of error in
cls_pkt_get_seq or cls_pkt_set_seq or odp_packet_copydata_out or
odp_packet_copydata_int ...

Pay attention that in case of success it doesn't mean that you receive
what you sent. That means, you if you have error with PMR and error with 
above functions you can pass the test successfully.

You see my point, so no need to continue.
I have no objections do like you think to be better. It's not very
big problem.
Balasubramanian Manoharan Aug. 3, 2015, 6:07 p.m. UTC | #19
On 3 August 2015 at 23:31, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> Bala,
>
> On 03.08.15 20:49, Bala Manoharan wrote:
>
>> Ivan,
>>
>> On 3 August 2015 at 22:58, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
>> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>>
>>     Bala,
>>
>>     On 03.08.15 20:16, Bala Manoharan wrote:
>>
>>         Ivan,
>>
>>         On 3 August 2015 at 22:33, Ivan Khoronzhuk
>>         <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>
>>         <mailto:ivan.khoronzhuk@linaro.org
>>         <mailto:ivan.khoronzhuk@linaro.org>>> wrote:
>>
>>              Bala,
>>
>>              On 03.08.15 19:51, Bala Manoharan wrote:
>>
>>
>>
>>                  On 3 August 2015 at 22:16, Ivan Khoronzhuk
>>                  <ivan.khoronzhuk@linaro.org
>>         <mailto:ivan.khoronzhuk@linaro.org>
>>         <mailto:ivan.khoronzhuk@linaro.org
>>         <mailto:ivan.khoronzhuk@linaro.org>>
>>                  <mailto:ivan.khoronzhuk@linaro.org
>>         <mailto:ivan.khoronzhuk@linaro.org>
>>
>>                  <mailto:ivan.khoronzhuk@linaro.org
>>         <mailto:ivan.khoronzhuk@linaro.org>>>> wrote:
>>
>>                       Bala,
>>
>>                       .......
>>
>>
>>
>>                                         what in case of TCP? Incorrect
>>         seq num?
>>
>>                                    Looks like a coding error. TCP should
>>         be added
>>                  using a
>>                           boolean flag.
>>
>>                                    Incorrect seq num is tested in the
>> ASSERT
>>                  function after
>>                                    receiving the
>>                                    packet.
>>                                    Seq num is used to check whether the
>>         received
>>                  packet is
>>                           the same
>>                                    which
>>                                    was sent.
>>
>>
>>                                That's not enough. You use the same "fail"
>>                  function before
>>                           and after.
>>                                It's not correct when you read it before
>>         sending
>>                  and after
>>                           sending.
>>
>>                                It can be assigned 1 while packet creation.
>>                                Read before sending: ffff
>>                                Read after sending: ffff
>>
>>                                No errors - it's the same.
>>                                But assigned 1, in fact that's error. And
>>         will not
>>                  be caught.
>>
>>
>>                           I understand your point. seq number should be
>>         tested for !=
>>                           TEST_SEQ_INVALID using a separate assert after
>>                  receiving the packet.
>>
>>
>>                       Smth similar. But I'm not sure if it's needed at
>> all.
>>
>>                       I've better added check like seq_num < 20 to cover
>> all
>>                  seqnumbers
>>                       that's not possible. (Maybe 20 or other num, but it
>>                  shouldn't be
>>                       very big)
>>
>>
>>                  But seq_num is somthing you generate and add right? So
>>         why do u
>>                  need to
>>                  check for multiple numbers?
>>                  we just need to know if the packet is the same which we
>>         sent through
>>                  scheduler/poll queue.
>>                  Do you return different numbers for different error case
>> or
>>                  something?
>>
>>
>>              No. It just thought.
>>              Maybe it's not correct place for such deep check of seqnum
>>         assigning.
>>              I just wanted to point that when you use cls_pkt_set_seq()
>>         inside of
>>              packet creation function it doesn't mean that this number
>>         is correctly
>>              assigned in the packet.
>>
>>              When you compare set and rcv values, you should use real
>>         value, you've
>>              set, not read. It's needed to exclude some strange errors.
>>
>>              Maybe it's not correct place for catching such king of
>> errors.
>>              But anyway, I'll better change it.
>>
>>              For instance:
>>              What about to use following in each test:
>>
>>              cls_pkt_set_seq(pkt, ++seq_num);
>>              rcv_pkt(pkt);
>>              ASSERT(seq_num == cls_pkt_get_seq(pkt))
>>
>>              instead of:
>>
>>              seq_num = cls_pkt_get_seq(pkt);
>>              rcv_pkt(pkt);
>>              ASSERT(seq_num == cls_pkt_get_seq(pkt))
>>
>>
>>              cls_pkt_get_seq(pkt) can always return the same value or etc.
>>              You will never catch the error.
>>
>>              If you want to do it in packet creation function, then it's
>>              better to check on range of real seqnums (that was my
>>         proposition).
>>
>>
>>         Actually the current code flow is something like,
>>
>>         pkt = create_pkt() // This call sets the seq num by calling
>>
>>     I think it's not correct place to set seqnum
>>
>>
>> I tend to disagree since we are creating a packet and we should be able
>> to add most of the parameters in this single call.
>>
>
> As you wish,
> But you tend to pass test successfully in case of error in
> cls_pkt_get_seq or cls_pkt_set_seq or odp_packet_copydata_out or
> odp_packet_copydata_int ...
>

I agree it was a valid error and I will correct the same.

>
> Pay attention that in case of success it doesn't mean that you receive
> what you sent. That means, you if you have error with PMR and error with
> above functions you can pass the test successfully.
>
> You see my point, so no need to continue.
> I have no objections do like you think to be better. It's not very
> big problem.


It is just a difference in coding style but thanks for pointing out the
error.

Regards,
Bala

>
>
> --
> Regards,
> Ivan Khoronzhuk
>
diff mbox

Patch

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);