[lng-odp] [PATCHv2 2/2] validation: classification: add test case for ipv6 src and dst addr

2017-01-30 Thread Balasubramanian Manoharan
Adds test case for ipv6 source and destination address matching

Signed-off-by: Balasubramanian Manoharan 
---
 .../validation/api/classification/classification.h |  21 ++
 .../api/classification/odp_classification_common.c | 149 ++-
 .../classification/odp_classification_test_pmr.c   | 292 +++--
 .../api/classification/odp_classification_tests.c  |  42 ++-
 .../classification/odp_classification_testsuites.h |  14 +-
 5 files changed, 421 insertions(+), 97 deletions(-)

diff --git a/test/common_plat/validation/api/classification/classification.h 
b/test/common_plat/validation/api/classification/classification.h
index d73c821..0192e24 100644
--- a/test/common_plat/validation/api/classification/classification.h
+++ b/test/common_plat/validation/api/classification/classification.h
@@ -55,6 +55,27 @@
 #define DATA_MAGIC 0x01020304
 #define TEST_SEQ_INVALID   ((uint32_t)~0)
 
+/* Test packet Time-to-live */
+#define DEFAULT_TTL  128
+
+/* Test packet default DSCP value */
+#define LOW_DROP_PRECEDENCE  0x02
+#define MEDIUM_DROP_PRECEDENCE   0x04
+#define HIGH_DROP_PRECEDENCE 0x06
+#define DROP_PRECEDENCE_MASK 0x06
+#define DSCP_CLASS1  0x08
+#define DSCP_CLASS2  0x10
+#define DSCP_CLASS3  0x18
+#define DSCP_CLASS4  0x20
+#define DEFAULT_DSCP (DSCP_CLASS2 | LOW_DROP_PRECEDENCE)
+
+/* Test packet default ECN */
+#define DEFAULT_ECN  ODPH_IP_ECN_ECT0
+
+/* Test packet default TOS */
+#define DEFAULT_TOS  ((DEFAULT_DSCP << ODPH_IP_TOS_DSCP_SHIFT) | \
+   DEFAULT_ECN)
+
 /* test functions: */
 void classification_test_create_cos(void);
 void classification_test_destroy_cos(void);
diff --git 
a/test/common_plat/validation/api/classification/odp_classification_common.c 
b/test/common_plat/validation/api/classification/odp_classification_common.c
index f7ec6e5..0ca9083 100644
--- a/test/common_plat/validation/api/classification/odp_classification_common.c
+++ b/test/common_plat/validation/api/classification/odp_classification_common.c
@@ -14,6 +14,16 @@ typedef struct cls_test_packet {
odp_u32be_t seq;
 } cls_test_packet_t;
 
+static uint8_t IPV6_SRC_ADDR[ODPH_IPV6ADDR_LEN] = {
+   /* I.e. :::10.0.0.1 */
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 10, 0, 0, 1
+};
+
+static uint8_t IPV6_DST_ADDR[ODPH_IPV6ADDR_LEN] = {
+   /* I.e. :::10.0.0.100 */
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 10, 0, 0, 100
+};
+
 odp_pktio_t create_pktio(odp_queue_type_t q_type, odp_pool_t pool)
 {
odp_pktio_t pktio;
@@ -211,30 +221,30 @@ odp_pool_t pool_create(const char *poolname)
return odp_pool_create(poolname, ¶m);
 }
 
-odp_packet_t create_packet(odp_pool_t pool, bool vlan,
-  odp_atomic_u32_t *seq, bool flag_udp)
-{
-   return create_packet_len(pool, vlan, seq, flag_udp, 0);
-}
-
-odp_packet_t create_packet_len(odp_pool_t pool, bool vlan,
-  odp_atomic_u32_t *seq, bool flag_udp,
-  uint16_t len)
+odp_packet_t create_packet(cls_packet_info_t pkt_info)
 {
uint32_t seqno;
odph_ethhdr_t *ethhdr;
odph_udphdr_t *udp;
odph_tcphdr_t *tcp;
odph_ipv4hdr_t *ip;
+   odph_ipv6hdr_t *ipv6;
uint16_t payload_len;
uint64_t src_mac = CLS_DEFAULT_SMAC;
uint64_t dst_mac = CLS_DEFAULT_DMAC;
uint64_t dst_mac_be;
uint32_t addr = 0;
uint32_t mask;
-   int offset;
odp_packet_t pkt;
int packet_len = 0;
+   uint32_tversion, tc, flow, ver_tc_flow;
+   uint8_t *buf, next_hdr;
+   uint32_tl4_len, l3_len, l2_len, l3_offset, l4_offset;
+   uint16_t vlan_hdr_len = 0;
+   uint16_t l2_hdr_len = 0;
+   uint16_t l3_hdr_len = 0;
+   uint16_t l4_hdr_len = 0;
+   uint16_t eth_type;
 
/* 48 bit ethernet address needs to be left shifted for proper
value after changing to be*/
@@ -242,77 +252,85 @@ odp_packet_t create_packet_len(odp_pool_t pool, bool vlan,
if (dst_mac != dst_mac_be)
dst_mac_be = dst_mac_be >> (64 - 8 * ODPH_ETHADDR_LEN);
 
-   payload_len = sizeof(cls_test_packet_t) + len;
-   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);
+   payload_len = sizeof(cls_test_packet_t) + pkt_info.len;
+   seqno = odp_atomic_fetch_inc_u32(pkt_info.seq);
+
+   vlan_hdr_len = pkt_info.vlan ? ODPH_VLANHDR_LEN : 0;
+   l3_hdr_len = pkt_info.ipv6 ? ODPH_IPV6HDR_LEN : ODPH_IPV4HDR_LEN;
+   l4_hdr_len = pkt_info.udp ? ODPH_UDPHDR_LEN : ODP

[lng-odp] [PATCHv2 1/2] linux-generic: classification: implement ipv6 packet matching rule

2017-01-30 Thread Balasubramanian Manoharan
Adds test case for ipv6 source and destination address matching

Signed-off-by: Balasubramanian Manoharan 
---
v2: clang compilation fix
 .../include/odp_classification_datamodel.h | 11 +-
 .../include/odp_classification_inlines.h   | 44 ++
 .../linux-generic/include/odp_packet_internal.h|  5 +++
 platform/linux-generic/odp_classification.c| 26 +
 4 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/platform/linux-generic/include/odp_classification_datamodel.h 
b/platform/linux-generic/include/odp_classification_datamodel.h
index f6393ee..5b1cde3 100644
--- a/platform/linux-generic/include/odp_classification_datamodel.h
+++ b/platform/linux-generic/include/odp_classification_datamodel.h
@@ -25,6 +25,7 @@ extern "C" {
 #include 
 #include 
 #include 
+#include 
 
 /* Maximum Class Of Service Entry */
 #define ODP_COS_MAX_ENTRY  64
@@ -43,7 +44,7 @@ extern "C" {
 /* Max L3 QoS Value */
 #define ODP_COS_MAX_L3_QOS (1 << ODP_COS_L3_QOS_BITS)
 /* Max PMR Term bits */
-#define ODP_PMR_TERM_BYTES_MAX 8
+#define ODP_PMR_TERM_BYTES_MAX 16
 
 /**
 Packet Matching Rule Term Value
@@ -67,6 +68,14 @@ typedef struct pmr_term_value {
/** End value of the range */
uint64_tval_end;
} range;
+   struct {
+   uint8_t value[_ODP_IPV6ADDR_LEN];
+   uint8_t mask[_ODP_IPV6ADDR_LEN];
+   } match_ipv6;
+   struct {
+   uint8_t val_start[_ODP_IPV6ADDR_LEN];
+   uint8_t val_end[_ODP_IPV6ADDR_LEN];
+   } range_ipv6;
};
uint32_toffset; /**< Offset if term == ODP_PMR_CUSTOM_FRAME */
uint32_tval_sz; /**< Size of the value to be matched */
diff --git a/platform/linux-generic/include/odp_classification_inlines.h 
b/platform/linux-generic/include/odp_classification_inlines.h
index b839197..4d85cf2 100644
--- a/platform/linux-generic/include/odp_classification_inlines.h
+++ b/platform/linux-generic/include/odp_classification_inlines.h
@@ -179,19 +179,47 @@ static inline int verify_pmr_dmac(const uint8_t *pkt_addr,
return 0;
 }
 
-static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr ODP_UNUSED,
-   odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
-   pmr_term_value_t *term_value ODP_UNUSED)
+static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr,
+   odp_packet_hdr_t *pkt_hdr,
+   pmr_term_value_t *term_value)
 {
-   ODP_UNIMPLEMENTED();
+   const _odp_ipv6hdr_t *ipv6;
+   uint8_t src_addr[_ODP_IPV6ADDR_LEN];
+   uint8_t i;
+
+   if (!packet_hdr_has_ipv6(pkt_hdr))
+   return 0;
+
+   ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
+   memcpy(src_addr, ipv6->src_addr, _ODP_IPV6ADDR_LEN);
+   for (i = 0; i < _ODP_IPV6ADDR_LEN; i++)
+   src_addr[i] = src_addr[i] & term_value->match_ipv6.mask[i];
+
+   if (!memcmp(term_value->match_ipv6.value, src_addr, _ODP_IPV6ADDR_LEN))
+   return 1;
+
return 0;
 }
 
-static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr ODP_UNUSED,
-   odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
-   pmr_term_value_t *term_value ODP_UNUSED)
+static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr,
+   odp_packet_hdr_t *pkt_hdr,
+   pmr_term_value_t *term_value)
 {
-   ODP_UNIMPLEMENTED();
+   const _odp_ipv6hdr_t *ipv6;
+   uint8_t dst_addr[_ODP_IPV6ADDR_LEN];
+   uint8_t i;
+
+   if (!packet_hdr_has_ipv6(pkt_hdr))
+   return 0;
+
+   ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
+   memcpy(dst_addr, ipv6->dst_addr, _ODP_IPV6ADDR_LEN);
+   for (i = 0; i < _ODP_IPV6ADDR_LEN; i++)
+   dst_addr[i] = dst_addr[i] & term_value->match_ipv6.mask[i];
+
+   if (!memcmp(term_value->match_ipv6.value, dst_addr, _ODP_IPV6ADDR_LEN))
+   return 1;
+
return 0;
 }
 
diff --git a/platform/linux-generic/include/odp_packet_internal.h 
b/platform/linux-generic/include/odp_packet_internal.h
index e6e9d74..e3ada5c 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -294,6 +294,11 @@ static inline int packet_hdr_has_eth(odp_packet_hdr_t 
*pkt_hdr)
return pkt_hdr->p.input_flags.eth;
 }
 
+static inline int packet_hdr_has_ipv6(odp_packet_hdr_t *pkt_hdr)
+{
+   return pkt_hdr->p.input_flags.ipv6;
+}
+
 static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts)
 {
if (ts != 

Re: [lng-odp] [PATCH v2] example: add IPv4 fragmentation/reassembly example

2017-01-30 Thread Ola Liljedahl
On 30 January 2017 at 23:50, Bill Fischofer  wrote:
> Checkpatch still has some issues with this:
>
> ill@Ubuntu15:~/linaro/review$ ./scripts/checkpatch.pl
> 0001-example-add-IPv4-fragmentation-reassembly-example.patch
> WARNING: 'DONT' may be misspelled - perhaps 'DON'T'?
> #1056: FILE: example/ipfragreass/odp_ipfragreass_ip.h:20:
> +#define IP_FRAG_DONT 0x4000 /**< "Don't Fragment" (DF) fragment flag */
Seems like a design problem in checkpatch, breaking apart symbolic
names and testing the individual word fragments. Do all versions of
checkpatch behave like this? "Your symbolic names must consist of
properly spelled English words!".

I think we should ignore checkpatch. And IPv4 came before checkpatch.

-- Ola

>
> WARNING: 'dont' may be misspelled - perhaps 'don't'?
> #1122: FILE: example/ipfragreass/odp_ipfragreass_ip.h:86:
> +static inline bool ipv4hdr_dont_fragment(odph_ipv4hdr_t h)
>
> WARNING: 'DONT' may be misspelled - perhaps 'DON'T'?
> #1124: FILE: example/ipfragreass/odp_ipfragreass_ip.h:88:
> + return (h.frag_offset & odp_cpu_to_be_16(IP_FRAG_DONT));
>
> WARNING: 'dont' may be misspelled - perhaps 'don't'?
> #1133: FILE: example/ipfragreass/odp_ipfragreass_ip.h:97:
> +static inline void ipv4hdr_set_dont_fragment(odph_ipv4hdr_t *h, bool df)
>
> WARNING: 'DONT' may be misspelled - perhaps 'DON'T'?
> #1136: FILE: example/ipfragreass/odp_ipfragreass_ip.h:100:
> + h->frag_offset |=  odp_cpu_to_be_16(IP_FRAG_DONT);
>
> WARNING: 'DONT' may be misspelled - perhaps 'DON'T'?
> #1138: FILE: example/ipfragreass/odp_ipfragreass_ip.h:102:
> + h->frag_offset &= ~odp_cpu_to_be_16(IP_FRAG_DONT);
>
> WARNING: 'dont' may be misspelled - perhaps 'don't'?
> #1662: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:369:
> + * @param dont_assemble Whether reassembly should be attempted by default
>
> WARNING: 'dont' may be misspelled - perhaps 'don't'?
> #1668: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:375:
> +odp_queue_t out, bool dont_assemble)
>
> WARNING: 'dont' may be misspelled - perhaps 'don't'?
> #1686: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:393:
> + dont_assemble = false;
>
> WARNING: 'dont' may be misspelled - perhaps 'don't'?
> #1711: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:418:
> + if (newfl.part_len < newfl.whole_len || dont_assemble) {
>
> WARNING: 'dont' may be misspelled - perhaps 'don't'?
> #1764: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:471:
> + dont_assemble = 1;
>
> WARNING: 'dont' may be misspelled - perhaps 'don't'?
> #1774: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:481:
> + dont_assemble = 0;
>
> total: 0 errors, 12 warnings, 0 checks, 2175 lines checked
>
> NOTE: Ignored message types: BIT_MACRO COMPARISON_TO_NULL
> DEPRECATED_VARIABLE NEW_TYPEDEFS SPLIT_STRING SSCANF_TO_KSTRTO
>
> 0001-example-add-IPv4-fragmentation-reassembly-example.patch has style
> problems, please review.
>
> These are unfortunate since they are part of #defines. Perhaps a
> different choice of name here? I'm not sure what tweaks we can do to
> checkpatch to address this.
>
>
> On Mon, Jan 30, 2017 at 4:32 AM, Joe Savage  wrote:
>> Add an example application implementing lock-free IPv4 fragmentation
>> and reassembly functionality using ODP's packet "concat" and "split".
>>
>> Signed-off-by: Joe Savage 
>> ---
>> (This code contribution is provided under the terms of agreement 
>> LES-LTM-21309)
>>
>>  doc/application-api-guide/examples.dox   |   5 +
>>  example/Makefile.am  |   1 +
>>  example/ipfragreass/.gitignore   |   3 +
>>  example/ipfragreass/Makefile.am  |  22 +
>>  example/ipfragreass/odp_ipfragreass.c| 393 
>>  example/ipfragreass/odp_ipfragreass_atomics.h| 124 
>>  example/ipfragreass/odp_ipfragreass_fragment.c   |  99 +++
>>  example/ipfragreass/odp_ipfragreass_fragment.h   |  28 +
>>  example/ipfragreass/odp_ipfragreass_helpers.c| 121 
>>  example/ipfragreass/odp_ipfragreass_helpers.h| 129 
>>  example/ipfragreass/odp_ipfragreass_ip.h | 251 
>>  example/ipfragreass/odp_ipfragreass_reassemble.c | 772 
>> +++
>>  example/ipfragreass/odp_ipfragreass_reassemble.h | 211 +++
>>  example/m4/configure.m4  |   1 +
>>  14 files changed, 2160 insertions(+)
>>  create mode 100644 example/ipfragreass/.gitignore
>>  create mode 100644 example/ipfragreass/Makefile.am
>>  create mode 100644 example/ipfragreass/odp_ipfragreass.c
>>  create mode 100644 example/ipfragreass/odp_ipfragreass_atomics.h
>>  create mode 100644 example/ipfragreass/odp_ipfragreass_fragment.c
>>  create mode 100644 example/ipfragreass/odp_ipfragreass_fragment.h
>>  create mode 100644 example/ipfragreass/odp_ipfragreass_helpers.c
>>  create mode 100644 example/ipfragreass/odp_ipfragreass_helpers.h
>>  create mode 100644 example/ipfragreass/odp_ipfragreass_ip.h
>>  create mode 100644 example/ipfra

Re: [lng-odp] [PATCH v2] example: add IPv4 fragmentation/reassembly example

2017-01-30 Thread Bill Fischofer
Checkpatch still has some issues with this:

ill@Ubuntu15:~/linaro/review$ ./scripts/checkpatch.pl
0001-example-add-IPv4-fragmentation-reassembly-example.patch
WARNING: 'DONT' may be misspelled - perhaps 'DON'T'?
#1056: FILE: example/ipfragreass/odp_ipfragreass_ip.h:20:
+#define IP_FRAG_DONT 0x4000 /**< "Don't Fragment" (DF) fragment flag */

WARNING: 'dont' may be misspelled - perhaps 'don't'?
#1122: FILE: example/ipfragreass/odp_ipfragreass_ip.h:86:
+static inline bool ipv4hdr_dont_fragment(odph_ipv4hdr_t h)

WARNING: 'DONT' may be misspelled - perhaps 'DON'T'?
#1124: FILE: example/ipfragreass/odp_ipfragreass_ip.h:88:
+ return (h.frag_offset & odp_cpu_to_be_16(IP_FRAG_DONT));

WARNING: 'dont' may be misspelled - perhaps 'don't'?
#1133: FILE: example/ipfragreass/odp_ipfragreass_ip.h:97:
+static inline void ipv4hdr_set_dont_fragment(odph_ipv4hdr_t *h, bool df)

WARNING: 'DONT' may be misspelled - perhaps 'DON'T'?
#1136: FILE: example/ipfragreass/odp_ipfragreass_ip.h:100:
+ h->frag_offset |=  odp_cpu_to_be_16(IP_FRAG_DONT);

WARNING: 'DONT' may be misspelled - perhaps 'DON'T'?
#1138: FILE: example/ipfragreass/odp_ipfragreass_ip.h:102:
+ h->frag_offset &= ~odp_cpu_to_be_16(IP_FRAG_DONT);

WARNING: 'dont' may be misspelled - perhaps 'don't'?
#1662: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:369:
+ * @param dont_assemble Whether reassembly should be attempted by default

WARNING: 'dont' may be misspelled - perhaps 'don't'?
#1668: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:375:
+odp_queue_t out, bool dont_assemble)

WARNING: 'dont' may be misspelled - perhaps 'don't'?
#1686: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:393:
+ dont_assemble = false;

WARNING: 'dont' may be misspelled - perhaps 'don't'?
#1711: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:418:
+ if (newfl.part_len < newfl.whole_len || dont_assemble) {

WARNING: 'dont' may be misspelled - perhaps 'don't'?
#1764: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:471:
+ dont_assemble = 1;

WARNING: 'dont' may be misspelled - perhaps 'don't'?
#1774: FILE: example/ipfragreass/odp_ipfragreass_reassemble.c:481:
+ dont_assemble = 0;

total: 0 errors, 12 warnings, 0 checks, 2175 lines checked

NOTE: Ignored message types: BIT_MACRO COMPARISON_TO_NULL
DEPRECATED_VARIABLE NEW_TYPEDEFS SPLIT_STRING SSCANF_TO_KSTRTO

0001-example-add-IPv4-fragmentation-reassembly-example.patch has style
problems, please review.

These are unfortunate since they are part of #defines. Perhaps a
different choice of name here? I'm not sure what tweaks we can do to
checkpatch to address this.


On Mon, Jan 30, 2017 at 4:32 AM, Joe Savage  wrote:
> Add an example application implementing lock-free IPv4 fragmentation
> and reassembly functionality using ODP's packet "concat" and "split".
>
> Signed-off-by: Joe Savage 
> ---
> (This code contribution is provided under the terms of agreement 
> LES-LTM-21309)
>
>  doc/application-api-guide/examples.dox   |   5 +
>  example/Makefile.am  |   1 +
>  example/ipfragreass/.gitignore   |   3 +
>  example/ipfragreass/Makefile.am  |  22 +
>  example/ipfragreass/odp_ipfragreass.c| 393 
>  example/ipfragreass/odp_ipfragreass_atomics.h| 124 
>  example/ipfragreass/odp_ipfragreass_fragment.c   |  99 +++
>  example/ipfragreass/odp_ipfragreass_fragment.h   |  28 +
>  example/ipfragreass/odp_ipfragreass_helpers.c| 121 
>  example/ipfragreass/odp_ipfragreass_helpers.h| 129 
>  example/ipfragreass/odp_ipfragreass_ip.h | 251 
>  example/ipfragreass/odp_ipfragreass_reassemble.c | 772 
> +++
>  example/ipfragreass/odp_ipfragreass_reassemble.h | 211 +++
>  example/m4/configure.m4  |   1 +
>  14 files changed, 2160 insertions(+)
>  create mode 100644 example/ipfragreass/.gitignore
>  create mode 100644 example/ipfragreass/Makefile.am
>  create mode 100644 example/ipfragreass/odp_ipfragreass.c
>  create mode 100644 example/ipfragreass/odp_ipfragreass_atomics.h
>  create mode 100644 example/ipfragreass/odp_ipfragreass_fragment.c
>  create mode 100644 example/ipfragreass/odp_ipfragreass_fragment.h
>  create mode 100644 example/ipfragreass/odp_ipfragreass_helpers.c
>  create mode 100644 example/ipfragreass/odp_ipfragreass_helpers.h
>  create mode 100644 example/ipfragreass/odp_ipfragreass_ip.h
>  create mode 100644 example/ipfragreass/odp_ipfragreass_reassemble.c
>  create mode 100644 example/ipfragreass/odp_ipfragreass_reassemble.h
>
> diff --git a/doc/application-api-guide/examples.dox 
> b/doc/application-api-guide/examples.dox
> index 60d4058..80fe467 100644
> --- a/doc/application-api-guide/examples.dox
> +++ b/doc/application-api-guide/examples.dox
> @@ -28,3 +28,8 @@
>   * @example odp_timer_test.c
>   * ODP timer example application
>   */
> +
> + /**
> +  * @example odp_ipfragreass.c
> +  * ODP IPv4 lock-free fragmentation a

[lng-odp] [API-NEXT PATCH] doc: userguide: add section on application portability

2017-01-30 Thread Bill Fischofer
Add a section to the ODP User Guide discussing application portability
considerations and the use of source and binary portability options
provided by ODP.

Signed-off-by: Bill Fischofer 
---
 doc/users-guide/users-guide.adoc | 120 +++
 1 file changed, 120 insertions(+)

diff --git a/doc/users-guide/users-guide.adoc b/doc/users-guide/users-guide.adoc
index 41c57d1..ead8da5 100755
--- a/doc/users-guide/users-guide.adoc
+++ b/doc/users-guide/users-guide.adoc
@@ -589,6 +589,126 @@ lookup. The lookup function is particularly useful to 
allow an ODP application
 that is divided into multiple processes to obtain the handle for the common
 resource.
 
+== Application Portability Considerations
+ODP is designed to support the creation of portable data plane applications
+that can easily be run on multiple target platforms while at the same time
+fully exploit hardware acceleration capabilities native to whatever platform
+it is running on. This section discusses tradeoffs that application writers
+should consider when using ODP.
+
+First, it should be noted that portability is not an absolute good nor is it a
+single-valued attribute (application is portable or is not portable). While
+any application can be ported from one platform to another the real question
+is: _at what cost?_ Costs can be measured in two dimensions: The level of
+effort needed to port, and the resulting performance differences seen due to
+the port. Ideally an application should be portable between platforms with
+minimal effort and equally minimal performance impact. While ODP is designed
+to support this ideal, each application must assess what its goals are in this
+area and how best to use ODP to achieve these goals.
+
+=== Portability and Coexistence
+Because ODP offers a programming _framework_ rather than a programming
+_environment_, it is designed to be able to work alongside APIs offered by
+other frameworks with minimual interference. Therefore when we speak of
+portability in an ODP context, we of necessity speak of portability of those
+portions of the application that make use of ODP APIs. If an application uses
+non-ODP APIs then those must be taken into consideration as well when
+assessing the portability of the entire application. For many applications, it
+suffices to isolate certain non-portable code to a few areas of the application
+with the result that the application is significantly more portable than it
+would be without using ODP. Especially when dealing with existing applications
+that run in production environments, ODP may well be introduced in an
+incremental manner with the result being that the application becomes more
+portable only over time.
+
+=== Source vs. Binary Portability
+ODP has been designed to support both source and binary portability. Source
+portability is intrinsic to the ODP API specification itself. Any application
+written to the ODP API specification will be source portable between any
+conforming ODP implementation with at most a recompile. This is because ODP
+APIs do not expose implementation details or internal structures that may vary
+from platform to platform.
+
+For platforms that share a common Instruction Set Architecture (ISA), ODP can
+also offer binary portability via the specification of an Application Binary
+Interface (ABI). This is especially useful in a Network Function
+Virtualization (NFV) environment where a data plane application may be
+developed and compiled on one platform for distribution and then deployed on
+many different platforms by an NFV Orchestrator function.
+
+=== ODP Application Profiles
+To assist in meeting these needs, ODP offers two distinct _application
+profiles_ that are designed to characterize the needs of different types of
+data plane applications: the _Embedded Profile_ and the _Cloud Profile_.
+
+ Embedded Profile
+The ODP Embedded Profile is designed to support applications that wish to
+target a specific platform and achieve optimal performance on that platform
+and where source code portability is sufficient. If such applications need to
+support more than one platform then they simply need to be recompiled against
+the ODP implementation for that platform.
+
+Embedded applications will typically work with a copy of ODP downloaded from
+a git repository so that it can be configured for the application's precise
+needs. To specify that the application wishes to use the embedded profile:
+
+`./configure --enable-abi-compat=no ...`
+
+should be used as part of the ODP configuration options. This allows
+applications to use inline forms of ODP APIs to give optimal performance
+on this platform, and may include additional optimizations that preclude
+binary portability to other platforms. The result is a binary that will achieve
+maximum performance on a given target platform and that can be ported to
+other platforms with a recompile.
+
+ Cloud Profile
+By contrast, the ODP Cloud Profile is design

Re: [lng-odp] [PATCH 2/2] validation: classification: add test case for ipv6 src and dst addr

2017-01-30 Thread Bill Fischofer
On Mon, Jan 30, 2017 at 6:56 AM, Balasubramanian Manoharan
 wrote:
> Adds test case for ipv6 source and destination address matching
>
> Signed-off-by: Balasubramanian Manoharan 
> ---
>  .../validation/api/classification/classification.h |  21 ++
>  .../api/classification/odp_classification_common.c | 149 ++-
>  .../classification/odp_classification_test_pmr.c   | 292 
> +++--
>  .../api/classification/odp_classification_tests.c  |  42 ++-
>  .../classification/odp_classification_testsuites.h |  14 +-
>  5 files changed, 423 insertions(+), 95 deletions(-)
>
> diff --git a/test/common_plat/validation/api/classification/classification.h 
> b/test/common_plat/validation/api/classification/classification.h
> index d73c821..0192e24 100644
> --- a/test/common_plat/validation/api/classification/classification.h
> +++ b/test/common_plat/validation/api/classification/classification.h
> @@ -55,6 +55,27 @@
>  #define DATA_MAGIC 0x01020304
>  #define TEST_SEQ_INVALID   ((uint32_t)~0)
>
> +/* Test packet Time-to-live */
> +#define DEFAULT_TTL  128
> +
> +/* Test packet default DSCP value */
> +#define LOW_DROP_PRECEDENCE  0x02
> +#define MEDIUM_DROP_PRECEDENCE   0x04
> +#define HIGH_DROP_PRECEDENCE 0x06
> +#define DROP_PRECEDENCE_MASK 0x06
> +#define DSCP_CLASS1  0x08
> +#define DSCP_CLASS2  0x10
> +#define DSCP_CLASS3  0x18
> +#define DSCP_CLASS4  0x20
> +#define DEFAULT_DSCP (DSCP_CLASS2 | LOW_DROP_PRECEDENCE)
> +
> +/* Test packet default ECN */
> +#define DEFAULT_ECN  ODPH_IP_ECN_ECT0
> +
> +/* Test packet default TOS */
> +#define DEFAULT_TOS  ((DEFAULT_DSCP << ODPH_IP_TOS_DSCP_SHIFT) | 
> \
> +   DEFAULT_ECN)
> +
>  /* test functions: */
>  void classification_test_create_cos(void);
>  void classification_test_destroy_cos(void);
> diff --git 
> a/test/common_plat/validation/api/classification/odp_classification_common.c 
> b/test/common_plat/validation/api/classification/odp_classification_common.c
> index f7ec6e5..a947074 100644
> --- 
> a/test/common_plat/validation/api/classification/odp_classification_common.c
> +++ 
> b/test/common_plat/validation/api/classification/odp_classification_common.c
> @@ -14,6 +14,16 @@ typedef struct cls_test_packet {
> odp_u32be_t seq;
>  } cls_test_packet_t;
>
> +static uint8_t IPV6_SRC_ADDR[ODPH_IPV6ADDR_LEN] = {
> +   /* I.e. :::10.0.0.1 */
> +   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 10, 0, 0, 1
> +};
> +
> +static uint8_t IPV6_DST_ADDR[ODPH_IPV6ADDR_LEN] = {
> +   /* I.e. :::10.0.0.100 */
> +   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 10, 0, 0, 100
> +};
> +
>  odp_pktio_t create_pktio(odp_queue_type_t q_type, odp_pool_t pool)
>  {
> odp_pktio_t pktio;
> @@ -211,21 +221,14 @@ odp_pool_t pool_create(const char *poolname)
> return odp_pool_create(poolname, ¶m);
>  }
>
> -odp_packet_t create_packet(odp_pool_t pool, bool vlan,
> -  odp_atomic_u32_t *seq, bool flag_udp)
> -{
> -   return create_packet_len(pool, vlan, seq, flag_udp, 0);
> -}
> -
> -odp_packet_t create_packet_len(odp_pool_t pool, bool vlan,
> -  odp_atomic_u32_t *seq, bool flag_udp,
> -  uint16_t len)
> +odp_packet_t create_packet(cls_packet_info_t pkt_info)
>  {
> uint32_t seqno;
> odph_ethhdr_t *ethhdr;
> odph_udphdr_t *udp;
> odph_tcphdr_t *tcp;
> odph_ipv4hdr_t *ip;
> +   odph_ipv6hdr_t *ipv6;
> uint16_t payload_len;
> uint64_t src_mac = CLS_DEFAULT_SMAC;
> uint64_t dst_mac = CLS_DEFAULT_DMAC;
> @@ -235,6 +238,14 @@ odp_packet_t create_packet_len(odp_pool_t pool, bool 
> vlan,
> int offset;
> odp_packet_t pkt;
> int packet_len = 0;
> +   uint32_tversion, tc, flow, ver_tc_flow;
> +   uint8_t *buf, next_hdr;
> +   uint32_tl4_len, l3_len, l2_len, l3_offset, l4_offset;
> +   uint16_t vlan_hdr_len = 0;
> +   uint16_t l2_hdr_len = 0;
> +   uint16_t l3_hdr_len = 0;
> +   uint16_t l4_hdr_len = 0;
> +   uint16_t eth_type;
>
> /* 48 bit ethernet address needs to be left shifted for proper
> value after changing to be*/
> @@ -242,77 +253,88 @@ odp_packet_t create_packet_len(odp_pool_t pool, bool 
> vlan,
> if (dst_mac != dst_mac_be)
> dst_mac_be = dst_mac_be >> (64 - 8 * ODPH_ETHADDR_LEN);
>
> -   payload_len = sizeof(cls_test_packet_t) + len;
> -   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_

Re: [lng-odp] [PATCH] helper: iplookuptable: avoid potential null pointer dereferences

2017-01-30 Thread Mike Holmes
Hi Bill

Did you run this in GitHub coverity_scan and did it clear the issue for you
?

I ran it, but I did not have a before view for that nice fuzzy feeling of
seeing it dissapear, only that I did not get informed of anything new with
your patch applied.
I think my results should be public if you have a github login, and the
change looks correct.

https://travis-ci.org/mike-holmes-linaro/odp/builds/196630581
https://scan.coverity.com/projects/mike-holmes-linaro-odp/view_defects

Mike

On 30 January 2017 at 09:35, Bill Fischofer 
wrote:

> Resolve Bug https://bugs.linaro.org/show_bug.cgi?id=2862 by checking
> pointer validity before dereferencing.
>
> Signed-off-by: Bill Fischofer 
>

Reviewed-by: Mike Holmes 



> ---
>  helper/iplookuptable.c | 20 ++--
>  1 file changed, 14 insertions(+), 6 deletions(-)
>
> diff --git a/helper/iplookuptable.c b/helper/iplookuptable.c
> index aaebea3..845125b 100644
> --- a/helper/iplookuptable.c
> +++ b/helper/iplookuptable.c
> @@ -666,12 +666,14 @@ odph_iplookup_table_put_value(odph_table_t tbl,
> void *key, void *value)
> odph_iplookup_table_impl *impl = (void *)tbl;
> odph_iplookup_prefix_t *prefix = (odph_iplookup_prefix_t *)key;
> prefix_entry_t *l1e = NULL;
> -   odp_buffer_t nexthop = *((odp_buffer_t *)value);
> +   odp_buffer_t nexthop;
> int ret = 0;
>
> if ((tbl == NULL) || (key == NULL) || (value == NULL))
> return -1;
>
> +   nexthop = *((odp_buffer_t *)value);
> +
> if (prefix->cidr == 0)
> return -1;
> prefix->ip = prefix->ip & (0x << (IP_LENGTH -
> prefix->cidr));
> @@ -708,13 +710,16 @@ int odph_iplookup_table_get_value(odph_table_t tbl,
> void *key,
>   uint32_t buffer_size ODP_UNUSED)
>  {
> odph_iplookup_table_impl *impl = (void *)tbl;
> -   uint32_t ip = *((uint32_t *)key);
> -   prefix_entry_t *entry = &impl->l1e[ip >> 16];
> +   uint32_t ip;
> +   prefix_entry_t *entry;
> odp_buffer_t *buff = (odp_buffer_t *)buffer;
>
> if ((tbl == NULL) || (key == NULL) || (buffer == NULL))
> return -EINVAL;
>
> +   ip = *((uint32_t *)key);
> +   entry = &impl->l1e[ip >> 16];
> +
> if (entry == NULL) {
> ODPH_DBG("failed to get L1 entry.\n");
> return -1;
> @@ -881,13 +886,16 @@ odph_iplookup_table_remove_value(odph_table_t tbl,
> void *key)
>  {
> odph_iplookup_table_impl *impl = (void *)tbl;
> odph_iplookup_prefix_t *prefix = (odph_iplookup_prefix_t *)key;
> -   uint32_t ip = prefix->ip;
> -   uint8_t cidr = prefix->cidr;
> +   uint32_t ip;
> +   uint8_t cidr;
>
> if ((tbl == NULL) || (key == NULL))
> return -EINVAL;
>
> -   if (!prefix->cidr)
> +   ip   = prefix->ip;
> +   cidr = prefix->cidr;
> +
> +   if (cidr == 0)
> return -EINVAL;
>
> prefix_entry_t *entry = &impl->l1e[ip >> 16];
> --
> 2.9.3
>
>


-- 
Mike Holmes
Program Manager - Linaro Networking Group
Linaro.org  *│ *Open source software for ARM SoCs
"Work should be fun and collaborative, the rest follows"


Re: [lng-odp] [PATCH] example: add IPv4 fragmentation/reassembly example

2017-01-30 Thread Maxim Uvarov
On 01/30/17 15:27, Ola Liljedahl wrote:
> 
> 
> On 30 January 2017 at 02:28, Bill Fischofer  > wrote:
> 
> As the maintainer of the ODP git repo, Maxim has final say on style
> questions for what is accepted into it, so I recommend deferring to
> him on this. This is true of all open source projects, so there's
> nothing new here.
> 
> I am pointing out that Maxim's knowledge and arguments about the C
> language are limited.
> "Create/call a separation function" is not always a meaningful
> alternative that simplifies complexity.
> An inner block with local declarations and a separate function are not
> semantically equivalent.
> Declaring variables at the top of the function scope could also make
> some C language features impossible to use, e.g. use const variables
> that are assigned the return value of a function call or some other
> value that cannot be computed at the top of the function.
> With this knowledge, perhaps the current rules can be improved.
>  
> 

Ola,

ODP accepted kernel code style described with that link:

https://www.kernel.org/doc/Documentation/process/coding-style.rst

according to line 407 I had to review any code as
"less-than-gifted first-year high-school student".

Item "6) Functions" describes acceptance criteria for functions. I see
that code does not match that item. If code is accepted which does not
match criteria described in that document community people can argue.

Best regards,
Maxim.

> 
> If we want to set up a separate ODP examples repo that can accommodate
> examples written in other languages, or that uses a different set of
> acceptable style rules, then final say on what would go into that repo
> would again be with that repo's maintainer. Actually, such an examples
> repo is probably a good idea as it would be very clear that these
> programs are designed to be compiled and run against many different
> ODP implementations.
> 
> It would be great to have dozens of example programs and applications
> that are published this way. Linaro could certainly host such a repo
> to make it clear that it is vendor-neutral, but I suspect we'd want to
> have another maintainer for it as Maxim's plate is already very full.
> Any volunteers?
> 
> On Fri, Jan 27, 2017 at 7:51 AM, Ola Liljedahl
> mailto:ola.liljed...@linaro.org>> wrote:
> > On 26 January 2017 at 16:56, Maxim Uvarov  > wrote:
> >
> >> On 01/26/17 18:27, Ola Liljedahl wrote:
> >> >
> >> >
> >> > On 26 January 2017 at 15:19, Joe Savage  
> >> > >> wrote:
> >> >
> >> > > >> It will be very helpful if rehe was some README with
> >> description about
> >> > > >> this app, run environments and some output. So people
> can learn
> >> > > >> something before looking to code.
> >> > > >
> >> > > > I can add one, but I don't think there's really that
> much to
> >> describe. Since
> >> > > > the example doesn't connect to the network, all that users
> >> really need to
> >> > > > know is that it fragments and reassembles IPv4 packets.
> >> > >
> >> > > you add that description here:
> >> > > ./doc/application-api-guide/examples.dox
> >> > >
> >> > > Description can be about application internals. Like you
> create N
> >> > > workers, use queue with nsize to reassembly packets. Use
> following
> >> > > algorithm.
> >> > >
> >> > > And why this app is not connected to network? I think it
> will be
> >> very
> >> > > useful if you can pass some pcap file and get pcap on
> output. And
> >> test
> >> > > this program work with other program which does
> reassembly. That
> >> looks
> >> > > like good proof that it works as expected.
> >> >
> >> > Adding the example to the list in examples.dox seems
> sensible, but I
> >> > think
> >> > the code and comments are probably the best description of the
> >> algorithm
> >> > itself.
> >> >
> >> > As for why it isn't network connected, I wanted to keep the
> example
> >> > somewhat
> >> > bare bones to its purpose. Dealing with a real network
> connection is
> >> > likely
> >> > to add clutter that doesn't really speak to the contents of
> this
> >> > specific
> >> > example. Anyone wanting to implement this kind of functionality
> >> > themselves
> >> > can simply glean this information from a different example
> focusing
> >> > around
> >> > the packet I/O interface.
> >> >
> >> > > >
> >> > > >> app naming might be not best.
> >> > > >
> >> >   

Re: [lng-odp] [PATCH] travis: several tries to download cunit

2017-01-30 Thread Mike Holmes
On 30 January 2017 at 10:11, Maxim Uvarov  wrote:

> On 01/30/17 17:57, Mike Holmes wrote:
> >
> >
> > On 30 January 2017 at 09:47, Maxim Uvarov  > > wrote:
> >
> > On 01/30/17 17:38, Bill Fischofer wrote:
> > > On Mon, Jan 30, 2017 at 8:30 AM, Mike Holmes <
> mike.hol...@linaro.org > wrote:
> > >> Currently we have forked the repo and we pull from that copy,
> that copy is
> > >> on Anders poeple.linaro.org  for the
> internal Jenkins CI
> > >>
> > >> Maybe we add cunit fork to the lng offical repo location so that
> we can do
> > >> this from github also and not  have to point at a personal
> location ?
> > >
> > > If we're going to fork, agree we should do so "officially" rather
> than
> > > in a personal repo.
> > >
> >
> > CUnit is in svn, so it will not be clean fork. We can put tar.gz to
> some
> > repo. But for now I would increase number of tries.
> >
> >
> > It is so easy to push the tar and then there is never an issue, I think
> > that would be better for internal CI so I will check with Anders and try
> > to move that at least.
> >
>
> we also need account 2 things:
>
> a) we should do exactly what is said in our README.
> b) we should use official repo. If it's dead other people also can not
> build odp. If we mirror it we should update README.
>
> If we said that we support:
>
> apt-get install libcunit1-dev
>
> then maybe get rid text from DEPENDANCIES about building it from src?
> People should know where to get it if they build it from src.
>
> Maxim.
>
>
Good points


> >
> >
> > Maxim.
> >
> >
> > >>
> > >> Mike
> > >>
> > >> On 29 January 2017 at 17:03, Bill Fischofer
> > mailto:bill.fischo...@linaro.org>>
> > >> wrote:
> > >>>
> > >>> On Fri, Jan 27, 2017 at 1:21 PM, Maxim Uvarov
> > mailto:maxim.uva...@linaro.org>>
> > >>> wrote:
> >  some time curl fails to download cunit from sf.net
> >  or it's
> >  mirrors. Try 10 times with 1 second delay.
> > 
> >  Signed-off-by: Maxim Uvarov  > >
> >  ---
> >   .travis.yml | 2 +-
> >   1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> >  diff --git a/.travis.yml b/.travis.yml
> >  index 03e61b18..363c1b3f 100644
> >  --- a/.travis.yml
> >  +++ b/.travis.yml
> >  @@ -25,7 +25,7 @@ before_install:
> > 
> >   #   Install cunit for the validation tests because distro
> > version
> >  is too old and fails C99 compile
> >   - export CUNIT_VERSION=2.1-3
> >  -- curl -sSOL
> > 
> > http://sourceforge.net/projects/cunit/files/CUnit/${
> CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
> >  CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2>
> >  +- for _ in {1..10}; do
> > 
> > http://souirceforge.net/projects/cunit/files/CUnit/${
> CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
> >  CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2>
> >  && break; sleep 1; done
> > >>>
> > >>> If we're going to make this more robust, what happens if the 10
> > >>> attempts all fail? Do we just run off the rails as before or
> make an
> > >>> attempt to quit with some sort of useful debug msg?
> > >>>
> >   - tar -jxf *.bz2
> >   - cd CUnit*
> >   - ./bootstrap
> >  --
> >  2.11.0.295.gd7dffce
> > 
> > >>
> > >>
> > >>
> > >>
> > >> --
> > >> Mike Holmes
> > >> Program Manager - Linaro Networking Group
> > >> Linaro.org │ Open source software for ARM SoCs
> > >> "Work should be fun and collaborative, the rest follows"
> > >>
> > >>
> >
> >
> >
> >
> > --
> > Mike Holmes
> > Program Manager - Linaro Networking Group
> > Linaro.org * **│ *Open source software for ARM
> SoCs
> > "Work should be fun and collaborative, the rest follows"
> >
> > __
> >
> >
>
>


-- 
Mike Holmes
Program Manager - Linaro Networking Group
Linaro.org  *│ *Open source software for ARM SoCs
"Work should be fun and collaborative, the rest follows"


Re: [lng-odp] [PATCH] travis: several tries to download cunit

2017-01-30 Thread Maxim Uvarov
On 01/30/17 17:57, Mike Holmes wrote:
> 
> 
> On 30 January 2017 at 09:47, Maxim Uvarov  > wrote:
> 
> On 01/30/17 17:38, Bill Fischofer wrote:
> > On Mon, Jan 30, 2017 at 8:30 AM, Mike Holmes  > wrote:
> >> Currently we have forked the repo and we pull from that copy, that 
> copy is
> >> on Anders poeple.linaro.org  for the 
> internal Jenkins CI
> >>
> >> Maybe we add cunit fork to the lng offical repo location so that we 
> can do
> >> this from github also and not  have to point at a personal location ?
> >
> > If we're going to fork, agree we should do so "officially" rather than
> > in a personal repo.
> >
> 
> CUnit is in svn, so it will not be clean fork. We can put tar.gz to some
> repo. But for now I would increase number of tries.
> 
> 
> It is so easy to push the tar and then there is never an issue, I think
> that would be better for internal CI so I will check with Anders and try
> to move that at least.
>  

we also need account 2 things:

a) we should do exactly what is said in our README.
b) we should use official repo. If it's dead other people also can not
build odp. If we mirror it we should update README.

If we said that we support:

apt-get install libcunit1-dev

then maybe get rid text from DEPENDANCIES about building it from src?
People should know where to get it if they build it from src.

Maxim.


> 
> 
> Maxim.
> 
> 
> >>
> >> Mike
> >>
> >> On 29 January 2017 at 17:03, Bill Fischofer
> mailto:bill.fischo...@linaro.org>>
> >> wrote:
> >>>
> >>> On Fri, Jan 27, 2017 at 1:21 PM, Maxim Uvarov
> mailto:maxim.uva...@linaro.org>>
> >>> wrote:
>  some time curl fails to download cunit from sf.net
>  or it's
>  mirrors. Try 10 times with 1 second delay.
> 
>  Signed-off-by: Maxim Uvarov  >
>  ---
>   .travis.yml | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
>  diff --git a/.travis.yml b/.travis.yml
>  index 03e61b18..363c1b3f 100644
>  --- a/.travis.yml
>  +++ b/.travis.yml
>  @@ -25,7 +25,7 @@ before_install:
> 
>   #   Install cunit for the validation tests because distro
> version
>  is too old and fails C99 compile
>   - export CUNIT_VERSION=2.1-3
>  -- curl -sSOL
> 
> 
> http://sourceforge.net/projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
> 
> 
>  +- for _ in {1..10}; do
> 
> 
> http://souirceforge.net/projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
> 
> 
>  && break; sleep 1; done
> >>>
> >>> If we're going to make this more robust, what happens if the 10
> >>> attempts all fail? Do we just run off the rails as before or make an
> >>> attempt to quit with some sort of useful debug msg?
> >>>
>   - tar -jxf *.bz2
>   - cd CUnit*
>   - ./bootstrap
>  --
>  2.11.0.295.gd7dffce
> 
> >>
> >>
> >>
> >>
> >> --
> >> Mike Holmes
> >> Program Manager - Linaro Networking Group
> >> Linaro.org │ Open source software for ARM SoCs
> >> "Work should be fun and collaborative, the rest follows"
> >>
> >>
> 
> 
> 
> 
> -- 
> Mike Holmes
> Program Manager - Linaro Networking Group
> Linaro.org * **│ *Open source software for ARM SoCs
> "Work should be fun and collaborative, the rest follows"
> 
> __
> 
> 



Re: [lng-odp] [PATCH] travis: several tries to download cunit

2017-01-30 Thread Mike Holmes
On 30 January 2017 at 09:47, Maxim Uvarov  wrote:

> On 01/30/17 17:38, Bill Fischofer wrote:
> > On Mon, Jan 30, 2017 at 8:30 AM, Mike Holmes 
> wrote:
> >> Currently we have forked the repo and we pull from that copy, that copy
> is
> >> on Anders poeple.linaro.org for the internal Jenkins CI
> >>
> >> Maybe we add cunit fork to the lng offical repo location so that we can
> do
> >> this from github also and not  have to point at a personal location ?
> >
> > If we're going to fork, agree we should do so "officially" rather than
> > in a personal repo.
> >
>
> CUnit is in svn, so it will not be clean fork. We can put tar.gz to some
> repo. But for now I would increase number of tries.
>

It is so easy to push the tar and then there is never an issue, I think
that would be better for internal CI so I will check with Anders and try to
move that at least.


>
> Maxim.
>
>
> >>
> >> Mike
> >>
> >> On 29 January 2017 at 17:03, Bill Fischofer 
> >> wrote:
> >>>
> >>> On Fri, Jan 27, 2017 at 1:21 PM, Maxim Uvarov  >
> >>> wrote:
>  some time curl fails to download cunit from sf.net or it's
>  mirrors. Try 10 times with 1 second delay.
> 
>  Signed-off-by: Maxim Uvarov 
>  ---
>   .travis.yml | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
>  diff --git a/.travis.yml b/.travis.yml
>  index 03e61b18..363c1b3f 100644
>  --- a/.travis.yml
>  +++ b/.travis.yml
>  @@ -25,7 +25,7 @@ before_install:
> 
>   #   Install cunit for the validation tests because distro version
>  is too old and fails C99 compile
>   - export CUNIT_VERSION=2.1-3
>  -- curl -sSOL
>  http://sourceforge.net/projects/cunit/files/CUnit/${
> CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
>  +- for _ in {1..10}; do
>  http://souirceforge.net/projects/cunit/files/CUnit/${
> CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
>  && break; sleep 1; done
> >>>
> >>> If we're going to make this more robust, what happens if the 10
> >>> attempts all fail? Do we just run off the rails as before or make an
> >>> attempt to quit with some sort of useful debug msg?
> >>>
>   - tar -jxf *.bz2
>   - cd CUnit*
>   - ./bootstrap
>  --
>  2.11.0.295.gd7dffce
> 
> >>
> >>
> >>
> >>
> >> --
> >> Mike Holmes
> >> Program Manager - Linaro Networking Group
> >> Linaro.org │ Open source software for ARM SoCs
> >> "Work should be fun and collaborative, the rest follows"
> >>
> >>
>
>


-- 
Mike Holmes
Program Manager - Linaro Networking Group
Linaro.org  *│ *Open source software for ARM SoCs
"Work should be fun and collaborative, the rest follows"


Re: [lng-odp] [PATCH] travis: several tries to download cunit

2017-01-30 Thread Maxim Uvarov
On 01/30/17 17:38, Bill Fischofer wrote:
> On Mon, Jan 30, 2017 at 8:30 AM, Mike Holmes  wrote:
>> Currently we have forked the repo and we pull from that copy, that copy is
>> on Anders poeple.linaro.org for the internal Jenkins CI
>>
>> Maybe we add cunit fork to the lng offical repo location so that we can do
>> this from github also and not  have to point at a personal location ?
> 
> If we're going to fork, agree we should do so "officially" rather than
> in a personal repo.
> 

CUnit is in svn, so it will not be clean fork. We can put tar.gz to some
repo. But for now I would increase number of tries.

Maxim.


>>
>> Mike
>>
>> On 29 January 2017 at 17:03, Bill Fischofer 
>> wrote:
>>>
>>> On Fri, Jan 27, 2017 at 1:21 PM, Maxim Uvarov 
>>> wrote:
 some time curl fails to download cunit from sf.net or it's
 mirrors. Try 10 times with 1 second delay.

 Signed-off-by: Maxim Uvarov 
 ---
  .travis.yml | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/.travis.yml b/.travis.yml
 index 03e61b18..363c1b3f 100644
 --- a/.travis.yml
 +++ b/.travis.yml
 @@ -25,7 +25,7 @@ before_install:

  #   Install cunit for the validation tests because distro version
 is too old and fails C99 compile
  - export CUNIT_VERSION=2.1-3
 -- curl -sSOL
 http://sourceforge.net/projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
 +- for _ in {1..10}; do
 http://souirceforge.net/projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
 && break; sleep 1; done
>>>
>>> If we're going to make this more robust, what happens if the 10
>>> attempts all fail? Do we just run off the rails as before or make an
>>> attempt to quit with some sort of useful debug msg?
>>>
  - tar -jxf *.bz2
  - cd CUnit*
  - ./bootstrap
 --
 2.11.0.295.gd7dffce

>>
>>
>>
>>
>> --
>> Mike Holmes
>> Program Manager - Linaro Networking Group
>> Linaro.org │ Open source software for ARM SoCs
>> "Work should be fun and collaborative, the rest follows"
>>
>>



Re: [lng-odp] [PATCH] travis: several tries to download cunit

2017-01-30 Thread Maxim Uvarov
On 01/30/17 01:03, Bill Fischofer wrote:
> On Fri, Jan 27, 2017 at 1:21 PM, Maxim Uvarov  wrote:
>> some time curl fails to download cunit from sf.net or it's
>> mirrors. Try 10 times with 1 second delay.
>>
>> Signed-off-by: Maxim Uvarov 
>> ---
>>  .travis.yml | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/.travis.yml b/.travis.yml
>> index 03e61b18..363c1b3f 100644
>> --- a/.travis.yml
>> +++ b/.travis.yml
>> @@ -25,7 +25,7 @@ before_install:
>>
>>  #   Install cunit for the validation tests because distro version is 
>> too old and fails C99 compile
>>  - export CUNIT_VERSION=2.1-3
>> -- curl -sSOL 
>> http://sourceforge.net/projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
>> +- for _ in {1..10}; do 
>> http://souirceforge.net/projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
>>  && break; sleep 1; done
> 
> If we're going to make this more robust, what happens if the 10
> attempts all fail? Do we just run off the rails as before or make an
> attempt to quit with some sort of useful debug msg?
> 

In that case CI will fail. It is clear from the log that it failed due
to missing CUnit.

Actually that is strange why it happens. I see the OE also downloads it
from sourceforge:
http://cgit.openembedded.org/meta-openembedded/tree/meta-oe/recipes-devtools/cunit/cunit_2.1-3.bb?h=master
and as back up there is mirror, which is also source forge:
http://git.yoctoproject.org/cgit.cgi/poky/plain/meta/conf/bitbake.conf?h=blinky

But there is no any reason to have mirror because curl has option to
follow redirections on the mirrors. I think that something in mirror
switching algorithm might be wrong. If I'm understand right main site
redirects to mirror which on access is down. Curl just fails with empty
response. On next try mirror list has to be already updated and alive
mirror will be selected.

Log message should be like this:
https://s3.amazonaws.com/archive.travis-ci.org/jobs/196256512/log.txt


If that later will not help we can put CUnit sources to our github.

Maxim.



>>  - tar -jxf *.bz2
>>  - cd CUnit*
>>  - ./bootstrap
>> --
>> 2.11.0.295.gd7dffce
>>



Re: [lng-odp] [PATCH] travis: several tries to download cunit

2017-01-30 Thread Bill Fischofer
On Mon, Jan 30, 2017 at 8:30 AM, Mike Holmes  wrote:
> Currently we have forked the repo and we pull from that copy, that copy is
> on Anders poeple.linaro.org for the internal Jenkins CI
>
> Maybe we add cunit fork to the lng offical repo location so that we can do
> this from github also and not  have to point at a personal location ?

If we're going to fork, agree we should do so "officially" rather than
in a personal repo.

>
> Mike
>
> On 29 January 2017 at 17:03, Bill Fischofer 
> wrote:
>>
>> On Fri, Jan 27, 2017 at 1:21 PM, Maxim Uvarov 
>> wrote:
>> > some time curl fails to download cunit from sf.net or it's
>> > mirrors. Try 10 times with 1 second delay.
>> >
>> > Signed-off-by: Maxim Uvarov 
>> > ---
>> >  .travis.yml | 2 +-
>> >  1 file changed, 1 insertion(+), 1 deletion(-)
>> >
>> > diff --git a/.travis.yml b/.travis.yml
>> > index 03e61b18..363c1b3f 100644
>> > --- a/.travis.yml
>> > +++ b/.travis.yml
>> > @@ -25,7 +25,7 @@ before_install:
>> >
>> >  #   Install cunit for the validation tests because distro version
>> > is too old and fails C99 compile
>> >  - export CUNIT_VERSION=2.1-3
>> > -- curl -sSOL
>> > http://sourceforge.net/projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
>> > +- for _ in {1..10}; do
>> > http://souirceforge.net/projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
>> > && break; sleep 1; done
>>
>> If we're going to make this more robust, what happens if the 10
>> attempts all fail? Do we just run off the rails as before or make an
>> attempt to quit with some sort of useful debug msg?
>>
>> >  - tar -jxf *.bz2
>> >  - cd CUnit*
>> >  - ./bootstrap
>> > --
>> > 2.11.0.295.gd7dffce
>> >
>
>
>
>
> --
> Mike Holmes
> Program Manager - Linaro Networking Group
> Linaro.org │ Open source software for ARM SoCs
> "Work should be fun and collaborative, the rest follows"
>
>


[lng-odp] [PATCH] helper: iplookuptable: avoid potential null pointer dereferences

2017-01-30 Thread Bill Fischofer
Resolve Bug https://bugs.linaro.org/show_bug.cgi?id=2862 by checking
pointer validity before dereferencing.

Signed-off-by: Bill Fischofer 
---
 helper/iplookuptable.c | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/helper/iplookuptable.c b/helper/iplookuptable.c
index aaebea3..845125b 100644
--- a/helper/iplookuptable.c
+++ b/helper/iplookuptable.c
@@ -666,12 +666,14 @@ odph_iplookup_table_put_value(odph_table_t tbl, void 
*key, void *value)
odph_iplookup_table_impl *impl = (void *)tbl;
odph_iplookup_prefix_t *prefix = (odph_iplookup_prefix_t *)key;
prefix_entry_t *l1e = NULL;
-   odp_buffer_t nexthop = *((odp_buffer_t *)value);
+   odp_buffer_t nexthop;
int ret = 0;
 
if ((tbl == NULL) || (key == NULL) || (value == NULL))
return -1;
 
+   nexthop = *((odp_buffer_t *)value);
+
if (prefix->cidr == 0)
return -1;
prefix->ip = prefix->ip & (0x << (IP_LENGTH - prefix->cidr));
@@ -708,13 +710,16 @@ int odph_iplookup_table_get_value(odph_table_t tbl, void 
*key,
  uint32_t buffer_size ODP_UNUSED)
 {
odph_iplookup_table_impl *impl = (void *)tbl;
-   uint32_t ip = *((uint32_t *)key);
-   prefix_entry_t *entry = &impl->l1e[ip >> 16];
+   uint32_t ip;
+   prefix_entry_t *entry;
odp_buffer_t *buff = (odp_buffer_t *)buffer;
 
if ((tbl == NULL) || (key == NULL) || (buffer == NULL))
return -EINVAL;
 
+   ip = *((uint32_t *)key);
+   entry = &impl->l1e[ip >> 16];
+
if (entry == NULL) {
ODPH_DBG("failed to get L1 entry.\n");
return -1;
@@ -881,13 +886,16 @@ odph_iplookup_table_remove_value(odph_table_t tbl, void 
*key)
 {
odph_iplookup_table_impl *impl = (void *)tbl;
odph_iplookup_prefix_t *prefix = (odph_iplookup_prefix_t *)key;
-   uint32_t ip = prefix->ip;
-   uint8_t cidr = prefix->cidr;
+   uint32_t ip;
+   uint8_t cidr;
 
if ((tbl == NULL) || (key == NULL))
return -EINVAL;
 
-   if (!prefix->cidr)
+   ip   = prefix->ip;
+   cidr = prefix->cidr;
+
+   if (cidr == 0)
return -EINVAL;
 
prefix_entry_t *entry = &impl->l1e[ip >> 16];
-- 
2.9.3



Re: [lng-odp] [PATCH] travis: several tries to download cunit

2017-01-30 Thread Mike Holmes
Currently we have forked the repo and we pull from that copy, that copy is
on Anders poeple.linaro.org for the internal Jenkins CI

Maybe we add cunit fork to the lng offical repo location so that we can do
this from github also and not  have to point at a personal location ?

Mike

On 29 January 2017 at 17:03, Bill Fischofer 
wrote:

> On Fri, Jan 27, 2017 at 1:21 PM, Maxim Uvarov 
> wrote:
> > some time curl fails to download cunit from sf.net or it's
> > mirrors. Try 10 times with 1 second delay.
> >
> > Signed-off-by: Maxim Uvarov 
> > ---
> >  .travis.yml | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/.travis.yml b/.travis.yml
> > index 03e61b18..363c1b3f 100644
> > --- a/.travis.yml
> > +++ b/.travis.yml
> > @@ -25,7 +25,7 @@ before_install:
> >
> >  #   Install cunit for the validation tests because distro version
> is too old and fails C99 compile
> >  - export CUNIT_VERSION=2.1-3
> > -- curl -sSOL http://sourceforge.net/
> projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
> > +- for _ in {1..10}; do http://souirceforge.net/
> projects/cunit/files/CUnit/${CUNIT_VERSION}/CUnit-${CUNIT_VERSION}.tar.bz2
> && break; sleep 1; done
>
> If we're going to make this more robust, what happens if the 10
> attempts all fail? Do we just run off the rails as before or make an
> attempt to quit with some sort of useful debug msg?
>
> >  - tar -jxf *.bz2
> >  - cd CUnit*
> >  - ./bootstrap
> > --
> > 2.11.0.295.gd7dffce
> >
>



-- 
Mike Holmes
Program Manager - Linaro Networking Group
Linaro.org  *│ *Open source software for ARM SoCs
"Work should be fun and collaborative, the rest follows"


[lng-odp] [PATCH 2/2] validation: classification: add test case for ipv6 src and dst addr

2017-01-30 Thread Balasubramanian Manoharan
Adds test case for ipv6 source and destination address matching

Signed-off-by: Balasubramanian Manoharan 
---
 .../validation/api/classification/classification.h |  21 ++
 .../api/classification/odp_classification_common.c | 149 ++-
 .../classification/odp_classification_test_pmr.c   | 292 +++--
 .../api/classification/odp_classification_tests.c  |  42 ++-
 .../classification/odp_classification_testsuites.h |  14 +-
 5 files changed, 423 insertions(+), 95 deletions(-)

diff --git a/test/common_plat/validation/api/classification/classification.h 
b/test/common_plat/validation/api/classification/classification.h
index d73c821..0192e24 100644
--- a/test/common_plat/validation/api/classification/classification.h
+++ b/test/common_plat/validation/api/classification/classification.h
@@ -55,6 +55,27 @@
 #define DATA_MAGIC 0x01020304
 #define TEST_SEQ_INVALID   ((uint32_t)~0)
 
+/* Test packet Time-to-live */
+#define DEFAULT_TTL  128
+
+/* Test packet default DSCP value */
+#define LOW_DROP_PRECEDENCE  0x02
+#define MEDIUM_DROP_PRECEDENCE   0x04
+#define HIGH_DROP_PRECEDENCE 0x06
+#define DROP_PRECEDENCE_MASK 0x06
+#define DSCP_CLASS1  0x08
+#define DSCP_CLASS2  0x10
+#define DSCP_CLASS3  0x18
+#define DSCP_CLASS4  0x20
+#define DEFAULT_DSCP (DSCP_CLASS2 | LOW_DROP_PRECEDENCE)
+
+/* Test packet default ECN */
+#define DEFAULT_ECN  ODPH_IP_ECN_ECT0
+
+/* Test packet default TOS */
+#define DEFAULT_TOS  ((DEFAULT_DSCP << ODPH_IP_TOS_DSCP_SHIFT) | \
+   DEFAULT_ECN)
+
 /* test functions: */
 void classification_test_create_cos(void);
 void classification_test_destroy_cos(void);
diff --git 
a/test/common_plat/validation/api/classification/odp_classification_common.c 
b/test/common_plat/validation/api/classification/odp_classification_common.c
index f7ec6e5..a947074 100644
--- a/test/common_plat/validation/api/classification/odp_classification_common.c
+++ b/test/common_plat/validation/api/classification/odp_classification_common.c
@@ -14,6 +14,16 @@ typedef struct cls_test_packet {
odp_u32be_t seq;
 } cls_test_packet_t;
 
+static uint8_t IPV6_SRC_ADDR[ODPH_IPV6ADDR_LEN] = {
+   /* I.e. :::10.0.0.1 */
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 10, 0, 0, 1
+};
+
+static uint8_t IPV6_DST_ADDR[ODPH_IPV6ADDR_LEN] = {
+   /* I.e. :::10.0.0.100 */
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 10, 0, 0, 100
+};
+
 odp_pktio_t create_pktio(odp_queue_type_t q_type, odp_pool_t pool)
 {
odp_pktio_t pktio;
@@ -211,21 +221,14 @@ odp_pool_t pool_create(const char *poolname)
return odp_pool_create(poolname, ¶m);
 }
 
-odp_packet_t create_packet(odp_pool_t pool, bool vlan,
-  odp_atomic_u32_t *seq, bool flag_udp)
-{
-   return create_packet_len(pool, vlan, seq, flag_udp, 0);
-}
-
-odp_packet_t create_packet_len(odp_pool_t pool, bool vlan,
-  odp_atomic_u32_t *seq, bool flag_udp,
-  uint16_t len)
+odp_packet_t create_packet(cls_packet_info_t pkt_info)
 {
uint32_t seqno;
odph_ethhdr_t *ethhdr;
odph_udphdr_t *udp;
odph_tcphdr_t *tcp;
odph_ipv4hdr_t *ip;
+   odph_ipv6hdr_t *ipv6;
uint16_t payload_len;
uint64_t src_mac = CLS_DEFAULT_SMAC;
uint64_t dst_mac = CLS_DEFAULT_DMAC;
@@ -235,6 +238,14 @@ odp_packet_t create_packet_len(odp_pool_t pool, bool vlan,
int offset;
odp_packet_t pkt;
int packet_len = 0;
+   uint32_tversion, tc, flow, ver_tc_flow;
+   uint8_t *buf, next_hdr;
+   uint32_tl4_len, l3_len, l2_len, l3_offset, l4_offset;
+   uint16_t vlan_hdr_len = 0;
+   uint16_t l2_hdr_len = 0;
+   uint16_t l3_hdr_len = 0;
+   uint16_t l4_hdr_len = 0;
+   uint16_t eth_type;
 
/* 48 bit ethernet address needs to be left shifted for proper
value after changing to be*/
@@ -242,77 +253,88 @@ odp_packet_t create_packet_len(odp_pool_t pool, bool vlan,
if (dst_mac != dst_mac_be)
dst_mac_be = dst_mac_be >> (64 - 8 * ODPH_ETHADDR_LEN);
 
-   payload_len = sizeof(cls_test_packet_t) + len;
-   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);
+   payload_len = sizeof(cls_test_packet_t) + pkt_info.len;
+   seqno = odp_atomic_fetch_inc_u32(pkt_info.seq);
+
+   vlan_hdr_len = pkt_info.vlan ? ODPH_VLANHDR_LEN : 0;
+   l3_hdr_len = pkt_info.ipv6 ? ODPH_IPV6HDR_LEN : ODPH_IPV4HDR_LEN;
+   l4_hdr_len = pkt_info.udp ? ODPH_UDPHDR_LEN : OD

[lng-odp] [PATCH 1/2] linux-generic: classification: implement ipv6 packet matching rule

2017-01-30 Thread Balasubramanian Manoharan
Implements IPV6 src and dst address packet matching rule

Signed-off-by: Balasubramanian Manoharan 
---
 .../include/odp_classification_datamodel.h | 11 +-
 .../include/odp_classification_inlines.h   | 44 ++
 .../linux-generic/include/odp_packet_internal.h|  5 +++
 platform/linux-generic/odp_classification.c| 26 +
 4 files changed, 77 insertions(+), 9 deletions(-)

diff --git a/platform/linux-generic/include/odp_classification_datamodel.h 
b/platform/linux-generic/include/odp_classification_datamodel.h
index f6393ee..5b1cde3 100644
--- a/platform/linux-generic/include/odp_classification_datamodel.h
+++ b/platform/linux-generic/include/odp_classification_datamodel.h
@@ -25,6 +25,7 @@ extern "C" {
 #include 
 #include 
 #include 
+#include 
 
 /* Maximum Class Of Service Entry */
 #define ODP_COS_MAX_ENTRY  64
@@ -43,7 +44,7 @@ extern "C" {
 /* Max L3 QoS Value */
 #define ODP_COS_MAX_L3_QOS (1 << ODP_COS_L3_QOS_BITS)
 /* Max PMR Term bits */
-#define ODP_PMR_TERM_BYTES_MAX 8
+#define ODP_PMR_TERM_BYTES_MAX 16
 
 /**
 Packet Matching Rule Term Value
@@ -67,6 +68,14 @@ typedef struct pmr_term_value {
/** End value of the range */
uint64_tval_end;
} range;
+   struct {
+   uint8_t value[_ODP_IPV6ADDR_LEN];
+   uint8_t mask[_ODP_IPV6ADDR_LEN];
+   } match_ipv6;
+   struct {
+   uint8_t val_start[_ODP_IPV6ADDR_LEN];
+   uint8_t val_end[_ODP_IPV6ADDR_LEN];
+   } range_ipv6;
};
uint32_toffset; /**< Offset if term == ODP_PMR_CUSTOM_FRAME */
uint32_tval_sz; /**< Size of the value to be matched */
diff --git a/platform/linux-generic/include/odp_classification_inlines.h 
b/platform/linux-generic/include/odp_classification_inlines.h
index b839197..4d85cf2 100644
--- a/platform/linux-generic/include/odp_classification_inlines.h
+++ b/platform/linux-generic/include/odp_classification_inlines.h
@@ -179,19 +179,47 @@ static inline int verify_pmr_dmac(const uint8_t *pkt_addr,
return 0;
 }
 
-static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr ODP_UNUSED,
-   odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
-   pmr_term_value_t *term_value ODP_UNUSED)
+static inline int verify_pmr_ipv6_saddr(const uint8_t *pkt_addr,
+   odp_packet_hdr_t *pkt_hdr,
+   pmr_term_value_t *term_value)
 {
-   ODP_UNIMPLEMENTED();
+   const _odp_ipv6hdr_t *ipv6;
+   uint8_t src_addr[_ODP_IPV6ADDR_LEN];
+   uint8_t i;
+
+   if (!packet_hdr_has_ipv6(pkt_hdr))
+   return 0;
+
+   ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
+   memcpy(src_addr, ipv6->src_addr, _ODP_IPV6ADDR_LEN);
+   for (i = 0; i < _ODP_IPV6ADDR_LEN; i++)
+   src_addr[i] = src_addr[i] & term_value->match_ipv6.mask[i];
+
+   if (!memcmp(term_value->match_ipv6.value, src_addr, _ODP_IPV6ADDR_LEN))
+   return 1;
+
return 0;
 }
 
-static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr ODP_UNUSED,
-   odp_packet_hdr_t *pkt_hdr ODP_UNUSED,
-   pmr_term_value_t *term_value ODP_UNUSED)
+static inline int verify_pmr_ipv6_daddr(const uint8_t *pkt_addr,
+   odp_packet_hdr_t *pkt_hdr,
+   pmr_term_value_t *term_value)
 {
-   ODP_UNIMPLEMENTED();
+   const _odp_ipv6hdr_t *ipv6;
+   uint8_t dst_addr[_ODP_IPV6ADDR_LEN];
+   uint8_t i;
+
+   if (!packet_hdr_has_ipv6(pkt_hdr))
+   return 0;
+
+   ipv6 = (const _odp_ipv6hdr_t *)(pkt_addr + pkt_hdr->p.l3_offset);
+   memcpy(dst_addr, ipv6->dst_addr, _ODP_IPV6ADDR_LEN);
+   for (i = 0; i < _ODP_IPV6ADDR_LEN; i++)
+   dst_addr[i] = dst_addr[i] & term_value->match_ipv6.mask[i];
+
+   if (!memcmp(term_value->match_ipv6.value, dst_addr, _ODP_IPV6ADDR_LEN))
+   return 1;
+
return 0;
 }
 
diff --git a/platform/linux-generic/include/odp_packet_internal.h 
b/platform/linux-generic/include/odp_packet_internal.h
index e6e9d74..e3ada5c 100644
--- a/platform/linux-generic/include/odp_packet_internal.h
+++ b/platform/linux-generic/include/odp_packet_internal.h
@@ -294,6 +294,11 @@ static inline int packet_hdr_has_eth(odp_packet_hdr_t 
*pkt_hdr)
return pkt_hdr->p.input_flags.eth;
 }
 
+static inline int packet_hdr_has_ipv6(odp_packet_hdr_t *pkt_hdr)
+{
+   return pkt_hdr->p.input_flags.ipv6;
+}
+
 static inline void packet_set_ts(odp_packet_hdr_t *pkt_hdr, odp_time_t *ts)
 {
if (ts != NULL) {
diff --git a/platform/lin

Re: [lng-odp] schedule_multi returning tasks from multiple queues

2017-01-30 Thread Bill Fischofer
On Mon, Jan 30, 2017 at 6:40 AM, Ola Liljedahl  wrote:
> On 30 January 2017 at 05:18, Honnappa Nagarahalli
>  wrote:
>> On 26 January 2017 at 15:10, Bill Fischofer  
>> wrote:
>>> On Wed, Jan 25, 2017 at 11:13 PM, Honnappa Nagarahalli
>>>  wrote:
 I agree, it needs additional operations. One could combine multiple
 atomic operations into a single stage where possible. If the scheduler
 is implemented in hardware, impact will be less.

 The other option is for the reordering logic to call per packet
 functions which run the atomic stage.
>>>
>>> The idea behind ordered locks is that while most of the processing for
>>> a packet can be done in parallel, there are certain critical sections
>>> that need to be performed in order, and these critical sections
>>> typically fall somewhere in the middle of packet processing rather
>>> than at the start or end where the scheduler might be able to fold
>>> them in in some way as part of the odp_schedule() call.
>>>
>>
>> Let us say that the packet processing pipeline is broken into 3
>> stages. Stage 1, Critical Section stage and Stage 2. Critical section
>> stage is accessible only through atomic queues. Packets, parallel
>> processed in Stage 1 are ordered and enter the Critical Section stage,
>> one at a time.This does not require ordered locking, scheduler ensures
>> Critical Section stage is accessed by one packet at a time.
> Yes but this repeated enqueue/dequeue (through the scheduler) likely
> has a lot of overhead. The ordered locks were added to avoid that
> overhead.

I agree. They were also added to surface HW support for this concept,
such as is present in some Cavium SoCs. ODP APIs try to serve two
goals: provide function that is useful at an application layer, and
allow platform-specific HW features to be exposed in a portable
manner. Ordered locks are an example of satisfying both of these
goals.

>
>>
>>
>>> So the concerns still exist if we allow events from multiple ordered
>>> queues to be returned from a single odp_schedule_multi() call.
>>>

 On 25 January 2017 at 04:16, Ola Liljedahl  
 wrote:
>
>
> On 25 January 2017 at 06:34, Honnappa Nagarahalli
>  wrote:
>>
>> On 24 January 2017 at 19:16, Bill Fischofer 
>> wrote:
>> > On Tue, Jan 24, 2017 at 8:30 AM, Nikhil Agarwal 
>> > 
>> > wrote:
>> >>
>> >>
>> >> -Original Message-
>> >> From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of
>> >> Bill Fischofer
>> >> Sent: Tuesday, January 24, 2017 1:15 AM
>> >> To: Nikhil Agarwal 
>> >> Cc: Kevin Wang ; lng-odp-forward
>> >> ; Yi He 
>> >> Subject: Re: [lng-odp] schedule_multi returning tasks from multiple
>> >> queues
>> >>
>> >> Moving this discussion on the ODP mailing list rather than the 
>> >> Internal
>> >> list as that way it will be archived.
>> >>
>> >> The existing ODP controls over scheduling include schedule groups as
>> >> well as queue priorities. The former is a strict requirement (threads 
>> >> can
>> >> only receive events from queues that belong to a matching scheduler 
>> >> group).
>> >> Queues can belong to only a single scheduler group that is set at
>> >> odp_queue_create() time and is fixed for the life of the queue. 
>> >> Threads can
>> >> belong to multiple scheduler groups and may change membership in these
>> >> groups dynamically via the
>> >> odp_schedule_group_join() and odp_schedule_group_leave() APIs.
>> >>
>> >> The latter (queue priority) is advisory. It is expected that in 
>> >> general
>> >> threads will receive events originating on higher-priority queues 
>> >> ahead of
>> >> those on lower-priority queues, but the default scheduler takes other
>> >> factors into consideration to avoid starvation, etc. The "strict 
>> >> priority"
>> >> (SP) scheduler makes priorities strict, so higher priority queues will
>> >> always be scheduled ahead of lower priority queues even at the risk of
>> >> starvation.
>> >>
>> >> What other scheduling controls are needed / desired?
>> >>
>> >> With regard to receiving events from multiple queues in response to
>> >> odp_schedule_multi() there are several points that need clarification:
>> >>
>> >> 1. What is the use case for this capability? How many different
>> >> events/queues would one expect to be eligible to be returned in a 
>> >> single
>> >> call? Presumably this is a relatively small number (< 10). How does 
>> >> this
>> >> compare with having multiple threads running in parallel servicing 
>> >> events
>> >> from individual queues?
>> >>
>> >> This will give benefit of burst processing and improve performance.
>> >> Generally we does burst processing of 8 packets. This will reduce 16
>> >> hardware interactions (in forwarding scenario, 8 RX and 8 

Re: [lng-odp] schedule_multi returning tasks from multiple queues

2017-01-30 Thread Ola Liljedahl
On 30 January 2017 at 05:18, Honnappa Nagarahalli
 wrote:
> On 26 January 2017 at 15:10, Bill Fischofer  wrote:
>> On Wed, Jan 25, 2017 at 11:13 PM, Honnappa Nagarahalli
>>  wrote:
>>> I agree, it needs additional operations. One could combine multiple
>>> atomic operations into a single stage where possible. If the scheduler
>>> is implemented in hardware, impact will be less.
>>>
>>> The other option is for the reordering logic to call per packet
>>> functions which run the atomic stage.
>>
>> The idea behind ordered locks is that while most of the processing for
>> a packet can be done in parallel, there are certain critical sections
>> that need to be performed in order, and these critical sections
>> typically fall somewhere in the middle of packet processing rather
>> than at the start or end where the scheduler might be able to fold
>> them in in some way as part of the odp_schedule() call.
>>
>
> Let us say that the packet processing pipeline is broken into 3
> stages. Stage 1, Critical Section stage and Stage 2. Critical section
> stage is accessible only through atomic queues. Packets, parallel
> processed in Stage 1 are ordered and enter the Critical Section stage,
> one at a time.This does not require ordered locking, scheduler ensures
> Critical Section stage is accessed by one packet at a time.
Yes but this repeated enqueue/dequeue (through the scheduler) likely
has a lot of overhead. The ordered locks were added to avoid that
overhead.

>
>
>> So the concerns still exist if we allow events from multiple ordered
>> queues to be returned from a single odp_schedule_multi() call.
>>
>>>
>>> On 25 January 2017 at 04:16, Ola Liljedahl  wrote:


 On 25 January 2017 at 06:34, Honnappa Nagarahalli
  wrote:
>
> On 24 January 2017 at 19:16, Bill Fischofer 
> wrote:
> > On Tue, Jan 24, 2017 at 8:30 AM, Nikhil Agarwal 
> > wrote:
> >>
> >>
> >> -Original Message-
> >> From: lng-odp [mailto:lng-odp-boun...@lists.linaro.org] On Behalf Of
> >> Bill Fischofer
> >> Sent: Tuesday, January 24, 2017 1:15 AM
> >> To: Nikhil Agarwal 
> >> Cc: Kevin Wang ; lng-odp-forward
> >> ; Yi He 
> >> Subject: Re: [lng-odp] schedule_multi returning tasks from multiple
> >> queues
> >>
> >> Moving this discussion on the ODP mailing list rather than the Internal
> >> list as that way it will be archived.
> >>
> >> The existing ODP controls over scheduling include schedule groups as
> >> well as queue priorities. The former is a strict requirement (threads 
> >> can
> >> only receive events from queues that belong to a matching scheduler 
> >> group).
> >> Queues can belong to only a single scheduler group that is set at
> >> odp_queue_create() time and is fixed for the life of the queue. 
> >> Threads can
> >> belong to multiple scheduler groups and may change membership in these
> >> groups dynamically via the
> >> odp_schedule_group_join() and odp_schedule_group_leave() APIs.
> >>
> >> The latter (queue priority) is advisory. It is expected that in general
> >> threads will receive events originating on higher-priority queues 
> >> ahead of
> >> those on lower-priority queues, but the default scheduler takes other
> >> factors into consideration to avoid starvation, etc. The "strict 
> >> priority"
> >> (SP) scheduler makes priorities strict, so higher priority queues will
> >> always be scheduled ahead of lower priority queues even at the risk of
> >> starvation.
> >>
> >> What other scheduling controls are needed / desired?
> >>
> >> With regard to receiving events from multiple queues in response to
> >> odp_schedule_multi() there are several points that need clarification:
> >>
> >> 1. What is the use case for this capability? How many different
> >> events/queues would one expect to be eligible to be returned in a 
> >> single
> >> call? Presumably this is a relatively small number (< 10). How does 
> >> this
> >> compare with having multiple threads running in parallel servicing 
> >> events
> >> from individual queues?
> >>
> >> This will give benefit of burst processing and improve performance.
> >> Generally we does burst processing of 8 packets. This will reduce 16
> >> hardware interactions (in forwarding scenario, 8 RX and 8 TX) to 2 and 
> >> gives
> >> significant boost in performance. Even the DPDK event scheduler gives 
> >> such
> >> flexibility.
> >>
> >> 2. While semantically this would work for parallel queues, since the
> >> scheduler provides no synchronization context for events originating 
> >> from
> >> parallel queues, is it acceptable / useful to have this restriction in 
> >> the
> >> API?  If not, then it's not obvious how multiple atomic or ordered 
> >> contexts
> >> are expected to be ma

Re: [lng-odp] odp_schedule_group_destroy API documentation

2017-01-30 Thread Ola Liljedahl
On 30 January 2017 at 04:21, Honnappa Nagarahalli
 wrote:
>
> On 29 January 2017 at 18:56, Bill Fischofer  wrote:
> > On Sat, Jan 28, 2017 at 1:40 PM, Honnappa Nagarahalli
> >  wrote:
> >> Hi,
> >>   The current documentation is as follows:
> >>
> >> /**
> >>  * Schedule group destroy
> >>  *
> >>  * Destroys a schedule group. All queues belonging to the schedule group 
> >> must
> >>  * be destroyed before destroying the group. Other operations on this group
> >>  * must not be invoked in parallel.
> >>  *
> >>  * @param group   Schedule group handle
> >>  *
> >>  * @retval 0 on success
> >>  * @retval <0 on failure
> >>  */
> >>
> >> I think this description is not complete. It needs to talk about the 
> >> threads.
> >
> > The ODP API specification is intended to be minimal to give
> > implementations maximum flexibility. Schedule groups are tied to
> > queues here because it is queues that are the schedulable entities,
> > not threads.  When a queue is being considered the question the
> > scheduler asks is "is this thread a member of this queue's scheduler
> > group"?
>
> So, the scheduler group has 2 relations, one with the queue and one
> with the threads.
>
> Whether the thread is also a member of some other schedule
> > group that is not under consideration is not relevant from a
> > scheduling standpoint, whether or not that schedule group exists.
> >
> >>
> >> What should the application do with the threads that have joined this 
> >> group?
> >
> > Resource release is always trickier than resource allocation. Best
> > practices would be for applications calling
> > odp_schedule_group_destroy() to ensure that no active threads are
> > members of that group. A documentation note is probably worthwhile to
> > include here, but the only thing actually required is that no queues
> > belong to the group being destroyed.
>
> Since the scheduler group has 2 relations, the documentation should
> talk about both the relations. Just like the queues, we should add
> 'all the threads that have joined the group must leave the group
> before destroying'.

I agree with Honnappa here. The current spec doesn't define what
should happen if you try to destroy a scheduler group while there are
still members (threads). Undefined or implementation specific
behaviour is a bad idea, this mistake is easy to make in an
application. It might then work with some ODP implementations and fail
with others.

The general principle in ODP seems to be that resources must be
explicitly returned (freed, closed etc). Are there any examples of the
opposite (automatic resource reclamation)?

>
>
> >
> >> If the group is an application created group, it is application's
> >> responsibility to remove the threads from this group. For the default
> >> groups (group_worker/all/control), the threads leave the group
> >> automatically, there is no action required from the application to
> >> remove the threads from the group.
> >>
> >> Is my understanding correct here?
> >
> > Predefined groups cannot be validly destroyed by the application since
> > it did not create them. odp-linux rejects such attempts, but it's
> > probably sufficient to say that results are undefined if this were
> > attempted.
> >
> >>
> >> Thank you,
> >> Honnappa


Re: [lng-odp] [PATCH] example: add IPv4 fragmentation/reassembly example

2017-01-30 Thread Ola Liljedahl
On 30 January 2017 at 02:28, Bill Fischofer 
wrote:

> As the maintainer of the ODP git repo, Maxim has final say on style
> questions for what is accepted into it, so I recommend deferring to
> him on this. This is true of all open source projects, so there's
> nothing new here.
>
I am pointing out that Maxim's knowledge and arguments about the C language
are limited.
"Create/call a separation function" is not always a meaningful alternative
that simplifies complexity.
An inner block with local declarations and a separate function are not
semantically equivalent.
Declaring variables at the top of the function scope could also make some C
language features impossible to use, e.g. use const variables that are
assigned the return value of a function call or some other value that
cannot be computed at the top of the function.
With this knowledge, perhaps the current rules can be improved.


>
> If we want to set up a separate ODP examples repo that can accommodate
> examples written in other languages, or that uses a different set of
> acceptable style rules, then final say on what would go into that repo
> would again be with that repo's maintainer. Actually, such an examples
> repo is probably a good idea as it would be very clear that these
> programs are designed to be compiled and run against many different
> ODP implementations.
>
> It would be great to have dozens of example programs and applications
> that are published this way. Linaro could certainly host such a repo
> to make it clear that it is vendor-neutral, but I suspect we'd want to
> have another maintainer for it as Maxim's plate is already very full.
> Any volunteers?
>
> On Fri, Jan 27, 2017 at 7:51 AM, Ola Liljedahl 
> wrote:
> > On 26 January 2017 at 16:56, Maxim Uvarov 
> wrote:
> >
> >> On 01/26/17 18:27, Ola Liljedahl wrote:
> >> >
> >> >
> >> > On 26 January 2017 at 15:19, Joe Savage  >> > > wrote:
> >> >
> >> > > >> It will be very helpful if rehe was some README with
> >> description about
> >> > > >> this app, run environments and some output. So people can
> learn
> >> > > >> something before looking to code.
> >> > > >
> >> > > > I can add one, but I don't think there's really that much to
> >> describe. Since
> >> > > > the example doesn't connect to the network, all that users
> >> really need to
> >> > > > know is that it fragments and reassembles IPv4 packets.
> >> > >
> >> > > you add that description here:
> >> > > ./doc/application-api-guide/examples.dox
> >> > >
> >> > > Description can be about application internals. Like you create
> N
> >> > > workers, use queue with nsize to reassembly packets. Use
> following
> >> > > algorithm.
> >> > >
> >> > > And why this app is not connected to network? I think it will be
> >> very
> >> > > useful if you can pass some pcap file and get pcap on output.
> And
> >> test
> >> > > this program work with other program which does reassembly. That
> >> looks
> >> > > like good proof that it works as expected.
> >> >
> >> > Adding the example to the list in examples.dox seems sensible,
> but I
> >> > think
> >> > the code and comments are probably the best description of the
> >> algorithm
> >> > itself.
> >> >
> >> > As for why it isn't network connected, I wanted to keep the
> example
> >> > somewhat
> >> > bare bones to its purpose. Dealing with a real network connection
> is
> >> > likely
> >> > to add clutter that doesn't really speak to the contents of this
> >> > specific
> >> > example. Anyone wanting to implement this kind of functionality
> >> > themselves
> >> > can simply glean this information from a different example
> focusing
> >> > around
> >> > the packet I/O interface.
> >> >
> >> > > >
> >> > > >> app naming might be not best.
> >> > > >
> >> > > > Hmm... do you have any other ideas? I didn't want it to be too
> >> long, and both
> >> > > > "fragmentation" and "reassembly" are unfortunately lengthy.
> >> > > >
> >> > >
> >> > > ipfrag or ipv4frag?
> >> >
> >> > Ehh, maybe. The fragmentation doesn't really play a huge role here
> >> > though,
> >> > the reassembly is really the star of the show. Perhaps ipfragreass
> >> > or just
> >> > ipreass?
> >> >
> >> >
> >> > > >> in early examples we defined max workers, but actully it's
> not
> >> needed
> >> > > >> becase you can ask odp how many workers are there with 0.
> >> > > >> I.e. in your code it will be:
> >> > > >> *num_workers = odp_cpumask_default_worker(cpumask, 0)
> >> > > >
> >> > > > I did see this in the documentation, but since the
> functionality
> >> was present
> >> > > > in other examples I thought it might be worthwhile to allow a
> >> maximum number
> >> > > > of workers to be set. Happy to remove this to use all
> available
> >> CPUs if it
> >> > > > is 

[lng-odp] [PATCH v2] example: add IPv4 fragmentation/reassembly example

2017-01-30 Thread Joe Savage
Add an example application implementing lock-free IPv4 fragmentation
and reassembly functionality using ODP's packet "concat" and "split".

Signed-off-by: Joe Savage 
---
(This code contribution is provided under the terms of agreement LES-LTM-21309)

 doc/application-api-guide/examples.dox   |   5 +
 example/Makefile.am  |   1 +
 example/ipfragreass/.gitignore   |   3 +
 example/ipfragreass/Makefile.am  |  22 +
 example/ipfragreass/odp_ipfragreass.c| 393 
 example/ipfragreass/odp_ipfragreass_atomics.h| 124 
 example/ipfragreass/odp_ipfragreass_fragment.c   |  99 +++
 example/ipfragreass/odp_ipfragreass_fragment.h   |  28 +
 example/ipfragreass/odp_ipfragreass_helpers.c| 121 
 example/ipfragreass/odp_ipfragreass_helpers.h| 129 
 example/ipfragreass/odp_ipfragreass_ip.h | 251 
 example/ipfragreass/odp_ipfragreass_reassemble.c | 772 +++
 example/ipfragreass/odp_ipfragreass_reassemble.h | 211 +++
 example/m4/configure.m4  |   1 +
 14 files changed, 2160 insertions(+)
 create mode 100644 example/ipfragreass/.gitignore
 create mode 100644 example/ipfragreass/Makefile.am
 create mode 100644 example/ipfragreass/odp_ipfragreass.c
 create mode 100644 example/ipfragreass/odp_ipfragreass_atomics.h
 create mode 100644 example/ipfragreass/odp_ipfragreass_fragment.c
 create mode 100644 example/ipfragreass/odp_ipfragreass_fragment.h
 create mode 100644 example/ipfragreass/odp_ipfragreass_helpers.c
 create mode 100644 example/ipfragreass/odp_ipfragreass_helpers.h
 create mode 100644 example/ipfragreass/odp_ipfragreass_ip.h
 create mode 100644 example/ipfragreass/odp_ipfragreass_reassemble.c
 create mode 100644 example/ipfragreass/odp_ipfragreass_reassemble.h

diff --git a/doc/application-api-guide/examples.dox 
b/doc/application-api-guide/examples.dox
index 60d4058..80fe467 100644
--- a/doc/application-api-guide/examples.dox
+++ b/doc/application-api-guide/examples.dox
@@ -28,3 +28,8 @@
  * @example odp_timer_test.c
  * ODP timer example application
  */
+
+ /**
+  * @example odp_ipfragreass.c
+  * ODP IPv4 lock-free fragmentation and reassembly example application
+  */
diff --git a/example/Makefile.am b/example/Makefile.am
index dfc07b6..9503a1b 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -2,6 +2,7 @@ SUBDIRS = classifier \
  generator \
  hello \
  ipsec \
+ ipfragreass \
  l2fwd_simple \
  l3fwd \
  packet \
diff --git a/example/ipfragreass/.gitignore b/example/ipfragreass/.gitignore
new file mode 100644
index 000..d25d758
--- /dev/null
+++ b/example/ipfragreass/.gitignore
@@ -0,0 +1,3 @@
+odp_ipfragreass
+*.log
+*.trs
diff --git a/example/ipfragreass/Makefile.am b/example/ipfragreass/Makefile.am
new file mode 100644
index 000..d9abce9
--- /dev/null
+++ b/example/ipfragreass/Makefile.am
@@ -0,0 +1,22 @@
+include $(top_srcdir)/example/Makefile.inc
+
+bin_PROGRAMS = odp_ipfragreass$(EXEEXT)
+odp_ipfragreass_LDFLAGS = $(AM_LDFLAGS) -static
+odp_ipfragreass_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example
+
+noinst_HEADERS = \
+ $(top_srcdir)/example/ipfragreass/odp_ipfragreass_atomics.h \
+ $(top_srcdir)/example/ipfragreass/odp_ipfragreass_fragment.h \
+ $(top_srcdir)/example/ipfragreass/odp_ipfragreass_helpers.h \
+ $(top_srcdir)/example/ipfragreass/odp_ipfragreass_ip.h \
+ 
$(top_srcdir)/example/ipfragreass/odp_ipfragreass_reassemble.h \
+ $(top_srcdir)/example/example_debug.h
+
+dist_odp_ipfragreass_SOURCES = odp_ipfragreass.c \
+  odp_ipfragreass_fragment.c \
+  odp_ipfragreass_helpers.c \
+  odp_ipfragreass_reassemble.c
+
+if test_example
+TESTS = odp_ipfragreass
+endif
diff --git a/example/ipfragreass/odp_ipfragreass.c 
b/example/ipfragreass/odp_ipfragreass.c
new file mode 100644
index 000..8956703
--- /dev/null
+++ b/example/ipfragreass/odp_ipfragreass.c
@@ -0,0 +1,393 @@
+/* Copyright (c) 2017, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * @example odp_ipfragreass.c  ODP IPv4 lock-free fragmentation and reassembly
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "odp_ipfragreass_fragment.h"
+#include "odp_ipfragreass_reassemble.h"
+#include "odp_ipfragreass_helpers.h"
+
+#define NUM_PACKETS 200   /**< Number of packets to fragment/reassemble */
+#define MAX_WORKERS 32/**< Maximum number of worker threads */
+#define FRAGLISTS   16384 /**< Hash map size for reassembly */
+
+#define MIN_MF_FRAG_SIZE  576  /**< Minimum fragment size */
+#define MAX_PKT_LEN  8192 /**< Maximum packet size */
+#define MAX_FRAGS_PER_PKT 6/**< Maximum number of fragments per packet */
+
+/**