aboutsummaryrefslogtreecommitdiff
path: root/helper/iplookuptable.c
diff options
context:
space:
mode:
Diffstat (limited to 'helper/iplookuptable.c')
-rw-r--r--helper/iplookuptable.c946
1 files changed, 0 insertions, 946 deletions
diff --git a/helper/iplookuptable.c b/helper/iplookuptable.c
deleted file mode 100644
index ac7d05872..000000000
--- a/helper/iplookuptable.c
+++ /dev/null
@@ -1,946 +0,0 @@
-/* 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 <odp/helper/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 {
- odp_buffer_t nexthop;
- void *ptr;
- };
- 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
- };
- };
-} prefix_entry_t;
-
-#define ENTRY_SIZE (sizeof(prefix_entry_t) + sizeof(odp_buffer_t))
-#define ENTRY_BUFF_ARR(x) ((odp_buffer_t *)(void *)((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 two 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). */
- odp_pool_param_init(&param);
- 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;
- odp_shm_t shm;
-
- if (name == NULL || strlen(name) >= ODPH_TABLE_NAME_LEN)
- return NULL;
-
- shm = odp_shm_lookup(name);
- if (shm != ODP_SHM_INVALID)
- tbl = (odph_iplookup_table_impl *)odp_shm_addr(shm);
-
- 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 p1 ODP_UNUSED,
- uint32_t p2 ODP_UNUSED,
- 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 = (void *)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 *)(void *)((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 *)(void *)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)
- (void)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)
-{
- odph_iplookup_table_impl *impl = (void *)tbl;
- odph_iplookup_prefix_t *prefix = (odph_iplookup_prefix_t *)key;
- prefix_entry_t *l1e = NULL;
- odp_buffer_t nexthop;
- int ret = 0;
-
- if ((tbl == NULL) || (key == NULL) || (value == NULL))
- return -1;
-
- nexthop = *((odp_buffer_t *)value);
-
- if (prefix->cidr == 0)
- return -1;
- prefix->ip = prefix->ip & (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 ODP_UNUSED,
- uint32_t buffer_size ODP_UNUSED)
-{
- odph_iplookup_table_impl *impl = (void *)tbl;
- uint32_t ip;
- prefix_entry_t *entry;
- odp_buffer_t *buff = (odp_buffer_t *)buffer;
-
- if ((tbl == NULL) || (key == NULL) || (buffer == NULL))
- return -EINVAL;
-
- ip = *((uint32_t *)key);
- entry = &impl->l1e[ip >> 16];
-
- if (entry == NULL) {
- ODPH_DBG("failed to get L1 entry.\n");
- return -1;
- }
-
- 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)
-{
- odph_iplookup_table_impl *impl = (void *)tbl;
- odph_iplookup_prefix_t *prefix = (odph_iplookup_prefix_t *)key;
- uint32_t ip;
- uint8_t cidr;
-
- if ((tbl == NULL) || (key == NULL))
- return -EINVAL;
-
- ip = prefix->ip;
- cidr = prefix->cidr;
-
- if (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
-};