xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_matcher.c (revision 0c036a1485b9d9163a8fa8059ed5272d060c05e0)
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 				    &params->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