diff mbox

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

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

Commit Message

Balasubramanian Manoharan Aug. 12, 2015, 8:53 a.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.

Fixes:
https://bugs.linaro.org/show_bug.cgi?id=1542
https://bugs.linaro.org/show_bug.cgi?id=1544
https://bugs.linaro.org/show_bug.cgi?id=1545
https://bugs.linaro.org/show_bug.cgi?id=1546

Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>
---
v2: Incorporates review comments from Ivan and Christophe

 helper/include/odp/helper/tcp.h                    |   4 +
 test/validation/classification/Makefile.am         |   2 +
 test/validation/classification/classification.c    |   5 +
 .../classification/odp_classification_common.c     | 225 ++++++++
 .../classification/odp_classification_test_pmr.c   | 640 +++++++++++++++++++++
 .../classification/odp_classification_tests.c      | 152 +----
 .../classification/odp_classification_testsuites.h |  10 +-
 7 files changed, 906 insertions(+), 132 deletions(-)
 create mode 100644 test/validation/classification/odp_classification_common.c
 create mode 100644 test/validation/classification/odp_classification_test_pmr.c

Comments

Ivan Khoronzhuk Aug. 14, 2015, 4:27 p.m. UTC | #1
Hi, Bala

Just checked if you added real MAC and seems you forgot to.
Or maybe you are planing to do it in separate patch.

On 12.08.15 11:53, 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.
>
> Fixes:
> https://bugs.linaro.org/show_bug.cgi?id=1542
> https://bugs.linaro.org/show_bug.cgi?id=1544
> https://bugs.linaro.org/show_bug.cgi?id=1545
> https://bugs.linaro.org/show_bug.cgi?id=1546
>
> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>
> ---
> v2: Incorporates review comments from Ivan and Christophe
>
>   helper/include/odp/helper/tcp.h                    |   4 +
>   test/validation/classification/Makefile.am         |   2 +
>   test/validation/classification/classification.c    |   5 +
>   .../classification/odp_classification_common.c     | 225 ++++++++
>   .../classification/odp_classification_test_pmr.c   | 640 +++++++++++++++++++++
>   .../classification/odp_classification_tests.c      | 152 +----
>   .../classification/odp_classification_testsuites.h |  10 +-
>   7 files changed, 906 insertions(+), 132 deletions(-)
>   create mode 100644 test/validation/classification/odp_classification_common.c
>   create mode 100644 test/validation/classification/odp_classification_test_pmr.c
>
......
> +
> +odp_packet_t create_packet(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);

I expect here will be real MAC address.
Like it was done for performance/odp_pktio_perf
01f5c738c6e73bd3ad75984d293c506f952a1eff

...
Balasubramanian Manoharan Aug. 14, 2015, 4:29 p.m. UTC | #2
Hi Ivan,

I am planning to add MAC support in a separate patch.
I believe MAC should be easier to get-in since it has been agreed.

Regards,
Bala

On 14 August 2015 at 21:57, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> Hi, Bala
>
> Just checked if you added real MAC and seems you forgot to.
> Or maybe you are planing to do it in separate patch.
>
> On 12.08.15 11:53, 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.
>>
>> Fixes:
>> https://bugs.linaro.org/show_bug.cgi?id=1542
>> https://bugs.linaro.org/show_bug.cgi?id=1544
>> https://bugs.linaro.org/show_bug.cgi?id=1545
>> https://bugs.linaro.org/show_bug.cgi?id=1546
>>
>> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>
>> ---
>> v2: Incorporates review comments from Ivan and Christophe
>>
>>   helper/include/odp/helper/tcp.h                    |   4 +
>>   test/validation/classification/Makefile.am         |   2 +
>>   test/validation/classification/classification.c    |   5 +
>>   .../classification/odp_classification_common.c     | 225 ++++++++
>>   .../classification/odp_classification_test_pmr.c   | 640
>> +++++++++++++++++++++
>>   .../classification/odp_classification_tests.c      | 152 +----
>>   .../classification/odp_classification_testsuites.h |  10 +-
>>   7 files changed, 906 insertions(+), 132 deletions(-)
>>   create mode 100644
>> test/validation/classification/odp_classification_common.c
>>   create mode 100644
>> test/validation/classification/odp_classification_test_pmr.c
>>
>> ......
>
> +
>> +odp_packet_t create_packet(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);
>>
>
> I expect here will be real MAC address.
> Like it was done for performance/odp_pktio_perf
> 01f5c738c6e73bd3ad75984d293c506f952a1eff
>
> ...
>
> --
> Regards,
> Ivan Khoronzhuk
>
Ivan Khoronzhuk Aug. 14, 2015, 4:30 p.m. UTC | #3
On 14.08.15 19:29, Bala Manoharan wrote:
> Hi Ivan,
>
> I am planning to add MAC support in a separate patch.
> I believe MAC should be easier to get-in since it has been agreed.

Ok.
Balasubramanian Manoharan Aug. 17, 2015, 4:08 p.m. UTC | #4
Ping.

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

>
> On 14.08.15 19:29, Bala Manoharan wrote:
>
>> Hi Ivan,
>>
>> I am planning to add MAC support in a separate patch.
>> I believe MAC should be easier to get-in since it has been agreed.
>>
>
> Ok.
>
Maxim Uvarov Aug. 18, 2015, 11:53 a.m. UTC | #5
Ivan, did you test that patches? Do you want to add your review-by?

Maxim.

On 08/17/15 19:08, Bala Manoharan wrote:
> Ping.
>
> On 14 August 2015 at 22:00, Ivan Khoronzhuk 
> <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>
>
>     On 14.08.15 19:29, Bala Manoharan wrote:
>
>         Hi Ivan,
>
>         I am planning to add MAC support in a separate patch.
>         I believe MAC should be easier to get-in since it has been agreed.
>
>
>     Ok.
>
>
>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
Ivan Khoronzhuk Aug. 18, 2015, 12:18 p.m. UTC | #6
One moment.
I need to checkout, I deep enough in some other stuff.

On 18.08.15 14:53, Maxim Uvarov wrote:
> Ivan, did you test that patches? Do you want to add your review-by?
>
> Maxim.
>
> On 08/17/15 19:08, Bala Manoharan wrote:
>> Ping.
>>
>> On 14 August 2015 at 22:00, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>>
>>
>>     On 14.08.15 19:29, Bala Manoharan wrote:
>>
>>         Hi Ivan,
>>
>>         I am planning to add MAC support in a separate patch.
>>         I believe MAC should be easier to get-in since it has been agreed.
>>
>>
>>     Ok.
>>
>>
>>
>>
>> _______________________________________________
>> lng-odp mailing list
>> lng-odp@lists.linaro.org
>> https://lists.linaro.org/mailman/listinfo/lng-odp
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
Ivan Khoronzhuk Aug. 18, 2015, 1:52 p.m. UTC | #7
Hi, Bala

Note: Your patch is based on API-NEXT and it obliged me to do some modifications
with odp_pktio_param_t before testing. Also I'm still not sure about using
odp_pmr_terms_cap(), but maybe it's OK to simply fail.

Short pretesting review farther below

On 12.08.15 11:53, 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.
>
> Fixes:
> https://bugs.linaro.org/show_bug.cgi?id=1542
> https://bugs.linaro.org/show_bug.cgi?id=1544
> https://bugs.linaro.org/show_bug.cgi?id=1545
> https://bugs.linaro.org/show_bug.cgi?id=1546
>
> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>
> ---
> v2: Incorporates review comments from Ivan and Christophe
>
>   helper/include/odp/helper/tcp.h                    |   4 +
>   test/validation/classification/Makefile.am         |   2 +
>   test/validation/classification/classification.c    |   5 +
>   .../classification/odp_classification_common.c     | 225 ++++++++
>   .../classification/odp_classification_test_pmr.c   | 640 +++++++++++++++++++++
>   .../classification/odp_classification_tests.c      | 152 +----
>   .../classification/odp_classification_testsuites.h |  10 +-
>   7 files changed, 906 insertions(+), 132 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

What about to name it ODPH_MIN_TCPHDR_LEN.

>
>   /** 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..a88a301 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_suite_pmr,
> +			.pInitFunc = classification_suite_pmr_init,
> +			.pCleanupFunc = classification_suite_pmr_term,
> +	},

I'm not sure if "classificatio pmr tests" should be after "classification tests"
Maybe better to insert it before. Just in order of complexity.

>   	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..fe392c0
> --- /dev/null
> +++ b/test/validation/classification/odp_classification_common.c
> @@ -0,0 +1,225 @@
> +/* 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;
> +
> +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;
> +}
> +
> +uint32_t cls_pkt_get_seq(odp_packet_t pkt)

On my opinion it should be complementary to cls_pkt_set_seq(),
with flag_udp or vise versa.

> +{
> +	uint32_t offset;
> +	cls_test_packet_t data;
> +	odph_ipv4hdr_t *ip;
> +
> +	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
> +	offset = odp_packet_l4_offset(pkt);
> +
> +	if (!offset && !ip)
> +		return TEST_SEQ_INVALID;
> +
> +	if (ip->proto == ODPH_IPPROTO_UDP)
> +		odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
> +					sizeof(data), &data);
> +	else
> +		odp_packet_copydata_out(pkt, offset + ODPH_TCPHDR_LEN,
> +					sizeof(data), &data);

adding to previous comment. If you wish ,in the same way, as you checked IP
proto field of IP header to identify UDP/TCP, you can count TCP header length
instead of hardcode ODPH_TCPHDR_LEN. It's just proposition, to make the function
independent from TCP header length and it's options.

> +
> +	if (data.magic == DATA_MAGIC)
> +		return data.seq;
> +
> +	return TEST_SEQ_INVALID;
> +}
> +
> +static inline
> +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask)

....
Ivan Khoronzhuk Aug. 18, 2015, 2:13 p.m. UTC | #8
>>
>> +/** 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
>
> What about to name it ODPH_MIN_TCPHDR_LEN.

But it's style already.
So, better leave as is. Only comment should be shorter.
Like for IP header:

#define ODPH_IPV4HDR_LEN     20  /**< Min length of IP header (no options) */
Balasubramanian Manoharan Aug. 18, 2015, 3:16 p.m. UTC | #9
Hi Ivan,

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

> Hi, Bala
>
> Note: Your patch is based on API-NEXT and it obliged me to do some
> modifications
> with odp_pktio_param_t before testing. Also I'm still not sure about using
> odp_pmr_terms_cap(), but maybe it's OK to simply fail.
>
> Short pretesting review farther below


>
> On 12.08.15 11:53, 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.
>>
>> Fixes:
>> https://bugs.linaro.org/show_bug.cgi?id=1542
>> https://bugs.linaro.org/show_bug.cgi?id=1544
>> https://bugs.linaro.org/show_bug.cgi?id=1545
>> https://bugs.linaro.org/show_bug.cgi?id=1546
>>
>> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>
>> ---
>> v2: Incorporates review comments from Ivan and Christophe
>>
>>   helper/include/odp/helper/tcp.h                    |   4 +
>>   test/validation/classification/Makefile.am         |   2 +
>>   test/validation/classification/classification.c    |   5 +
>>   .../classification/odp_classification_common.c     | 225 ++++++++
>>   .../classification/odp_classification_test_pmr.c   | 640
>> +++++++++++++++++++++
>>   .../classification/odp_classification_tests.c      | 152 +----
>>   .../classification/odp_classification_testsuites.h |  10 +-
>>   7 files changed, 906 insertions(+), 132 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
>>
>
> What about to name it ODPH_MIN_TCPHDR_LEN.


As you have mentioned in your next mail this, I have followed existing ODP
standard for naming convention.

>
>
>
>>   /** 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..a88a301 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_suite_pmr,
>> +                       .pInitFunc = classification_suite_pmr_init,
>> +                       .pCleanupFunc = classification_suite_pmr_term,
>> +       },
>>
>
> I'm not sure if "classificatio pmr tests" should be after "classification
> tests"
> Maybe better to insert it before. Just in order of complexity.


Yes. I will move this in the next patch.

>
>
>         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..fe392c0
>> --- /dev/null
>> +++ b/test/validation/classification/odp_classification_common.c
>> @@ -0,0 +1,225 @@
>> +/* 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;
>> +
>> +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;
>> +}
>> +
>> +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
>>
>
> On my opinion it should be complementary to cls_pkt_set_seq(),
> with flag_udp or vise versa.


It is a good point but actually I will have to read the UDP flag from the
packet if I have to send the flag into the cls_pkt_get_seq(pkt) function
but since we are sending the packet as input parameter to this function I
think it is better to check the same in the function itself.


>
> +{
>> +       uint32_t offset;
>> +       cls_test_packet_t data;
>> +       odph_ipv4hdr_t *ip;
>> +
>> +       ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>> +       offset = odp_packet_l4_offset(pkt);
>> +
>> +       if (!offset && !ip)
>> +               return TEST_SEQ_INVALID;
>> +
>> +       if (ip->proto == ODPH_IPPROTO_UDP)
>> +               odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
>> +                                       sizeof(data), &data);
>> +       else
>> +               odp_packet_copydata_out(pkt, offset + ODPH_TCPHDR_LEN,
>> +                                       sizeof(data), &data);
>>
>
> adding to previous comment. If you wish ,in the same way, as you checked IP
> proto field of IP header to identify UDP/TCP, you can count TCP header
> length
> instead of hardcode ODPH_TCPHDR_LEN. It's just proposition, to make the
> function
> independent from TCP header length and it's options.


I had my initial implementation reading the TCP header length from tcp
packet but i changed this since the received packets are created only by
this validation suite. I am fine changing this to read the header length
form tcp header field.


>
> +
>> +       if (data.magic == DATA_MAGIC)
>> +               return data.seq;
>> +
>> +       return TEST_SEQ_INVALID;
>> +}
>> +
>> +static inline
>> +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t
>> *mask)
>>
>
> ....
>
> --
> Regards,
> Ivan Khoronzhuk
>


If you have additional comments I can wait for further comments before
sending the next version.

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

On 18.08.15 18:16, Bala Manoharan wrote:
> Hi Ivan,
>
> On 18 August 2015 at 19:22, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>
>     Hi, Bala
>
>     Note: Your patch is based on API-NEXT and it obliged me to do some modifications
>     with odp_pktio_param_t before testing. Also I'm still not sure about using
>     odp_pmr_terms_cap(), but maybe it's OK to simply fail.

I understand that you want to simly fail test, but on my opinion
that's slightly different result. It be good to print some msg like
PMR is not supported...I'm printing the msg like Unsupported term, but
it's not printed in the summary. It's just slightly different result and
it worries me a little.

>
>     Short pretesting review farther below
>
>
>
>     On 12.08.15 11:53, 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.
>
>         Fixes:
>         https://bugs.linaro.org/show_bug.cgi?id=1542
>         https://bugs.linaro.org/show_bug.cgi?id=1544
>         https://bugs.linaro.org/show_bug.cgi?id=1545
>         https://bugs.linaro.org/show_bug.cgi?id=1546
>
>         Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org>>
>         ---
>         v2: Incorporates review comments from Ivan and Christophe
>
>            helper/include/odp/helper/tcp.h                    |   4 +
>            test/validation/classification/Makefile.am         |   2 +
>            test/validation/classification/classification.c    |   5 +
>            .../classification/odp_classification_common.c     | 225 ++++++++
>            .../classification/odp_classification_test_pmr.c   | 640 +++++++++++++++++++++
>            .../classification/odp_classification_tests.c      | 152 +----
>            .../classification/odp_classification_testsuites.h |  10 +-
>            7 files changed, 906 insertions(+), 132 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
>
>
>     What about to name it ODPH_MIN_TCPHDR_LEN.
>
>
> As you have mentioned in your next mail this, I have followed existing ODP standard for naming convention.

Don't forget to shorten the comment.

>
>
>
>
>            /** 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..a88a301 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_suite_pmr,
>         +                       .pInitFunc = classification_suite_pmr_init,
>         +                       .pCleanupFunc = classification_suite_pmr_term,
>         +       },
>
>
>     I'm not sure if "classificatio pmr tests" should be after "classification tests"
>     Maybe better to insert it before. Just in order of complexity.
>
>
> Yes. I will move this in the next patch.
>
>
>
>                  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..fe392c0
>         --- /dev/null
>         +++ b/test/validation/classification/odp_classification_common.c
>         @@ -0,0 +1,225 @@
>         +/* 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 <http://10.0.0.1/32>"
>         +#define CLS_DEFAULT_DADDR      "10.0.0.100/32 <http://10.0.0.100/32>"
>         +#define CLS_DEFAULT_SPORT      1024
>         +#define CLS_DEFAULT_DPORT      2048
>         +
>         +#define CLS_TEST_SPORT         4096
>         +#define CLS_TEST_DPORT         8192
>         +#define CLS_TEST_DADDR         "10.0.0.5/32 <http://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;
>         +
>         +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;
>         +}
>         +
>         +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
>
>
>     On my opinion it should be complementary to cls_pkt_set_seq(),
>     with flag_udp or vise versa.
>
>
> It is a good point but actually I will have to read the UDP flag from the packet if I have to send the flag into the cls_pkt_get_seq(pkt) function but since we are sending the packet as input parameter to this function I think it is better to check the same in the function itself.

I thing it shouldn't depend on external usage of the function.
Sorry, what decision?

>
>
>
>         +{
>         +       uint32_t offset;
>         +       cls_test_packet_t data;
>         +       odph_ipv4hdr_t *ip;
>         +
>         +       ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>         +       offset = odp_packet_l4_offset(pkt);
>         +
>         +       if (!offset && !ip)
>         +               return TEST_SEQ_INVALID;
>         +
>         +       if (ip->proto == ODPH_IPPROTO_UDP)
>         +               odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
>         +                                       sizeof(data), &data);
>         +       else
>         +               odp_packet_copydata_out(pkt, offset + ODPH_TCPHDR_LEN,
>         +                                       sizeof(data), &data);
>
>
>     adding to previous comment. If you wish ,in the same way, as you checked IP
>     proto field of IP header to identify UDP/TCP, you can count TCP header length
>     instead of hardcode ODPH_TCPHDR_LEN. It's just proposition, to make the function
>     independent from TCP header length and it's options.
>
>
> I had my initial implementation reading the TCP header length from tcp packet but i changed this since the received packets are created only by this validation suite.
> I am fine changing this to read the header length form tcp header field.

Ok.

>
>
>
>         +
>         +       if (data.magic == DATA_MAGIC)
>         +               return data.seq;
>         +
>         +       return TEST_SEQ_INVALID;
>         +}
>         +
>         +static inline
>         +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask)
>
>
>     ....
>
>     --
>     Regards,
>     Ivan Khoronzhuk
>
>
>
> If you have additional comments I can wait for further comments before sending the next version.

Yes, please wait a little.

>
> Regards,
> Bala
Balasubramanian Manoharan Aug. 18, 2015, 3:54 p.m. UTC | #11
Ivan,

On 18 August 2015 at 21:15, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> Bala,
>
> On 18.08.15 18:16, Bala Manoharan wrote:
>
>> Hi Ivan,
>>
>> On 18 August 2015 at 19:22, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
>> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>>
>>     Hi, Bala
>>
>>     Note: Your patch is based on API-NEXT and it obliged me to do some
>> modifications
>>     with odp_pktio_param_t before testing. Also I'm still not sure about
>> using
>>     odp_pmr_terms_cap(), but maybe it's OK to simply fail.
>>
>
> I understand that you want to simly fail test, but on my opinion
> that's slightly different result. It be good to print some msg like
> PMR is not supported...I'm printing the msg like Unsupported term, but
> it's not printed in the summary. It's just slightly different result and
> it worries me a little.
>
> Okay. We can discuss this further in arch call.


>
>>     Short pretesting review farther below
>>
>>
>>
>>     On 12.08.15 11:53, 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.
>>
>>         Fixes:
>>         https://bugs.linaro.org/show_bug.cgi?id=1542
>>         https://bugs.linaro.org/show_bug.cgi?id=1544
>>         https://bugs.linaro.org/show_bug.cgi?id=1545
>>         https://bugs.linaro.org/show_bug.cgi?id=1546
>>
>>         Signed-off-by: Balasubramanian Manoharan <
>> bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org>>
>>
>>         ---
>>         v2: Incorporates review comments from Ivan and Christophe
>>
>>            helper/include/odp/helper/tcp.h                    |   4 +
>>            test/validation/classification/Makefile.am         |   2 +
>>            test/validation/classification/classification.c    |   5 +
>>            .../classification/odp_classification_common.c     | 225
>> ++++++++
>>            .../classification/odp_classification_test_pmr.c   | 640
>> +++++++++++++++++++++
>>            .../classification/odp_classification_tests.c      | 152 +----
>>            .../classification/odp_classification_testsuites.h |  10 +-
>>            7 files changed, 906 insertions(+), 132 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
>>
>>
>>     What about to name it ODPH_MIN_TCPHDR_LEN.
>>
>>
>> As you have mentioned in your next mail this, I have followed existing
>> ODP standard for naming convention.
>>
>
> Don't forget to shorten the comment.
>

Okay.

>
>
>>
>>
>>
>>            /** 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..a88a301 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_suite_pmr,
>>         +                       .pInitFunc =
>> classification_suite_pmr_init,
>>         +                       .pCleanupFunc =
>> classification_suite_pmr_term,
>>         +       },
>>
>>
>>     I'm not sure if "classificatio pmr tests" should be after
>> "classification tests"
>>     Maybe better to insert it before. Just in order of complexity.
>>
>>
>> Yes. I will move this in the next patch.
>>
>>
>>
>>                  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..fe392c0
>>         --- /dev/null
>>         +++ b/test/validation/classification/odp_classification_common.c
>>         @@ -0,0 +1,225 @@
>>         +/* 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 <http://10.0.0.1/32
>> >"
>>         +#define CLS_DEFAULT_DADDR      "10.0.0.100/32 <
>> http://10.0.0.100/32>"
>>         +#define CLS_DEFAULT_SPORT      1024
>>         +#define CLS_DEFAULT_DPORT      2048
>>         +
>>         +#define CLS_TEST_SPORT         4096
>>         +#define CLS_TEST_DPORT         8192
>>         +#define CLS_TEST_DADDR         "10.0.0.5/32 <http://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;
>>         +
>>         +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;
>>         +}
>>         +
>>         +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
>>
>>
>>     On my opinion it should be complementary to cls_pkt_set_seq(),
>>     with flag_udp or vise versa.
>>
>>
>> It is a good point but actually I will have to read the UDP flag from the
>> packet if I have to send the flag into the cls_pkt_get_seq(pkt) function
>> but since we are sending the packet as input parameter to this function I
>> think it is better to check the same in the function itself.
>>
>
> I thing it shouldn't depend on external usage of the function.
> Sorry, what decision?


I thought your suggestion was to add "flag_udp" as part of input parameter
to cls_pkt_get_seq(odp_packet_t pkt) function. IMO since we are sending the
packet into this function it would be redundant to send the udp_flag
information since this function can deduct the same from the packet.


>
>
>>
>>
>>         +{
>>         +       uint32_t offset;
>>         +       cls_test_packet_t data;
>>         +       odph_ipv4hdr_t *ip;
>>         +
>>         +       ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>>         +       offset = odp_packet_l4_offset(pkt);
>>         +
>>         +       if (!offset && !ip)
>>         +               return TEST_SEQ_INVALID;
>>         +
>>         +       if (ip->proto == ODPH_IPPROTO_UDP)
>>         +               odp_packet_copydata_out(pkt, offset +
>> ODPH_UDPHDR_LEN,
>>         +                                       sizeof(data), &data);
>>         +       else
>>         +               odp_packet_copydata_out(pkt, offset +
>> ODPH_TCPHDR_LEN,
>>         +                                       sizeof(data), &data);
>>
>>
>>     adding to previous comment. If you wish ,in the same way, as you
>> checked IP
>>     proto field of IP header to identify UDP/TCP, you can count TCP
>> header length
>>     instead of hardcode ODPH_TCPHDR_LEN. It's just proposition, to make
>> the function
>>     independent from TCP header length and it's options.
>>
>>
>> I had my initial implementation reading the TCP header length from tcp
>> packet but i changed this since the received packets are created only by
>> this validation suite.
>> I am fine changing this to read the header length form tcp header field.
>>
>
> Ok.
>
>
>>
>>
>>         +
>>         +       if (data.magic == DATA_MAGIC)
>>         +               return data.seq;
>>         +
>>         +       return TEST_SEQ_INVALID;
>>         +}
>>         +
>>         +static inline
>>         +int parse_ipv4_string(const char *ipaddress, uint32_t *addr,
>> uint32_t *mask)
>>
>>
>>     ....
>>
>>     --
>>     Regards,
>>     Ivan Khoronzhuk
>>
>>
>>
>> If you have additional comments I can wait for further comments before
>> sending the next version.
>>
>
> Yes, please wait a little.
>
>
>> Regards,
>> Bala
>>
>
> --
> Regards,
> Ivan Khoronzhuk
>

Regards,
Bala
Ivan Khoronzhuk Aug. 18, 2015, 4:13 p.m. UTC | #12
Bala,

On 18.08.15 18:54, Bala Manoharan wrote:
> Ivan,
>
> On 18 August 2015 at 21:15, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>
>     Bala,
>
>     On 18.08.15 18:16, Bala Manoharan wrote:
>
>         Hi Ivan,
>
>         On 18 August 2015 at 19:22, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org> <mailto:ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>>> wrote:
>
>              Hi, Bala
>
>              Note: Your patch is based on API-NEXT and it obliged me to do some modifications
>              with odp_pktio_param_t before testing. Also I'm still not sure about using
>              odp_pmr_terms_cap(), but maybe it's OK to simply fail.
>
>
>     I understand that you want to simly fail test, but on my opinion
>     that's slightly different result. It be good to print some msg like
>     PMR is not supported...I'm printing the msg like Unsupported term, but
>     it's not printed in the summary. It's just slightly different result and
>     it worries me a little.
>
> Okay. We can discuss this further in arch call.

I don't have correct decision on this yet.
I hoped you have.

>
>
>              Short pretesting review farther below
>
>
>
>              On 12.08.15 11:53, 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.
>
>                  Fixes:
>         https://bugs.linaro.org/show_bug.cgi?id=1542
>         https://bugs.linaro.org/show_bug.cgi?id=1544
>         https://bugs.linaro.org/show_bug.cgi?id=1545
>         https://bugs.linaro.org/show_bug.cgi?id=1546
>
>                  Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org> <mailto:bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org>>>
>
>                  ---
>                  v2: Incorporates review comments from Ivan and Christophe
>
>                     helper/include/odp/helper/tcp.h                    |   4 +
>                     test/validation/classification/Makefile.am         |   2 +
>                     test/validation/classification/classification.c    |   5 +
>                     .../classification/odp_classification_common.c     | 225 ++++++++
>                     .../classification/odp_classification_test_pmr.c   | 640 +++++++++++++++++++++
>                     .../classification/odp_classification_tests.c      | 152 +----
>                     .../classification/odp_classification_testsuites.h |  10 +-
>                     7 files changed, 906 insertions(+), 132 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
>
>
>              What about to name it ODPH_MIN_TCPHDR_LEN.
>
>
>         As you have mentioned in your next mail this, I have followed existing ODP standard for naming convention.
>
>
>     Don't forget to shorten the comment.
>
> Okay.
>
>
>
>
>
>
>                     /** 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> <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..a88a301 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_suite_pmr,
>                  +                       .pInitFunc = classification_suite_pmr_init,
>                  +                       .pCleanupFunc = classification_suite_pmr_term,
>                  +       },
>
>
>              I'm not sure if "classificatio pmr tests" should be after "classification tests"
>              Maybe better to insert it before. Just in order of complexity.
>
>
>         Yes. I will move this in the next patch.
>
>
>
>                           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..fe392c0
>                  --- /dev/null
>                  +++ b/test/validation/classification/odp_classification_common.c
>                  @@ -0,0 +1,225 @@
>                  +/* 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 <http://10.0.0.1/32> <http://10.0.0.1/32>"
>                  +#define CLS_DEFAULT_DADDR      "10.0.0.100/32 <http://10.0.0.100/32> <http://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 <http://10.0.0.5/32> <http://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;
>                  +
>                  +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;
>                  +}
>                  +
>                  +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
>
>
>              On my opinion it should be complementary to cls_pkt_set_seq(),
>              with flag_udp or vise versa.
>
>
>         It is a good point but actually I will have to read the UDP flag from the packet if I have to send the flag into the cls_pkt_get_seq(pkt) function but since we are sending the packet as input parameter to this function I think it is better to check the same in the function itself.
>
>
>     I thing it shouldn't depend on external usage of the function.
>     Sorry, what decision?
>
>
> I thought your suggestion was to add "flag_udp" as part of input parameter to cls_pkt_get_seq(odp_packet_t pkt) function. IMO since we are sending the packet into this function it would be redundant to send the udp_flag information since this function can deduct the same from the packet.

Suggestion was to use flag in both cases or don't use flag at all.
In the tests you always know what kind of packet you are sending and receiving.
So no problem with this.
But on my opinion as you any way are going to parse TCP header to get TCP header length,
be better to do the same for identifying of packet type, so no need in this flag in "get"
function. Thus, no need in it in "set" function.
The same can be done in cls_pkt_set_seq(), just read it from the packet.
Can you read it from packet before sending, cannot?

So, my proposition: don't path this flag at all.
It's better to use the same method for retrieving information then different in
similar king of functions. It's not speed-critical peace of code, so no need to worry about.
Balasubramanian Manoharan Aug. 18, 2015, 4:26 p.m. UTC | #13
Ivan,

On 18 August 2015 at 21:43, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> Bala,
>
> On 18.08.15 18:54, Bala Manoharan wrote:
>
>> Ivan,
>>
>> On 18 August 2015 at 21:15, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
>> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>>
>>     Bala,
>>
>>     On 18.08.15 18:16, Bala Manoharan wrote:
>>
>>         Hi Ivan,
>>
>>         On 18 August 2015 at 19:22, Ivan Khoronzhuk <
>> ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org> <mailto:
>> ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>>> wrote:
>>
>>              Hi, Bala
>>
>>              Note: Your patch is based on API-NEXT and it obliged me to
>> do some modifications
>>              with odp_pktio_param_t before testing. Also I'm still not
>> sure about using
>>              odp_pmr_terms_cap(), but maybe it's OK to simply fail.
>>
>>
>>     I understand that you want to simly fail test, but on my opinion
>>     that's slightly different result. It be good to print some msg like
>>     PMR is not supported...I'm printing the msg like Unsupported term, but
>>     it's not printed in the summary. It's just slightly different result
>> and
>>     it worries me a little.
>>
>> Okay. We can discuss this further in arch call.
>>
>
> I don't have correct decision on this yet.
> I hoped you have.
>

Yes. I have an idea about this. I thought of discussing this on arch call
would be better than in mail chain.

>
>
>>
>>              Short pretesting review farther below
>>
>>
>>
>>              On 12.08.15 11:53, 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.
>>
>>                  Fixes:
>>         https://bugs.linaro.org/show_bug.cgi?id=1542
>>         https://bugs.linaro.org/show_bug.cgi?id=1544
>>         https://bugs.linaro.org/show_bug.cgi?id=1545
>>         https://bugs.linaro.org/show_bug.cgi?id=1546
>>
>>                  Signed-off-by: Balasubramanian Manoharan <
>> bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org> <mailto:
>> bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org>>>
>>
>>
>>                  ---
>>                  v2: Incorporates review comments from Ivan and Christophe
>>
>>                     helper/include/odp/helper/tcp.h                    |
>>  4 +
>>                     test/validation/classification/Makefile.am         |
>>  2 +
>>                     test/validation/classification/classification.c    |
>>  5 +
>>                     .../classification/odp_classification_common.c     |
>> 225 ++++++++
>>                     .../classification/odp_classification_test_pmr.c   |
>> 640 +++++++++++++++++++++
>>                     .../classification/odp_classification_tests.c      |
>> 152 +----
>>                     .../classification/odp_classification_testsuites.h |
>> 10 +-
>>                     7 files changed, 906 insertions(+), 132 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
>>
>>
>>              What about to name it ODPH_MIN_TCPHDR_LEN.
>>
>>
>>         As you have mentioned in your next mail this, I have followed
>> existing ODP standard for naming convention.
>>
>>
>>     Don't forget to shorten the comment.
>>
>> Okay.
>>
>>
>>
>>
>>
>>
>>                     /** 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> <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..a88a301 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_suite_pmr,
>>                  +                       .pInitFunc =
>> classification_suite_pmr_init,
>>                  +                       .pCleanupFunc =
>> classification_suite_pmr_term,
>>                  +       },
>>
>>
>>              I'm not sure if "classificatio pmr tests" should be after
>> "classification tests"
>>              Maybe better to insert it before. Just in order of
>> complexity.
>>
>>
>>         Yes. I will move this in the next patch.
>>
>>
>>
>>                           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..fe392c0
>>                  --- /dev/null
>>                  +++
>> b/test/validation/classification/odp_classification_common.c
>>                  @@ -0,0 +1,225 @@
>>                  +/* 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 <
>> http://10.0.0.1/32> <http://10.0.0.1/32>"
>>                  +#define CLS_DEFAULT_DADDR      "10.0.0.100/32 <
>> http://10.0.0.100/32> <http://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 <
>> http://10.0.0.5/32> <http://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;
>>                  +
>>                  +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;
>>                  +}
>>                  +
>>                  +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
>>
>>
>>              On my opinion it should be complementary to
>> cls_pkt_set_seq(),
>>              with flag_udp or vise versa.
>>
>>
>>         It is a good point but actually I will have to read the UDP flag
>> from the packet if I have to send the flag into the cls_pkt_get_seq(pkt)
>> function but since we are sending the packet as input parameter to this
>> function I think it is better to check the same in the function itself.
>>
>>
>>     I thing it shouldn't depend on external usage of the function.
>>     Sorry, what decision?
>>
>>
>> I thought your suggestion was to add "flag_udp" as part of input
>> parameter to cls_pkt_get_seq(odp_packet_t pkt) function. IMO since we are
>> sending the packet into this function it would be redundant to send the
>> udp_flag information since this function can deduct the same from the
>> packet.
>>
>
> Suggestion was to use flag in both cases or don't use flag at all.
> In the tests you always know what kind of packet you are sending and
> receiving.
> So no problem with this.
> But on my opinion as you any way are going to parse TCP header to get TCP
> header length,
> be better to do the same for identifying of packet type, so no need in
> this flag in "get"
> function. Thus, no need in it in "set" function.
> The same can be done in cls_pkt_set_seq(), just read it from the packet.
> Can you read it from packet before sending, cannot?
>
> So, my proposition: don't path this flag at all.
> It's better to use the same method for retrieving information then
> different in
> similar king of functions. It's not speed-critical peace of code, so no
> need to worry about.
>

Okay. I understand your point, I will update this in the next patch.

>
> --
> Regards,
> Ivan Khoronzhuk
>

Regards,
Bala
Ivan Khoronzhuk Aug. 18, 2015, 5:09 p.m. UTC | #14
post test review.

I've tested. It works for me. (except UDP/TCP src, as it's not supported).
Why you didn't add here others PMR? Are you planing it after?
Also there is no some "inter-PMR" tests, like:
1 - create PMR_dudp-CoS1 (port X)
2 - create PMR_dtcp-CoS2 (same port X)
3 - send UDP packet with port X
4 - check if it was received with CoS1
5 - send TCP packet with same port X
6 - check if it was received with CoS2

Maybe it's not place for it, but it definitly should be added.
It can help to figure out issues when L4 layer cannot differ type of packet.
And implementor has to add some inter PMR to dispatch packet by type on L3 level.

Some additional comments below.

On 12.08.15 11:53, 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.
>
> Fixes:
> https://bugs.linaro.org/show_bug.cgi?id=1542
> https://bugs.linaro.org/show_bug.cgi?id=1544
> https://bugs.linaro.org/show_bug.cgi?id=1545
> https://bugs.linaro.org/show_bug.cgi?id=1546
>
> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>
> ---
> v2: Incorporates review comments from Ivan and Christophe
>
>   helper/include/odp/helper/tcp.h                    |   4 +
>   test/validation/classification/Makefile.am         |   2 +
>   test/validation/classification/classification.c    |   5 +
>   .../classification/odp_classification_common.c     | 225 ++++++++
>   .../classification/odp_classification_test_pmr.c   | 640 +++++++++++++++++++++
>   .../classification/odp_classification_tests.c      | 152 +----
>   .../classification/odp_classification_testsuites.h |  10 +-
>   7 files changed, 906 insertions(+), 132 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..a88a301 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_suite_pmr,
> +			.pInitFunc = classification_suite_pmr_init,
> +			.pCleanupFunc = classification_suite_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..fe392c0
> --- /dev/null
> +++ b/test/validation/classification/odp_classification_common.c
> @@ -0,0 +1,225 @@
> +/* 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;
> +
> +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;
> +}
> +
> +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
> +{
> +	uint32_t offset;
> +	cls_test_packet_t data;
> +	odph_ipv4hdr_t *ip;
> +
> +	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
> +	offset = odp_packet_l4_offset(pkt);
> +
> +	if (!offset && !ip)
> +		return TEST_SEQ_INVALID;
> +
> +	if (ip->proto == ODPH_IPPROTO_UDP)
> +		odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
> +					sizeof(data), &data);
> +	else
> +		odp_packet_copydata_out(pkt, offset + ODPH_TCPHDR_LEN,
> +					sizeof(data), &data);
> +
> +	if (data.magic == DATA_MAGIC)
> +		return data.seq;
> +
> +	return TEST_SEQ_INVALID;
> +}
> +
> +static inline
> +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask)

Seems it should be public function.
I believe it was your intention.
See below.

> +{
> +	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(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..df14bb5
> --- /dev/null
> +++ b/test/validation/classification/odp_classification_test_pmr.c
> @@ -0,0 +1,640 @@
> +/* 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)

This function is created in several files (common, this one and classification_tests).
Maybe it's time to make it common?
It's not used in this module, at least for now.
Delete it from odp_classification_tests.c also.

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

common? it's also in odp_classification_tests.c
But probably better delete it. It's not used in this module.
At least for now. And even you are going to use it, probably be
better to reuse enqueue_pktio_interface for this like:

static inline void enqueue_loop_interface()
{
	enqueue_pktio_interface(pkt, pktio_loop);
}

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

It might be, as in odp_classification_tests.c:
(I don't recomend)
	
if (!(CU_ASSERT(odp_queue_enq(defqueue, ev) == 0))) #### just cut from tests
	odp_packet_free(pkt);

But after check I see that doesn't. It's a potential bug.
So, if you are not going to make this function common, then
it be good to add patch that fixes same function in
odp_classification_tests.c, as packet there can be deleted twice.

> +}
> +
> +static inline
> +odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns)

what about to make this function common?

> +{
> +	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 int destroy_inq(odp_pktio_t pktio)

Seems is common with odp_classification_tests.c

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

Do we need it here? Why?

> +	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_suite_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_test_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;
> +	seq = 0;
> +
> +	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(pool_default, false, false);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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(pool_default, false, false);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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);
> +	odp_cos_destroy(cos);
> +	odp_pmr_destroy(pmr);
> +	destroy_inq(pktio);
> +	odp_queue_destroy(queue);
> +	odp_pktio_close(pktio);
> +}
> +
> +static void classification_test_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;
> +	seq = 0;
> +
> +	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(pool_default, false, false);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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(pool_default, false, false);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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);
> +	odp_cos_destroy(cos);
> +	odp_pmr_destroy(pmr);
> +	destroy_inq(pktio);
> +	odp_queue_destroy(queue);
> +	odp_pktio_close(pktio);
> +}
> +
> +static void classification_test_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;
> +	seq = 0;
> +
> +	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, "udp_dport");
> +	cos = odp_cos_create(cosname);
> +	CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
> +
> +	sprintf(queuename, "%s", "udp_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(pool_default, false, true);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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(pool_default, false, true);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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);
> +	odp_cos_destroy(cos);
> +	odp_pmr_destroy(pmr);
> +	destroy_inq(pktio);
> +	odp_queue_destroy(queue);
> +	odp_pktio_close(pktio);
> +}
> +
> +static void classification_test_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;
> +	seq = 0;
> +
> +	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(pool_default, false, true);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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(pool_default, false, true);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);

TEST_SEQ_INVALID check, why are you doing it here?
If it's needed then why it's not done a little above and in functions:
classification_test_pmr_term_udp_dport();
classification_test_pmr_term_tcp_sport();
classification_test_pmr_term_tcp_dport();


> +	CU_ASSERT(seq == cls_pkt_get_seq(pkt));
> +	CU_ASSERT(retqueue == defqueue);
> +	odp_packet_free(pkt);
> +
> +	odp_cos_destroy(cos);
> +	odp_pmr_destroy(pmr);
> +	destroy_inq(pktio);
> +	odp_queue_destroy(queue);
> +	odp_pktio_close(pktio);
> +}
> +
> +static void classification_test_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;
> +	seq = 0;
> +
> +	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(pool_default, false, true);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	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(pool_default, false, false);
> +	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
> +	enqueue_pktio_interface(pkt, pktio);
> +
> +	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
> +	CU_ASSERT(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);

redundancy like above?

> +	CU_ASSERT(seq == cls_pkt_get_seq(pkt));
> +	CU_ASSERT(retqueue == defqueue);
> +
> +	odp_cos_destroy(cos);
> +	odp_pmr_destroy(pmr);
> +	odp_packet_free(pkt);
> +	destroy_inq(pktio);
> +	odp_queue_destroy(queue);
> +	odp_pktio_close(pktio);
> +}
> +
> +CU_TestInfo classification_suite_pmr[] = {
> +	_CU_TEST_INFO(classification_test_pmr_term_tcp_dport),
> +	_CU_TEST_INFO(classification_test_pmr_term_tcp_sport),
> +	_CU_TEST_INFO(classification_test_pmr_term_udp_dport),
> +	_CU_TEST_INFO(classification_test_pmr_term_udp_sport),
> +	_CU_TEST_INFO(classification_test_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..e2232a1 100644
> --- a/test/validation/classification/odp_classification_tests.c
> +++ b/test/validation/classification/odp_classification_tests.c
> @@ -122,42 +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;
> -	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;
> @@ -184,89 +148,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)
>   {
> @@ -440,10 +321,12 @@ void test_cls_pmr_chain(void)
>   	odp_queue_t queue;
>   	uint32_t addr = 0;
>   	uint32_t mask;
> -	uint32_t seq;
> +	uint32_t seq = 0;
>
> -	pkt = create_packet(false);
> +	pkt = create_packet(pool_default, false, true);
>   	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
>   	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>   	parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
>   	ip->src_addr = odp_cpu_to_be_32(addr);
> @@ -460,8 +343,10 @@ 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(pool_default, false, true);
>   	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
>   	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>   	parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
>   	ip->src_addr = odp_cpu_to_be_32(addr);
> @@ -506,10 +391,12 @@ void test_pktio_default_cos(void)
>   {
>   	odp_packet_t pkt;
>   	odp_queue_t queue;
> -	uint32_t seq;
> +	uint32_t seq = 0;
>   	/* create a default packet */
> -	pkt = create_packet(false);
> +	pkt = create_packet(pool_default, false, true);
>   	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
> +
>   	enqueue_loop_interface(pkt);
>
>   	pkt = receive_packet(&queue, ODP_TIME_SEC);
> @@ -554,7 +441,7 @@ void test_pktio_error_cos(void)
>   	odp_packet_t pkt;
>
>   	/*Create an error packet */
> -	pkt = create_packet(false);
> +	pkt = create_packet(pool_default, false, true);
>   	odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>
>   	/* Incorrect IpV4 version */
> @@ -644,12 +531,13 @@ void test_cos_with_l2_priority(void)
>   	odph_ethhdr_t *ethhdr;
>   	odph_vlanhdr_t *vlan;
>   	odp_queue_t queue;
> -	uint32_t seq;
> +	uint32_t seq = 0;
>
>   	uint8_t i;
>   	for (i = 0; i < CLS_L2_QOS_MAX; i++) {
> -		pkt = create_packet(true);
> +		pkt = create_packet(pool_default, true, true);
>   		seq = cls_pkt_get_seq(pkt);
> +		CU_ASSERT(seq != TEST_SEQ_INVALID);
>   		ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
>   		vlan = (odph_vlanhdr_t *)(&ethhdr->type);
>   		vlan->tci = odp_cpu_to_be_16(i << 13);
> @@ -704,10 +592,11 @@ void test_pmr_cos(void)
>   	odp_packet_t pkt;
>   	odph_udphdr_t *udp;
>   	odp_queue_t queue;
> -	uint32_t seq;
> +	uint32_t seq = 0;
>
> -	pkt = create_packet(false);
> +	pkt = create_packet(pool_default, false, true);
>   	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
>   	udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
>   	udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT);
>   	enqueue_loop_interface(pkt);
> @@ -778,10 +667,11 @@ void test_pktio_pmr_match_set_cos(void)
>   	odph_udphdr_t *udp;
>   	odp_packet_t pkt;
>   	odp_queue_t queue;
> -	uint32_t seq;
> +	uint32_t seq = 0;
>
> -	pkt = create_packet(false);
> +	pkt = create_packet(pool_default, false, true);
>   	seq = cls_pkt_get_seq(pkt);
> +	CU_ASSERT(seq != TEST_SEQ_INVALID);
>   	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>   	parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask);
>   	ip->src_addr = odp_cpu_to_be_32(addr);
> diff --git a/test/validation/classification/odp_classification_testsuites.h b/test/validation/classification/odp_classification_testsuites.h
> index f603f30..293729e 100644
> --- a/test/validation/classification/odp_classification_testsuites.h
> +++ b/test/validation/classification/odp_classification_testsuites.h
> @@ -16,11 +16,19 @@
>
>   extern CU_TestInfo classification_suite[];
>   extern CU_TestInfo classification_suite_basic[];
> +extern CU_TestInfo classification_suite_pmr[];
>
>   int classification_suite_init(void);
>   int classification_suite_term(void);
>
> -odp_packet_t create_packet(bool vlan);
> +int classification_suite_pmr_term(void);
> +int classification_suite_pmr_init(void);
> +
> +odp_packet_t create_packet(odp_pool_t pool, bool vlan, bool udp);
> +int cls_pkt_set_seq(odp_packet_t pkt, bool flag_udp);
> +uint32_t cls_pkt_get_seq(odp_packet_t pkt);
> +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);
>
Balasubramanian Manoharan Aug. 19, 2015, 5:45 a.m. UTC | #15
Ivan,

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

> post test review.
>
> I've tested. It works for me. (except UDP/TCP src, as it's not supported).
> Why you didn't add here others PMR? Are you planing it after?
> Also there is no some "inter-PMR" tests, like:
> 1 - create PMR_dudp-CoS1 (port X)
> 2 - create PMR_dtcp-CoS2 (same port X)
> 3 - send UDP packet with port X
> 4 - check if it was received with CoS1
> 5 - send TCP packet with same port X
> 6 - check if it was received with CoS2
>
> Maybe it's not place for it, but it definitly should be added.
> It can help to figure out issues when L4 layer cannot differ type of
> packet.
> And implementor has to add some inter PMR to dispatch packet by type on L3
> level.
>
> Yes. I am planning to add more complex Test Cases in a separate suite. So
that the user can first test whether the basic functionality is working
fine.
This current patch contains the basic test suite suite which tests the
basic functionality of all the APIs.

Some additional comments below.
>
> On 12.08.15 11:53, 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.
>>
>> Fixes:
>> https://bugs.linaro.org/show_bug.cgi?id=1542
>> https://bugs.linaro.org/show_bug.cgi?id=1544
>> https://bugs.linaro.org/show_bug.cgi?id=1545
>> https://bugs.linaro.org/show_bug.cgi?id=1546
>>
>> Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org>
>> ---
>> v2: Incorporates review comments from Ivan and Christophe
>>
>>   helper/include/odp/helper/tcp.h                    |   4 +
>>   test/validation/classification/Makefile.am         |   2 +
>>   test/validation/classification/classification.c    |   5 +
>>   .../classification/odp_classification_common.c     | 225 ++++++++
>>   .../classification/odp_classification_test_pmr.c   | 640
>> +++++++++++++++++++++
>>   .../classification/odp_classification_tests.c      | 152 +----
>>   .../classification/odp_classification_testsuites.h |  10 +-
>>   7 files changed, 906 insertions(+), 132 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..a88a301 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_suite_pmr,
>> +                       .pInitFunc = classification_suite_pmr_init,
>> +                       .pCleanupFunc = classification_suite_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..fe392c0
>> --- /dev/null
>> +++ b/test/validation/classification/odp_classification_common.c
>> @@ -0,0 +1,225 @@
>> +/* 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;
>> +
>> +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;
>> +}
>> +
>> +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
>> +{
>> +       uint32_t offset;
>> +       cls_test_packet_t data;
>> +       odph_ipv4hdr_t *ip;
>> +
>> +       ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>> +       offset = odp_packet_l4_offset(pkt);
>> +
>> +       if (!offset && !ip)
>> +               return TEST_SEQ_INVALID;
>> +
>> +       if (ip->proto == ODPH_IPPROTO_UDP)
>> +               odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
>> +                                       sizeof(data), &data);
>> +       else
>> +               odp_packet_copydata_out(pkt, offset + ODPH_TCPHDR_LEN,
>> +                                       sizeof(data), &data);
>> +
>> +       if (data.magic == DATA_MAGIC)
>> +               return data.seq;
>> +
>> +       return TEST_SEQ_INVALID;
>> +}
>> +
>> +static inline
>> +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t
>> *mask)
>>
>
> Seems it should be public function.
> I believe it was your intention.
> See below.


Yes. This can be moved into common file.

>
>
> +{
>> +       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(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..df14bb5
>> --- /dev/null
>> +++ b/test/validation/classification/odp_classification_test_pmr.c
>> @@ -0,0 +1,640 @@
>> +/* 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)
>>
>
> This function is created in several files (common, this one and
> classification_tests).
> Maybe it's time to make it common?
> It's not used in this module, at least for now.
> Delete it from odp_classification_tests.c also.


Okay.

>


>
> +{
>> +       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)
>>
>
> common? it's also in odp_classification_tests.c
> But probably better delete it. It's not used in this module.
> At least for now. And even you are going to use it, probably be
> better to reuse enqueue_pktio_interface for this like:
>
> static inline void enqueue_loop_interface()
> {
>         enqueue_pktio_interface(pkt, pktio_loop);
> }
>
> +{
>> +       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);
>>
>
> It might be, as in odp_classification_tests.c:
> (I don't recomend)
>
> if (!(CU_ASSERT(odp_queue_enq(defqueue, ev) == 0))) #### just cut from
> tests
>         odp_packet_free(pkt);
>

In validation suite usually the cleanup is not done during failure case and
if the enqueue fails for some reason the validation suite will return an
error and the user will have to correct the error case and memory leak
during failure test case was not a big deal.
But as you said since it will cause a leak I will cleanup the buffer during
failure scenario also.

>
> But after check I see that doesn't. It's a potential bug.
> So, if you are not going to make this function common, then
> it be good to add patch that fixes same function in
> odp_classification_tests.c, as packet there can be deleted twice.
>
> +}
>> +
>> +static inline
>> +odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns)
>>
>
> what about to make this function common?


Yes. It can be moved to common file.

>
>
> +{
>> +       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 int destroy_inq(odp_pktio_t pktio)
>>
>
> Seems is common with odp_classification_tests.c


Okay.

>
>
> +{
>> +       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_suite_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");
>>
>
> Do we need it here? Why?


Okay. I will optimise this in the next update.

>
>
> +       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_suite_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_test_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;
>> +       seq = 0;
>> +
>> +       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(pool_default, false, false);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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(pool_default, false, false);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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);
>> +       odp_cos_destroy(cos);
>> +       odp_pmr_destroy(pmr);
>> +       destroy_inq(pktio);
>> +       odp_queue_destroy(queue);
>> +       odp_pktio_close(pktio);
>> +}
>> +
>> +static void classification_test_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;
>> +       seq = 0;
>> +
>> +       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(pool_default, false, false);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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(pool_default, false, false);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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);
>> +       odp_cos_destroy(cos);
>> +       odp_pmr_destroy(pmr);
>> +       destroy_inq(pktio);
>> +       odp_queue_destroy(queue);
>> +       odp_pktio_close(pktio);
>> +}
>> +
>> +static void classification_test_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;
>> +       seq = 0;
>> +
>> +       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, "udp_dport");
>> +       cos = odp_cos_create(cosname);
>> +       CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
>> +
>> +       sprintf(queuename, "%s", "udp_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(pool_default, false, true);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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(pool_default, false, true);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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);
>> +       odp_cos_destroy(cos);
>> +       odp_pmr_destroy(pmr);
>> +       destroy_inq(pktio);
>> +       odp_queue_destroy(queue);
>> +       odp_pktio_close(pktio);
>> +}
>> +
>> +static void classification_test_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;
>> +       seq = 0;
>> +
>> +       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(pool_default, false, true);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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(pool_default, false, true);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);
>>
>
> TEST_SEQ_INVALID check, why are you doing it here?
> If it's needed then why it's not done a little above and in functions:
> classification_test_pmr_term_udp_dport();
> classification_test_pmr_term_tcp_sport();
> classification_test_pmr_term_tcp_dport();


No. This is not needed here. Looks like I forgot to remove this CU_ASSERT.

>
>
>
> +       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
>> +       CU_ASSERT(retqueue == defqueue);
>> +       odp_packet_free(pkt);
>> +
>> +       odp_cos_destroy(cos);
>> +       odp_pmr_destroy(pmr);
>> +       destroy_inq(pktio);
>> +       odp_queue_destroy(queue);
>> +       odp_pktio_close(pktio);
>> +}
>> +
>> +static void classification_test_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;
>> +       seq = 0;
>> +
>> +       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(pool_default, false, true);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       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(pool_default, false, false);
>> +       seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>> +       enqueue_pktio_interface(pkt, pktio);
>> +
>> +       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>> +       CU_ASSERT(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);
>>
>
> redundancy like above?
>
>
> +       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
>> +       CU_ASSERT(retqueue == defqueue);
>> +
>> +       odp_cos_destroy(cos);
>> +       odp_pmr_destroy(pmr);
>> +       odp_packet_free(pkt);
>> +       destroy_inq(pktio);
>> +       odp_queue_destroy(queue);
>> +       odp_pktio_close(pktio);
>> +}
>> +
>> +CU_TestInfo classification_suite_pmr[] = {
>> +       _CU_TEST_INFO(classification_test_pmr_term_tcp_dport),
>> +       _CU_TEST_INFO(classification_test_pmr_term_tcp_sport),
>> +       _CU_TEST_INFO(classification_test_pmr_term_udp_dport),
>> +       _CU_TEST_INFO(classification_test_pmr_term_udp_sport),
>> +       _CU_TEST_INFO(classification_test_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..e2232a1 100644
>> --- a/test/validation/classification/odp_classification_tests.c
>> +++ b/test/validation/classification/odp_classification_tests.c
>> @@ -122,42 +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;
>> -       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;
>> @@ -184,89 +148,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)
>>   {
>> @@ -440,10 +321,12 @@ void test_cls_pmr_chain(void)
>>         odp_queue_t queue;
>>         uint32_t addr = 0;
>>         uint32_t mask;
>> -       uint32_t seq;
>> +       uint32_t seq = 0;
>>
>> -       pkt = create_packet(false);
>> +       pkt = create_packet(pool_default, false, true);
>>         seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>>         ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>>         parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
>>         ip->src_addr = odp_cpu_to_be_32(addr);
>> @@ -460,8 +343,10 @@ 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(pool_default, false, true);
>>         seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>>         ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>>         parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
>>         ip->src_addr = odp_cpu_to_be_32(addr);
>> @@ -506,10 +391,12 @@ void test_pktio_default_cos(void)
>>   {
>>         odp_packet_t pkt;
>>         odp_queue_t queue;
>> -       uint32_t seq;
>> +       uint32_t seq = 0;
>>         /* create a default packet */
>> -       pkt = create_packet(false);
>> +       pkt = create_packet(pool_default, false, true);
>>         seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>> +
>>         enqueue_loop_interface(pkt);
>>
>>         pkt = receive_packet(&queue, ODP_TIME_SEC);
>> @@ -554,7 +441,7 @@ void test_pktio_error_cos(void)
>>         odp_packet_t pkt;
>>
>>         /*Create an error packet */
>> -       pkt = create_packet(false);
>> +       pkt = create_packet(pool_default, false, true);
>>         odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt,
>> NULL);
>>
>>         /* Incorrect IpV4 version */
>> @@ -644,12 +531,13 @@ void test_cos_with_l2_priority(void)
>>         odph_ethhdr_t *ethhdr;
>>         odph_vlanhdr_t *vlan;
>>         odp_queue_t queue;
>> -       uint32_t seq;
>> +       uint32_t seq = 0;
>>
>>         uint8_t i;
>>         for (i = 0; i < CLS_L2_QOS_MAX; i++) {
>> -               pkt = create_packet(true);
>> +               pkt = create_packet(pool_default, true, true);
>>                 seq = cls_pkt_get_seq(pkt);
>> +               CU_ASSERT(seq != TEST_SEQ_INVALID);
>>                 ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
>>                 vlan = (odph_vlanhdr_t *)(&ethhdr->type);
>>                 vlan->tci = odp_cpu_to_be_16(i << 13);
>> @@ -704,10 +592,11 @@ void test_pmr_cos(void)
>>         odp_packet_t pkt;
>>         odph_udphdr_t *udp;
>>         odp_queue_t queue;
>> -       uint32_t seq;
>> +       uint32_t seq = 0;
>>
>> -       pkt = create_packet(false);
>> +       pkt = create_packet(pool_default, false, true);
>>         seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
>>         udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT);
>>         enqueue_loop_interface(pkt);
>> @@ -778,10 +667,11 @@ void test_pktio_pmr_match_set_cos(void)
>>         odph_udphdr_t *udp;
>>         odp_packet_t pkt;
>>         odp_queue_t queue;
>> -       uint32_t seq;
>> +       uint32_t seq = 0;
>>
>> -       pkt = create_packet(false);
>> +       pkt = create_packet(pool_default, false, true);
>>         seq = cls_pkt_get_seq(pkt);
>> +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>>         parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask);
>>         ip->src_addr = odp_cpu_to_be_32(addr);
>> diff --git
>> a/test/validation/classification/odp_classification_testsuites.h
>> b/test/validation/classification/odp_classification_testsuites.h
>> index f603f30..293729e 100644
>> --- a/test/validation/classification/odp_classification_testsuites.h
>> +++ b/test/validation/classification/odp_classification_testsuites.h
>> @@ -16,11 +16,19 @@
>>
>>   extern CU_TestInfo classification_suite[];
>>   extern CU_TestInfo classification_suite_basic[];
>> +extern CU_TestInfo classification_suite_pmr[];
>>
>>   int classification_suite_init(void);
>>   int classification_suite_term(void);
>>
>> -odp_packet_t create_packet(bool vlan);
>> +int classification_suite_pmr_term(void);
>> +int classification_suite_pmr_init(void);
>> +
>> +odp_packet_t create_packet(odp_pool_t pool, bool vlan, bool udp);
>> +int cls_pkt_set_seq(odp_packet_t pkt, bool flag_udp);
>> +uint32_t cls_pkt_get_seq(odp_packet_t pkt);
>> +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);
>>
>>
> --
> Regards,
> Ivan Khoronzhuk
>

Regards,
Bala
Ivan Khoronzhuk Aug. 19, 2015, 9:32 a.m. UTC | #16
Hi Bala,

just several comments I forgot to mention.

On 19.08.15 08:45, Bala Manoharan wrote:
> Ivan,
>
> On 18 August 2015 at 22:39, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>
>     post test review.
>
>     I've tested. It works for me. (except UDP/TCP src, as it's not supported).
>     Why you didn't add here others PMR? Are you planing it after?
>     Also there is no some "inter-PMR" tests, like:
>     1 - create PMR_dudp-CoS1 (port X)
>     2 - create PMR_dtcp-CoS2 (same port X)
>     3 - send UDP packet with port X
>     4 - check if it was received with CoS1
>     5 - send TCP packet with same port X
>     6 - check if it was received with CoS2
>
>     Maybe it's not place for it, but it definitly should be added.
>     It can help to figure out issues when L4 layer cannot differ type of packet.
>     And implementor has to add some inter PMR to dispatch packet by type on L3 level.
>
> Yes. I am planning to add more complex Test Cases in a separate suite. So that the user can first test whether the basic functionality is working fine.
> This current patch contains the basic test suite suite which tests the basic functionality of all the APIs.
>
>     Some additional comments below.
>
>     On 12.08.15 11:53, 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.
>
>         Fixes:
>         https://bugs.linaro.org/show_bug.cgi?id=1542
>         https://bugs.linaro.org/show_bug.cgi?id=1544
>         https://bugs.linaro.org/show_bug.cgi?id=1545
>         https://bugs.linaro.org/show_bug.cgi?id=1546
>
>         Signed-off-by: Balasubramanian Manoharan <bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org>>
>         ---
>         v2: Incorporates review comments from Ivan and Christophe
>
>            helper/include/odp/helper/tcp.h                    |   4 +
>            test/validation/classification/Makefile.am         |   2 +
>            test/validation/classification/classification.c    |   5 +
>            .../classification/odp_classification_common.c     | 225 ++++++++
>            .../classification/odp_classification_test_pmr.c   | 640 +++++++++++++++++++++
>            .../classification/odp_classification_tests.c      | 152 +----
>            .../classification/odp_classification_testsuites.h |  10 +-
>            7 files changed, 906 insertions(+), 132 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..a88a301 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_suite_pmr,
>         +                       .pInitFunc = classification_suite_pmr_init,
>         +                       .pCleanupFunc = classification_suite_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..fe392c0
>         --- /dev/null
>         +++ b/test/validation/classification/odp_classification_common.c
>         @@ -0,0 +1,225 @@
>         +/* 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 <http://10.0.0.1/32>"
>         +#define CLS_DEFAULT_DADDR      "10.0.0.100/32 <http://10.0.0.100/32>"
>         +#define CLS_DEFAULT_SPORT      1024
>         +#define CLS_DEFAULT_DPORT      2048
>         +
>         +#define CLS_TEST_SPORT         4096
>         +#define CLS_TEST_DPORT         8192
>         +#define CLS_TEST_DADDR         "10.0.0.5/32 <http://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;

Why be?

>         +} cls_test_packet_t;
>         +
>         +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;
>         +}
>         +
>         +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
>         +{
>         +       uint32_t offset;
>         +       cls_test_packet_t data;
>         +       odph_ipv4hdr_t *ip;
>         +
>         +       ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>         +       offset = odp_packet_l4_offset(pkt);
>         +
>         +       if (!offset && !ip)
>         +               return TEST_SEQ_INVALID;
>         +
>         +       if (ip->proto == ODPH_IPPROTO_UDP)
>         +               odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
>         +                                       sizeof(data), &data);
>         +       else
>         +               odp_packet_copydata_out(pkt, offset + ODPH_TCPHDR_LEN,
>         +                                       sizeof(data), &data);
>         +
>         +       if (data.magic == DATA_MAGIC)
>         +               return data.seq;
>         +
>         +       return TEST_SEQ_INVALID;
>         +}
>         +
>         +static inline
>         +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask)
>
>
>     Seems it should be public function.
>     I believe it was your intention.
>     See below.
>
>
> Yes. This can be moved into common file.
>
>
>
>         +{
>         +       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(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..df14bb5
>         --- /dev/null
>         +++ b/test/validation/classification/odp_classification_test_pmr.c
>         @@ -0,0 +1,640 @@
>         +/* 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 <http://10.0.0.1/32>"
>         +#define CLS_DEFAULT_DADDR      "10.0.0.100/32 <http://10.0.0.100/32>"
>         +#define CLS_DEFAULT_SPORT      1024
>         +#define CLS_DEFAULT_DPORT      2048
>         +
>         +#define CLS_TEST_SPORT         4096
>         +#define CLS_TEST_DPORT         8192
>         +#define CLS_TEST_DADDR         "10.0.0.5/32 <http://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;

no need in it here
Same for odp_classification_tests.c
It's currently in common file.

>         +
>         +typedef struct cls_test_packet {
>         +       uint32be_t magic;
>         +       uint32be_t seq;
>         +} cls_test_packet_t;

no need in it here any more.
Same for odp_classification_tests.c

>         +
>         +static inline
>         +int parse_ipv4_string(const char *ipaddress, uint32_t *addr, uint32_t *mask)
>
>
>     This function is created in several files (common, this one and classification_tests).
>     Maybe it's time to make it common?
>     It's not used in this module, at least for now.
>     Delete it from odp_classification_tests.c also.
>
>
> Okay.
>
>
>
>         +{
>         +       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)
>
>
>     common? it's also in odp_classification_tests.c
>     But probably better delete it. It's not used in this module.
>     At least for now. And even you are going to use it, probably be
>     better to reuse enqueue_pktio_interface for this like:
>
>     static inline void enqueue_loop_interface()
>     {
>              enqueue_pktio_interface(pkt, pktio_loop);
>     }
>
>         +{
>         +       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);
>
>
>     It might be, as in odp_classification_tests.c:
>     (I don't recomend)
>
>     if (!(CU_ASSERT(odp_queue_enq(defqueue, ev) == 0))) #### just cut from tests
>              odp_packet_free(pkt);
>
>
> In validation suite usually the cleanup is not done during failure case and if the enqueue fails for some reason the validation suite will return an error and the user will have to correct the error case and memory leak during failure test case was not a big deal.
> But as you said since it will cause a leak I will cleanup the buffer during failure scenario also.
>
>
>     But after check I see that doesn't. It's a potential bug.
>     So, if you are not going to make this function common, then
>     it be good to add patch that fixes same function in
>     odp_classification_tests.c, as packet there can be deleted twice.
>
>         +}
>         +
>         +static inline
>         +odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns)
>
>
>     what about to make this function common?
>
>
> Yes. It can be moved to common file.
>
>
>
>         +{
>         +       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 int destroy_inq(odp_pktio_t pktio)
>
>
>     Seems is common with odp_classification_tests.c
>
>
> Okay.
>
>
>
>         +{
>         +       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_suite_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");
>
>
>     Do we need it here? Why?
>
>
> Okay. I will optimise this in the next update.
>
>
>
>         +       if (pool_default == ODP_POOL_INVALID)
>         +               return -1;
>         +
>         +       odp_atomic_init_u32(&seq, 0);

no need in it here any more.
Same for odp_classification_tests.c

>         +       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_suite_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_test_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;
>         +       seq = 0;
>         +
>         +       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(pool_default, false, false);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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(pool_default, false, false);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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);
>         +       odp_cos_destroy(cos);
>         +       odp_pmr_destroy(pmr);
>         +       destroy_inq(pktio);
>         +       odp_queue_destroy(queue);
>         +       odp_pktio_close(pktio);
>         +}
>         +
>         +static void classification_test_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;
>         +       seq = 0;
>         +
>         +       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(pool_default, false, false);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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(pool_default, false, false);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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);
>         +       odp_cos_destroy(cos);
>         +       odp_pmr_destroy(pmr);
>         +       destroy_inq(pktio);
>         +       odp_queue_destroy(queue);
>         +       odp_pktio_close(pktio);
>         +}
>         +
>         +static void classification_test_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;
>         +       seq = 0;
>         +
>         +       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, "udp_dport");
>         +       cos = odp_cos_create(cosname);
>         +       CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
>         +
>         +       sprintf(queuename, "%s", "udp_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(pool_default, false, true);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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(pool_default, false, true);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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);
>         +       odp_cos_destroy(cos);
>         +       odp_pmr_destroy(pmr);
>         +       destroy_inq(pktio);
>         +       odp_queue_destroy(queue);
>         +       odp_pktio_close(pktio);
>         +}
>         +
>         +static void classification_test_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;
>         +       seq = 0;
>         +
>         +       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(pool_default, false, true);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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(pool_default, false, true);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);
>
>
>     TEST_SEQ_INVALID check, why are you doing it here?
>     If it's needed then why it's not done a little above and in functions:
>     classification_test_pmr_term_udp_dport();
>     classification_test_pmr_term_tcp_sport();
>     classification_test_pmr_term_tcp_dport();
>
>
> No. This is not needed here. Looks like I forgot to remove this CU_ASSERT.
>
>
>
>
>         +       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
>         +       CU_ASSERT(retqueue == defqueue);
>         +       odp_packet_free(pkt);
>         +
>         +       odp_cos_destroy(cos);
>         +       odp_pmr_destroy(pmr);
>         +       destroy_inq(pktio);
>         +       odp_queue_destroy(queue);
>         +       odp_pktio_close(pktio);
>         +}
>         +
>         +static void classification_test_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;
>         +       seq = 0;
>         +
>         +       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(pool_default, false, true);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       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(pool_default, false, false);
>         +       seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>         +       enqueue_pktio_interface(pkt, pktio);
>         +
>         +       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>         +       CU_ASSERT(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);
>
>
>     redundancy like above?
>
>
>         +       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
>         +       CU_ASSERT(retqueue == defqueue);
>         +
>         +       odp_cos_destroy(cos);
>         +       odp_pmr_destroy(pmr);
>         +       odp_packet_free(pkt);
>         +       destroy_inq(pktio);
>         +       odp_queue_destroy(queue);
>         +       odp_pktio_close(pktio);
>         +}
>         +
>         +CU_TestInfo classification_suite_pmr[] = {
>         +       _CU_TEST_INFO(classification_test_pmr_term_tcp_dport),
>         +       _CU_TEST_INFO(classification_test_pmr_term_tcp_sport),
>         +       _CU_TEST_INFO(classification_test_pmr_term_udp_dport),
>         +       _CU_TEST_INFO(classification_test_pmr_term_udp_sport),
>         +       _CU_TEST_INFO(classification_test_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..e2232a1 100644
>         --- a/test/validation/classification/odp_classification_tests.c
>         +++ b/test/validation/classification/odp_classification_tests.c
>         @@ -122,42 +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;
>         -       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;
>         @@ -184,89 +148,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)
>            {
>         @@ -440,10 +321,12 @@ void test_cls_pmr_chain(void)
>                  odp_queue_t queue;
>                  uint32_t addr = 0;
>                  uint32_t mask;
>         -       uint32_t seq;
>         +       uint32_t seq = 0;
>
>         -       pkt = create_packet(false);
>         +       pkt = create_packet(pool_default, false, true);
>                  seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>                  ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>                  parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
>                  ip->src_addr = odp_cpu_to_be_32(addr);
>         @@ -460,8 +343,10 @@ 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(pool_default, false, true);
>                  seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>                  ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>                  parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
>                  ip->src_addr = odp_cpu_to_be_32(addr);
>         @@ -506,10 +391,12 @@ void test_pktio_default_cos(void)
>            {
>                  odp_packet_t pkt;
>                  odp_queue_t queue;
>         -       uint32_t seq;
>         +       uint32_t seq = 0;
>                  /* create a default packet */
>         -       pkt = create_packet(false);
>         +       pkt = create_packet(pool_default, false, true);
>                  seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>         +
>                  enqueue_loop_interface(pkt);
>
>                  pkt = receive_packet(&queue, ODP_TIME_SEC);
>         @@ -554,7 +441,7 @@ void test_pktio_error_cos(void)
>                  odp_packet_t pkt;
>
>                  /*Create an error packet */
>         -       pkt = create_packet(false);
>         +       pkt = create_packet(pool_default, false, true);
>                  odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>
>                  /* Incorrect IpV4 version */
>         @@ -644,12 +531,13 @@ void test_cos_with_l2_priority(void)
>                  odph_ethhdr_t *ethhdr;
>                  odph_vlanhdr_t *vlan;
>                  odp_queue_t queue;
>         -       uint32_t seq;
>         +       uint32_t seq = 0;
>
>                  uint8_t i;
>                  for (i = 0; i < CLS_L2_QOS_MAX; i++) {
>         -               pkt = create_packet(true);
>         +               pkt = create_packet(pool_default, true, true);
>                          seq = cls_pkt_get_seq(pkt);
>         +               CU_ASSERT(seq != TEST_SEQ_INVALID);
>                          ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
>                          vlan = (odph_vlanhdr_t *)(&ethhdr->type);
>                          vlan->tci = odp_cpu_to_be_16(i << 13);
>         @@ -704,10 +592,11 @@ void test_pmr_cos(void)
>                  odp_packet_t pkt;
>                  odph_udphdr_t *udp;
>                  odp_queue_t queue;
>         -       uint32_t seq;
>         +       uint32_t seq = 0;
>
>         -       pkt = create_packet(false);
>         +       pkt = create_packet(pool_default, false, true);
>                  seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>                  udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
>                  udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT);
>                  enqueue_loop_interface(pkt);
>         @@ -778,10 +667,11 @@ void test_pktio_pmr_match_set_cos(void)
>                  odph_udphdr_t *udp;
>                  odp_packet_t pkt;
>                  odp_queue_t queue;
>         -       uint32_t seq;
>         +       uint32_t seq = 0;
>
>         -       pkt = create_packet(false);
>         +       pkt = create_packet(pool_default, false, true);
>                  seq = cls_pkt_get_seq(pkt);
>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>                  ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>                  parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask);
>                  ip->src_addr = odp_cpu_to_be_32(addr);
>         diff --git a/test/validation/classification/odp_classification_testsuites.h b/test/validation/classification/odp_classification_testsuites.h
>         index f603f30..293729e 100644
>         --- a/test/validation/classification/odp_classification_testsuites.h
>         +++ b/test/validation/classification/odp_classification_testsuites.h
>         @@ -16,11 +16,19 @@
>
>            extern CU_TestInfo classification_suite[];
>            extern CU_TestInfo classification_suite_basic[];
>         +extern CU_TestInfo classification_suite_pmr[];
>
>            int classification_suite_init(void);
>            int classification_suite_term(void);
>
>         -odp_packet_t create_packet(bool vlan);
>         +int classification_suite_pmr_term(void);
>         +int classification_suite_pmr_init(void);
>         +
>         +odp_packet_t create_packet(odp_pool_t pool, bool vlan, bool udp);
>         +int cls_pkt_set_seq(odp_packet_t pkt, bool flag_udp);
>         +uint32_t cls_pkt_get_seq(odp_packet_t pkt);
>         +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);
>
>
>     --
>     Regards,
>     Ivan Khoronzhuk
>
>
> Regards,
> Bala
>
Balasubramanian Manoharan Aug. 19, 2015, 1:52 p.m. UTC | #17
Hi Ivan,

On 19 August 2015 at 15:02, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org>
wrote:

> Hi Bala,
>
> just several comments I forgot to mention.
>
> On 19.08.15 08:45, Bala Manoharan wrote:
>
>> Ivan,
>>
>> On 18 August 2015 at 22:39, Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org
>> <mailto:ivan.khoronzhuk@linaro.org>> wrote:
>>
>>     post test review.
>>
>>     I've tested. It works for me. (except UDP/TCP src, as it's not
>> supported).
>>     Why you didn't add here others PMR? Are you planing it after?
>>     Also there is no some "inter-PMR" tests, like:
>>     1 - create PMR_dudp-CoS1 (port X)
>>     2 - create PMR_dtcp-CoS2 (same port X)
>>     3 - send UDP packet with port X
>>     4 - check if it was received with CoS1
>>     5 - send TCP packet with same port X
>>     6 - check if it was received with CoS2
>>
>>     Maybe it's not place for it, but it definitly should be added.
>>     It can help to figure out issues when L4 layer cannot differ type of
>> packet.
>>     And implementor has to add some inter PMR to dispatch packet by type
>> on L3 level.
>>
>> Yes. I am planning to add more complex Test Cases in a separate suite. So
>> that the user can first test whether the basic functionality is working
>> fine.
>> This current patch contains the basic test suite suite which tests the
>> basic functionality of all the APIs.
>>
>>     Some additional comments below.
>>
>>     On 12.08.15 11:53, 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.
>>
>>         Fixes:
>>         https://bugs.linaro.org/show_bug.cgi?id=1542
>>         https://bugs.linaro.org/show_bug.cgi?id=1544
>>         https://bugs.linaro.org/show_bug.cgi?id=1545
>>         https://bugs.linaro.org/show_bug.cgi?id=1546
>>
>>         Signed-off-by: Balasubramanian Manoharan <
>> bala.manoharan@linaro.org <mailto:bala.manoharan@linaro.org>>
>>         ---
>>         v2: Incorporates review comments from Ivan and Christophe
>>
>>            helper/include/odp/helper/tcp.h                    |   4 +
>>            test/validation/classification/Makefile.am         |   2 +
>>            test/validation/classification/classification.c    |   5 +
>>            .../classification/odp_classification_common.c     | 225
>> ++++++++
>>            .../classification/odp_classification_test_pmr.c   | 640
>> +++++++++++++++++++++
>>            .../classification/odp_classification_tests.c      | 152 +----
>>            .../classification/odp_classification_testsuites.h |  10 +-
>>            7 files changed, 906 insertions(+), 132 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..a88a301 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_suite_pmr,
>>         +                       .pInitFunc =
>> classification_suite_pmr_init,
>>         +                       .pCleanupFunc =
>> classification_suite_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..fe392c0
>>         --- /dev/null
>>         +++ b/test/validation/classification/odp_classification_common.c
>>         @@ -0,0 +1,225 @@
>>         +/* 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 <http://10.0.0.1/32
>> >"
>>         +#define CLS_DEFAULT_DADDR      "10.0.0.100/32 <
>> http://10.0.0.100/32>"
>>         +#define CLS_DEFAULT_SPORT      1024
>>         +#define CLS_DEFAULT_DPORT      2048
>>         +
>>         +#define CLS_TEST_SPORT         4096
>>         +#define CLS_TEST_DPORT         8192
>>         +#define CLS_TEST_DADDR         "10.0.0.5/32 <http://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;
>>
>
> Why be?
>

uint32be_t is just a typedef with __attribute__(bitwise) so that Sparse can
generate warning and since in this case we receive the packet from
interface we need to get it as big indian and then convert to cpu endian.

But I think there is a potential bug since get_seq() and set_seq() function
is not converting this cls_test_packet_t variables to cpu_endian before
accessing the value.
I will update in the next patch.

Regards,
Bala


>
>         +} cls_test_packet_t;
>>         +
>>         +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;
>>         +}
>>         +
>>         +uint32_t cls_pkt_get_seq(odp_packet_t pkt)
>>         +{
>>         +       uint32_t offset;
>>         +       cls_test_packet_t data;
>>         +       odph_ipv4hdr_t *ip;
>>         +
>>         +       ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>>         +       offset = odp_packet_l4_offset(pkt);
>>         +
>>         +       if (!offset && !ip)
>>         +               return TEST_SEQ_INVALID;
>>         +
>>         +       if (ip->proto == ODPH_IPPROTO_UDP)
>>         +               odp_packet_copydata_out(pkt, offset +
>> ODPH_UDPHDR_LEN,
>>         +                                       sizeof(data), &data);
>>         +       else
>>         +               odp_packet_copydata_out(pkt, offset +
>> ODPH_TCPHDR_LEN,
>>         +                                       sizeof(data), &data);
>>         +
>>         +       if (data.magic == DATA_MAGIC)
>>         +               return data.seq;
>>         +
>>         +       return TEST_SEQ_INVALID;
>>         +}
>>         +
>>         +static inline
>>         +int parse_ipv4_string(const char *ipaddress, uint32_t *addr,
>> uint32_t *mask)
>>
>>
>>     Seems it should be public function.
>>     I believe it was your intention.
>>     See below.
>>
>>
>> Yes. This can be moved into common file.
>>
>>
>>
>>         +{
>>         +       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(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..df14bb5
>>         --- /dev/null
>>         +++ b/test/validation/classification/odp_classification_test_pmr.c
>>         @@ -0,0 +1,640 @@
>>         +/* 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 <http://10.0.0.1/32
>> >"
>>         +#define CLS_DEFAULT_DADDR      "10.0.0.100/32 <
>> http://10.0.0.100/32>"
>>         +#define CLS_DEFAULT_SPORT      1024
>>         +#define CLS_DEFAULT_DPORT      2048
>>         +
>>         +#define CLS_TEST_SPORT         4096
>>         +#define CLS_TEST_DPORT         8192
>>         +#define CLS_TEST_DADDR         "10.0.0.5/32 <http://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;
>>
>
> no need in it here
> Same for odp_classification_tests.c
> It's currently in common file.
>
>         +
>>         +typedef struct cls_test_packet {
>>         +       uint32be_t magic;
>>         +       uint32be_t seq;
>>         +} cls_test_packet_t;
>>
>
> no need in it here any more.
> Same for odp_classification_tests.c
>
>         +
>>         +static inline
>>         +int parse_ipv4_string(const char *ipaddress, uint32_t *addr,
>> uint32_t *mask)
>>
>>
>>     This function is created in several files (common, this one and
>> classification_tests).
>>     Maybe it's time to make it common?
>>     It's not used in this module, at least for now.
>>     Delete it from odp_classification_tests.c also.
>>
>>
>> Okay.
>>
>>
>>
>>         +{
>>         +       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)
>>
>>
>>     common? it's also in odp_classification_tests.c
>>     But probably better delete it. It's not used in this module.
>>     At least for now. And even you are going to use it, probably be
>>     better to reuse enqueue_pktio_interface for this like:
>>
>>     static inline void enqueue_loop_interface()
>>     {
>>              enqueue_pktio_interface(pkt, pktio_loop);
>>     }
>>
>>         +{
>>         +       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);
>>
>>
>>     It might be, as in odp_classification_tests.c:
>>     (I don't recomend)
>>
>>     if (!(CU_ASSERT(odp_queue_enq(defqueue, ev) == 0))) #### just cut
>> from tests
>>              odp_packet_free(pkt);
>>
>>
>> In validation suite usually the cleanup is not done during failure case
>> and if the enqueue fails for some reason the validation suite will return
>> an error and the user will have to correct the error case and memory leak
>> during failure test case was not a big deal.
>> But as you said since it will cause a leak I will cleanup the buffer
>> during failure scenario also.
>>
>>
>>     But after check I see that doesn't. It's a potential bug.
>>     So, if you are not going to make this function common, then
>>     it be good to add patch that fixes same function in
>>     odp_classification_tests.c, as packet there can be deleted twice.
>>
>>         +}
>>         +
>>         +static inline
>>         +odp_packet_t receive_packet(odp_queue_t *queue, uint64_t ns)
>>
>>
>>     what about to make this function common?
>>
>>
>> Yes. It can be moved to common file.
>>
>>
>>
>>         +{
>>         +       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 int destroy_inq(odp_pktio_t pktio)
>>
>>
>>     Seems is common with odp_classification_tests.c
>>
>>
>> Okay.
>>
>>
>>
>>         +{
>>         +       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_suite_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");
>>
>>
>>     Do we need it here? Why?
>>
>>
>> Okay. I will optimise this in the next update.
>>
>>
>>
>>         +       if (pool_default == ODP_POOL_INVALID)
>>         +               return -1;
>>         +
>>         +       odp_atomic_init_u32(&seq, 0);
>>
>
> no need in it here any more.
> Same for odp_classification_tests.c
>
>         +       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_suite_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_test_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;
>>         +       seq = 0;
>>         +
>>         +       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(pool_default, false, false);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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(pool_default, false, false);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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);
>>         +       odp_cos_destroy(cos);
>>         +       odp_pmr_destroy(pmr);
>>         +       destroy_inq(pktio);
>>         +       odp_queue_destroy(queue);
>>         +       odp_pktio_close(pktio);
>>         +}
>>         +
>>         +static void classification_test_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;
>>         +       seq = 0;
>>         +
>>         +       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(pool_default, false, false);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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(pool_default, false, false);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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);
>>         +       odp_cos_destroy(cos);
>>         +       odp_pmr_destroy(pmr);
>>         +       destroy_inq(pktio);
>>         +       odp_queue_destroy(queue);
>>         +       odp_pktio_close(pktio);
>>         +}
>>         +
>>         +static void classification_test_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;
>>         +       seq = 0;
>>         +
>>         +       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, "udp_dport");
>>         +       cos = odp_cos_create(cosname);
>>         +       CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
>>         +
>>         +       sprintf(queuename, "%s", "udp_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(pool_default, false, true);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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(pool_default, false, true);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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);
>>         +       odp_cos_destroy(cos);
>>         +       odp_pmr_destroy(pmr);
>>         +       destroy_inq(pktio);
>>         +       odp_queue_destroy(queue);
>>         +       odp_pktio_close(pktio);
>>         +}
>>         +
>>         +static void classification_test_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;
>>         +       seq = 0;
>>         +
>>         +       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(pool_default, false, true);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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(pool_default, false, true);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);
>>
>>
>>     TEST_SEQ_INVALID check, why are you doing it here?
>>     If it's needed then why it's not done a little above and in functions:
>>     classification_test_pmr_term_udp_dport();
>>     classification_test_pmr_term_tcp_sport();
>>     classification_test_pmr_term_tcp_dport();
>>
>>
>> No. This is not needed here. Looks like I forgot to remove this CU_ASSERT.
>>
>>
>>
>>
>>         +       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
>>         +       CU_ASSERT(retqueue == defqueue);
>>         +       odp_packet_free(pkt);
>>         +
>>         +       odp_cos_destroy(cos);
>>         +       odp_pmr_destroy(pmr);
>>         +       destroy_inq(pktio);
>>         +       odp_queue_destroy(queue);
>>         +       odp_pktio_close(pktio);
>>         +}
>>         +
>>         +static void classification_test_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;
>>         +       seq = 0;
>>         +
>>         +       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(pool_default, false, true);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       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(pool_default, false, false);
>>         +       seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>         +       enqueue_pktio_interface(pkt, pktio);
>>         +
>>         +       pkt = receive_packet(&retqueue, ODP_TIME_SEC);
>>         +       CU_ASSERT(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);
>>
>>
>>     redundancy like above?
>>
>>
>>         +       CU_ASSERT(seq == cls_pkt_get_seq(pkt));
>>         +       CU_ASSERT(retqueue == defqueue);
>>         +
>>         +       odp_cos_destroy(cos);
>>         +       odp_pmr_destroy(pmr);
>>         +       odp_packet_free(pkt);
>>         +       destroy_inq(pktio);
>>         +       odp_queue_destroy(queue);
>>         +       odp_pktio_close(pktio);
>>         +}
>>         +
>>         +CU_TestInfo classification_suite_pmr[] = {
>>         +       _CU_TEST_INFO(classification_test_pmr_term_tcp_dport),
>>         +       _CU_TEST_INFO(classification_test_pmr_term_tcp_sport),
>>         +       _CU_TEST_INFO(classification_test_pmr_term_udp_dport),
>>         +       _CU_TEST_INFO(classification_test_pmr_term_udp_sport),
>>         +       _CU_TEST_INFO(classification_test_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..e2232a1 100644
>>         --- a/test/validation/classification/odp_classification_tests.c
>>         +++ b/test/validation/classification/odp_classification_tests.c
>>         @@ -122,42 +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;
>>         -       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;
>>         @@ -184,89 +148,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)
>>            {
>>         @@ -440,10 +321,12 @@ void test_cls_pmr_chain(void)
>>                  odp_queue_t queue;
>>                  uint32_t addr = 0;
>>                  uint32_t mask;
>>         -       uint32_t seq;
>>         +       uint32_t seq = 0;
>>
>>         -       pkt = create_packet(false);
>>         +       pkt = create_packet(pool_default, false, true);
>>                  seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>                  ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>>                  parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
>>                  ip->src_addr = odp_cpu_to_be_32(addr);
>>         @@ -460,8 +343,10 @@ 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(pool_default, false, true);
>>                  seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>                  ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
>>                  parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
>>                  ip->src_addr = odp_cpu_to_be_32(addr);
>>         @@ -506,10 +391,12 @@ void test_pktio_default_cos(void)
>>            {
>>                  odp_packet_t pkt;
>>                  odp_queue_t queue;
>>         -       uint32_t seq;
>>         +       uint32_t seq = 0;
>>                  /* create a default packet */
>>         -       pkt = create_packet(false);
>>         +       pkt = create_packet(pool_default, false, true);
>>                  seq = cls_pkt_get_seq(pkt);
>>         +       CU_ASSERT(seq != TEST_SEQ_INVALID);
>>         +
>>                  enqueue_loop_interface(pkt);
>>
>>                  pkt = receive_packet(&queue, ODP_TIME_SEC);
>>         @@ -554,7 +441,7 @@ void test_pktio_error_cos(void)
>>                  odp_packet_t pkt;
>>
>>                  /*Create an error packet */
>>         -       pkt = create_packet(false);
>>         +       pkt = create_packet(pool_default, false, true);
>>                  odph_ipv4hdr_t *ip = (odph_ipv4hdr_t
>> *)odp_packet_l3_ptr(pkt, NULL);
>>
>>                  /* Incorrect IpV4 version */
>>         @@ -644,12 +531,13 @@ void test_cos_with_l2_priority(void)
>>                  odph_ethhdr_t *ethhdr;
>>                  odph_vlanhdr_t *vlan;
>>                  odp_queue_t queue;
>>         -       uint32_t seq;
>>         +       uint32_t seq = 0;
>>
>>                  uint8_t i;
>>                  for (i = 0; i < CLS_L2_QOS_MAX; i++) {
>>         -               pkt = create_packet(true);
>>         +               pkt = create_packet(pool_default, true, true);
>
>
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..a88a301 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_suite_pmr,
+			.pInitFunc = classification_suite_pmr_init,
+			.pCleanupFunc = classification_suite_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..fe392c0
--- /dev/null
+++ b/test/validation/classification/odp_classification_common.c
@@ -0,0 +1,225 @@ 
+/* 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;
+
+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;
+}
+
+uint32_t cls_pkt_get_seq(odp_packet_t pkt)
+{
+	uint32_t offset;
+	cls_test_packet_t data;
+	odph_ipv4hdr_t *ip;
+
+	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
+	offset = odp_packet_l4_offset(pkt);
+
+	if (!offset && !ip)
+		return TEST_SEQ_INVALID;
+
+	if (ip->proto == ODPH_IPPROTO_UDP)
+		odp_packet_copydata_out(pkt, offset + ODPH_UDPHDR_LEN,
+					sizeof(data), &data);
+	else
+		odp_packet_copydata_out(pkt, offset + ODPH_TCPHDR_LEN,
+					sizeof(data), &data);
+
+	if (data.magic == DATA_MAGIC)
+		return data.seq;
+
+	return TEST_SEQ_INVALID;
+}
+
+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(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..df14bb5
--- /dev/null
+++ b/test/validation/classification/odp_classification_test_pmr.c
@@ -0,0 +1,640 @@ 
+/* 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 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_suite_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_suite_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_test_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;
+	seq = 0;
+
+	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(pool_default, false, false);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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(pool_default, false, false);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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);
+	odp_cos_destroy(cos);
+	odp_pmr_destroy(pmr);
+	destroy_inq(pktio);
+	odp_queue_destroy(queue);
+	odp_pktio_close(pktio);
+}
+
+static void classification_test_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;
+	seq = 0;
+
+	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(pool_default, false, false);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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(pool_default, false, false);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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);
+	odp_cos_destroy(cos);
+	odp_pmr_destroy(pmr);
+	destroy_inq(pktio);
+	odp_queue_destroy(queue);
+	odp_pktio_close(pktio);
+}
+
+static void classification_test_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;
+	seq = 0;
+
+	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, "udp_dport");
+	cos = odp_cos_create(cosname);
+	CU_ASSERT_FATAL(cos != ODP_COS_INVALID);
+
+	sprintf(queuename, "%s", "udp_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(pool_default, false, true);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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(pool_default, false, true);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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);
+	odp_cos_destroy(cos);
+	odp_pmr_destroy(pmr);
+	destroy_inq(pktio);
+	odp_queue_destroy(queue);
+	odp_pktio_close(pktio);
+}
+
+static void classification_test_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;
+	seq = 0;
+
+	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(pool_default, false, true);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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(pool_default, false, true);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);
+	CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+	CU_ASSERT(retqueue == defqueue);
+	odp_packet_free(pkt);
+
+	odp_cos_destroy(cos);
+	odp_pmr_destroy(pmr);
+	destroy_inq(pktio);
+	odp_queue_destroy(queue);
+	odp_pktio_close(pktio);
+}
+
+static void classification_test_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;
+	seq = 0;
+
+	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(pool_default, false, true);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	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(pool_default, false, false);
+	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
+	enqueue_pktio_interface(pkt, pktio);
+
+	pkt = receive_packet(&retqueue, ODP_TIME_SEC);
+	CU_ASSERT(cls_pkt_get_seq(pkt) != TEST_SEQ_INVALID);
+	CU_ASSERT(seq == cls_pkt_get_seq(pkt));
+	CU_ASSERT(retqueue == defqueue);
+
+	odp_cos_destroy(cos);
+	odp_pmr_destroy(pmr);
+	odp_packet_free(pkt);
+	destroy_inq(pktio);
+	odp_queue_destroy(queue);
+	odp_pktio_close(pktio);
+}
+
+CU_TestInfo classification_suite_pmr[] = {
+	_CU_TEST_INFO(classification_test_pmr_term_tcp_dport),
+	_CU_TEST_INFO(classification_test_pmr_term_tcp_sport),
+	_CU_TEST_INFO(classification_test_pmr_term_udp_dport),
+	_CU_TEST_INFO(classification_test_pmr_term_udp_sport),
+	_CU_TEST_INFO(classification_test_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..e2232a1 100644
--- a/test/validation/classification/odp_classification_tests.c
+++ b/test/validation/classification/odp_classification_tests.c
@@ -122,42 +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;
-	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;
@@ -184,89 +148,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)
 {
@@ -440,10 +321,12 @@  void test_cls_pmr_chain(void)
 	odp_queue_t queue;
 	uint32_t addr = 0;
 	uint32_t mask;
-	uint32_t seq;
+	uint32_t seq = 0;
 
-	pkt = create_packet(false);
+	pkt = create_packet(pool_default, false, true);
 	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
 	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 	parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
 	ip->src_addr = odp_cpu_to_be_32(addr);
@@ -460,8 +343,10 @@  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(pool_default, false, true);
 	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
 	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 	parse_ipv4_string(CLS_PMR_CHAIN_SADDR, &addr, &mask);
 	ip->src_addr = odp_cpu_to_be_32(addr);
@@ -506,10 +391,12 @@  void test_pktio_default_cos(void)
 {
 	odp_packet_t pkt;
 	odp_queue_t queue;
-	uint32_t seq;
+	uint32_t seq = 0;
 	/* create a default packet */
-	pkt = create_packet(false);
+	pkt = create_packet(pool_default, false, true);
 	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
+
 	enqueue_loop_interface(pkt);
 
 	pkt = receive_packet(&queue, ODP_TIME_SEC);
@@ -554,7 +441,7 @@  void test_pktio_error_cos(void)
 	odp_packet_t pkt;
 
 	/*Create an error packet */
-	pkt = create_packet(false);
+	pkt = create_packet(pool_default, false, true);
 	odph_ipv4hdr_t *ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 
 	/* Incorrect IpV4 version */
@@ -644,12 +531,13 @@  void test_cos_with_l2_priority(void)
 	odph_ethhdr_t *ethhdr;
 	odph_vlanhdr_t *vlan;
 	odp_queue_t queue;
-	uint32_t seq;
+	uint32_t seq = 0;
 
 	uint8_t i;
 	for (i = 0; i < CLS_L2_QOS_MAX; i++) {
-		pkt = create_packet(true);
+		pkt = create_packet(pool_default, true, true);
 		seq = cls_pkt_get_seq(pkt);
+		CU_ASSERT(seq != TEST_SEQ_INVALID);
 		ethhdr = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
 		vlan = (odph_vlanhdr_t *)(&ethhdr->type);
 		vlan->tci = odp_cpu_to_be_16(i << 13);
@@ -704,10 +592,11 @@  void test_pmr_cos(void)
 	odp_packet_t pkt;
 	odph_udphdr_t *udp;
 	odp_queue_t queue;
-	uint32_t seq;
+	uint32_t seq = 0;
 
-	pkt = create_packet(false);
+	pkt = create_packet(pool_default, false, true);
 	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
 	udp = (odph_udphdr_t *)odp_packet_l4_ptr(pkt, NULL);
 	udp->src_port = odp_cpu_to_be_16(CLS_PMR_SPORT);
 	enqueue_loop_interface(pkt);
@@ -778,10 +667,11 @@  void test_pktio_pmr_match_set_cos(void)
 	odph_udphdr_t *udp;
 	odp_packet_t pkt;
 	odp_queue_t queue;
-	uint32_t seq;
+	uint32_t seq = 0;
 
-	pkt = create_packet(false);
+	pkt = create_packet(pool_default, false, true);
 	seq = cls_pkt_get_seq(pkt);
+	CU_ASSERT(seq != TEST_SEQ_INVALID);
 	ip = (odph_ipv4hdr_t *)odp_packet_l3_ptr(pkt, NULL);
 	parse_ipv4_string(CLS_PMR_SET_SADDR, &addr, &mask);
 	ip->src_addr = odp_cpu_to_be_32(addr);
diff --git a/test/validation/classification/odp_classification_testsuites.h b/test/validation/classification/odp_classification_testsuites.h
index f603f30..293729e 100644
--- a/test/validation/classification/odp_classification_testsuites.h
+++ b/test/validation/classification/odp_classification_testsuites.h
@@ -16,11 +16,19 @@ 
 
 extern CU_TestInfo classification_suite[];
 extern CU_TestInfo classification_suite_basic[];
+extern CU_TestInfo classification_suite_pmr[];
 
 int classification_suite_init(void);
 int classification_suite_term(void);
 
-odp_packet_t create_packet(bool vlan);
+int classification_suite_pmr_term(void);
+int classification_suite_pmr_init(void);
+
+odp_packet_t create_packet(odp_pool_t pool, bool vlan, bool udp);
+int cls_pkt_set_seq(odp_packet_t pkt, bool flag_udp);
+uint32_t cls_pkt_get_seq(odp_packet_t pkt);
+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);