1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2014-2023 Broadcom 3 * All rights reserved. 4 */ 5 6 #include <rte_malloc.h> 7 #include "ulp_matcher.h" 8 #include "ulp_mapper.h" 9 #include "ulp_utils.h" 10 #include "bnxt_ulp_utils.h" 11 12 #ifndef RTE_HASH_BUCKET_ENTRIES 13 /* it is defined in lib/hash/rte_cuckoo_hash.h */ 14 #define RTE_HASH_BUCKET_ENTRIES 8 15 #endif /* RTE_HASH_BUCKET_ENTRIES */ 16 17 static int32_t 18 ulp_matcher_class_list_lookup(struct ulp_rte_parser_params *params, 19 uint32_t *class_match_idx) 20 { 21 struct bnxt_ulp_class_match_info *class_list = ulp_class_match_list; 22 uint32_t idx = 0; 23 24 while (++idx < BNXT_ULP_CLASS_MATCH_LIST_MAX_SZ) { 25 /* iterate the list of class matches to find header match */ 26 if (class_list[idx].app_id == params->app_id && 27 !ULP_BITMAP_CMP(&class_list[idx].hdr_bitmap, 28 ¶ms->hdr_bitmap)) { 29 /* Found the match */ 30 *class_match_idx = idx; 31 return 0; 32 } 33 } 34 BNXT_DRV_DBG(DEBUG, "Did not find any matching protocol hdr\n"); 35 return -1; 36 } 37 38 static int32_t 39 ulp_matcher_action_list_lookup(struct ulp_rte_parser_params *params, 40 uint32_t *act_tmpl_idx) 41 { 42 struct bnxt_ulp_act_match_info *act_list = ulp_act_match_list; 43 uint64_t act_bits = params->act_bitmap.bits; 44 uint32_t idx = 0; 45 46 while (++idx < BNXT_ULP_ACT_MATCH_LIST_MAX_SZ) { 47 /* iterate the list of action matches to find header match */ 48 if ((act_bits & act_list[idx].act_bitmap.bits) == act_bits) { 49 /* Found the match */ 50 *act_tmpl_idx = act_list[idx].act_tid; 51 /* set the comp field to enable action reject cond */ 52 ULP_COMP_FLD_IDX_WR(params, 53 BNXT_ULP_CF_IDX_ACT_REJ_COND_EN, 1); 54 return 0; 55 } 56 } 57 return -1; 58 } 59 60 static int32_t 61 ulp_matcher_class_hdr_field_validate(struct ulp_rte_parser_params *params, 62 uint32_t idx) 63 { 64 struct bnxt_ulp_class_match_info *info = &ulp_class_match_list[idx]; 65 uint64_t bitmap; 66 67 /* manadatory fields should be enabled */ 68 if ((params->fld_s_bitmap.bits & info->field_man_bitmap) != 69 info->field_man_bitmap){ 70 BNXT_DRV_DBG(DEBUG, "mismatch in manadatory hdr fields.\n"); 71 return -EINVAL; 72 } 73 74 /* optional fields may be enabled or not so ignore them */ 75 bitmap = params->fld_s_bitmap.bits & (~info->field_man_bitmap); 76 if ((bitmap && (bitmap & info->field_opt_bitmap) != bitmap)) { 77 BNXT_DRV_DBG(DEBUG, "mismatch in optional hdr fields.\n"); 78 return -EINVAL; 79 } 80 81 return 0; 82 } 83 84 static uint64_t 85 ulp_matcher_class_hdr_field_signature(struct ulp_rte_parser_params *params, 86 uint32_t idx) 87 { 88 struct bnxt_ulp_class_match_info *info = &ulp_class_match_list[idx]; 89 90 /* remove the exclude bits */ 91 return params->fld_s_bitmap.bits & ~info->field_exclude_bitmap; 92 } 93 94 static uint64_t 95 ulp_matcher_class_wc_fld_get(uint32_t idx) 96 { 97 struct bnxt_ulp_class_match_info *info = &ulp_class_match_list[idx]; 98 uint64_t bits; 99 100 bits = info->field_opt_bitmap | info->field_man_bitmap; 101 bits &= ~info->field_exclude_bitmap; 102 return bits; 103 } 104 105 static int32_t 106 ulp_matcher_class_hash_lookup(struct bnxt_ulp_matcher_data *matcher_data, 107 struct ulp_rte_parser_params *params, 108 uint32_t *class_hash_idx) 109 { 110 struct ulp_matcher_hash_db_key key = { {0} }; 111 struct ulp_matcher_class_db_node *node; 112 int32_t idx; 113 int32_t rc = -ENOENT; 114 115 /* populate the key for the search */ 116 key.app_id = params->app_id; 117 key.hdr_bitmap = params->hdr_bitmap; 118 119 /* search the hash table for the hdr bit match */ 120 idx = rte_hash_lookup(matcher_data->class_matcher_db, 121 (const void *)&key); 122 if (idx < 0 || idx >= matcher_data->class_list_size) 123 return rc; /* No Entry */ 124 125 node = &matcher_data->class_list[idx]; 126 if (!node->in_use) { 127 BNXT_DRV_DBG(ERR, "PANIC: Matcher database is corrupt %d\n", 128 idx); 129 return rc; 130 } 131 *class_hash_idx = idx; 132 return 0; /* Success */ 133 } 134 135 static int32_t 136 ulp_matcher_class_hash_add(struct bnxt_ulp_matcher_data *matcher_data, 137 struct ulp_rte_parser_params *params, 138 uint32_t class_match_idx, 139 uint32_t *class_hash_idx) 140 { 141 struct ulp_matcher_hash_db_key key = { {0} }; 142 struct ulp_matcher_class_db_node *node; 143 int32_t hash_idx; 144 int32_t rc = -EINVAL; 145 146 /* populate the key for the search */ 147 key.app_id = params->app_id; 148 key.hdr_bitmap = params->hdr_bitmap; 149 150 /* add to the hash table for the hdr bit match */ 151 hash_idx = rte_hash_add_key(matcher_data->class_matcher_db, 152 (const void *)&key); 153 if (hash_idx < 0 || hash_idx >= matcher_data->class_list_size) { 154 BNXT_DRV_DBG(ERR, "unable to add entry to matcher hash %d\n", 155 hash_idx); 156 return rc; 157 } 158 /* Initialize the class db node with default values */ 159 node = &matcher_data->class_list[hash_idx]; 160 node->in_use = 1; 161 node->match_info_idx = class_match_idx; 162 *class_hash_idx = hash_idx; 163 return 0; 164 } 165 166 /* 167 * Function to handle the matching of RTE Flows and validating 168 * the pattern masks against the flow templates. 169 */ 170 int32_t 171 ulp_matcher_pattern_match(struct ulp_rte_parser_params *params, 172 uint32_t *class_id) 173 { 174 struct bnxt_ulp_class_match_info *class_match; 175 struct ulp_matcher_class_db_node *class_node; 176 struct bnxt_ulp_matcher_data *matcher_data; 177 uint32_t class_match_idx = 0; 178 uint32_t hash_idx; 179 uint64_t bits = 0; 180 181 /* Get the matcher data for hash lookup */ 182 matcher_data = (struct bnxt_ulp_matcher_data *) 183 bnxt_ulp_cntxt_ptr2_matcher_data_get(params->ulp_ctx); 184 if (!matcher_data) { 185 BNXT_DRV_DBG(ERR, "Failed to get the ulp matcher data\n"); 186 return -EINVAL; 187 } 188 189 bits = bnxt_ulp_cntxt_ptr2_default_class_bits_get(params->ulp_ctx); 190 params->hdr_bitmap.bits |= bits; 191 192 /* search the matcher hash db for the entry */ 193 if (ulp_matcher_class_hash_lookup(matcher_data, params, 194 &hash_idx) == -ENOENT) { 195 /* find the class list entry */ 196 if (ulp_matcher_class_list_lookup(params, &class_match_idx)) 197 goto error; 198 199 /* add it to the hash */ 200 if (ulp_matcher_class_hash_add(matcher_data, params, 201 class_match_idx, &hash_idx)) 202 goto error; 203 } 204 class_node = &matcher_data->class_list[hash_idx]; 205 class_match = &ulp_class_match_list[class_node->match_info_idx]; 206 class_match_idx = class_node->match_info_idx; 207 208 /* perform the field bitmap validation */ 209 if (ulp_matcher_class_hdr_field_validate(params, 210 class_node->match_info_idx)) 211 goto error; 212 213 /* Update the fields for further processing */ 214 *class_id = class_match->class_tid; 215 params->class_info_idx = class_node->match_info_idx; 216 params->flow_sig_id = 217 ulp_matcher_class_hdr_field_signature(params, class_match_idx); 218 params->flow_pattern_id = class_match->flow_pattern_id; 219 params->wc_field_bitmap = ulp_matcher_class_wc_fld_get(class_match_idx); 220 params->exclude_field_bitmap = class_match->field_exclude_bitmap; 221 222 BNXT_DRV_DBG(DEBUG, "Found matching pattern template %u:%d\n", 223 class_match_idx, class_match->class_tid); 224 return BNXT_TF_RC_SUCCESS; 225 226 error: 227 BNXT_DRV_DBG(DEBUG, "Did not find any matching template\n"); 228 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 229 BNXT_DRV_DBG(DEBUG, 230 "hid:%x,Hdr:%" PRIX64 " Fld:%" PRIX64 " SFl:%" PRIX64 "\n", 231 class_match_idx, params->hdr_bitmap.bits, 232 params->fld_bitmap.bits, params->fld_s_bitmap.bits); 233 #endif 234 *class_id = 0; 235 return BNXT_TF_RC_ERROR; 236 } 237 238 static int32_t 239 ulp_matcher_action_hash_lookup(struct bnxt_ulp_matcher_data *matcher_data, 240 struct ulp_rte_parser_params *params, 241 uint32_t *act_tmpl_idx) 242 { 243 struct ulp_matcher_action_hash_db_key key = { {0} }; 244 struct ulp_matcher_act_db_node *node; 245 int32_t idx; 246 247 /* populate the key for the search */ 248 key.act_bitmap = params->act_bitmap; 249 250 /* search the hash table for the hdr bit match */ 251 idx = rte_hash_lookup(matcher_data->action_matcher_db, 252 (const void *)&key); 253 if (idx < 0 || idx >= BNXT_ULP_ACT_HASH_LIST_SIZE) 254 return -ENOENT; /* No Entry */ 255 256 node = &matcher_data->act_list[idx]; 257 *act_tmpl_idx = node->act_tmpl_idx; 258 return 0; /* Success */ 259 } 260 261 static int32_t 262 ulp_matcher_action_hash_add(struct bnxt_ulp_matcher_data *matcher_data, 263 struct ulp_rte_parser_params *params, 264 uint32_t match_idx) 265 { 266 struct ulp_matcher_action_hash_db_key key = { {0} }; 267 struct ulp_matcher_act_db_node *node; 268 int32_t hash_idx; 269 int32_t rc = -EINVAL; 270 271 /* populate the key for the search */ 272 key.act_bitmap = params->act_bitmap; 273 274 /* add to the hash table for the hdr bit match */ 275 hash_idx = rte_hash_add_key(matcher_data->action_matcher_db, 276 (const void *)&key); 277 if (hash_idx < 0 || hash_idx >= BNXT_ULP_ACT_HASH_LIST_SIZE) { 278 BNXT_DRV_DBG(ERR, "unable to add entry to action hash %d\n", 279 hash_idx); 280 return rc; 281 } 282 /* Initialize the class db node with default values */ 283 node = &matcher_data->act_list[hash_idx]; 284 node->act_tmpl_idx = match_idx; 285 return 0; 286 } 287 288 /* 289 * Function to handle the matching of RTE Flows and validating 290 * the action against the flow templates. 291 */ 292 int32_t 293 ulp_matcher_action_match(struct ulp_rte_parser_params *params, 294 uint32_t *act_id) 295 { 296 struct bnxt_ulp_matcher_data *matcher_data; 297 uint32_t act_tmpl_idx = 0; 298 uint64_t bits = 0; 299 300 /* Get the matcher data for hash lookup */ 301 matcher_data = (struct bnxt_ulp_matcher_data *) 302 bnxt_ulp_cntxt_ptr2_matcher_data_get(params->ulp_ctx); 303 if (!matcher_data) { 304 BNXT_DRV_DBG(ERR, "Failed to get the ulp matcher data\n"); 305 return -EINVAL; 306 } 307 308 bits = bnxt_ulp_cntxt_ptr2_default_act_bits_get(params->ulp_ctx); 309 params->act_bitmap.bits |= bits; 310 311 /* search the matcher hash db for the entry */ 312 if (ulp_matcher_action_hash_lookup(matcher_data, params, 313 &act_tmpl_idx) == -ENOENT) { 314 /* find the action entry */ 315 if (ulp_matcher_action_list_lookup(params, &act_tmpl_idx)) 316 goto error; 317 318 /* add it to the hash */ 319 if (ulp_matcher_action_hash_add(matcher_data, params, 320 act_tmpl_idx)) 321 goto error; 322 } 323 324 BNXT_DRV_DBG(DEBUG, "Found matching action template %u\n", act_tmpl_idx); 325 *act_id = act_tmpl_idx; 326 return BNXT_TF_RC_SUCCESS; 327 error: 328 BNXT_DRV_DBG(DEBUG, "Did not find any matching action template\n"); 329 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG 330 BNXT_DRV_DBG(DEBUG, "Hdr:%" PRIX64 "\n", params->act_bitmap.bits); 331 #endif 332 *act_id = 0; 333 return BNXT_TF_RC_ERROR; 334 } 335 336 int32_t ulp_matcher_init(struct bnxt_ulp_context *ulp_ctx) 337 { 338 struct rte_hash_parameters hash_tbl_params = {0}; 339 char hash_class_tbl_name[64] = {0}; 340 char hash_act_tbl_name[64] = {0}; 341 struct bnxt_ulp_matcher_data *data; 342 uint16_t port_id; 343 344 /* append port_id to the buffer name */ 345 port_id = ulp_ctx->bp->eth_dev->data->port_id; 346 snprintf(hash_class_tbl_name, sizeof(hash_class_tbl_name), 347 "bnxt_ulp_class_matcher_%d", port_id); 348 snprintf(hash_act_tbl_name, sizeof(hash_act_tbl_name), 349 "bnxt_ulp_act_matcher_%d", port_id); 350 351 data = rte_zmalloc("bnxt_ulp_matcher_data", 352 sizeof(struct bnxt_ulp_matcher_data), 0); 353 if (!data) { 354 BNXT_DRV_DBG(ERR, "Failed to allocate the matcher data\n"); 355 return -ENOMEM; 356 } 357 358 if (bnxt_ulp_cntxt_ptr2_matcher_data_set(ulp_ctx, data)) { 359 BNXT_DRV_DBG(ERR, "Failed to set matcher data in context\n"); 360 rte_free(data); 361 return -ENOMEM; 362 } 363 364 /* create the hash table for the matcher entries */ 365 hash_tbl_params.name = hash_class_tbl_name; 366 hash_tbl_params.entries = BNXT_ULP_CLASS_MATCH_LIST_MAX_SZ + 367 RTE_HASH_BUCKET_ENTRIES; 368 369 hash_tbl_params.key_len = sizeof(struct ulp_matcher_hash_db_key); 370 hash_tbl_params.socket_id = rte_socket_id(); 371 data->class_matcher_db = rte_hash_create(&hash_tbl_params); 372 if (data->class_matcher_db == NULL) { 373 BNXT_DRV_DBG(ERR, "Failed to create class matcher hash tbl\n"); 374 goto error; 375 } 376 377 /* allocate memorry for the class list */ 378 data->class_list_size = hash_tbl_params.entries; 379 data->class_list = rte_zmalloc("bnxt_ulp_matcher_class_list", 380 sizeof(struct ulp_matcher_class_db_node) 381 * data->class_list_size, 0); 382 if (data->class_list == NULL) { 383 BNXT_DRV_DBG(ERR, "Failed to create matcher class list\n"); 384 goto error; 385 } 386 387 /* create the hash table for the action entries */ 388 hash_tbl_params.name = hash_act_tbl_name; 389 /* The hash list size set to max support and not dependent on template*/ 390 hash_tbl_params.entries = BNXT_ULP_ACT_HASH_LIST_SIZE; 391 hash_tbl_params.key_len = sizeof(struct ulp_matcher_action_hash_db_key); 392 hash_tbl_params.socket_id = rte_socket_id(); 393 data->action_matcher_db = rte_hash_create(&hash_tbl_params); 394 if (data->action_matcher_db == NULL) { 395 BNXT_DRV_DBG(ERR, "Failed to create action matcher hash tbl\n"); 396 goto error; 397 } 398 399 /* allocate memorry for the action list */ 400 data->act_list = rte_zmalloc("bnxt_ulp_matcher_act_list", 401 sizeof(struct ulp_matcher_act_db_node) 402 * BNXT_ULP_ACT_HASH_LIST_SIZE, 0); 403 if (data->act_list == NULL) { 404 BNXT_DRV_DBG(ERR, "Failed to create matcher act list\n"); 405 goto error; 406 } 407 return 0; 408 error: 409 ulp_matcher_deinit(ulp_ctx); 410 return -ENOMEM; 411 } 412 413 void ulp_matcher_deinit(struct bnxt_ulp_context *ulp_ctx) 414 { 415 struct bnxt_ulp_matcher_data *data; 416 417 if (!ulp_ctx) { 418 BNXT_DRV_DBG(ERR, "Failed to acquire ulp context\n"); 419 return; 420 } 421 422 data = (struct bnxt_ulp_matcher_data *) 423 bnxt_ulp_cntxt_ptr2_matcher_data_get(ulp_ctx); 424 if (!data) { 425 /* Go ahead and return since there is no allocated data. */ 426 BNXT_DRV_DBG(ERR, "No data appears to have been allocated.\n"); 427 return; 428 } 429 430 /* Delete all the hash nodes and the hash list */ 431 rte_hash_free(data->class_matcher_db); 432 data->class_matcher_db = NULL; 433 434 /* free matcher class list */ 435 rte_free(data->class_list); 436 data->class_list = NULL; 437 438 /* Delete all the hash nodes and the hash list */ 439 rte_hash_free(data->action_matcher_db); 440 data->action_matcher_db = NULL; 441 442 /* free matcher act list */ 443 rte_free(data->act_list); 444 data->act_list = NULL; 445 446 /* free the matcher data */ 447 rte_free(data); 448 449 /* Reset the data pointer within the ulp_ctx. */ 450 bnxt_ulp_cntxt_ptr2_matcher_data_set(ulp_ctx, NULL); 451 } 452