Yes, I'm seeing this on API-NEXT as well as master.

On Wednesday, June 29, 2016, HePeng <[email protected]> wrote:

> Hi, do you guys use patch this using API-NEXT branch?
>
>
> > 在 2016年6月30日,上午1:23,Bill Fischofer <[email protected]
> <javascript:;>> 写道:
> >
> > I see the same behavior.  git am reports the first patch is corrupt at
> line
> > 14, but patch can apply it.  Not sure what is going on with that.
> >
> > The test runs fine, however this still has a number of checkpatch issues
> > that need to be addressed:
> >
> > WARNING: please, no spaces at the start of a line
> > #480: FILE: helper/iplookuptable.c:434:
> > +    return NULL;$
> >
> > WARNING: braces {} are not necessary for single statement blocks
> > #532: FILE: helper/iplookuptable.c:486:
> > + for (i = 0; i < ENTRY_NUM_L1; i++) {
> > + tbl->l1e[i].nexthop = ODP_BUFFER_INVALID;
> > + }
> >
> > WARNING: please, no spaces at the start of a line
> > #617: FILE: helper/iplookuptable.c:571:
> > +    return 0;$
> >
> > WARNING: line over 80 characters
> > #660: FILE: helper/iplookuptable.c:614:
> > + odph_iplookup_table_impl *tbl, prefix_entry_t *entry, odp_buffer_t
> *buff,
> >
> > WARNING: line over 80 characters
> > #730: FILE: helper/iplookuptable.c:684:
> > + impl, impl->trie, prefix->ip, prefix->cidr, nexthop);
> >
> > WARNING: line over 80 characters
> > #792: FILE: helper/iplookuptable.c:746:
> > + odph_iplookup_table_impl *tbl, prefix_entry_t *l1e, odp_buffer_t *buff,
> >
> > WARNING: line over 80 characters
> > #872: FILE: helper/iplookuptable.c:826:
> > + if (ne->child != 0 || ne->cidr != cidr || ne->nexthop != index) {
> >
> > WARNING: line over 80 characters
> > #882: FILE: helper/iplookuptable.c:836:
> > + odph_iplookup_table_impl *tbl, prefix_entry_t *e, odp_buffer_t *buff,
> >
> > WARNING: line over 80 characters
> > #899: FILE: helper/iplookuptable.c:853:
> > + tbl, ne, nbuff, ip, cidr - 8, level + 8, depth + 1);
> >
> > total: 0 errors, 9 warnings, 0 checks, 1007 lines checked
> >
> > NOTE: Ignored message types: BIT_MACRO COMPARISON_TO_NULL
> > DEPRECATED_VARIABLE NEW_TYPEDEFS SPLIT_STRING SSCANF_TO_KSTRTO
> >
> > 0001-helper-table-add-impl-of-ip-lookup-table.patch has style problems,
> > please review.
> >
> > If any of these errors are false positives, please report
> > them to the maintainer, see CHECKPATCH in MAINTAINERS.
> > total: 0 errors, 0 warnings, 0 checks, 187 lines checked
> >
> > NOTE: Ignored message types: BIT_MACRO COMPARISON_TO_NULL
> > DEPRECATED_VARIABLE NEW_TYPEDEFS SPLIT_STRING SSCANF_TO_KSTRTO
> >
> > 0002-helper-test-add-validation-test-of-ip-lookup-table.patch has no
> > obvious style problems and is ready for submission.
> >
> >
> > On Fri, Jun 17, 2016 at 2:13 AM, Maxim Uvarov <[email protected]
> <javascript:;>>
> > wrote:
> >
> >> Bill,
> >>
> >> I'm able to apply it with just:
> >> git am -s -3 /tmp/1/*.eml
> >> patch -p1 < /opt/Linaro/odp3.git/.git/rebase-apply/patch
> >> git add -A
> >> git am --continue
> >>
> >> Interesting that git am -3 can not resolve conflicts but patch -p1 works
> >> fine.
> >>
> >> He, Bill is travelling and will be on conference so it will take some
> time
> >> for him to respond / review.
> >>
> >> Maxim.
> >>
> >>
> >> On 06/17/16 09:01, HePeng wrote:
> >>
> >>> Ping?
> >>>
> >>>> 在 2016年6月14日,上午9:30,HePeng <[email protected] <javascript:;>> 写道:
> >>>>
> >>>> Hi, bill
> >>>> this patch is based on the current API-NEXT …
> >>>>
> >>>> 在 2016年6月14日,上午6:24,Bill Fischofer <[email protected]
> <javascript:;>> 写道:
> >>>>>
> >>>>> v4 of this patch still doesn't apply for me:
> >>>>>
> >>>>> bill@Ubuntu15:~/linaro/review$ git am --reject ~/Mail/Incoming/Ru/5
> >>>>> Applying: helper: table: add impl of ip lookup table
> >>>>> fatal: corrupt patch at line 14
> >>>>> Patch failed at 0001 helper: table: add impl of ip lookup table
> >>>>> The copy of the patch that failed is found in:
> .git/rebase-apply/patch
> >>>>> When you have resolved this problem, run "git am --continue".
> >>>>> If you prefer to skip this patch, run "git am --skip" instead.
> >>>>> To restore the original branch and stop patching, run "git am
> --abort".
> >>>>>
> >>>>> Looks like this still needs a rebase on to the current master?
> >>>>>
> >>>>> Thanks.
> >>>>>
> >>>>> Bill
> >>>>>
> >>>>>
> >>>>>
> >>>>> On Mon, Jun 13, 2016 at 3:57 AM, Ru Jia <[email protected]
> <javascript:;>> wrote:
> >>>>>
> >>>>> This is an implementation of the 16,8,8 ip lookup
> >>>>>> (longest prefix matching) algorithm. The key of the
> >>>>>> table is 32-bit IPv4 address.
> >>>>>>
> >>>>>> Signed-off-by: Ru Jia <[email protected] <javascript:;>>
> >>>>>> ---
> >>>>>> helper/Makefile.am          |   4 +-
> >>>>>> helper/iplookuptable.c      | 934
> >>>>>> ++++++++++++++++++++++++++++++++++++++++++++
> >>>>>> helper/odph_iplookuptable.h |  58 +++
> >>>>>> 3 files changed, 995 insertions(+), 1 deletion(-)
> >>>>>> create mode 100644 helper/iplookuptable.c
> >>>>>> create mode 100644 helper/odph_iplookuptable.h
> >>>>>>
> >>>>>> diff --git a/helper/Makefile.am b/helper/Makefile.am
> >>>>>> index aa58e8c..2e1d519 100644
> >>>>>> --- a/helper/Makefile.am
> >>>>>> +++ b/helper/Makefile.am
> >>>>>> @@ -27,6 +27,7 @@ noinst_HEADERS = \
> >>>>>>                $(srcdir)/odph_debug.h \
> >>>>>>                $(srcdir)/odph_hashtable.h \
> >>>>>>                $(srcdir)/odph_lineartable.h \
> >>>>>> +                $(srcdir)/odph_iplookuptable.h \
> >>>>>>                $(srcdir)/odph_list_internal.h
> >>>>>>
> >>>>>> __LIB__libodphelper_linux_la_SOURCES = \
> >>>>>> @@ -35,6 +36,7 @@ __LIB__libodphelper_linux_la_SOURCES = \
> >>>>>>                                       chksum.c \
> >>>>>>                                       linux.c \
> >>>>>>                                       hashtable.c \
> >>>>>> -                                       lineartable.c
> >>>>>> +                                       lineartable.c \
> >>>>>> +                                       iplookuptable.c
> >>>>>>
> >>>>>> lib_LTLIBRARIES = $(LIB)/libodphelper-linux.la
> >>>>>> diff --git a/helper/iplookuptable.c b/helper/iplookuptable.c
> >>>>>> new file mode 100644
> >>>>>> index 0000000..8763abc
> >>>>>> --- /dev/null
> >>>>>> +++ b/helper/iplookuptable.c
> >>>>>> @@ -0,0 +1,934 @@
> >>>>>> +/* Copyright (c) 2016, Linaro Limited
> >>>>>> + * All rights reserved.
> >>>>>> + *
> >>>>>> + * SPDX-License-Identifier:     BSD-3-Clause
> >>>>>> + */
> >>>>>> +
> >>>>>> +#include <string.h>
> >>>>>> +#include <stdint.h>
> >>>>>> +#include <errno.h>
> >>>>>> +#include <stdio.h>
> >>>>>> +
> >>>>>> +#include "odph_iplookuptable.h"
> >>>>>> +#include "odph_list_internal.h"
> >>>>>> +#include "odph_debug.h"
> >>>>>> +#include <odp_api.h>
> >>>>>> +
> >>>>>> +/** @magic word, write to the first byte of the memory block
> >>>>>> + *   to indicate this block is used by a ip lookup table
> >>>>>> + */
> >>>>>> +#define ODPH_IP_LOOKUP_TABLE_MAGIC_WORD 0xCFCFFCFC
> >>>>>> +
> >>>>>> +/* The length(bit) of the IPv4 address */
> >>>>>> +#define IP_LENGTH 32
> >>>>>> +
> >>>>>> +/* The number of L1 entries */
> >>>>>> +#define ENTRY_NUM_L1           (1 << 16)
> >>>>>> +/* The size of one L2\L3 subtree */
> >>>>>> +#define ENTRY_NUM_SUBTREE      (1 << 8)
> >>>>>> +
> >>>>>> +#define WHICH_CHILD(ip, cidr) ((ip >> (IP_LENGTH - cidr)) &
> >>>>>> 0x00000001)
> >>>>>> +
> >>>>>> +/** @internal entry struct
> >>>>>> + *   Structure store an entry of the ip prefix table.
> >>>>>> + *   Because of the leaf pushing, each entry of the table must have
> >>>>>> + *   either a child entry, or a nexthop info.
> >>>>>> + *   If child == 0 and index != ODP_BUFFER_INVALID, this entry has
> >>>>>> + *             a nexthop info, index indicates the buffer that
> stores
> >>>>>> the
> >>>>>> + *             nexthop value, and ptr points to the address of the
> >>>>>> buffer.
> >>>>>> + *   If child == 1, this entry has a subtree, index indicates
> >>>>>> + *             the buffer that stores the subtree, and ptr points
> to
> >>>>>> the
> >>>>>> + *             address of the buffer.
> >>>>>> + */
> >>>>>> +typedef struct {
> >>>>>> +       union {
> >>>>>> +               uint8_t u8;
> >>>>>> +               struct {
> >>>>>> +#if ODP_BYTE_ORDER == ODP_BIG_ENDIAN
> >>>>>> +                       uint8_t child : 1;
> >>>>>> +                       uint8_t cidr  : 7;
> >>>>>> +#else
> >>>>>> +                       uint8_t cidr  : 7;
> >>>>>> +                       uint8_t child : 1;
> >>>>>> +#endif
> >>>>>> +               };
> >>>>>> +       };
> >>>>>> +       union {
> >>>>>> +               odp_buffer_t nexthop;
> >>>>>> +               void *ptr;
> >>>>>> +       };
> >>>>>> +} prefix_entry_t;
> >>>>>> +
> >>>>>> +#define ENTRY_SIZE (sizeof(prefix_entry_t) + sizeof(odp_buffer_t))
> >>>>>> +#define ENTRY_BUFF_ARR(x) ((odp_buffer_t *)((char *)x \
> >>>>>> +                       + sizeof(prefix_entry_t) *
> ENTRY_NUM_SUBTREE))
> >>>>>> +
> >>>>>> +/** @internal trie node struct
> >>>>>> + *  In this IP lookup algorithm, we use a
> >>>>>> + *  binary tire to detect the overlap prefix.
> >>>>>> + */
> >>>>>> +typedef struct trie_node {
> >>>>>> +       /* tree structure */
> >>>>>> +       struct trie_node *parent;
> >>>>>> +       struct trie_node *left;
> >>>>>> +       struct trie_node *right;
> >>>>>> +       /* IP prefix length */
> >>>>>> +       uint8_t cidr;
> >>>>>> +       /* Nexthop buffer index */
> >>>>>> +       odp_buffer_t nexthop;
> >>>>>> +       /* Buffer that stores this node */
> >>>>>> +       odp_buffer_t buffer;
> >>>>>> +} trie_node_t;
> >>>>>> +
> >>>>>> +/** Number of L2\L3 entries(subtrees) per cache cube. */
> >>>>>> +#define CACHE_NUM_SUBTREE      (1 << 13)
> >>>>>> +/** Number of trie nodes per cache cube. */
> >>>>>> +#define CACHE_NUM_TRIE         (1 << 20)
> >>>>>> +
> >>>>>> +/** @typedef cache_type_t
> >>>>>> + *     Cache node type
> >>>>>> + */
> >>>>>> +typedef enum {
> >>>>>> +       CACHE_TYPE_SUBTREE = 0,
> >>>>>> +       CACHE_TYPE_TRIE
> >>>>>> +} cache_type_t;
> >>>>>> +
> >>>>>> +/** A IP lookup table structure. */
> >>>>>> +typedef struct {
> >>>>>> +       /**< for check */
> >>>>>> +       uint32_t magicword;
> >>>>>> +       /** Name of the hash. */
> >>>>>> +       char name[ODPH_TABLE_NAME_LEN];
> >>>>>> +       /** Total L1 entries. */
> >>>>>> +       prefix_entry_t *l1e;
> >>>>>> +       /** Root node of the binary trie */
> >>>>>> +       trie_node_t *trie;
> >>>>>> +       /** Length of value. */
> >>>>>> +       uint32_t nexthop_len;
> >>>>>> +       /** Queues of free slots (caches)
> >>>>>> +        *  There are three queues:
> >>>>>> +        *  - free_slots[CACHE_TYPE_SUBTREE] is used for L2 and
> >>>>>> +        *    L3 entries (subtrees). Each entry stores an 8-bit
> >>>>>> +        *    subtree.
> >>>>>> +        *  - free_slots[CACHE_TYPE_TRIE] is used for the binary
> >>>>>> +        *    trie. Each entry contains a trie node.
> >>>>>> +        */
> >>>>>> +       odp_queue_t free_slots[2];
> >>>>>> +       /** The number of pool used by each queue. */
> >>>>>> +       uint32_t cache_count[2];
> >>>>>> +} odph_iplookup_table_impl ODP_ALIGNED_CACHE;
> >>>>>> +
> >>>>>> +/***********************************************************
> >>>>>> + *****************   Cache management   ********************
> >>>>>> + ***********************************************************/
> >>>>>> +
> >>>>>> +/** Destroy all caches */
> >>>>>> +static void
> >>>>>> +cache_destroy(odph_iplookup_table_impl *impl)
> >>>>>> +{
> >>>>>> +       odp_queue_t queue;
> >>>>>> +       odp_event_t ev;
> >>>>>> +       uint32_t i = 0, count = 0;
> >>>>>> +       char pool_name[ODPH_TABLE_NAME_LEN + 8];
> >>>>>> +
> >>>>>> +       /* free all buffers in the queue */
> >>>>>> +       for (; i < 2; i++) {
> >>>>>> +               queue = impl->free_slots[i];
> >>>>>> +               if (queue == ODP_QUEUE_INVALID)
> >>>>>> +                       continue;
> >>>>>> +
> >>>>>> +               while ((ev = odp_queue_deq(queue))
> >>>>>> +                               != ODP_EVENT_INVALID) {
> >>>>>> +                       odp_buffer_free(odp_buffer_from_event(ev));
> >>>>>> +               }
> >>>>>> +               odp_queue_destroy(queue);
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* destroy all cache pools */
> >>>>>> +       for (i = 0; i < 2; i++) {
> >>>>>> +               for (count = 0; count < impl->cache_count[i];
> count++)
> >>>>>> {
> >>>>>> +                       sprintf(
> >>>>>> +                                       pool_name, "%s_%d_%d",
> >>>>>> +                                       impl->name, i, count);
> >>>>>> +
>  odp_pool_destroy(odp_pool_lookup(pool_name));
> >>>>>> +               }
> >>>>>> +       }
> >>>>>> +}
> >>>>>> +
> >>>>>> +/** According to the type of cahce, set the value of
> >>>>>> + *  a buffer to the initial value.
> >>>>>> + */
> >>>>>> +static void
> >>>>>> +cache_init_buffer(odp_buffer_t buffer, cache_type_t type, uint32_t
> >>>>>> size)
> >>>>>> +{
> >>>>>> +       int i = 0;
> >>>>>> +       void *addr = odp_buffer_addr(buffer);
> >>>>>> +
> >>>>>> +       memset(addr, 0, size);
> >>>>>> +       if (type == CACHE_TYPE_SUBTREE) {
> >>>>>> +               prefix_entry_t *entry = (prefix_entry_t *)addr;
> >>>>>> +
> >>>>>> +               for (i = 0; i < ENTRY_NUM_SUBTREE; i++, entry++)
> >>>>>> +                       entry->nexthop = ODP_BUFFER_INVALID;
> >>>>>> +       } else if (type == CACHE_TYPE_TRIE) {
> >>>>>> +               trie_node_t *node = (trie_node_t *)addr;
> >>>>>> +
> >>>>>> +               node->buffer = buffer;
> >>>>>> +               node->nexthop = ODP_BUFFER_INVALID;
> >>>>>> +       }
> >>>>>> +}
> >>>>>> +
> >>>>>> +/** Create a new buffer pool, and insert its buffer into the
> queue. */
> >>>>>> +static int
> >>>>>> +cache_alloc_new_pool(
> >>>>>> +               odph_iplookup_table_impl *tbl, cache_type_t type)
> >>>>>> +{
> >>>>>> +       odp_pool_t pool;
> >>>>>> +       odp_pool_param_t param;
> >>>>>> +       odp_queue_t queue = tbl->free_slots[type];
> >>>>>> +
> >>>>>> +       odp_buffer_t buffer;
> >>>>>> +       char pool_name[ODPH_TABLE_NAME_LEN + 8];
> >>>>>> +       uint32_t size = 0, num = 0;
> >>>>>> +
> >>>>>> +       /* Create new pool (new free buffers). */
> >>>>>> +       param.type = ODP_POOL_BUFFER;
> >>>>>> +       param.buf.align = ODP_CACHE_LINE_SIZE;
> >>>>>> +       if (type == CACHE_TYPE_SUBTREE) {
> >>>>>> +               num = CACHE_NUM_SUBTREE;
> >>>>>> +               size = ENTRY_SIZE * ENTRY_NUM_SUBTREE;
> >>>>>> +       } else if (type == CACHE_TYPE_TRIE) {
> >>>>>> +               num = CACHE_NUM_TRIE;
> >>>>>> +               size = sizeof(trie_node_t);
> >>>>>> +       } else {
> >>>>>> +               ODPH_DBG("wrong cache_type_t.\n");
> >>>>>> +               return -1;
> >>>>>> +       }
> >>>>>> +       param.buf.size = size;
> >>>>>> +       param.buf.num = num;
> >>>>>> +
> >>>>>> +       sprintf(
> >>>>>> +                       pool_name, "%s_%d_%d",
> >>>>>> +                       tbl->name, type, tbl->cache_count[type]);
> >>>>>> +       pool = odp_pool_create(pool_name, &param);
> >>>>>> +       if (pool == ODP_POOL_INVALID) {
> >>>>>> +               ODPH_DBG("failed to create a new pool.\n");
> >>>>>> +               return -1;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* insert new free buffers into queue */
> >>>>>> +       while ((buffer = odp_buffer_alloc(pool))
> >>>>>> +                       != ODP_BUFFER_INVALID) {
> >>>>>> +               cache_init_buffer(buffer, type, size);
> >>>>>> +               odp_queue_enq(queue, odp_buffer_to_event(buffer));
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       tbl->cache_count[type]++;
> >>>>>> +       return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/** Get a new buffer from a cache list. If there is no
> >>>>>> + *  available buffer, allocate a new pool.
> >>>>>> + */
> >>>>>> +static odp_buffer_t
> >>>>>> +cache_get_buffer(odph_iplookup_table_impl *tbl, cache_type_t type)
> >>>>>> +{
> >>>>>> +       odp_buffer_t buffer = ODP_BUFFER_INVALID;
> >>>>>> +       odp_queue_t queue = tbl->free_slots[type];
> >>>>>> +
> >>>>>> +       /* get free buffer from queue */
> >>>>>> +       buffer = odp_buffer_from_event(
> >>>>>> +                               odp_queue_deq(queue));
> >>>>>> +
> >>>>>> +       /* If there is no free buffer available, allocate new pool
> */
> >>>>>> +       if (buffer == ODP_BUFFER_INVALID) {
> >>>>>> +               cache_alloc_new_pool(tbl, type);
> >>>>>> +               buffer =
> odp_buffer_from_event(odp_queue_deq(queue));
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       return buffer;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/***********************************************************
> >>>>>> + ******************     Binary trie     ********************
> >>>>>> + ***********************************************************/
> >>>>>> +
> >>>>>> +/* Initialize the root node of the trie */
> >>>>>> +static int
> >>>>>> +trie_init(odph_iplookup_table_impl *tbl)
> >>>>>> +{
> >>>>>> +       trie_node_t *root = NULL;
> >>>>>> +       odp_buffer_t buffer = cache_get_buffer(tbl,
> CACHE_TYPE_TRIE);
> >>>>>> +
> >>>>>> +       if (buffer != ODP_BUFFER_INVALID) {
> >>>>>> +               root = (trie_node_t *)odp_buffer_addr(buffer);
> >>>>>> +               root->cidr = 0;
> >>>>>> +               tbl->trie = root;
> >>>>>> +               return 0;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       return -1;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/* Destroy the whole trie (recursively) */
> >>>>>> +static void
> >>>>>> +trie_destroy(odph_iplookup_table_impl *tbl, trie_node_t *trie)
> >>>>>> +{
> >>>>>> +       if (trie->left != NULL)
> >>>>>> +               trie_destroy(tbl, trie->left);
> >>>>>> +       if (trie->right != NULL)
> >>>>>> +               trie_destroy(tbl, trie->right);
> >>>>>> +
> >>>>>> +       /* destroy this node */
> >>>>>> +       odp_queue_enq(
> >>>>>> +                       tbl->free_slots[CACHE_TYPE_TRIE],
> >>>>>> +                       odp_buffer_to_event(trie->buffer));
> >>>>>> +}
> >>>>>> +
> >>>>>> +/* Insert a new prefix node into the trie
> >>>>>> + * If the node is already existed, update its nexthop info,
> >>>>>> + *   Return 0 and set nexthop pointer to INVALID.
> >>>>>> + * If the node is not exitsed, create this target node and
> >>>>>> + *   all nodes along the path from root to the target node.
> >>>>>> + *   Then return 0 and set nexthop pointer points to the
> >>>>>> + *   new buffer.
> >>>>>> + * Return -1 for error.
> >>>>>> + */
> >>>>>> +static int
> >>>>>> +trie_insert_node(
> >>>>>> +               odph_iplookup_table_impl *tbl, trie_node_t *root,
> >>>>>> +               uint32_t ip, uint8_t cidr, odp_buffer_t nexthop)
> >>>>>> +{
> >>>>>> +       uint8_t level = 0, child;
> >>>>>> +       odp_buffer_t buf;
> >>>>>> +       trie_node_t *node = root, *prev = root;
> >>>>>> +
> >>>>>> +       /* create/update all nodes along the path
> >>>>>> +        * from root to the new node. */
> >>>>>> +       for (level = 1; level <= cidr; level++) {
> >>>>>> +               child = WHICH_CHILD(ip, level);
> >>>>>> +
> >>>>>> +               node = child == 0 ? prev->left : prev->right;
> >>>>>> +               /* If the child node doesn't exit, create it. */
> >>>>>> +               if (node == NULL) {
> >>>>>> +                       buf = cache_get_buffer(tbl,
> CACHE_TYPE_TRIE);
> >>>>>> +                       if (buf == ODP_BUFFER_INVALID)
> >>>>>> +                               return -1;
> >>>>>> +
> >>>>>> +                       node = (trie_node_t *)odp_buffer_addr(buf);
> >>>>>> +                       node->cidr = level;
> >>>>>> +                       node->parent = prev;
> >>>>>> +
> >>>>>> +                       if (child == 0)
> >>>>>> +                               prev->left = node;
> >>>>>> +                       else
> >>>>>> +                               prev->right = node;
> >>>>>> +               }
> >>>>>> +               prev = node;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* The final one is the target. */
> >>>>>> +       node->nexthop = nexthop;
> >>>>>> +       return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/* Delete a node */
> >>>>>> +static int
> >>>>>> +trie_delete_node(
> >>>>>> +               odph_iplookup_table_impl *tbl,
> >>>>>> +               trie_node_t *root, uint32_t ip, uint8_t cidr)
> >>>>>> +{
> >>>>>> +       if (root == NULL)
> >>>>>> +               return -1;
> >>>>>> +
> >>>>>> +       /* The default prefix (root node) cannot be deleted. */
> >>>>>> +       if (cidr == 0)
> >>>>>> +               return -1;
> >>>>>> +
> >>>>>> +       trie_node_t *node = root, *prev = NULL;
> >>>>>> +       uint8_t level = 1, child = 0;
> >>>>>> +       odp_buffer_t tmp;
> >>>>>> +
> >>>>>> +       /* Find the target node. */
> >>>>>> +       for (level = 1; level <= cidr; level++) {
> >>>>>> +               child = WHICH_CHILD(ip, level);
> >>>>>> +               node = (child == 0) ? node->left : node->right;
> >>>>>> +               if (node == NULL) {
> >>>>>> +                       ODPH_DBG("Trie node is not existed\n");
> >>>>>> +                       return -1;
> >>>>>> +               }
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       node->nexthop = ODP_BUFFER_INVALID;
> >>>>>> +
> >>>>>> +       /* Delete all redundant nodes along the path. */
> >>>>>> +       for (level = cidr; level > 0; level--) {
> >>>>>> +               if (
> >>>>>> +                       node->left != NULL || node->right != NULL ||
> >>>>>> +                       node->nexthop != ODP_BUFFER_INVALID)
> >>>>>> +                       break;
> >>>>>> +
> >>>>>> +               child = WHICH_CHILD(ip, level);
> >>>>>> +               prev = node->parent;
> >>>>>> +
> >>>>>> +               /* free trie node */
> >>>>>> +               tmp = node->buffer;
> >>>>>> +               cache_init_buffer(
> >>>>>> +                               tmp, CACHE_TYPE_TRIE,
> >>>>>> sizeof(trie_node_t));
> >>>>>> +               odp_queue_enq(
> >>>>>> +                               tbl->free_slots[CACHE_TYPE_TRIE],
> >>>>>> +                               odp_buffer_to_event(tmp));
> >>>>>> +
> >>>>>> +               if (child == 0)
> >>>>>> +                       prev->left = NULL;
> >>>>>> +               else
> >>>>>> +                       prev->right = NULL;
> >>>>>> +               node = prev;
> >>>>>> +       }
> >>>>>> +       return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/* Detect the longest overlapping prefix. */
> >>>>>> +static int
> >>>>>> +trie_detect_overlap(
> >>>>>> +               trie_node_t *trie, uint32_t ip, uint8_t cidr,
> >>>>>> +               uint8_t leaf_push, uint8_t *over_cidr,
> >>>>>> +               odp_buffer_t *over_nexthop)
> >>>>>> +{
> >>>>>> +       uint8_t child = 0;
> >>>>>> +       uint32_t level, limit = cidr > leaf_push ? leaf_push + 1 :
> >>>>>> cidr;
> >>>>>> +       trie_node_t *node = trie, *longest = trie;
> >>>>>> +
> >>>>>> +       for (level = 1; level < limit; level++) {
> >>>>>> +               child = WHICH_CHILD(ip, level);
> >>>>>> +               node = (child == 0) ? node->left : node->right;
> >>>>>> +               if (node->nexthop != ODP_BUFFER_INVALID)
> >>>>>> +                       longest = node;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       *over_cidr = longest->cidr;
> >>>>>> +       *over_nexthop = longest->nexthop;
> >>>>>> +       return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/***********************************************************
> >>>>>> + ***************   IP prefix lookup table   ****************
> >>>>>> + ***********************************************************/
> >>>>>> +
> >>>>>> +odph_table_t
> >>>>>> +odph_iplookup_table_lookup(const char *name)
> >>>>>> +{
> >>>>>> +       odph_iplookup_table_impl *tbl = NULL;
> >>>>>> +
> >>>>>> +       if (name == NULL || strlen(name) >= ODPH_TABLE_NAME_LEN)
> >>>>>> +               return NULL;
> >>>>>> +
> >>>>>> +       tbl = (odph_iplookup_table_impl
> >>>>>> *)odp_shm_addr(odp_shm_lookup(name));
> >>>>>> +
> >>>>>> +       if (
> >>>>>> +               tbl != NULL &&
> >>>>>> +               tbl->magicword == ODPH_IP_LOOKUP_TABLE_MAGIC_WORD &&
> >>>>>> +               strcmp(tbl->name, name) == 0)
> >>>>>> +               return (odph_table_t)tbl;
> >>>>>> +
> >>>>>> +    return NULL;
> >>>>>> +}
> >>>>>> +
> >>>>>> +odph_table_t
> >>>>>> +odph_iplookup_table_create(
> >>>>>> +               const char *name, uint32_t ODP_IGNORED_1,
> >>>>>> +               uint32_t ODP_IGNORED_2, uint32_t value_size)
> >>>>>> +{
> >>>>>> +       odph_iplookup_table_impl *tbl;
> >>>>>> +       odp_shm_t shm_tbl;
> >>>>>> +       odp_queue_t queue;
> >>>>>> +       odp_queue_param_t qparam;
> >>>>>> +
> >>>>>> +       unsigned i;
> >>>>>> +       uint32_t impl_size, l1_size;
> >>>>>> +       char queue_name[ODPH_TABLE_NAME_LEN + 2];
> >>>>>> +
> >>>>>> +       /* Check for valid parameters */
> >>>>>> +       if (strlen(name) == 0) {
> >>>>>> +               ODPH_DBG("invalid parameters\n");
> >>>>>> +               return NULL;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* Guarantee there's no existing */
> >>>>>> +       tbl = (odph_iplookup_table_impl
> >>>>>> *)odph_iplookup_table_lookup(name);
> >>>>>> +       if (tbl != NULL) {
> >>>>>> +               ODPH_DBG("IP prefix table %s already exists\n",
> name);
> >>>>>> +               return NULL;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* Calculate the sizes of different parts of IP prefix
> table */
> >>>>>> +       impl_size = sizeof(odph_iplookup_table_impl);
> >>>>>> +       l1_size = ENTRY_SIZE * ENTRY_NUM_L1;
> >>>>>> +
> >>>>>> +       shm_tbl = odp_shm_reserve(
> >>>>>> +                               name, impl_size + l1_size,
> >>>>>> +                               ODP_CACHE_LINE_SIZE,
> ODP_SHM_SW_ONLY);
> >>>>>> +
> >>>>>> +       if (shm_tbl == ODP_SHM_INVALID) {
> >>>>>> +               ODPH_DBG(
> >>>>>> +                       "shm allocation failed for
> >>>>>> odph_iplookup_table_impl %s\n",
> >>>>>> +                       name);
> >>>>>> +               return NULL;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       tbl = (odph_iplookup_table_impl *)odp_shm_addr(shm_tbl);
> >>>>>> +       memset(tbl, 0, impl_size + l1_size);
> >>>>>> +
> >>>>>> +       /* header of this mem block is the table impl struct,
> >>>>>> +        * then the l1 entries array.
> >>>>>> +        */
> >>>>>> +       tbl->l1e = (prefix_entry_t *)((char *)tbl + impl_size);
> >>>>>> +       for (i = 0; i < ENTRY_NUM_L1; i++) {
> >>>>>> +               tbl->l1e[i].nexthop = ODP_BUFFER_INVALID;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* Setup table context. */
> >>>>>> +       snprintf(tbl->name, sizeof(tbl->name), "%s", name);
> >>>>>> +       tbl->magicword = ODPH_IP_LOOKUP_TABLE_MAGIC_WORD;
> >>>>>> +       tbl->nexthop_len = value_size;
> >>>>>> +
> >>>>>> +       /* Initialize cache */
> >>>>>> +       for (i = 0; i < 2; i++) {
> >>>>>> +               tbl->cache_count[i] = 0;
> >>>>>> +
> >>>>>> +               odp_queue_param_init(&qparam);
> >>>>>> +               qparam.type = ODP_QUEUE_TYPE_PLAIN;
> >>>>>> +               sprintf(queue_name, "%s_%d", name, i);
> >>>>>> +               queue = odp_queue_create(queue_name, &qparam);
> >>>>>> +               if (queue == ODP_QUEUE_INVALID) {
> >>>>>> +                       ODPH_DBG("failed to create queue");
> >>>>>> +                       cache_destroy(tbl);
> >>>>>> +                       return NULL;
> >>>>>> +               }
> >>>>>> +               tbl->free_slots[i] = queue;
> >>>>>> +               cache_alloc_new_pool(tbl, i);
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* Initialize tire */
> >>>>>> +       if (trie_init(tbl) < 0) {
> >>>>>> +               odp_shm_free(shm_tbl);
> >>>>>> +               return NULL;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       return (odph_table_t)tbl;
> >>>>>> +}
> >>>>>> +
> >>>>>> +int
> >>>>>> +odph_iplookup_table_destroy(odph_table_t tbl)
> >>>>>> +{
> >>>>>> +       int i, j;
> >>>>>> +       odph_iplookup_table_impl *impl = NULL;
> >>>>>> +       prefix_entry_t *subtree = NULL;
> >>>>>> +       odp_buffer_t *buff1 = NULL, *buff2 = NULL;
> >>>>>> +
> >>>>>> +       if (tbl == NULL)
> >>>>>> +               return -1;
> >>>>>> +
> >>>>>> +       impl = (odph_iplookup_table_impl *)tbl;
> >>>>>> +
> >>>>>> +       /* check magic word */
> >>>>>> +       if (impl->magicword != ODPH_IP_LOOKUP_TABLE_MAGIC_WORD) {
> >>>>>> +               ODPH_DBG("wrong magicword for IP prefix table\n");
> >>>>>> +               return -1;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* destroy trie */
> >>>>>> +       trie_destroy(impl, impl->trie);
> >>>>>> +
> >>>>>> +       /* free all L2 and L3 entries */
> >>>>>> +       buff1 = ENTRY_BUFF_ARR(impl->l1e);
> >>>>>> +       for (i = 0; i < ENTRY_NUM_L1; i++) {
> >>>>>> +               if ((impl->l1e[i]).child == 0)
> >>>>>> +                       continue;
> >>>>>> +
> >>>>>> +               subtree = (prefix_entry_t *)impl->l1e[i].ptr;
> >>>>>> +               buff2 = ENTRY_BUFF_ARR(subtree);
> >>>>>> +               /* destroy all l3 subtrees of this l2 subtree */
> >>>>>> +               for (j = 0; j < ENTRY_NUM_SUBTREE; j++) {
> >>>>>> +                       if (subtree[j].child == 0)
> >>>>>> +                               continue;
> >>>>>> +                       odp_queue_enq(
> >>>>>> +
> >>>>>> impl->free_slots[CACHE_TYPE_TRIE],
> >>>>>> +
>  odp_buffer_to_event(buff2[j]));
> >>>>>> +               }
> >>>>>> +               /* destroy this l2 subtree */
> >>>>>> +               odp_queue_enq(
> >>>>>> +                               impl->free_slots[CACHE_TYPE_TRIE],
> >>>>>> +                               odp_buffer_to_event(buff1[i]));
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* destroy all cache */
> >>>>>> +       cache_destroy(impl);
> >>>>>> +
> >>>>>> +       /* free impl */
> >>>>>> +       odp_shm_free(odp_shm_lookup(impl->name));
> >>>>>> +
> >>>>>> +    return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/* Insert the prefix into level x
> >>>>>> + * Return:
> >>>>>> + *   -1        error
> >>>>>> + *   0 the table is unmodified
> >>>>>> + *   1 the table is modified
> >>>>>> + */
> >>>>>> +static int
> >>>>>> +prefix_insert_into_lx(
> >>>>>> +               odph_iplookup_table_impl *tbl, prefix_entry_t
> *entry,
> >>>>>> +               uint8_t cidr, odp_buffer_t nexthop, uint8_t level)
> >>>>>> +{
> >>>>>> +       uint8_t ret = 0;
> >>>>>> +       uint32_t i = 0, limit = (1 << (level - cidr));
> >>>>>> +       prefix_entry_t *e = entry, *ne = NULL;
> >>>>>> +
> >>>>>> +       for (i = 0; i < limit; i++, e++) {
> >>>>>> +               if (e->child == 1) {
> >>>>>> +                       if (e->cidr > cidr)
> >>>>>> +                               continue;
> >>>>>> +
> >>>>>> +                       e->cidr = cidr;
> >>>>>> +                       /* push to next level */
> >>>>>> +                       ne = (prefix_entry_t *)e->ptr;
> >>>>>> +                       ret = prefix_insert_into_lx(
> >>>>>> +                                       tbl, ne, cidr, nexthop,
> cidr +
> >>>>>> 8);
> >>>>>> +               } else {
> >>>>>> +                       if (e->cidr > cidr)
> >>>>>> +                               continue;
> >>>>>> +
> >>>>>> +                       e->child = 0;
> >>>>>> +                       e->cidr = cidr;
> >>>>>> +                       e->nexthop = nexthop;
> >>>>>> +                       ret = 1;
> >>>>>> +               }
> >>>>>> +       }
> >>>>>> +       return ret;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static int
> >>>>>> +prefix_insert_iter(
> >>>>>> +               odph_iplookup_table_impl *tbl, prefix_entry_t
> *entry,
> >>>>>> odp_buffer_t *buff,
> >>>>>> +               uint32_t ip, uint8_t cidr, odp_buffer_t nexthop,
> >>>>>> +               uint8_t level, uint8_t depth)
> >>>>>> +{
> >>>>>> +       uint8_t state = 0;
> >>>>>> +       prefix_entry_t *ne = NULL;
> >>>>>> +       odp_buffer_t *nbuff = NULL;
> >>>>>> +
> >>>>>> +       /* If child subtree is existed, get it. */
> >>>>>> +       if (entry->child) {
> >>>>>> +               ne = (prefix_entry_t *)entry->ptr;
> >>>>>> +               nbuff = ENTRY_BUFF_ARR(ne);
> >>>>>> +       } else {
> >>>>>> +               /* If the child is not existed, create a new
> subtree.
> >>>>>> */
> >>>>>> +               odp_buffer_t buf, push = entry->nexthop;
> >>>>>> +
> >>>>>> +               buf = cache_get_buffer(tbl, CACHE_TYPE_SUBTREE);
> >>>>>> +               if (buf == ODP_BUFFER_INVALID) {
> >>>>>> +                       ODPH_DBG("failed to get subtree buffer from
> >>>>>> cache.\n");
> >>>>>> +                       return -1;
> >>>>>> +               }
> >>>>>> +               ne = (prefix_entry_t *)odp_buffer_addr(buf);
> >>>>>> +               nbuff = ENTRY_BUFF_ARR(ne);
> >>>>>> +
> >>>>>> +               entry->child = 1;
> >>>>>> +               entry->ptr = ne;
> >>>>>> +               *buff = buf;
> >>>>>> +
> >>>>>> +               /* If this entry contains a nexthop and a small
> cidr,
> >>>>>> +                * push it to the next level.
> >>>>>> +                */
> >>>>>> +               if (entry->cidr > 0) {
> >>>>>> +                       state = prefix_insert_into_lx(
> >>>>>> +                                       tbl, ne, entry->cidr,
> >>>>>> +                                       push, entry->cidr + 8);
> >>>>>> +               }
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       ne += (ip >> 24);
> >>>>>> +       nbuff += (ip >> 24);
> >>>>>> +       if (cidr <= 8) {
> >>>>>> +               state = prefix_insert_into_lx(
> >>>>>> +                               tbl, ne, cidr + depth * 8, nexthop,
> >>>>>> level);
> >>>>>> +       } else {
> >>>>>> +               state = prefix_insert_iter(
> >>>>>> +                               tbl, ne, nbuff, ip << 8, cidr - 8,
> >>>>>> +                               nexthop, level + 8, depth + 1);
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       return state;
> >>>>>> +}
> >>>>>> +
> >>>>>> +int
> >>>>>> +odph_iplookup_table_put_value(odph_table_t tbl, void *key, void
> >>>>>> *value)
> >>>>>> +{
> >>>>>> +       if ((tbl == NULL) || (key == NULL) || (value == NULL))
> >>>>>> +               return -1;
> >>>>>> +
> >>>>>> +       odph_iplookup_table_impl *impl = (odph_iplookup_table_impl
> >>>>>> *)tbl;
> >>>>>> +       odph_iplookup_prefix_t *prefix = (odph_iplookup_prefix_t
> *)key;
> >>>>>> +       prefix_entry_t *l1e = NULL;
> >>>>>> +       odp_buffer_t nexthop = *((odp_buffer_t *)value);
> >>>>>> +       int ret = 0;
> >>>>>> +
> >>>>>> +       if (prefix->cidr == 0)
> >>>>>> +               return -1;
> >>>>>> +       prefix->ip = prefix->ip & (0xffffffff << (IP_LENGTH -
> >>>>>> prefix->cidr));
> >>>>>> +
> >>>>>> +       /* insert into trie */
> >>>>>> +       ret = trie_insert_node(
> >>>>>> +                               impl, impl->trie, prefix->ip,
> >>>>>> prefix->cidr, nexthop);
> >>>>>> +
> >>>>>> +       if (ret < 0) {
> >>>>>> +               ODPH_DBG("failed to insert into trie\n");
> >>>>>> +               return -1;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* get L1 entry */
> >>>>>> +       l1e = &impl->l1e[prefix->ip >> 16];
> >>>>>> +       odp_buffer_t *buff = ENTRY_BUFF_ARR(impl->l1e) +
> (prefix->ip >>
> >>>>>> 16);
> >>>>>> +
> >>>>>> +       if (prefix->cidr <= 16) {
> >>>>>> +               ret = prefix_insert_into_lx(
> >>>>>> +                               impl, l1e, prefix->cidr, nexthop,
> 16);
> >>>>>> +       } else {
> >>>>>> +               ret = prefix_insert_iter(
> >>>>>> +                               impl, l1e, buff,
> >>>>>> +                               ((prefix->ip) << 16), prefix->cidr -
> >>>>>> 16,
> >>>>>> +                               nexthop, 24, 2);
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       return ret;
> >>>>>> +}
> >>>>>> +
> >>>>>> +int
> >>>>>> +odph_iplookup_table_get_value(
> >>>>>> +               odph_table_t tbl, void *key, void *buffer, uint32_t
> >>>>>> buffer_size)
> >>>>>> +{
> >>>>>> +       if ((tbl == NULL) || (key == NULL) || (buffer == NULL))
> >>>>>> +               return -EINVAL;
> >>>>>> +
> >>>>>> +       odph_iplookup_table_impl *impl = (odph_iplookup_table_impl
> >>>>>> *)tbl;
> >>>>>> +       uint32_t ip = *((uint32_t *)key);
> >>>>>> +       prefix_entry_t *entry = &impl->l1e[ip >> 16];
> >>>>>> +       odp_buffer_t *buff = (odp_buffer_t *)buffer;
> >>>>>> +
> >>>>>> +       if (entry == NULL) {
> >>>>>> +               ODPH_DBG("failed to get L1 entry.\n");
> >>>>>> +               return -1;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       ip <<= 16;
> >>>>>> +       while (entry->child) {
> >>>>>> +               entry = (prefix_entry_t *)entry->ptr;
> >>>>>> +               entry += ip >> 24;
> >>>>>> +               ip <<= 8;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       /* copy data */
> >>>>>> +       if (entry->nexthop == ODP_BUFFER_INVALID) {
> >>>>>> +               /* ONLY match the default prefix */
> >>>>>> +               printf("only match the default prefix\n");
> >>>>>> +               *buff = ODP_BUFFER_INVALID;
> >>>>>> +       } else {
> >>>>>> +               *buff = entry->nexthop;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       return 0;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static int
> >>>>>> +prefix_delete_lx(
> >>>>>> +               odph_iplookup_table_impl *tbl, prefix_entry_t *l1e,
> >>>>>> odp_buffer_t *buff,
> >>>>>> +               uint8_t cidr, uint8_t over_cidr, odp_buffer_t
> >>>>>> over_nexthop,
> >>>>>> +               uint8_t level)
> >>>>>> +{
> >>>>>> +       uint8_t ret, flag = 1;
> >>>>>> +       prefix_entry_t *e = l1e;
> >>>>>> +       odp_buffer_t *b = buff;
> >>>>>> +       uint32_t i = 0, limit = 1 << (level - cidr);
> >>>>>> +
> >>>>>> +       for (i = 0; i < limit; i++, e++, b++) {
> >>>>>> +               if (e->child == 1) {
> >>>>>> +                       if (e->cidr > cidr) {
> >>>>>> +                               flag = 0;
> >>>>>> +                               continue;
> >>>>>> +                       }
> >>>>>> +
> >>>>>> +                       prefix_entry_t *ne = (prefix_entry_t
> *)e->ptr;
> >>>>>> +                       odp_buffer_t *nbuff = ENTRY_BUFF_ARR(ne);
> >>>>>> +
> >>>>>> +                       e->cidr = over_cidr;
> >>>>>> +                       ret = prefix_delete_lx(
> >>>>>> +                                       tbl, ne, nbuff, cidr,
> >>>>>> over_cidr,
> >>>>>> +                                       over_nexthop, cidr + 8);
> >>>>>> +
> >>>>>> +                       /* If ret == 1, the next 2^8 entries equal
> to
> >>>>>> +                        * (over_cidr, over_nexthop). In this case,
> we
> >>>>>> +                        * should not push the (over_cidr,
> >>>>>> over_nexthop)
> >>>>>> +                        * to the next level. In fact, we should
> >>>>>> recycle
> >>>>>> +                        * the next 2^8 entries.
> >>>>>> +                        */
> >>>>>> +                       if (ret) {
> >>>>>> +                               /* destroy subtree */
> >>>>>> +                               cache_init_buffer(
> >>>>>> +                                       *b, CACHE_TYPE_SUBTREE,
> >>>>>> +                                       ENTRY_SIZE *
> >>>>>> ENTRY_NUM_SUBTREE);
> >>>>>> +                               odp_queue_enq(
> >>>>>> +
> >>>>>> tbl->free_slots[CACHE_TYPE_SUBTREE],
> >>>>>> +                                       odp_buffer_to_event(*b));
> >>>>>> +                               e->child = 0;
> >>>>>> +                               e->nexthop = over_nexthop;
> >>>>>> +                       } else {
> >>>>>> +                               flag = 0;
> >>>>>> +                       }
> >>>>>> +               } else {
> >>>>>> +                       if (e->cidr > cidr) {
> >>>>>> +                               flag = 0;
> >>>>>> +                               continue;
> >>>>>> +                       } else {
> >>>>>> +                               e->cidr = over_cidr;
> >>>>>> +                               e->nexthop = over_nexthop;
> >>>>>> +                       }
> >>>>>> +               }
> >>>>>> +       }
> >>>>>> +       return flag;
> >>>>>> +}
> >>>>>> +
> >>>>>> +/* Check if the entry can be recycled.
> >>>>>> + * An entry can be recycled duo to two reasons:
> >>>>>> + * - all children of the entry are the same,
> >>>>>> + * - all children of the entry have a cidr smaller than the level
> >>>>>> + *   bottom bound.
> >>>>>> + */
> >>>>>> +static uint8_t
> >>>>>> +can_recycle(prefix_entry_t *e, uint32_t level)
> >>>>>> +{
> >>>>>> +       uint8_t recycle = 1;
> >>>>>> +       int i = 1;
> >>>>>> +       prefix_entry_t *ne = (prefix_entry_t *)e->ptr;
> >>>>>> +
> >>>>>> +       if (ne->child)
> >>>>>> +               return 0;
> >>>>>> +
> >>>>>> +       uint8_t cidr = ne->cidr;
> >>>>>> +       odp_buffer_t index = ne->nexthop;
> >>>>>> +
> >>>>>> +       if (cidr > level)
> >>>>>> +               return 0;
> >>>>>> +
> >>>>>> +       ne++;
> >>>>>> +       for (; i < 256; i++, ne++) {
> >>>>>> +               if (ne->child != 0 || ne->cidr != cidr ||
> ne->nexthop
> >>>>>> !=
> >>>>>> index) {
> >>>>>> +                       recycle = 0;
> >>>>>> +                       break;
> >>>>>> +               }
> >>>>>> +       }
> >>>>>> +       return recycle;
> >>>>>> +}
> >>>>>> +
> >>>>>> +static uint8_t
> >>>>>> +prefix_delete_iter(
> >>>>>> +               odph_iplookup_table_impl *tbl, prefix_entry_t *e,
> >>>>>> odp_buffer_t *buff,
> >>>>>> +               uint32_t ip, uint8_t cidr, uint8_t level, uint8_t
> >>>>>> depth)
> >>>>>> +{
> >>>>>> +       uint8_t ret = 0, over_cidr;
> >>>>>> +       odp_buffer_t over_nexthop;
> >>>>>> +
> >>>>>> +       trie_detect_overlap(
> >>>>>> +                       tbl->trie, ip, cidr + 8 * depth, level,
> >>>>>> +                       &over_cidr, &over_nexthop);
> >>>>>> +       if (cidr > 8) {
> >>>>>> +               prefix_entry_t *ne =
> >>>>>> +                       (prefix_entry_t *)e->ptr;
> >>>>>> +               odp_buffer_t *nbuff = ENTRY_BUFF_ARR(ne);
> >>>>>> +
> >>>>>> +               ne += ((uint32_t)(ip << level) >> 24);
> >>>>>> +               nbuff += ((uint32_t)(ip << level) >> 24);
> >>>>>> +               ret = prefix_delete_iter(
> >>>>>> +                               tbl, ne, nbuff, ip, cidr - 8, level
> +
> >>>>>> 8,
> >>>>>> depth + 1);
> >>>>>> +
> >>>>>> +               if (ret && can_recycle(e, level)) {
> >>>>>> +                       /* destroy subtree */
> >>>>>> +                       cache_init_buffer(
> >>>>>> +                               *buff, CACHE_TYPE_SUBTREE,
> >>>>>> +                               ENTRY_SIZE * ENTRY_NUM_SUBTREE);
> >>>>>> +                       odp_queue_enq(
> >>>>>> +                               tbl->free_slots[CACHE_TYPE_SUBTREE],
> >>>>>> +                               odp_buffer_to_event(*buff));
> >>>>>> +                       e->child = 0;
> >>>>>> +                       e->nexthop = over_nexthop;
> >>>>>> +                       e->cidr = over_cidr;
> >>>>>> +                       return 1;
> >>>>>> +               }
> >>>>>> +               return 0;
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       ret = prefix_delete_lx(
> >>>>>> +                       tbl, e, buff, cidr + 8 * depth,
> >>>>>> +                       over_cidr, over_nexthop, level);
> >>>>>> +       return ret;
> >>>>>> +}
> >>>>>> +
> >>>>>> +int
> >>>>>> +odph_iplookup_table_remove_value(odph_table_t tbl, void *key)
> >>>>>> +{
> >>>>>> +       if ((tbl == NULL) || (key == NULL))
> >>>>>> +               return -EINVAL;
> >>>>>> +
> >>>>>> +       odph_iplookup_table_impl *impl = (odph_iplookup_table_impl
> >>>>>> *)tbl;
> >>>>>> +       odph_iplookup_prefix_t *prefix = (odph_iplookup_prefix_t
> *)key;
> >>>>>> +       uint32_t ip = prefix->ip;
> >>>>>> +       uint8_t cidr = prefix->cidr;
> >>>>>> +
> >>>>>> +       if (prefix->cidr < 0)
> >>>>>> +               return -EINVAL;
> >>>>>> +
> >>>>>> +       prefix_entry_t *entry = &impl->l1e[ip >> 16];
> >>>>>> +       odp_buffer_t *buff = ENTRY_BUFF_ARR(impl->l1e) + (ip >> 16);
> >>>>>> +       uint8_t over_cidr, ret;
> >>>>>> +       odp_buffer_t over_nexthop;
> >>>>>> +
> >>>>>> +       trie_detect_overlap(
> >>>>>> +                       impl->trie, ip, cidr, 16, &over_cidr,
> >>>>>> &over_nexthop);
> >>>>>> +
> >>>>>> +       if (cidr <= 16) {
> >>>>>> +               prefix_delete_lx(
> >>>>>> +                       impl, entry, buff, cidr, over_cidr,
> >>>>>> over_nexthop,
> >>>>>> 16);
> >>>>>> +       } else {
> >>>>>> +               prefix_entry_t *ne = (prefix_entry_t *)entry->ptr;
> >>>>>> +               odp_buffer_t *nbuff = ENTRY_BUFF_ARR(ne);
> >>>>>> +
> >>>>>> +               ne += ((uint32_t)(ip << 16) >> 24);
> >>>>>> +               nbuff += ((uint32_t)(ip << 16) >> 24);
> >>>>>> +               ret = prefix_delete_iter(impl, ne, nbuff, ip, cidr -
> >>>>>> 16,
> >>>>>> 24, 2);
> >>>>>> +
> >>>>>> +               if (ret && can_recycle(entry, 16)) {
> >>>>>> +                       /* destroy subtree */
> >>>>>> +                       cache_init_buffer(
> >>>>>> +                               *buff, CACHE_TYPE_SUBTREE,
> >>>>>> +                               sizeof(prefix_entry_t) *
> >>>>>> ENTRY_NUM_SUBTREE);
> >>>>>> +                       odp_queue_enq(
> >>>>>> +
>  impl->free_slots[CACHE_TYPE_SUBTREE],
> >>>>>> +                               odp_buffer_to_event(*buff));
> >>>>>> +                       entry->child = 0;
> >>>>>> +                       entry->cidr = over_cidr;
> >>>>>> +                       entry->nexthop = over_nexthop;
> >>>>>> +               }
> >>>>>> +       }
> >>>>>> +
> >>>>>> +       return trie_delete_node(impl, impl->trie, ip, cidr);
> >>>>>> +}
> >>>>>> +
> >>>>>> +odph_table_ops_t odph_iplookup_table_ops = {
> >>>>>> +       odph_iplookup_table_create,
> >>>>>> +       odph_iplookup_table_lookup,
> >>>>>> +       odph_iplookup_table_destroy,
> >>>>>> +       odph_iplookup_table_put_value,
> >>>>>> +       odph_iplookup_table_get_value,
> >>>>>> +       odph_iplookup_table_remove_value
> >>>>>> +};
> >>>>>> diff --git a/helper/odph_iplookuptable.h
> b/helper/odph_iplookuptable.h
> >>>>>> new file mode 100644
> >>>>>> index 0000000..e6040ca
> >>>>>> --- /dev/null
> >>>>>> +++ b/helper/odph_iplookuptable.h
> >>>>>> @@ -0,0 +1,58 @@
> >>>>>> +/* Copyright (c) 2016, Linaro Limited
> >>>>>> + * All rights reserved.
> >>>>>> + *
> >>>>>> + * SPDX-License-Identifier:    BSD-3-Clause
> >>>>>> + */
> >>>>>> +
> >>>>>> +/**
> >>>>>> + * @file
> >>>>>> + *
> >>>>>> + * ODP IP Lookup Table
> >>>>>> + *
> >>>>>> + * This is an implementation of the IP lookup table. The key of
> >>>>>> + * this table is IPv4 address (32 bits), and the value can be
> >>>>>> + * defined by user. This table uses the 16,8,8 ip lookup (longest
> >>>>>> + * prefix matching) algorithm.
> >>>>>> + */
> >>>>>> +
> >>>>>> +#ifndef odph_iplookup_TABLE_H_
> >>>>>> +#define odph_iplookup_TABLE_H_
> >>>>>> +
> >>>>>> +#include <odp/helper/table.h>
> >>>>>> +
> >>>>>> +#ifdef __cplusplus
> >>>>>> +extern "C" {
> >>>>>> +#endif
> >>>>>> +
> >>>>>> +typedef struct {
> >>>>>> +       uint32_t ip;
> >>>>>> +       uint8_t cidr;
> >>>>>> +} odph_iplookup_prefix_t;
> >>>>>> +
> >>>>>> +odph_table_t odph_iplookup_table_create(
> >>>>>> +               const char *name,
> >>>>>> +               uint32_t ODP_IGNORED_1,
> >>>>>> +               uint32_t ODP_IGNORED_2,
> >>>>>> +               uint32_t value_size);
> >>>>>> +
> >>>>>> +odph_table_t odph_iplookup_table_lookup(const char *name);
> >>>>>> +
> >>>>>> +int odph_iplookup_table_destroy(odph_table_t table);
> >>>>>> +
> >>>>>> +int odph_iplookup_table_put_value(
> >>>>>> +               odph_table_t table, void *key, void *value);
> >>>>>> +
> >>>>>> +int odph_iplookup_table_get_value(
> >>>>>> +               odph_table_t table, void *key,
> >>>>>> +               void *buffer, uint32_t buffer_size);
> >>>>>> +
> >>>>>> +int odph_iplookup_table_remove_value(
> >>>>>> +               odph_table_t table, void *key);
> >>>>>> +
> >>>>>> +extern odph_table_ops_t odph_iplookup_table_ops;
> >>>>>> +
> >>>>>> +#ifdef __cplusplus
> >>>>>> +}
> >>>>>> +#endif
> >>>>>> +
> >>>>>> +#endif /* odph_iplookup_TABLE_H_ */
> >>>>>> --
> >>>>>> 1.9.1
> >>>>>>
> >>>>>> _______________________________________________
> >>>>>> lng-odp mailing list
> >>>>>> [email protected] <javascript:;>
> >>>>>> https://lists.linaro.org/mailman/listinfo/lng-odp
> >>>>>>
> >>>>>> _______________________________________________
> >>>>> lng-odp mailing list
> >>>>> [email protected] <javascript:;>
> >>>>> https://lists.linaro.org/mailman/listinfo/lng-odp
> >>>>>
> >>>>
> >>> _______________________________________________
> >>> lng-odp mailing list
> >>> [email protected] <javascript:;>
> >>> https://lists.linaro.org/mailman/listinfo/lng-odp
> >>>
> >>
> >> _______________________________________________
> >> lng-odp mailing list
> >> [email protected] <javascript:;>
> >> https://lists.linaro.org/mailman/listinfo/lng-odp
> >>
> > _______________________________________________
> > lng-odp mailing list
> > [email protected] <javascript:;>
> > https://lists.linaro.org/mailman/listinfo/lng-odp
>
>
>
_______________________________________________
lng-odp mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to