1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <stdalign.h> 6 #include <stdio.h> 7 #include <string.h> 8 9 #include <rte_common.h> 10 #include <rte_malloc.h> 11 #include <rte_log.h> 12 13 #include "rte_table_array.h" 14 15 #include "table_log.h" 16 17 #ifdef RTE_TABLE_STATS_COLLECT 18 19 #define RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(table, val) \ 20 table->stats.n_pkts_in += val 21 #define RTE_TABLE_ARRAY_STATS_PKTS_LOOKUP_MISS(table, val) \ 22 table->stats.n_pkts_lookup_miss += val 23 24 #else 25 26 #define RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(table, val) 27 #define RTE_TABLE_ARRAY_STATS_PKTS_LOOKUP_MISS(table, val) 28 29 #endif 30 31 struct rte_table_array { 32 struct rte_table_stats stats; 33 34 /* Input parameters */ 35 uint32_t entry_size; 36 uint32_t n_entries; 37 uint32_t offset; 38 39 /* Internal fields */ 40 uint32_t entry_pos_mask; 41 42 /* Internal table */ 43 alignas(RTE_CACHE_LINE_SIZE) uint8_t array[0]; 44 } __rte_cache_aligned; 45 46 static void * 47 rte_table_array_create(void *params, int socket_id, uint32_t entry_size) 48 { 49 struct rte_table_array_params *p = params; 50 struct rte_table_array *t; 51 uint32_t total_cl_size, total_size; 52 53 /* Check input parameters */ 54 if ((p == NULL) || 55 (p->n_entries == 0) || 56 (!rte_is_power_of_2(p->n_entries))) 57 return NULL; 58 59 /* Memory allocation */ 60 total_cl_size = (sizeof(struct rte_table_array) + 61 RTE_CACHE_LINE_SIZE) / RTE_CACHE_LINE_SIZE; 62 total_cl_size += (p->n_entries * entry_size + 63 RTE_CACHE_LINE_SIZE) / RTE_CACHE_LINE_SIZE; 64 total_size = total_cl_size * RTE_CACHE_LINE_SIZE; 65 t = rte_zmalloc_socket("TABLE", total_size, RTE_CACHE_LINE_SIZE, socket_id); 66 if (t == NULL) { 67 TABLE_LOG(ERR, 68 "%s: Cannot allocate %u bytes for array table", 69 __func__, total_size); 70 return NULL; 71 } 72 73 /* Memory initialization */ 74 t->entry_size = entry_size; 75 t->n_entries = p->n_entries; 76 t->offset = p->offset; 77 t->entry_pos_mask = t->n_entries - 1; 78 79 return t; 80 } 81 82 static int 83 rte_table_array_free(void *table) 84 { 85 struct rte_table_array *t = table; 86 87 /* Check input parameters */ 88 if (t == NULL) { 89 TABLE_LOG(ERR, "%s: table parameter is NULL", __func__); 90 return -EINVAL; 91 } 92 93 /* Free previously allocated resources */ 94 rte_free(t); 95 96 return 0; 97 } 98 99 static int 100 rte_table_array_entry_add( 101 void *table, 102 void *key, 103 void *entry, 104 int *key_found, 105 void **entry_ptr) 106 { 107 struct rte_table_array *t = table; 108 struct rte_table_array_key *k = key; 109 uint8_t *table_entry; 110 111 /* Check input parameters */ 112 if (table == NULL) { 113 TABLE_LOG(ERR, "%s: table parameter is NULL", __func__); 114 return -EINVAL; 115 } 116 if (key == NULL) { 117 TABLE_LOG(ERR, "%s: key parameter is NULL", __func__); 118 return -EINVAL; 119 } 120 if (entry == NULL) { 121 TABLE_LOG(ERR, "%s: entry parameter is NULL", __func__); 122 return -EINVAL; 123 } 124 if (key_found == NULL) { 125 TABLE_LOG(ERR, "%s: key_found parameter is NULL", 126 __func__); 127 return -EINVAL; 128 } 129 if (entry_ptr == NULL) { 130 TABLE_LOG(ERR, "%s: entry_ptr parameter is NULL", 131 __func__); 132 return -EINVAL; 133 } 134 135 table_entry = &t->array[k->pos * t->entry_size]; 136 memcpy(table_entry, entry, t->entry_size); 137 *key_found = 1; 138 *entry_ptr = (void *) table_entry; 139 140 return 0; 141 } 142 143 static int 144 rte_table_array_lookup( 145 void *table, 146 struct rte_mbuf **pkts, 147 uint64_t pkts_mask, 148 uint64_t *lookup_hit_mask, 149 void **entries) 150 { 151 struct rte_table_array *t = (struct rte_table_array *) table; 152 __rte_unused uint32_t n_pkts_in = rte_popcount64(pkts_mask); 153 RTE_TABLE_ARRAY_STATS_PKTS_IN_ADD(t, n_pkts_in); 154 *lookup_hit_mask = pkts_mask; 155 156 if ((pkts_mask & (pkts_mask + 1)) == 0) { 157 uint64_t n_pkts = rte_popcount64(pkts_mask); 158 uint32_t i; 159 160 for (i = 0; i < n_pkts; i++) { 161 struct rte_mbuf *pkt = pkts[i]; 162 uint32_t entry_pos = RTE_MBUF_METADATA_UINT32(pkt, 163 t->offset) & t->entry_pos_mask; 164 165 entries[i] = (void *) &t->array[entry_pos * 166 t->entry_size]; 167 } 168 } else { 169 for ( ; pkts_mask; ) { 170 uint32_t pkt_index = rte_ctz64(pkts_mask); 171 uint64_t pkt_mask = 1LLU << pkt_index; 172 struct rte_mbuf *pkt = pkts[pkt_index]; 173 uint32_t entry_pos = RTE_MBUF_METADATA_UINT32(pkt, 174 t->offset) & t->entry_pos_mask; 175 176 entries[pkt_index] = (void *) &t->array[entry_pos * 177 t->entry_size]; 178 pkts_mask &= ~pkt_mask; 179 } 180 } 181 182 return 0; 183 } 184 185 static int 186 rte_table_array_stats_read(void *table, struct rte_table_stats *stats, int clear) 187 { 188 struct rte_table_array *array = table; 189 190 if (stats != NULL) 191 memcpy(stats, &array->stats, sizeof(array->stats)); 192 193 if (clear) 194 memset(&array->stats, 0, sizeof(array->stats)); 195 196 return 0; 197 } 198 199 struct rte_table_ops rte_table_array_ops = { 200 .f_create = rte_table_array_create, 201 .f_free = rte_table_array_free, 202 .f_add = rte_table_array_entry_add, 203 .f_delete = NULL, 204 .f_add_bulk = NULL, 205 .f_delete_bulk = NULL, 206 .f_lookup = rte_table_array_lookup, 207 .f_stats = rte_table_array_stats_read, 208 }; 209