[lng-odp] [PATCH v1 1/1] linux-gen: add runtime configuration file

2018-02-23 Thread Github ODP bot
From: Matias Elo 

Enables changing ODP runtime configuration options by using an optional
configuration file (libconfig). Path to the conf file is passed using
environment variable ODP_CONF_FILE. If ODP_CONF_FILE or a particular option
is not set, hardcoded default values are used intead. An example
configuration file is provided in config/odp-linux.conf.

Runtime configuration is initially used by DPDK pktio to set NIC options.

Adds new dependency to libconfig library.

Signed-off-by: Matias Elo 
---
/** Email created from pull request 499 (matiaselo:dev/dpdk_dev_config)
 ** https://github.com/Linaro/odp/pull/499
 ** Patch: https://github.com/Linaro/odp/pull/499.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: ab13bcecea3972b5af189e9e5d6d4873790fb554
 **/
 .travis.yml|  3 +-
 DEPENDENCIES   |  2 +-
 config/README  |  8 +++
 config/odp-linux.conf  | 20 +++
 m4/odp_libconfig.m4| 60 +
 platform/linux-generic/Makefile.am |  4 ++
 platform/linux-generic/include/odp_internal.h  |  4 ++
 .../linux-generic/include/odp_libconfig_internal.h | 29 ++
 platform/linux-generic/include/odp_packet_dpdk.h   |  8 +++
 platform/linux-generic/libodp-linux.pc.in  |  4 +-
 platform/linux-generic/m4/configure.m4 |  1 +
 platform/linux-generic/odp_init.c  | 14 +
 platform/linux-generic/odp_libconfig.c | 57 
 platform/linux-generic/pktio/dpdk.c| 63 --
 platform/linux-generic/test/ring/Makefile.am   |  1 +
 15 files changed, 271 insertions(+), 7 deletions(-)
 create mode 100644 config/odp-linux.conf
 create mode 100644 m4/odp_libconfig.m4
 create mode 100644 platform/linux-generic/include/odp_libconfig_internal.h
 create mode 100644 platform/linux-generic/odp_libconfig.c

diff --git a/.travis.yml b/.travis.yml
index d9423adcc..4095516c9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,6 +21,7 @@ addons:
 - gcc
 - clang-3.8
 - automake autoconf libtool libssl-dev graphviz mscgen
+- libconfig-dev
 - codespell
 - libpcap-dev
 - libnuma-dev
@@ -254,7 +255,7 @@ script:
 - make -j $(nproc)
 - mkdir /dev/shm/odp
 - if [ -z "$CROSS_ARCH" ] ; then
-  sudo 
LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" 
ODP_SHM_DIR=/dev/shm/odp make check ;
+  sudo ODP_CONFIG_FILE="`pwd`/config/odp-linux.conf" 
LD_LIBRARY_PATH="$HOME/cunit-install/$CROSS_ARCH/lib:$LD_LIBRARY_PATH" 
ODP_SHM_DIR=/dev/shm/odp make check ;
   fi
 - make install
 
diff --git a/DEPENDENCIES b/DEPENDENCIES
index 6f374ca92..b6765fecd 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -19,7 +19,7 @@ Prerequisites for building the OpenDataPlane (ODP) API
 
 3. Required libraries
 
-   Libraries currently required to link: openssl, libatomic
+   Libraries currently required to link: openssl, libatomic, libconfig
 
 3.1 OpenSSL native compile
 
diff --git a/config/README b/config/README
index 3f4336103..415334255 100644
--- a/config/README
+++ b/config/README
@@ -1,2 +1,10 @@
 ODP configuration options
 -
+
+Runtime configuration options can be passed to an ODP instance by
+setting ODP_CONFIG_FILE environment variable to point to a libconfig
+format configuration file. An example configuration file with default
+values is provided in config/odp-linux.conf. If ODP_CONFIG_FILE is not
+found, hardcoded default values are used instead of any configuration
+file. A configuration file doesn't have to include all available
+options. The missing options are replaced with hardcoded default values.
diff --git a/config/odp-linux.conf b/config/odp-linux.conf
new file mode 100644
index 0..eb40f5212
--- /dev/null
+++ b/config/odp-linux.conf
@@ -0,0 +1,20 @@
+# ODP runtime configuration options
+#
+# A configuration file doesn't have to include all available
+# options. The missing options are replaced with hardcoded default
+# values.
+#
+# See libconfig syntax: 
https://hyperrealm.github.io/libconfig/libconfig_manual.html#Configuration-Files
+
+# DPDK pktio options
+pktio_dpdk: {
+   # Default options
+   num_rx_desc = 128
+   num_tx_desc = 512
+   rx_drop_en = 0
+
+   # Driver specific options (use PMD names from DPDK)
+   net_ixgbe: {
+   rx_drop_en = 1
+   }
+}
diff --git a/m4/odp_libconfig.m4 b/m4/odp_libconfig.m4
new file mode 100644
index 0..e5b1d8acd
--- /dev/null
+++ b/m4/odp_libconfig.m4
@@ -0,0 +1,60 @@
+# ODP_LIBCONFIG([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# 

[lng-odp] [PATCH v1 0/1] linux-gen: add runtime configuration file

2018-02-23 Thread Github ODP bot
Enables changing ODP runtime configuration options by using an optional
configuration file (libconfig). Path to the conf file is passed using
environment variable ODP_CONF_FILE. If ODP_CONF_FILE or a particular option
is not set, hardcoded default values are used intead. An example
configuration file is provided in config/odp-linux.conf.
Runtime configuration is initially used by DPDK pktio to set NIC options.
Adds new dependency to libconfig library.
Signed-off-by: Matias Elo matias@nokia.com

github
/** Email created from pull request 499 (matiaselo:dev/dpdk_dev_config)
 ** https://github.com/Linaro/odp/pull/499
 ** Patch: https://github.com/Linaro/odp/pull/499.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: ab13bcecea3972b5af189e9e5d6d4873790fb554
 **/
/github

checkpatch.pl
WARNING: 'intead' may be misspelled - perhaps 'instead'?
#10: 
is not set, hardcoded default values are used intead. An example

WARNING: externs should be avoided in .c files
#394: FILE: platform/linux-generic/odp_libconfig.c:16:
+extern struct odp_global_data_s odp_global_data;

CHECK: Avoid CamelCase: 
#503: FILE: platform/linux-generic/pktio/dpdk.c:141:
+   printf("DPDK interface (%s): %" PRIu16 "\n", dev_info->driver_name,

total: 0 errors, 2 warnings, 1 checks, 420 lines checked


to_send-p-000.patch has style problems, please review.

If any of these errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
/checkpatch.pl


[lng-odp] [PATCH v7 2/2] validation: pool: verify pool data range

2018-02-23 Thread Github ODP bot
From: Michal Mazur 

Allocate maximum number of packets from pool and verify that packet
data are located inside range returned by odp_pool_info.

Signed-off-by: Michal Mazur 
---
/** Email created from pull request 495 (semihalf-mazur-michal:master)
 ** https://github.com/Linaro/odp/pull/495
 ** Patch: https://github.com/Linaro/odp/pull/495.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: 79aeba092a0c85e26786ff8efbaeb71608ae1fa3
 **/
 test/validation/api/pool/pool.c | 54 +
 1 file changed, 54 insertions(+)

diff --git a/test/validation/api/pool/pool.c b/test/validation/api/pool/pool.c
index 34f973573..394c79497 100644
--- a/test/validation/api/pool/pool.c
+++ b/test/validation/api/pool/pool.c
@@ -217,6 +217,59 @@ static void pool_test_info_packet(void)
CU_ASSERT(odp_pool_destroy(pool) == 0);
 }
 
+static void pool_test_info_data_range(void)
+{
+   odp_pool_t pool;
+   odp_pool_info_t info;
+   odp_pool_param_t param;
+   odp_packet_t pkt[PKT_NUM];
+   uint32_t i, num;
+   uintptr_t pool_len;
+
+   odp_pool_param_init(¶m);
+
+   param.type = ODP_POOL_PACKET;
+   param.pkt.num  = PKT_NUM;
+   param.pkt.len  = PKT_LEN;
+
+   pool = odp_pool_create(NULL, ¶m);
+   CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+   CU_ASSERT_FATAL(odp_pool_info(pool, &info) == 0);
+
+   pool_len = info.max_data_addr - info.min_data_addr + 1;
+   CU_ASSERT(pool_len >= PKT_NUM * PKT_LEN);
+
+   num = 0;
+
+   for (i = 0; i < PKT_NUM; i++) {
+   pkt[num] = odp_packet_alloc(pool, PKT_LEN);
+   CU_ASSERT(pkt[num] != ODP_PACKET_INVALID);
+
+   if (pkt[num] != ODP_PACKET_INVALID)
+   num++;
+   }
+
+   for (i = 0; i < num; i++) {
+   uintptr_t pkt_data, pkt_data_end;
+   uint32_t offset = 0, seg_len;
+   uint32_t pkt_len = odp_packet_len(pkt[i]);
+
+   while (offset < pkt_len) {
+   pkt_data = (uintptr_t)odp_packet_offset(pkt[i], offset,
+   &seg_len, NULL);
+   pkt_data_end = pkt_data + seg_len - 1;
+   CU_ASSERT((pkt_data >= info.min_data_addr) &&
+ (pkt_data_end <= info.max_data_addr));
+   offset += seg_len;
+   }
+
+   odp_packet_free(pkt[i]);
+   }
+
+   CU_ASSERT(odp_pool_destroy(pool) == 0);
+}
+
 odp_testinfo_t pool_suite[] = {
ODP_TEST_INFO(pool_test_create_destroy_buffer),
ODP_TEST_INFO(pool_test_create_destroy_packet),
@@ -225,6 +278,7 @@ odp_testinfo_t pool_suite[] = {
ODP_TEST_INFO(pool_test_alloc_packet_subparam),
ODP_TEST_INFO(pool_test_info_packet),
ODP_TEST_INFO(pool_test_lookup_info_print),
+   ODP_TEST_INFO(pool_test_info_data_range),
ODP_TEST_INFO_NULL,
 };
 



[lng-odp] [PATCH v7 1/2] linux-generic: pool: Return address range in pool info

2018-02-23 Thread Github ODP bot
From: Michal Mazur 

Implement support in odp_pool_info function to provide
address range of pool data available to application.

Pull request of related API change:
https://github.com/Linaro/odp/pull/200

Signed-off-by: Michal Mazur 
---
/** Email created from pull request 495 (semihalf-mazur-michal:master)
 ** https://github.com/Linaro/odp/pull/495
 ** Patch: https://github.com/Linaro/odp/pull/495.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: 79aeba092a0c85e26786ff8efbaeb71608ae1fa3
 **/
 platform/linux-generic/odp_pool.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/platform/linux-generic/odp_pool.c 
b/platform/linux-generic/odp_pool.c
index e5ba8982a..03578135c 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -693,6 +693,9 @@ int odp_pool_info(odp_pool_t pool_hdl, odp_pool_info_t 
*info)
if (pool->params.type == ODP_POOL_PACKET)
info->pkt.max_num = pool->num;
 
+   info->min_data_addr = (uintptr_t)pool->base_addr;
+   info->max_data_addr = (uintptr_t)pool->base_addr + pool->shm_size - 1;
+
return 0;
 }
 



[lng-odp] [PATCH v7 0/2] linux-generic: pool: Return address range in pool info

2018-02-23 Thread Github ODP bot
Implement support in odp_pool_info function to provide
address range of pool data available to application.
Similar change was already merged to caterpillar/linux-dpdk:
#400
Pull request of related API change:
#200

github
/** Email created from pull request 495 (semihalf-mazur-michal:master)
 ** https://github.com/Linaro/odp/pull/495
 ** Patch: https://github.com/Linaro/odp/pull/495.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: 79aeba092a0c85e26786ff8efbaeb71608ae1fa3
 **/
/github

checkpatch.pl
total: 0 errors, 0 warnings, 0 checks, 9 lines checked


to_send-p-000.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 0 checks, 66 lines checked


to_send-p-001.patch has no obvious style problems and is ready for submission.
/checkpatch.pl


Re: [lng-odp] [PATCH v2] Ring implementation of queues

2018-02-23 Thread Github ODP bot
Bill Fischofer(Bill-Fischofer-Linaro) replied on github web page:

platform/linux-generic/include/odp_ring_st_internal.h
line 78
@@ -0,0 +1,118 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_RING_ST_INTERNAL_H_
+#define ODP_RING_ST_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include 
+#include 
+
+/* Basic ring for single thread usage. Operations must be synchronized by using
+ * locks (or other means), when multiple threads use the same ring. */
+typedef struct {
+   uint32_t head;
+   uint32_t tail;
+   uint32_t mask;
+   uint32_t *data;
+
+} ring_st_t;
+
+/* Initialize ring. Ring size must be a power of two. */
+static inline void ring_st_init(ring_st_t *ring, uint32_t *data, uint32_t size)
+{
+   ring->head = 0;
+   ring->tail = 0;
+   ring->mask = size - 1;
+   ring->data = data;
+}
+
+/* Dequeue data from the ring head. Max_num is smaller than ring size.*/
+static inline uint32_t ring_st_deq_multi(ring_st_t *ring, uint32_t data[],
+uint32_t max_num)
+{
+   uint32_t head, tail, mask, idx;
+   uint32_t num, i;
+
+   head = ring->head;
+   tail = ring->tail;
+   mask = ring->mask;
+   num  = tail - head;
+
+   /* Empty */
+   if (num == 0)
+   return 0;
+
+   if (num > max_num)
+   num = max_num;
+
+   idx = head & mask;
+
+   for (i = 0; i < num; i++) {
+   data[i] = ring->data[idx];
+   idx = (idx + 1) & mask;
+   }
+
+   ring->head = head + num;
+
+   return num;
+}
+
+/* Enqueue data into the ring tail. Num_data is smaller than ring size. */
+static inline uint32_t ring_st_enq_multi(ring_st_t *ring, const uint32_t 
data[],
+uint32_t num_data)
+{
+   uint32_t head, tail, mask, size, idx;
+   uint32_t num, i;
+
+   head = ring->head;
+   tail = ring->tail;
+   mask = ring->mask;
+   size = mask + 1;
+   num  = size - (tail - head);


Comment:
Please see above discussion. The comment stands.

> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Not true. See the comment below where it's clear that `head` and `tail` are 
> free running and thus will eventually wrap as described above. If these were 
> `uint64_t` variables you could argue that the wraps would take centuries and 
> hence are nothing to worry about, but being `uint32_t` variables this should 
> be expected to happen regularly on heavily used queues. 
> 
> `abs()` adds no overhead since compilers treat it as an intrinsic.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Note that neither `head` nor `tail` get masked when doing enqueues or 
>> dequeues, so they will traverse the entire 32-bit range of the variable over 
>> time. While the ring itself will never hold more than `size` entries, `head` 
>> and `tail` will wrap around. When you index into the ring you do so via a 
>> mask (`idx = head & mask;`), but calculating the number of elements in the 
>> ring doesn't do this, which is why `abs()` is needed.


>>> Petri Savolainen(psavol) wrote:
>>> Plus this is done only once - in pool create phase.


 Petri Savolainen(psavol) wrote:
 No since ring size will be much smaller than 4 billion.


> Petri Savolainen(psavol) wrote:
> The point is that ring size will never be close to 4 billion entries. 
> E.g. currently tail is always max 4096 larger than head. Your example 
> above is based assumption of 4 billion entry ring. Overflow is avoided 
> when ring size if <2 billion, as 32 bit indexes can be still used to 
> calculate number of items correctly.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Agreed.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Agreed, this is good for now. Later we may wish to honor the 
>>> user-requested queue `size` parameter.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 Agreed.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Correct, as noted earlier. I withdraw that comment.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Presumably the compiler will see the overlap and optimize away the 
>> redundancy, so I assume the performance impact will be nil here.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Since you're allowing `head` and `tail` to run over the entire 
>>> 32-bit range, you're correct that you can completely fill the ring. 
>>> I did miss that point. However, as shown above you still need this 
>>> to be:
>>> 
>>> ```
>>> num = size - abs(tail - head);
>>> ```
>>> To avoid problems at the 32-bit wrap boundary.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 You're computing in 32 bits not 8 bits, and your ring 

Re: [lng-odp] [PATCH v2] Ring implementation of queues

2018-02-23 Thread Github ODP bot
Bill Fischofer(Bill-Fischofer-Linaro) replied on github web page:

platform/linux-generic/include/odp_ring_st_internal.h
line 46
@@ -0,0 +1,118 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_RING_ST_INTERNAL_H_
+#define ODP_RING_ST_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include 
+#include 
+
+/* Basic ring for single thread usage. Operations must be synchronized by using
+ * locks (or other means), when multiple threads use the same ring. */
+typedef struct {
+   uint32_t head;
+   uint32_t tail;
+   uint32_t mask;
+   uint32_t *data;
+
+} ring_st_t;
+
+/* Initialize ring. Ring size must be a power of two. */
+static inline void ring_st_init(ring_st_t *ring, uint32_t *data, uint32_t size)
+{
+   ring->head = 0;
+   ring->tail = 0;
+   ring->mask = size - 1;
+   ring->data = data;
+}
+
+/* Dequeue data from the ring head. Max_num is smaller than ring size.*/
+static inline uint32_t ring_st_deq_multi(ring_st_t *ring, uint32_t data[],
+uint32_t max_num)
+{
+   uint32_t head, tail, mask, idx;
+   uint32_t num, i;
+
+   head = ring->head;
+   tail = ring->tail;
+   mask = ring->mask;
+   num  = tail - head;


Comment:
Not true. See the comment below where it's clear that `head` and `tail` are 
free running and thus will eventually wrap as described above. If these were 
`uint64_t` variables you could argue that the wraps would take centuries and 
hence are nothing to worry about, but being `uint32_t` variables this should be 
expected to happen regularly on heavily used queues. 

`abs()` adds no overhead since compilers treat it as an intrinsic.

> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Note that neither `head` nor `tail` get masked when doing enqueues or 
> dequeues, so they will traverse the entire 32-bit range of the variable over 
> time. While the ring itself will never hold more than `size` entries, `head` 
> and `tail` will wrap around. When you index into the ring you do so via a 
> mask (`idx = head & mask;`), but calculating the number of elements in the 
> ring doesn't do this, which is why `abs()` is needed.


>> Petri Savolainen(psavol) wrote:
>> Plus this is done only once - in pool create phase.


>>> Petri Savolainen(psavol) wrote:
>>> No since ring size will be much smaller than 4 billion.


 Petri Savolainen(psavol) wrote:
 The point is that ring size will never be close to 4 billion entries. E.g. 
 currently tail is always max 4096 larger than head. Your example above is 
 based assumption of 4 billion entry ring. Overflow is avoided when ring 
 size if <2 billion, as 32 bit indexes can be still used to calculate 
 number of items correctly.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Agreed.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Agreed, this is good for now. Later we may wish to honor the 
>> user-requested queue `size` parameter.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Agreed.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 Correct, as noted earlier. I withdraw that comment.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Presumably the compiler will see the overlap and optimize away the 
> redundancy, so I assume the performance impact will be nil here.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Since you're allowing `head` and `tail` to run over the entire 
>> 32-bit range, you're correct that you can completely fill the ring. 
>> I did miss that point. However, as shown above you still need this 
>> to be:
>> 
>> ```
>> num = size - abs(tail - head);
>> ```
>> To avoid problems at the 32-bit wrap boundary.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> You're computing in 32 bits not 8 bits, and your ring size is less 
>>> than 2^32 elements. Consider the following test program:
>>> ```
>>> #include 
>>> #include 
>>> #include 
>>> #include 
>>> 
>>> void main() {
>>> uint32_t head[4] = {0, 1, 2, 3};
>>> uint32_t tail[4] = {0, 0x, 0xfffe, 0xfffd};
>>> uint32_t mask = 4095;
>>> uint32_t result;
>>> int i;
>>> 
>>> for (i = 0; i < 4; i++) {
>>> printf("head = %" PRIu32 " tail = %" PRIu32 ":\n",
>>>head[i], tail[i]);
>>> 
>>> result = tail[i] - head[i];
>>> printf("tail - head = %" PRIu32 "\n", result);
>>> 
>>> result = (tail[i] - head[i]) & mask;
>>> printf("(tail - head) & mask = %" PRIu32 "\n", result);
>>> 
>>>

Re: [lng-odp] [PATCH v2] Ring implementation of queues

2018-02-23 Thread Github ODP bot
Bill Fischofer(Bill-Fischofer-Linaro) replied on github web page:

platform/linux-generic/include/odp_ring_st_internal.h
line 62
@@ -0,0 +1,109 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_RING_ST_INTERNAL_H_
+#define ODP_RING_ST_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include 
+#include 
+
+/* Basic ring for single thread usage. Operations must be synchronized by using
+ * locks (or other means), when multiple threads use the same ring. */
+typedef struct {
+   uint32_t head;
+   uint32_t tail;
+   uint32_t mask;
+   uint32_t *data;
+
+} ring_st_t;
+
+/* Initialize ring. Ring size must be a power of two. */
+static inline void ring_st_init(ring_st_t *ring, uint32_t *data, uint32_t size)
+{
+   ring->head = 0;
+   ring->tail = 0;
+   ring->mask = size - 1;
+   ring->data = data;
+}
+
+/* Dequeue data from the ring head. Max_num is smaller than ring size.*/
+static inline uint32_t ring_st_deq_multi(ring_st_t *ring, uint32_t data[],
+uint32_t max_num)
+{
+   uint32_t head, tail, mask, idx;
+   uint32_t num, i;
+
+   head = ring->head;
+   tail = ring->tail;
+   mask = ring->mask;
+   num  = tail - head;
+
+   /* Empty */
+   if (num == 0)
+   return 0;
+
+   if (num > max_num)
+   num = max_num;
+
+   idx = head & mask;
+
+   for (i = 0; i < num; i++) {
+   data[i] = ring->data[idx];
+   idx = (idx + 1) & mask;
+   }
+
+   ring->head = head + num;


Comment:
Note that neither `head` nor `tail` get masked when doing enqueues or dequeues, 
so they will traverse the entire 32-bit range of the variable over time. While 
the ring itself will never hold more than `size` entries, `head` and `tail` 
will wrap around. When you index into the ring you do so via a mask (`idx = 
head & mask;`), but calculating the number of elements in the ring doesn't do 
this, which is why `abs()` is needed.

> Petri Savolainen(psavol) wrote:
> Plus this is done only once - in pool create phase.


>> Petri Savolainen(psavol) wrote:
>> No since ring size will be much smaller than 4 billion.


>>> Petri Savolainen(psavol) wrote:
>>> The point is that ring size will never be close to 4 billion entries. E.g. 
>>> currently tail is always max 4096 larger than head. Your example above is 
>>> based assumption of 4 billion entry ring. Overflow is avoided when ring 
>>> size if <2 billion, as 32 bit indexes can be still used to calculate number 
>>> of items correctly.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 Agreed.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Agreed, this is good for now. Later we may wish to honor the 
> user-requested queue `size` parameter.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Agreed.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Correct, as noted earlier. I withdraw that comment.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 Presumably the compiler will see the overlap and optimize away the 
 redundancy, so I assume the performance impact will be nil here.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Since you're allowing `head` and `tail` to run over the entire 32-bit 
> range, you're correct that you can completely fill the ring. I did 
> miss that point. However, as shown above you still need this to be:
> 
> ```
> num = size - abs(tail - head);
> ```
> To avoid problems at the 32-bit wrap boundary.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> You're computing in 32 bits not 8 bits, and your ring size is less 
>> than 2^32 elements. Consider the following test program:
>> ```
>> #include 
>> #include 
>> #include 
>> #include 
>> 
>> void main() {
>>  uint32_t head[4] = {0, 1, 2, 3};
>>  uint32_t tail[4] = {0, 0x, 0xfffe, 0xfffd};
>>  uint32_t mask = 4095;
>>  uint32_t result;
>>  int i;
>> 
>>  for (i = 0; i < 4; i++) {
>>  printf("head = %" PRIu32 " tail = %" PRIu32 ":\n",
>> head[i], tail[i]);
>> 
>>  result = tail[i] - head[i];
>>  printf("tail - head = %" PRIu32 "\n", result);
>> 
>>  result = (tail[i] - head[i]) & mask;
>>  printf("(tail - head) & mask = %" PRIu32 "\n", result);
>> 
>>  result = abs(tail[i] - head[i]);
>>  printf("abs(tail - head) = %" PRIu32 "\n\n", result);
>>  }
>> }
>> ```
>> in theory `tail - head` should be the number of elem

Re: [lng-odp] [PATCH API-NEXT v1] api: packet: data and segment length

2018-02-23 Thread Github ODP bot
Bill Fischofer(Bill-Fischofer-Linaro) replied on github web page:

include/odp/api/spec/packet.h
line 39
@@ -401,30 +401,39 @@ uint32_t odp_packet_buf_len(odp_packet_t pkt);
 /**
  * Packet data pointer
  *
- * Returns the current packet data pointer. When a packet is received
- * from packet input, this points to the first byte of the received
- * packet. Packet level offsets are calculated relative to this position.
+ * Returns pointer to the first byte of packet data. When packet is segmented,
+ * only a portion of packet data follows the pointer. When unsure, use e.g.
+ * odp_packet_seg_len() to check the data length following the pointer. Packet
+ * level offsets are calculated relative to this position.
  *
- * User can adjust the data pointer with head_push/head_pull (does not modify
- * segmentation) and add_data/rem_data calls (may modify segmentation).
+ * When a packet is received from packet input, this points to the first byte
+ * of the received packet. Pool configuration parameters may be used to ensure
+ * that the first packet segment contains all/most of the data relevant to the
+ * application.
+ *
+ * User can adjust the data pointer with e.g. push_head/pull_head (does not
+ * modify segmentation) and extend_head/trunc_head (may modify segmentation)
+ * calls.
  *
  * @param pkt  Packet handle
  *
  * @return  Pointer to the packet data
  *
- * @see odp_packet_l2_ptr(), odp_packet_seg_len()
+ * @see odp_packet_seg_len(), odp_packet_push_head(), odp_packet_extend_head()
  */
 void *odp_packet_data(odp_packet_t pkt);
 
 /**
- * Packet segment data length
+ * Packet data length following the data pointer
  *
- * Returns number of data bytes following the current data pointer
- * (odp_packet_data()) location in the segment.
+ * Returns number of data bytes (in the segment) following the current data
+ * pointer position. When unsure, use this function to check how many bytes


Comment:
Segments are inherently implementation-dependent, which is why portable 
applications should avoid processing packets in terms of segments. Applications 
only need be aware that segments may exist, meaning that packets may not be 
contiguously addressable. This is why a `seg_len` is returned on the various 
routines that provide addressability to packets. `odp_packet_data()` is the 
exception, and this was done as an efficiency measure for applications looking 
at headers contained at the start of the packet that are known to be contiguous 
because of the `min_seg_len` pool specification.

> Petri Savolainen(psavol) wrote:
> Yes. I didn't want to introduce a new limitation to segment/reference 
> implementation here. This patch just tries to make it clear that packets may 
> be segmented.
> 
>  E.g. Bill's reference implementation resulted packets that had first segment 
> length 0 and data pointer pointed to the second segment. It passed all 
> validation tests. From application point of view, it does not matter much if 
> spec allows empty segments to be linked into packet, although it's not very 
> intuitive and should be avoided when possible. 


>> Balasubramanian Manoharan(bala-manoharan) wrote:
>> In the entire documentation you have avoided the term "first segment" is it 
>> by choice?
>> IMO we could refer this as first segment valid data bytes


>>> Petri Savolainen(psavol) wrote:
>>> seg_len / push_head / extend_head are mentioned above. Packet_offset is not 
>>> specialized for handling first N bytes of packet, so it's not directly 
>>> related to these ones.


 Petri Savolainen(psavol) wrote:
 packet_offset is for different purpose (access data on arbitrary offset), 
 these calls are optimized for the common case (offset zero). Also 
 odp_packet_seg_data_len(), the new data_seg_len(),  odp_packet_l2_ptr(), 
 odp_packet_l3_ptr()  and odp_packet_l4_ptr() output seg len, but we don't 
 need to list all possible ways to get it. It's enough that the reader 
 understands that a packet may have segments and segment length is 
 different thing than total packet length


> Dmitry Eremin-Solenikov(lumag) wrote:
> And here too, please.


>> Dmitry Eremin-Solenikov(lumag) wrote:
>> odp_packet_seg_len() **or odp_packet_offset()**, if you don't mind.


https://github.com/Linaro/odp/pull/497#discussion_r170275071
updated_at 2018-02-23 15:06:52


[lng-odp] [PATCH v6 1/2] linux-generic: pool: Return address range in pool info

2018-02-23 Thread Github ODP bot
From: Michal Mazur 

Implement support in odp_pool_info function to provide
address range of pool data available to application.

Pull request of related API change:
https://github.com/Linaro/odp/pull/200

Signed-off-by: Michal Mazur 
---
/** Email created from pull request 495 (semihalf-mazur-michal:master)
 ** https://github.com/Linaro/odp/pull/495
 ** Patch: https://github.com/Linaro/odp/pull/495.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: 0390589df2dbf51cfd601bc4baf1b06b571653bb
 **/
 platform/linux-generic/odp_pool.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/platform/linux-generic/odp_pool.c 
b/platform/linux-generic/odp_pool.c
index e5ba8982a..03578135c 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -693,6 +693,9 @@ int odp_pool_info(odp_pool_t pool_hdl, odp_pool_info_t 
*info)
if (pool->params.type == ODP_POOL_PACKET)
info->pkt.max_num = pool->num;
 
+   info->min_data_addr = (uintptr_t)pool->base_addr;
+   info->max_data_addr = (uintptr_t)pool->base_addr + pool->shm_size - 1;
+
return 0;
 }
 



[lng-odp] [PATCH v6 2/2] validation: pool: verify pool data range

2018-02-23 Thread Github ODP bot
From: Michal Mazur 

Allocate maximum number of packets from pool and verify that packet
data are located inside range returned by odp_pool_info.

Signed-off-by: Michal Mazur 
---
/** Email created from pull request 495 (semihalf-mazur-michal:master)
 ** https://github.com/Linaro/odp/pull/495
 ** Patch: https://github.com/Linaro/odp/pull/495.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: 0390589df2dbf51cfd601bc4baf1b06b571653bb
 **/
 test/validation/api/pool/pool.c | 46 +
 1 file changed, 46 insertions(+)

diff --git a/test/validation/api/pool/pool.c b/test/validation/api/pool/pool.c
index 34f973573..f6ebb6886 100644
--- a/test/validation/api/pool/pool.c
+++ b/test/validation/api/pool/pool.c
@@ -217,6 +217,51 @@ static void pool_test_info_packet(void)
CU_ASSERT(odp_pool_destroy(pool) == 0);
 }
 
+static void pool_test_info_data_range(void)
+{
+   odp_pool_t pool;
+   odp_pool_info_t info;
+   odp_pool_param_t param;
+   odp_packet_t pkt[PKT_NUM];
+   uint32_t i, num, seg_len;
+   uintptr_t pkt_data, pool_len;
+
+   odp_pool_param_init(¶m);
+
+   param.type = ODP_POOL_PACKET;
+   param.pkt.num  = PKT_NUM;
+   param.pkt.len  = PKT_LEN;
+
+   pool = odp_pool_create(NULL, ¶m);
+   CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+   CU_ASSERT_FATAL(odp_pool_info(pool, &info) == 0);
+
+   pool_len = info.max_data_addr - info.min_data_addr + 1;
+   CU_ASSERT(pool_len >= PKT_NUM * PKT_LEN);
+
+   num = 0;
+
+   for (i = 0; i < PKT_NUM; i++) {
+   pkt[num] = odp_packet_alloc(pool, PKT_LEN);
+   CU_ASSERT(pkt[num] != ODP_PACKET_INVALID);
+
+   if (pkt[num] != ODP_PACKET_INVALID)
+   num++;
+   }
+
+   for (i = 0; i < num; i++) {
+   pkt_data = (uintptr_t)odp_packet_data(pkt[i]);
+   seg_len = odp_packet_seg_len(pkt[i]);
+   CU_ASSERT((pkt_data >= info.min_data_addr) &&
+ (pkt_data + seg_len - 1 <= info.max_data_addr));
+
+   odp_packet_free(pkt[i]);
+   }
+
+   CU_ASSERT(odp_pool_destroy(pool) == 0);
+}
+
 odp_testinfo_t pool_suite[] = {
ODP_TEST_INFO(pool_test_create_destroy_buffer),
ODP_TEST_INFO(pool_test_create_destroy_packet),
@@ -225,6 +270,7 @@ odp_testinfo_t pool_suite[] = {
ODP_TEST_INFO(pool_test_alloc_packet_subparam),
ODP_TEST_INFO(pool_test_info_packet),
ODP_TEST_INFO(pool_test_lookup_info_print),
+   ODP_TEST_INFO(pool_test_info_data_range),
ODP_TEST_INFO_NULL,
 };
 



[lng-odp] [PATCH v6 0/2] linux-generic: pool: Return address range in pool info

2018-02-23 Thread Github ODP bot
Implement support in odp_pool_info function to provide
address range of pool data available to application.
Similar change was already merged to caterpillar/linux-dpdk:
#400
Pull request of related API change:
#200

github
/** Email created from pull request 495 (semihalf-mazur-michal:master)
 ** https://github.com/Linaro/odp/pull/495
 ** Patch: https://github.com/Linaro/odp/pull/495.patch
 ** Base sha: 5a58bbf2bb331fd7dde2ebbc0430634ace6900fb
 ** Merge commit sha: 0390589df2dbf51cfd601bc4baf1b06b571653bb
 **/
/github

checkpatch.pl
total: 0 errors, 0 warnings, 0 checks, 9 lines checked


to_send-p-000.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 0 checks, 58 lines checked


to_send-p-001.patch has no obvious style problems and is ready for submission.
/checkpatch.pl


Re: [lng-odp] [PATCH API-NEXT v1] api: packet: data and segment length

2018-02-23 Thread Github ODP bot
Petri Savolainen(psavol) replied on github web page:

include/odp/api/spec/packet.h
line 39
@@ -401,30 +401,39 @@ uint32_t odp_packet_buf_len(odp_packet_t pkt);
 /**
  * Packet data pointer
  *
- * Returns the current packet data pointer. When a packet is received
- * from packet input, this points to the first byte of the received
- * packet. Packet level offsets are calculated relative to this position.
+ * Returns pointer to the first byte of packet data. When packet is segmented,
+ * only a portion of packet data follows the pointer. When unsure, use e.g.
+ * odp_packet_seg_len() to check the data length following the pointer. Packet
+ * level offsets are calculated relative to this position.
  *
- * User can adjust the data pointer with head_push/head_pull (does not modify
- * segmentation) and add_data/rem_data calls (may modify segmentation).
+ * When a packet is received from packet input, this points to the first byte
+ * of the received packet. Pool configuration parameters may be used to ensure
+ * that the first packet segment contains all/most of the data relevant to the
+ * application.
+ *
+ * User can adjust the data pointer with e.g. push_head/pull_head (does not
+ * modify segmentation) and extend_head/trunc_head (may modify segmentation)
+ * calls.
  *
  * @param pkt  Packet handle
  *
  * @return  Pointer to the packet data
  *
- * @see odp_packet_l2_ptr(), odp_packet_seg_len()
+ * @see odp_packet_seg_len(), odp_packet_push_head(), odp_packet_extend_head()
  */
 void *odp_packet_data(odp_packet_t pkt);
 
 /**
- * Packet segment data length
+ * Packet data length following the data pointer
  *
- * Returns number of data bytes following the current data pointer
- * (odp_packet_data()) location in the segment.
+ * Returns number of data bytes (in the segment) following the current data
+ * pointer position. When unsure, use this function to check how many bytes


Comment:
Yes. I didn't want to introduce a new limitation to segment/reference 
implementation here. This patch just tries to make it clear that packets may be 
segmented.

 E.g. Bill's reference implementation resulted packets that had first segment 
length 0 and data pointer pointed to the second segment. It passed all 
validation tests. From application point of view, it does not matter much if 
spec allows empty segments to be linked into packet, although it's not very 
intuitive and should be avoided when possible. 

> Balasubramanian Manoharan(bala-manoharan) wrote:
> In the entire documentation you have avoided the term "first segment" is it 
> by choice?
> IMO we could refer this as first segment valid data bytes


>> Petri Savolainen(psavol) wrote:
>> seg_len / push_head / extend_head are mentioned above. Packet_offset is not 
>> specialized for handling first N bytes of packet, so it's not directly 
>> related to these ones.


>>> Petri Savolainen(psavol) wrote:
>>> packet_offset is for different purpose (access data on arbitrary offset), 
>>> these calls are optimized for the common case (offset zero). Also 
>>> odp_packet_seg_data_len(), the new data_seg_len(),  odp_packet_l2_ptr(), 
>>> odp_packet_l3_ptr()  and odp_packet_l4_ptr() output seg len, but we don't 
>>> need to list all possible ways to get it. It's enough that the reader 
>>> understands that a packet may have segments and segment length is different 
>>> thing than total packet length


 Dmitry Eremin-Solenikov(lumag) wrote:
 And here too, please.


> Dmitry Eremin-Solenikov(lumag) wrote:
> odp_packet_seg_len() **or odp_packet_offset()**, if you don't mind.


https://github.com/Linaro/odp/pull/497#discussion_r170220664
updated_at 2018-02-23 10:45:55


Re: [lng-odp] [PATCH API-NEXT v1] api: packet: data and segment length

2018-02-23 Thread Github ODP bot
Balasubramanian Manoharan(bala-manoharan) replied on github web page:

include/odp/api/spec/packet.h
line 39
@@ -401,30 +401,39 @@ uint32_t odp_packet_buf_len(odp_packet_t pkt);
 /**
  * Packet data pointer
  *
- * Returns the current packet data pointer. When a packet is received
- * from packet input, this points to the first byte of the received
- * packet. Packet level offsets are calculated relative to this position.
+ * Returns pointer to the first byte of packet data. When packet is segmented,
+ * only a portion of packet data follows the pointer. When unsure, use e.g.
+ * odp_packet_seg_len() to check the data length following the pointer. Packet
+ * level offsets are calculated relative to this position.
  *
- * User can adjust the data pointer with head_push/head_pull (does not modify
- * segmentation) and add_data/rem_data calls (may modify segmentation).
+ * When a packet is received from packet input, this points to the first byte
+ * of the received packet. Pool configuration parameters may be used to ensure
+ * that the first packet segment contains all/most of the data relevant to the
+ * application.
+ *
+ * User can adjust the data pointer with e.g. push_head/pull_head (does not
+ * modify segmentation) and extend_head/trunc_head (may modify segmentation)
+ * calls.
  *
  * @param pkt  Packet handle
  *
  * @return  Pointer to the packet data
  *
- * @see odp_packet_l2_ptr(), odp_packet_seg_len()
+ * @see odp_packet_seg_len(), odp_packet_push_head(), odp_packet_extend_head()
  */
 void *odp_packet_data(odp_packet_t pkt);
 
 /**
- * Packet segment data length
+ * Packet data length following the data pointer
  *
- * Returns number of data bytes following the current data pointer
- * (odp_packet_data()) location in the segment.
+ * Returns number of data bytes (in the segment) following the current data
+ * pointer position. When unsure, use this function to check how many bytes


Comment:
In the entire documentation you have avoided the term "first segment" is it by 
choice?
IMO we could refer this as first segment valid data bytes

> Petri Savolainen(psavol) wrote:
> seg_len / push_head / extend_head are mentioned above. Packet_offset is not 
> specialized for handling first N bytes of packet, so it's not directly 
> related to these ones.


>> Petri Savolainen(psavol) wrote:
>> packet_offset is for different purpose (access data on arbitrary offset), 
>> these calls are optimized for the common case (offset zero). Also 
>> odp_packet_seg_data_len(), the new data_seg_len(),  odp_packet_l2_ptr(), 
>> odp_packet_l3_ptr()  and odp_packet_l4_ptr() output seg len, but we don't 
>> need to list all possible ways to get it. It's enough that the reader 
>> understands that a packet may have segments and segment length is different 
>> thing than total packet length


>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>> And here too, please.


 Dmitry Eremin-Solenikov(lumag) wrote:
 odp_packet_seg_len() **or odp_packet_offset()**, if you don't mind.


https://github.com/Linaro/odp/pull/497#discussion_r170204670
updated_at 2018-02-23 09:36:37


Re: [lng-odp] [PATCH v5] linux-generic: pool: Return address range in pool info

2018-02-23 Thread Github ODP bot
Petri Savolainen(psavol) replied on github web page:

test/validation/api/pool/pool.c
line 40
@@ -217,6 +217,50 @@ static void pool_test_info_packet(void)
CU_ASSERT(odp_pool_destroy(pool) == 0);
 }
 
+static void pool_test_info_data_range(void)
+{
+   odp_pool_t pool;
+   odp_pool_info_t info;
+   odp_pool_param_t param;
+   odp_packet_t pkt[PKT_NUM];
+   uint32_t i, num;
+   uintptr_t pkt_data, pool_len;
+
+   odp_pool_param_init(¶m);
+
+   param.type = ODP_POOL_PACKET;
+   param.pkt.num  = PKT_NUM;
+   param.pkt.len  = PKT_LEN;
+
+   pool = odp_pool_create(NULL, ¶m);
+   CU_ASSERT_FATAL(pool != ODP_POOL_INVALID);
+
+   CU_ASSERT_FATAL(odp_pool_info(pool, &info) == 0);
+
+   pool_len = info.max_data_addr - info.min_data_addr + 1;
+   CU_ASSERT(pool_len >= PKT_NUM * PKT_LEN);
+
+   num = 0;
+
+   for (i = 0; i < PKT_NUM; i++) {
+   pkt[num] = odp_packet_alloc(pool, PKT_LEN);
+   CU_ASSERT(pkt[num] != ODP_PACKET_INVALID);
+
+   if (pkt[num] != ODP_PACKET_INVALID)
+   num++;
+   }
+
+   for (i = 0; i < num; i++) {
+   pkt_data = (uintptr_t)odp_packet_data(pkt[i]);
+   CU_ASSERT((pkt_data >= info.min_data_addr) &&
+ (pkt_data + PKT_LEN - 1 <= info.max_data_addr));


Comment:
It wrong to assume that entire packet data follows data pointer. Use 
odp_packet_seg_len() instead of PKT_LEN here.

> semihalf-mazur-michal wrote
> Fixed in v4


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> I'd make this `CU_ASSERT()` rather than `CU_ASSERT_FATAL()` so all 
>> discrepancies can be caught. `CU_ASSERT_FATAL()` is reserved for setup 
>> failures that invalidate the entire test (_e.g.,_ not being able to create 
>> the pool, `odp_pool_info()` reporting an error, etc.)


https://github.com/Linaro/odp/pull/495#discussion_r170193779
updated_at 2018-02-23 08:43:57


Re: [lng-odp] [PATCH v2] Ring implementation of queues

2018-02-23 Thread Github ODP bot
Petri Savolainen(psavol) replied on github web page:

platform/linux-generic/odp_pool.c
line 28
@@ -296,7 +282,9 @@ static void init_buffers(pool_t *pool)
memset(buf_hdr, 0, (uintptr_t)data - (uintptr_t)buf_hdr);
 
/* Initialize buffer metadata */
-   buf_hdr->index = i;
+   buf_hdr->index.u32= 0;
+   buf_hdr->index.pool   = pool->pool_idx;
+   buf_hdr->index.buffer = i;


Comment:
Plus this is done only once - in pool create phase.

> Petri Savolainen(psavol) wrote:
> No since ring size will be much smaller than 4 billion.


>> Petri Savolainen(psavol) wrote:
>> The point is that ring size will never be close to 4 billion entries. E.g. 
>> currently tail is always max 4096 larger than head. Your example above is 
>> based assumption of 4 billion entry ring. Overflow is avoided when ring size 
>> if <2 billion, as 32 bit indexes can be still used to calculate number of 
>> items correctly.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Agreed.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 Agreed, this is good for now. Later we may wish to honor the 
 user-requested queue `size` parameter.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Agreed.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Correct, as noted earlier. I withdraw that comment.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Presumably the compiler will see the overlap and optimize away the 
>>> redundancy, so I assume the performance impact will be nil here.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 Since you're allowing `head` and `tail` to run over the entire 32-bit 
 range, you're correct that you can completely fill the ring. I did 
 miss that point. However, as shown above you still need this to be:
 
 ```
 num = size - abs(tail - head);
 ```
 To avoid problems at the 32-bit wrap boundary.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> You're computing in 32 bits not 8 bits, and your ring size is less 
> than 2^32 elements. Consider the following test program:
> ```
> #include 
> #include 
> #include 
> #include 
> 
> void main() {
>   uint32_t head[4] = {0, 1, 2, 3};
>   uint32_t tail[4] = {0, 0x, 0xfffe, 0xfffd};
>   uint32_t mask = 4095;
>   uint32_t result;
>   int i;
> 
>   for (i = 0; i < 4; i++) {
>   printf("head = %" PRIu32 " tail = %" PRIu32 ":\n",
>  head[i], tail[i]);
> 
>   result = tail[i] - head[i];
>   printf("tail - head = %" PRIu32 "\n", result);
> 
>   result = (tail[i] - head[i]) & mask;
>   printf("(tail - head) & mask = %" PRIu32 "\n", result);
> 
>   result = abs(tail[i] - head[i]);
>   printf("abs(tail - head) = %" PRIu32 "\n\n", result);
>   }
> }
> ```
> in theory `tail - head` should be the number of elements in the ring, 
> in this case 0, 2, 4, and 6. But running this test program gives the 
> following output:
> ```
> head = 0 tail = 0:
> tail - head = 0
> (tail - head) & mask = 0
> abs(tail - head) = 0
> 
> head = 1 tail = 4294967295:
> tail - head = 4294967294
> (tail - head) & mask = 4094
> abs(tail - head) = 2
> 
> head = 2 tail = 4294967294:
> tail - head = 4294967292
> (tail - head) & mask = 4092
> abs(tail - head) = 4
> 
> head = 3 tail = 4294967293:
> tail - head = 4294967290
> (tail - head) & mask = 4090
> abs(tail - head) = 6
> ```
> Since you're allowing head to run free over the 32-bit range of the 
> variable, when the 32-bits rolls over you'll get a large positive 
> number, not the small one you need to stay within the ring bounds. 
> The alternative is to mask `head` and `tail` as you increment them, 
> but then you run into the effective range issue.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> OK


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> OK, the `ODP_ASSERT()` would still be useful for debugging.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 That functionality is not obvious from the name. It either implies 
 that one of the input arguments is written (not true here) or the 
 reader might assume that it is an expression without side-effect 
 and should be deleted (what I originally thought when reading it). 
 You should

Re: [lng-odp] [PATCH v2] Ring implementation of queues

2018-02-23 Thread Github ODP bot
Petri Savolainen(psavol) replied on github web page:

platform/linux-generic/include/odp_ring_st_internal.h
line 78
@@ -0,0 +1,118 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_RING_ST_INTERNAL_H_
+#define ODP_RING_ST_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include 
+#include 
+
+/* Basic ring for single thread usage. Operations must be synchronized by using
+ * locks (or other means), when multiple threads use the same ring. */
+typedef struct {
+   uint32_t head;
+   uint32_t tail;
+   uint32_t mask;
+   uint32_t *data;
+
+} ring_st_t;
+
+/* Initialize ring. Ring size must be a power of two. */
+static inline void ring_st_init(ring_st_t *ring, uint32_t *data, uint32_t size)
+{
+   ring->head = 0;
+   ring->tail = 0;
+   ring->mask = size - 1;
+   ring->data = data;
+}
+
+/* Dequeue data from the ring head. Max_num is smaller than ring size.*/
+static inline uint32_t ring_st_deq_multi(ring_st_t *ring, uint32_t data[],
+uint32_t max_num)
+{
+   uint32_t head, tail, mask, idx;
+   uint32_t num, i;
+
+   head = ring->head;
+   tail = ring->tail;
+   mask = ring->mask;
+   num  = tail - head;
+
+   /* Empty */
+   if (num == 0)
+   return 0;
+
+   if (num > max_num)
+   num = max_num;
+
+   idx = head & mask;
+
+   for (i = 0; i < num; i++) {
+   data[i] = ring->data[idx];
+   idx = (idx + 1) & mask;
+   }
+
+   ring->head = head + num;
+
+   return num;
+}
+
+/* Enqueue data into the ring tail. Num_data is smaller than ring size. */
+static inline uint32_t ring_st_enq_multi(ring_st_t *ring, const uint32_t 
data[],
+uint32_t num_data)
+{
+   uint32_t head, tail, mask, size, idx;
+   uint32_t num, i;
+
+   head = ring->head;
+   tail = ring->tail;
+   mask = ring->mask;
+   size = mask + 1;
+   num  = size - (tail - head);


Comment:
No since ring size will be much smaller than 4 billion.

> Petri Savolainen(psavol) wrote:
> The point is that ring size will never be close to 4 billion entries. E.g. 
> currently tail is always max 4096 larger than head. Your example above is 
> based assumption of 4 billion entry ring. Overflow is avoided when ring size 
> if <2 billion, as 32 bit indexes can be still used to calculate number of 
> items correctly.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Agreed.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Agreed, this is good for now. Later we may wish to honor the user-requested 
>>> queue `size` parameter.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 Agreed.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Correct, as noted earlier. I withdraw that comment.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Presumably the compiler will see the overlap and optimize away the 
>> redundancy, so I assume the performance impact will be nil here.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Since you're allowing `head` and `tail` to run over the entire 32-bit 
>>> range, you're correct that you can completely fill the ring. I did miss 
>>> that point. However, as shown above you still need this to be:
>>> 
>>> ```
>>> num = size - abs(tail - head);
>>> ```
>>> To avoid problems at the 32-bit wrap boundary.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 You're computing in 32 bits not 8 bits, and your ring size is less 
 than 2^32 elements. Consider the following test program:
 ```
 #include 
 #include 
 #include 
 #include 
 
 void main() {
uint32_t head[4] = {0, 1, 2, 3};
uint32_t tail[4] = {0, 0x, 0xfffe, 0xfffd};
uint32_t mask = 4095;
uint32_t result;
int i;
 
for (i = 0; i < 4; i++) {
printf("head = %" PRIu32 " tail = %" PRIu32 ":\n",
   head[i], tail[i]);
 
result = tail[i] - head[i];
printf("tail - head = %" PRIu32 "\n", result);
 
result = (tail[i] - head[i]) & mask;
printf("(tail - head) & mask = %" PRIu32 "\n", result);
 
result = abs(tail[i] - head[i]);
printf("abs(tail - head) = %" PRIu32 "\n\n", result);
}
 }
 ```
 in theory `tail - head` should be the number of elements in the ring, 
 in this case 0, 2, 4, and 6. But running this test program gives the 
 following output:
 ```
 head = 0 tail = 0:
 tail - head = 0
>>>

Re: [lng-odp] [PATCH v2] Ring implementation of queues

2018-02-23 Thread Github ODP bot
Petri Savolainen(psavol) replied on github web page:

platform/linux-generic/include/odp_ring_st_internal.h
line 46
@@ -0,0 +1,118 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef ODP_RING_ST_INTERNAL_H_
+#define ODP_RING_ST_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include 
+#include 
+
+/* Basic ring for single thread usage. Operations must be synchronized by using
+ * locks (or other means), when multiple threads use the same ring. */
+typedef struct {
+   uint32_t head;
+   uint32_t tail;
+   uint32_t mask;
+   uint32_t *data;
+
+} ring_st_t;
+
+/* Initialize ring. Ring size must be a power of two. */
+static inline void ring_st_init(ring_st_t *ring, uint32_t *data, uint32_t size)
+{
+   ring->head = 0;
+   ring->tail = 0;
+   ring->mask = size - 1;
+   ring->data = data;
+}
+
+/* Dequeue data from the ring head. Max_num is smaller than ring size.*/
+static inline uint32_t ring_st_deq_multi(ring_st_t *ring, uint32_t data[],
+uint32_t max_num)
+{
+   uint32_t head, tail, mask, idx;
+   uint32_t num, i;
+
+   head = ring->head;
+   tail = ring->tail;
+   mask = ring->mask;
+   num  = tail - head;


Comment:
The point is that ring size will never be close to 4 billion entries. E.g. 
currently tail is always max 4096 larger than head. Your example above is based 
assumption of 4 billion entry ring. Overflow is avoided when ring size if <2 
billion, as 32 bit indexes can be still used to calculate number of items 
correctly.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Agreed.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Agreed, this is good for now. Later we may wish to honor the user-requested 
>> queue `size` parameter.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> Agreed.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 Correct, as noted earlier. I withdraw that comment.


> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
> Presumably the compiler will see the overlap and optimize away the 
> redundancy, so I assume the performance impact will be nil here.


>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>> Since you're allowing `head` and `tail` to run over the entire 32-bit 
>> range, you're correct that you can completely fill the ring. I did miss 
>> that point. However, as shown above you still need this to be:
>> 
>> ```
>> num = size - abs(tail - head);
>> ```
>> To avoid problems at the 32-bit wrap boundary.


>>> Bill Fischofer(Bill-Fischofer-Linaro) wrote:
>>> You're computing in 32 bits not 8 bits, and your ring size is less than 
>>> 2^32 elements. Consider the following test program:
>>> ```
>>> #include 
>>> #include 
>>> #include 
>>> #include 
>>> 
>>> void main() {
>>> uint32_t head[4] = {0, 1, 2, 3};
>>> uint32_t tail[4] = {0, 0x, 0xfffe, 0xfffd};
>>> uint32_t mask = 4095;
>>> uint32_t result;
>>> int i;
>>> 
>>> for (i = 0; i < 4; i++) {
>>> printf("head = %" PRIu32 " tail = %" PRIu32 ":\n",
>>>head[i], tail[i]);
>>> 
>>> result = tail[i] - head[i];
>>> printf("tail - head = %" PRIu32 "\n", result);
>>> 
>>> result = (tail[i] - head[i]) & mask;
>>> printf("(tail - head) & mask = %" PRIu32 "\n", result);
>>> 
>>> result = abs(tail[i] - head[i]);
>>> printf("abs(tail - head) = %" PRIu32 "\n\n", result);
>>> }
>>> }
>>> ```
>>> in theory `tail - head` should be the number of elements in the ring, 
>>> in this case 0, 2, 4, and 6. But running this test program gives the 
>>> following output:
>>> ```
>>> head = 0 tail = 0:
>>> tail - head = 0
>>> (tail - head) & mask = 0
>>> abs(tail - head) = 0
>>> 
>>> head = 1 tail = 4294967295:
>>> tail - head = 4294967294
>>> (tail - head) & mask = 4094
>>> abs(tail - head) = 2
>>> 
>>> head = 2 tail = 4294967294:
>>> tail - head = 4294967292
>>> (tail - head) & mask = 4092
>>> abs(tail - head) = 4
>>> 
>>> head = 3 tail = 4294967293:
>>> tail - head = 4294967290
>>> (tail - head) & mask = 4090
>>> abs(tail - head) = 6
>>> ```
>>> Since you're allowing head to run free over the 32-bit range of the 
>>> variable, when the 32-bits rolls over you'll get a large positive 
>>> number, not the small one you need to stay within the ring bounds. The 
>>> alternative is to mask `head` and `tail` as you increment them, but 
>>> then you run into the effective range issue.


 Bill Fischofer(Bill-Fischofer-Linaro) wrote:
 OK


> 

Re: [lng-odp] [PATCH API-NEXT v1] api: packet: data and segment length

2018-02-23 Thread Github ODP bot
Petri Savolainen(psavol) replied on github web page:

include/odp/api/spec/packet.h
line 28
@@ -401,30 +401,39 @@ uint32_t odp_packet_buf_len(odp_packet_t pkt);
 /**
  * Packet data pointer
  *
- * Returns the current packet data pointer. When a packet is received
- * from packet input, this points to the first byte of the received
- * packet. Packet level offsets are calculated relative to this position.
+ * Returns pointer to the first byte of packet data. When packet is segmented,
+ * only a portion of packet data follows the pointer. When unsure, use e.g.
+ * odp_packet_seg_len() to check the data length following the pointer. Packet
+ * level offsets are calculated relative to this position.
  *
- * User can adjust the data pointer with head_push/head_pull (does not modify
- * segmentation) and add_data/rem_data calls (may modify segmentation).
+ * When a packet is received from packet input, this points to the first byte
+ * of the received packet. Pool configuration parameters may be used to ensure
+ * that the first packet segment contains all/most of the data relevant to the
+ * application.
+ *
+ * User can adjust the data pointer with e.g. push_head/pull_head (does not
+ * modify segmentation) and extend_head/trunc_head (may modify segmentation)
+ * calls.
  *
  * @param pkt  Packet handle
  *
  * @return  Pointer to the packet data
  *
- * @see odp_packet_l2_ptr(), odp_packet_seg_len()
+ * @see odp_packet_seg_len(), odp_packet_push_head(), odp_packet_extend_head()


Comment:
seg_len / push_head / extend_head are mentioned above. Packet_offset is not 
specialized for handling first N bytes of packet, so it's not directly related 
to these ones.

> Petri Savolainen(psavol) wrote:
> packet_offset is for different purpose (access data on arbitrary offset), 
> these calls are optimized for the common case (offset zero). Also 
> odp_packet_seg_data_len(), the new data_seg_len(),  odp_packet_l2_ptr(), 
> odp_packet_l3_ptr()  and odp_packet_l4_ptr() output seg len, but we don't 
> need to list all possible ways to get it. It's enough that the reader 
> understands that a packet may have segments and segment length is different 
> thing than total packet length


>> Dmitry Eremin-Solenikov(lumag) wrote:
>> And here too, please.


>>> Dmitry Eremin-Solenikov(lumag) wrote:
>>> odp_packet_seg_len() **or odp_packet_offset()**, if you don't mind.


https://github.com/Linaro/odp/pull/497#discussion_r170183024
updated_at 2018-02-23 07:36:58


Re: [lng-odp] [PATCH API-NEXT v1] api: packet: data and segment length

2018-02-23 Thread Github ODP bot
Petri Savolainen(psavol) replied on github web page:

include/odp/api/spec/packet.h
line 9
@@ -401,30 +401,39 @@ uint32_t odp_packet_buf_len(odp_packet_t pkt);
 /**
  * Packet data pointer
  *
- * Returns the current packet data pointer. When a packet is received
- * from packet input, this points to the first byte of the received
- * packet. Packet level offsets are calculated relative to this position.
+ * Returns pointer to the first byte of packet data. When packet is segmented,
+ * only a portion of packet data follows the pointer. When unsure, use e.g.
+ * odp_packet_seg_len() to check the data length following the pointer. Packet


Comment:
packet_offset is for different purpose (access data on arbitrary offset), these 
calls are optimized for the common case (offset zero). Also 
odp_packet_seg_data_len(), the new data_seg_len(),  odp_packet_l2_ptr(), 
odp_packet_l3_ptr()  and odp_packet_l4_ptr() output seg len, but we don't need 
to list all possible ways to get it. It's enough that the reader understands 
that a packet may have segments and segment length is different thing than 
total packet length

> Dmitry Eremin-Solenikov(lumag) wrote:
> And here too, please.


>> Dmitry Eremin-Solenikov(lumag) wrote:
>> odp_packet_seg_len() **or odp_packet_offset()**, if you don't mind.


https://github.com/Linaro/odp/pull/497#discussion_r170182482
updated_at 2018-02-23 07:33:19