199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 5*e9fd1ebfSTyler Retzlaff #include <stdalign.h> 699a2dd95SBruce Richardson #include <stdio.h> 7*e9fd1ebfSTyler Retzlaff #include <string.h> 899a2dd95SBruce Richardson 999a2dd95SBruce Richardson #include <rte_common.h> 1099a2dd95SBruce Richardson #include <rte_malloc.h> 1199a2dd95SBruce Richardson #include <rte_log.h> 1299a2dd95SBruce Richardson 1399a2dd95SBruce Richardson #include "rte_table_array.h" 1499a2dd95SBruce Richardson 15ae67895bSDavid Marchand #include "table_log.h" 16ae67895bSDavid Marchand 1799a2dd95SBruce Richardson #ifdef RTE_TABLE_STATS_COLLECT 1899a2dd95SBruce Richardson 1999a2dd95SBruce Richardson #define RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(table, val) \ 2099a2dd95SBruce Richardson table->stats.n_pkts_in += val 2199a2dd95SBruce Richardson #define RTE_TABLE_ARRAY_STATS_PKTS_LOOKUP_MISS(table, val) \ 2299a2dd95SBruce Richardson table->stats.n_pkts_lookup_miss += val 2399a2dd95SBruce Richardson 2499a2dd95SBruce Richardson #else 2599a2dd95SBruce Richardson 2699a2dd95SBruce Richardson #define RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(table, val) 2799a2dd95SBruce Richardson #define RTE_TABLE_ARRAY_STATS_PKTS_LOOKUP_MISS(table, val) 2899a2dd95SBruce Richardson 2999a2dd95SBruce Richardson #endif 3099a2dd95SBruce Richardson 3199a2dd95SBruce Richardson struct rte_table_array { 3299a2dd95SBruce Richardson struct rte_table_stats stats; 3399a2dd95SBruce Richardson 3499a2dd95SBruce Richardson /* Input parameters */ 3599a2dd95SBruce Richardson uint32_t entry_size; 3699a2dd95SBruce Richardson uint32_t n_entries; 3799a2dd95SBruce Richardson uint32_t offset; 3899a2dd95SBruce Richardson 3999a2dd95SBruce Richardson /* Internal fields */ 4099a2dd95SBruce Richardson uint32_t entry_pos_mask; 4199a2dd95SBruce Richardson 4299a2dd95SBruce Richardson /* Internal table */ 43*e9fd1ebfSTyler Retzlaff alignas(RTE_CACHE_LINE_SIZE) uint8_t array[0]; 4499a2dd95SBruce Richardson } __rte_cache_aligned; 4599a2dd95SBruce Richardson 4699a2dd95SBruce Richardson static void * 4799a2dd95SBruce Richardson rte_table_array_create(void *params, int socket_id, uint32_t entry_size) 4899a2dd95SBruce Richardson { 4999a2dd95SBruce Richardson struct rte_table_array_params *p = params; 5099a2dd95SBruce Richardson struct rte_table_array *t; 5199a2dd95SBruce Richardson uint32_t total_cl_size, total_size; 5299a2dd95SBruce Richardson 5399a2dd95SBruce Richardson /* Check input parameters */ 5499a2dd95SBruce Richardson if ((p == NULL) || 5599a2dd95SBruce Richardson (p->n_entries == 0) || 5699a2dd95SBruce Richardson (!rte_is_power_of_2(p->n_entries))) 5799a2dd95SBruce Richardson return NULL; 5899a2dd95SBruce Richardson 5999a2dd95SBruce Richardson /* Memory allocation */ 6099a2dd95SBruce Richardson total_cl_size = (sizeof(struct rte_table_array) + 6199a2dd95SBruce Richardson RTE_CACHE_LINE_SIZE) / RTE_CACHE_LINE_SIZE; 6299a2dd95SBruce Richardson total_cl_size += (p->n_entries * entry_size + 6399a2dd95SBruce Richardson RTE_CACHE_LINE_SIZE) / RTE_CACHE_LINE_SIZE; 6499a2dd95SBruce Richardson total_size = total_cl_size * RTE_CACHE_LINE_SIZE; 6599a2dd95SBruce Richardson t = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); 6699a2dd95SBruce Richardson if (t == NULL) { 67ae67895bSDavid Marchand TABLE_LOG(ERR, 68ae67895bSDavid Marchand "%s: Cannot allocate %u bytes for array table", 6999a2dd95SBruce Richardson __func__, total_size); 7099a2dd95SBruce Richardson return NULL; 7199a2dd95SBruce Richardson } 7299a2dd95SBruce Richardson 7399a2dd95SBruce Richardson /* Memory initialization */ 7499a2dd95SBruce Richardson t->entry_size = entry_size; 7599a2dd95SBruce Richardson t->n_entries = p->n_entries; 7699a2dd95SBruce Richardson t->offset = p->offset; 7799a2dd95SBruce Richardson t->entry_pos_mask = t->n_entries - 1; 7899a2dd95SBruce Richardson 7999a2dd95SBruce Richardson return t; 8099a2dd95SBruce Richardson } 8199a2dd95SBruce Richardson 8299a2dd95SBruce Richardson static int 8399a2dd95SBruce Richardson rte_table_array_free(void *table) 8499a2dd95SBruce Richardson { 8599a2dd95SBruce Richardson struct rte_table_array *t = table; 8699a2dd95SBruce Richardson 8799a2dd95SBruce Richardson /* Check input parameters */ 8899a2dd95SBruce Richardson if (t == NULL) { 89ae67895bSDavid Marchand TABLE_LOG(ERR, "%s: table parameter is NULL", __func__); 9099a2dd95SBruce Richardson return -EINVAL; 9199a2dd95SBruce Richardson } 9299a2dd95SBruce Richardson 9399a2dd95SBruce Richardson /* Free previously allocated resources */ 9499a2dd95SBruce Richardson rte_free(t); 9599a2dd95SBruce Richardson 9699a2dd95SBruce Richardson return 0; 9799a2dd95SBruce Richardson } 9899a2dd95SBruce Richardson 9999a2dd95SBruce Richardson static int 10099a2dd95SBruce Richardson rte_table_array_entry_add( 10199a2dd95SBruce Richardson void *table, 10299a2dd95SBruce Richardson void *key, 10399a2dd95SBruce Richardson void *entry, 10499a2dd95SBruce Richardson int *key_found, 10599a2dd95SBruce Richardson void **entry_ptr) 10699a2dd95SBruce Richardson { 10799a2dd95SBruce Richardson struct rte_table_array *t = table; 10899a2dd95SBruce Richardson struct rte_table_array_key *k = key; 10999a2dd95SBruce Richardson uint8_t *table_entry; 11099a2dd95SBruce Richardson 11199a2dd95SBruce Richardson /* Check input parameters */ 11299a2dd95SBruce Richardson if (table == NULL) { 113ae67895bSDavid Marchand TABLE_LOG(ERR, "%s: table parameter is NULL", __func__); 11499a2dd95SBruce Richardson return -EINVAL; 11599a2dd95SBruce Richardson } 11699a2dd95SBruce Richardson if (key == NULL) { 117ae67895bSDavid Marchand TABLE_LOG(ERR, "%s: key parameter is NULL", __func__); 11899a2dd95SBruce Richardson return -EINVAL; 11999a2dd95SBruce Richardson } 12099a2dd95SBruce Richardson if (entry == NULL) { 121ae67895bSDavid Marchand TABLE_LOG(ERR, "%s: entry parameter is NULL", __func__); 12299a2dd95SBruce Richardson return -EINVAL; 12399a2dd95SBruce Richardson } 12499a2dd95SBruce Richardson if (key_found == NULL) { 125ae67895bSDavid Marchand TABLE_LOG(ERR, "%s: key_found parameter is NULL", 12699a2dd95SBruce Richardson __func__); 12799a2dd95SBruce Richardson return -EINVAL; 12899a2dd95SBruce Richardson } 12999a2dd95SBruce Richardson if (entry_ptr == NULL) { 130ae67895bSDavid Marchand TABLE_LOG(ERR, "%s: entry_ptr parameter is NULL", 13199a2dd95SBruce Richardson __func__); 13299a2dd95SBruce Richardson return -EINVAL; 13399a2dd95SBruce Richardson } 13499a2dd95SBruce Richardson 13599a2dd95SBruce Richardson table_entry = &t->array[k->pos * t->entry_size]; 13699a2dd95SBruce Richardson memcpy(table_entry, entry, t->entry_size); 13799a2dd95SBruce Richardson *key_found = 1; 13899a2dd95SBruce Richardson *entry_ptr = (void *) table_entry; 13999a2dd95SBruce Richardson 14099a2dd95SBruce Richardson return 0; 14199a2dd95SBruce Richardson } 14299a2dd95SBruce Richardson 14399a2dd95SBruce Richardson static int 14499a2dd95SBruce Richardson rte_table_array_lookup( 14599a2dd95SBruce Richardson void *table, 14699a2dd95SBruce Richardson struct rte_mbuf **pkts, 14799a2dd95SBruce Richardson uint64_t pkts_mask, 14899a2dd95SBruce Richardson uint64_t *lookup_hit_mask, 14999a2dd95SBruce Richardson void **entries) 15099a2dd95SBruce Richardson { 15199a2dd95SBruce Richardson struct rte_table_array *t = (struct rte_table_array *) table; 1523d4e27fdSDavid Marchand __rte_unused uint32_t n_pkts_in = rte_popcount64(pkts_mask); 15399a2dd95SBruce Richardson RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(t, n_pkts_in); 15499a2dd95SBruce Richardson *lookup_hit_mask = pkts_mask; 15599a2dd95SBruce Richardson 15699a2dd95SBruce Richardson if ((pkts_mask & (pkts_mask + 1)) == 0) { 1573d4e27fdSDavid Marchand uint64_t n_pkts = rte_popcount64(pkts_mask); 15899a2dd95SBruce Richardson uint32_t i; 15999a2dd95SBruce Richardson 16099a2dd95SBruce Richardson for (i = 0; i < n_pkts; i++) { 16199a2dd95SBruce Richardson struct rte_mbuf *pkt = pkts[i]; 16299a2dd95SBruce Richardson uint32_t entry_pos = RTE_MBUF_METADATA_UINT32(pkt, 16399a2dd95SBruce Richardson t->offset) & t->entry_pos_mask; 16499a2dd95SBruce Richardson 16599a2dd95SBruce Richardson entries[i] = (void *) &t->array[entry_pos * 16699a2dd95SBruce Richardson t->entry_size]; 16799a2dd95SBruce Richardson } 16899a2dd95SBruce Richardson } else { 16999a2dd95SBruce Richardson for ( ; pkts_mask; ) { 1703d4e27fdSDavid Marchand uint32_t pkt_index = rte_ctz64(pkts_mask); 17199a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << pkt_index; 17299a2dd95SBruce Richardson struct rte_mbuf *pkt = pkts[pkt_index]; 17399a2dd95SBruce Richardson uint32_t entry_pos = RTE_MBUF_METADATA_UINT32(pkt, 17499a2dd95SBruce Richardson t->offset) & t->entry_pos_mask; 17599a2dd95SBruce Richardson 17699a2dd95SBruce Richardson entries[pkt_index] = (void *) &t->array[entry_pos * 17799a2dd95SBruce Richardson t->entry_size]; 17899a2dd95SBruce Richardson pkts_mask &= ~pkt_mask; 17999a2dd95SBruce Richardson } 18099a2dd95SBruce Richardson } 18199a2dd95SBruce Richardson 18299a2dd95SBruce Richardson return 0; 18399a2dd95SBruce Richardson } 18499a2dd95SBruce Richardson 18599a2dd95SBruce Richardson static int 18699a2dd95SBruce Richardson rte_table_array_stats_read(void *table, struct rte_table_stats *stats, int clear) 18799a2dd95SBruce Richardson { 18899a2dd95SBruce Richardson struct rte_table_array *array = table; 18999a2dd95SBruce Richardson 19099a2dd95SBruce Richardson if (stats != NULL) 19199a2dd95SBruce Richardson memcpy(stats, &array->stats, sizeof(array->stats)); 19299a2dd95SBruce Richardson 19399a2dd95SBruce Richardson if (clear) 19499a2dd95SBruce Richardson memset(&array->stats, 0, sizeof(array->stats)); 19599a2dd95SBruce Richardson 19699a2dd95SBruce Richardson return 0; 19799a2dd95SBruce Richardson } 19899a2dd95SBruce Richardson 19999a2dd95SBruce Richardson struct rte_table_ops rte_table_array_ops = { 20099a2dd95SBruce Richardson .f_create = rte_table_array_create, 20199a2dd95SBruce Richardson .f_free = rte_table_array_free, 20299a2dd95SBruce Richardson .f_add = rte_table_array_entry_add, 20399a2dd95SBruce Richardson .f_delete = NULL, 20499a2dd95SBruce Richardson .f_add_bulk = NULL, 20599a2dd95SBruce Richardson .f_delete_bulk = NULL, 20699a2dd95SBruce Richardson .f_lookup = rte_table_array_lookup, 20799a2dd95SBruce Richardson .f_stats = rte_table_array_stats_read, 20899a2dd95SBruce Richardson }; 209