xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_def_rules.c (revision d4b36fc5f0dc59b256441c82e5a9395054026496)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2023 Broadcom
3  * All rights reserved.
4  */
5 
6 #include "bnxt_tf_common.h"
7 #include "bnxt_ulp_utils.h"
8 #include "ulp_template_struct.h"
9 #include "ulp_template_db_enum.h"
10 #include "ulp_template_db_field.h"
11 #include "ulp_utils.h"
12 #include "ulp_port_db.h"
13 #include "ulp_flow_db.h"
14 #include "ulp_mapper.h"
15 #include "ulp_rte_parser.h"
16 static void
17 ulp_l2_custom_tunnel_id_update(struct bnxt *bp,
18 			       struct bnxt_ulp_mapper_parms *params);
19 
20 struct bnxt_ulp_def_param_handler {
21 	int32_t (*vfr_func)(struct bnxt_ulp_context *ulp_ctx,
22 			    struct ulp_tlv_param *param,
23 			    struct bnxt_ulp_mapper_parms *mapper_params);
24 };
25 
26 static int32_t
27 ulp_set_svif_in_comp_fld(struct bnxt_ulp_context *ulp_ctx,
28 			 uint32_t  ifindex, uint8_t svif_type,
29 			 struct bnxt_ulp_mapper_parms *mapper_params)
30 {
31 	uint16_t svif;
32 	uint8_t idx;
33 	int rc;
34 
35 	rc = ulp_port_db_svif_get(ulp_ctx, ifindex, svif_type, &svif);
36 	if (rc)
37 		return rc;
38 
39 	if (svif_type == BNXT_ULP_PHY_PORT_SVIF)
40 		idx = BNXT_ULP_CF_IDX_PHY_PORT_SVIF;
41 	else if (svif_type == BNXT_ULP_DRV_FUNC_SVIF)
42 		idx = BNXT_ULP_CF_IDX_DRV_FUNC_SVIF;
43 	else
44 		idx = BNXT_ULP_CF_IDX_VF_FUNC_SVIF;
45 
46 	ULP_COMP_FLD_IDX_WR(mapper_params, idx, svif);
47 
48 	return 0;
49 }
50 
51 static int32_t
52 ulp_set_spif_in_comp_fld(struct bnxt_ulp_context *ulp_ctx,
53 			 uint32_t  ifindex, uint8_t spif_type,
54 			 struct bnxt_ulp_mapper_parms *mapper_params)
55 {
56 	uint16_t spif;
57 	uint8_t idx;
58 	int rc;
59 
60 	rc = ulp_port_db_spif_get(ulp_ctx, ifindex, spif_type, &spif);
61 	if (rc)
62 		return rc;
63 
64 	if (spif_type == BNXT_ULP_PHY_PORT_SPIF)
65 		idx = BNXT_ULP_CF_IDX_PHY_PORT_SPIF;
66 	else if (spif_type == BNXT_ULP_DRV_FUNC_SPIF)
67 		idx = BNXT_ULP_CF_IDX_DRV_FUNC_SPIF;
68 	else
69 		idx = BNXT_ULP_CF_IDX_VF_FUNC_SPIF;
70 
71 	ULP_COMP_FLD_IDX_WR(mapper_params, idx, spif);
72 
73 	return 0;
74 }
75 
76 static int32_t
77 ulp_set_parif_in_comp_fld(struct bnxt_ulp_context *ulp_ctx,
78 			  uint32_t  ifindex, uint8_t parif_type,
79 			  struct bnxt_ulp_mapper_parms *mapper_params)
80 {
81 	uint16_t parif;
82 	uint8_t idx;
83 	int rc;
84 
85 	rc = ulp_port_db_parif_get(ulp_ctx, ifindex, parif_type, &parif);
86 	if (rc)
87 		return rc;
88 
89 	if (parif_type == BNXT_ULP_PHY_PORT_PARIF)
90 		idx = BNXT_ULP_CF_IDX_PHY_PORT_PARIF;
91 	else if (parif_type == BNXT_ULP_DRV_FUNC_PARIF)
92 		idx = BNXT_ULP_CF_IDX_DRV_FUNC_PARIF;
93 	else
94 		idx = BNXT_ULP_CF_IDX_VF_FUNC_PARIF;
95 
96 	ULP_COMP_FLD_IDX_WR(mapper_params, idx, parif);
97 
98 	return 0;
99 }
100 
101 static int32_t
102 ulp_set_vport_in_comp_fld(struct bnxt_ulp_context *ulp_ctx, uint32_t ifindex,
103 			  struct bnxt_ulp_mapper_parms *mapper_params)
104 {
105 	uint16_t vport;
106 	int rc;
107 
108 	rc = ulp_port_db_vport_get(ulp_ctx, ifindex, &vport);
109 	if (rc)
110 		return rc;
111 
112 	ULP_COMP_FLD_IDX_WR(mapper_params, BNXT_ULP_CF_IDX_PHY_PORT_VPORT,
113 			    vport);
114 	return 0;
115 }
116 
117 static int32_t
118 ulp_set_vnic_in_comp_fld(struct bnxt_ulp_context *ulp_ctx,
119 			 uint32_t  ifindex, uint8_t vnic_type,
120 			 struct bnxt_ulp_mapper_parms *mapper_params)
121 {
122 	uint16_t vnic;
123 	uint8_t idx;
124 	int rc;
125 
126 	rc = ulp_port_db_default_vnic_get(ulp_ctx, ifindex, vnic_type, &vnic);
127 	if (rc)
128 		return rc;
129 
130 	if (vnic_type == BNXT_ULP_DRV_FUNC_VNIC)
131 		idx = BNXT_ULP_CF_IDX_DRV_FUNC_VNIC;
132 	else
133 		idx = BNXT_ULP_CF_IDX_VF_FUNC_VNIC;
134 
135 	ULP_COMP_FLD_IDX_WR(mapper_params, idx, vnic);
136 
137 	return 0;
138 }
139 
140 static int32_t
141 ulp_set_vlan_in_act_prop(uint16_t port_id,
142 			 struct bnxt_ulp_mapper_parms *mapper_params)
143 {
144 	struct ulp_rte_act_prop *act_prop = mapper_params->act_prop;
145 
146 	if (ULP_BITMAP_ISSET(mapper_params->act_bitmap->bits,
147 			     BNXT_ULP_ACT_BIT_SET_VLAN_VID)) {
148 		BNXT_DRV_DBG(ERR,
149 			     "VLAN already set, multiple VLANs unsupported\n");
150 		return BNXT_TF_RC_ERROR;
151 	}
152 
153 	port_id = rte_cpu_to_be_16(port_id);
154 
155 	ULP_BITMAP_SET(mapper_params->act_bitmap->bits,
156 		       BNXT_ULP_ACT_BIT_SET_VLAN_VID);
157 
158 	memcpy(&act_prop->act_details[BNXT_ULP_ACT_PROP_IDX_ENCAP_VTAG],
159 	       &port_id, sizeof(port_id));
160 
161 	return 0;
162 }
163 
164 static int32_t
165 ulp_set_mark_in_act_prop(uint16_t port_id,
166 			 struct bnxt_ulp_mapper_parms *mapper_params)
167 {
168 	if (ULP_BITMAP_ISSET(mapper_params->act_bitmap->bits,
169 			     BNXT_ULP_ACT_BIT_MARK)) {
170 		BNXT_DRV_DBG(ERR,
171 			     "MARK already set, multiple MARKs unsupported\n");
172 		return BNXT_TF_RC_ERROR;
173 	}
174 
175 	ULP_COMP_FLD_IDX_WR(mapper_params, BNXT_ULP_CF_IDX_DEV_PORT_ID,
176 			    port_id);
177 
178 	return 0;
179 }
180 
181 static int32_t
182 ulp_df_dev_port_handler(struct bnxt_ulp_context *ulp_ctx,
183 			struct ulp_tlv_param *param,
184 			struct bnxt_ulp_mapper_parms *mapper_params)
185 {
186 	uint16_t port_id;
187 	uint16_t parif;
188 	uint32_t ifindex;
189 	int rc;
190 
191 	port_id = param->value[0] | param->value[1];
192 
193 	rc = ulp_port_db_dev_port_to_ulp_index(ulp_ctx, port_id, &ifindex);
194 	if (rc) {
195 		BNXT_DRV_DBG(ERR, "Invalid port id\n");
196 		return BNXT_TF_RC_ERROR;
197 	}
198 
199 	/* Set port SVIF */
200 	rc = ulp_set_svif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_PHY_PORT_SVIF,
201 				      mapper_params);
202 	if (rc)
203 		return rc;
204 
205 	/* Set DRV Func SVIF */
206 	rc = ulp_set_svif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_DRV_FUNC_SVIF,
207 				      mapper_params);
208 	if (rc)
209 		return rc;
210 
211 	/* Set VF Func SVIF */
212 	rc = ulp_set_svif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_VF_FUNC_SVIF,
213 				      mapper_params);
214 	if (rc)
215 		return rc;
216 
217 	/* Set port SPIF */
218 	rc = ulp_set_spif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_PHY_PORT_SPIF,
219 				      mapper_params);
220 	if (rc)
221 		return rc;
222 
223 	/* Set DRV Func SPIF */
224 	rc = ulp_set_spif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_DRV_FUNC_SPIF,
225 				      mapper_params);
226 	if (rc)
227 		return rc;
228 
229 	/* Set VF Func SPIF */
230 	rc = ulp_set_spif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_DRV_FUNC_SPIF,
231 				      mapper_params);
232 	if (rc)
233 		return rc;
234 
235 	/* Set port PARIF */
236 	rc = ulp_set_parif_in_comp_fld(ulp_ctx, ifindex,
237 				       BNXT_ULP_PHY_PORT_PARIF, mapper_params);
238 	if (rc)
239 		return rc;
240 
241 	/* Set DRV Func PARIF */
242 	rc = ulp_set_parif_in_comp_fld(ulp_ctx, ifindex,
243 				       BNXT_ULP_DRV_FUNC_PARIF, mapper_params);
244 	if (rc)
245 		return rc;
246 
247 	/* Note:
248 	 * We save the drv_func_parif into CF_IDX of phy_port_parif,
249 	 * since that index is currently referenced by ingress templates
250 	 * for datapath flows. If in the future we change the parser to
251 	 * save it in the CF_IDX of drv_func_parif we also need to update
252 	 * the template.
253 	 * WARNING: Two VFs on same parent PF will not work, as the parif is
254 	 * based on fw fid of the parent PF.
255 	 */
256 	parif = ULP_COMP_FLD_IDX_RD(mapper_params, BNXT_ULP_CF_IDX_DRV_FUNC_PARIF);
257 	ULP_COMP_FLD_IDX_WR(mapper_params, BNXT_ULP_CF_IDX_PHY_PORT_PARIF, parif);
258 
259 	/* Set VF Func PARIF */
260 	rc = ulp_set_parif_in_comp_fld(ulp_ctx, ifindex, BNXT_ULP_VF_FUNC_PARIF,
261 				       mapper_params);
262 	if (rc)
263 		return rc;
264 
265 	/* Set uplink VNIC */
266 	rc = ulp_set_vnic_in_comp_fld(ulp_ctx, ifindex, true, mapper_params);
267 	if (rc)
268 		return rc;
269 
270 	/* Set VF VNIC */
271 	rc = ulp_set_vnic_in_comp_fld(ulp_ctx, ifindex, false, mapper_params);
272 	if (rc)
273 		return rc;
274 
275 	/* Set VPORT */
276 	rc = ulp_set_vport_in_comp_fld(ulp_ctx, ifindex, mapper_params);
277 	if (rc)
278 		return rc;
279 
280 	/* Set VLAN */
281 	rc = ulp_set_vlan_in_act_prop(port_id, mapper_params);
282 	if (rc)
283 		return rc;
284 
285 	/* Set MARK */
286 	rc = ulp_set_mark_in_act_prop(port_id, mapper_params);
287 	if (rc)
288 		return rc;
289 
290 	return 0;
291 }
292 
293 struct bnxt_ulp_def_param_handler ulp_def_handler_tbl[] = {
294 	[BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID] = {
295 			.vfr_func = ulp_df_dev_port_handler }
296 };
297 
298 /*
299  * Function to create default rules for the following paths
300  * 1) Device PORT to DPDK App
301  * 2) DPDK App to Device PORT
302  * 3) VF Representor to VF
303  * 4) VF to VF Representor
304  *
305  * eth_dev [in] Ptr to rte eth device.
306  * param_list [in] Ptr to a list of parameters (Currently, only DPDK port_id).
307  * ulp_class_tid [in] Class template ID number.
308  * flow_id [out] Ptr to flow identifier.
309  *
310  * Returns 0 on success or negative number on failure.
311  */
312 int32_t
313 ulp_default_flow_create(struct rte_eth_dev *eth_dev,
314 			struct ulp_tlv_param *param_list,
315 			uint32_t ulp_class_tid,
316 			uint16_t port_id,
317 			uint32_t *flow_id)
318 {
319 	struct ulp_rte_hdr_field	hdr_field[BNXT_ULP_PROTO_HDR_MAX];
320 	uint64_t			comp_fld[BNXT_ULP_CF_IDX_LAST];
321 	struct bnxt_ulp_mapper_parms mapper_params = { 0 };
322 	struct ulp_rte_act_prop		act_prop;
323 	struct ulp_rte_act_bitmap	act = { 0 };
324 	struct bnxt_ulp_context		*ulp_ctx;
325 	uint32_t type, ulp_flags = 0, fid;
326 	struct bnxt *bp = eth_dev->data->dev_private;
327 	uint16_t static_port = 0;
328 	int rc = 0;
329 
330 	memset(&mapper_params, 0, sizeof(mapper_params));
331 	memset(hdr_field, 0, sizeof(hdr_field));
332 	memset(comp_fld, 0, sizeof(comp_fld));
333 	memset(&act_prop, 0, sizeof(act_prop));
334 
335 	mapper_params.hdr_field = hdr_field;
336 	mapper_params.act_bitmap = &act;
337 	mapper_params.act_prop = &act_prop;
338 	mapper_params.comp_fld = comp_fld;
339 	mapper_params.class_tid = ulp_class_tid;
340 	mapper_params.flow_type = BNXT_ULP_FDB_TYPE_DEFAULT;
341 	mapper_params.port_id = eth_dev->data->port_id;
342 
343 	ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
344 	if (!ulp_ctx) {
345 		BNXT_DRV_DBG(ERR,
346 			     "ULP is not init'ed. Fail to create dflt flow.\n");
347 		return -EINVAL;
348 	}
349 
350 	/* update the vf rep flag */
351 	if (bnxt_ulp_cntxt_ptr2_ulp_flags_get(ulp_ctx, &ulp_flags)) {
352 		BNXT_DRV_DBG(ERR, "Error in getting ULP context flags\n");
353 		return -EINVAL;
354 	}
355 	if (ULP_VF_REP_IS_ENABLED(ulp_flags))
356 		ULP_COMP_FLD_IDX_WR(&mapper_params,
357 				    BNXT_ULP_CF_IDX_VFR_MODE, 1);
358 
359 	type = param_list->type;
360 	while (type != BNXT_ULP_DF_PARAM_TYPE_LAST) {
361 		if (ulp_def_handler_tbl[type].vfr_func) {
362 			rc = ulp_def_handler_tbl[type].vfr_func(ulp_ctx,
363 								param_list,
364 								&mapper_params);
365 			if (rc) {
366 				BNXT_DRV_DBG(ERR,
367 					    "Failed to create default flow.\n");
368 				return rc;
369 			}
370 		}
371 
372 		param_list++;
373 		type = param_list->type;
374 	}
375 
376 	/* Get the function id */
377 	if (ulp_port_db_port_func_id_get(ulp_ctx,
378 					 port_id,
379 					 &mapper_params.func_id)) {
380 		BNXT_DRV_DBG(ERR, "conversion of port to func id failed\n");
381 		goto err1;
382 	}
383 
384 	/* update the VF meta function id  */
385 	ULP_COMP_FLD_IDX_WR(&mapper_params, BNXT_ULP_CF_IDX_VF_META_FID,
386 			    BNXT_ULP_META_VF_FLAG | mapper_params.func_id);
387 
388 	/* update the upar id */
389 	ulp_l2_custom_tunnel_id_update(bp, &mapper_params);
390 
391 	/* update the vxlan port */
392 	if (ULP_APP_STATIC_VXLAN_PORT_EN(ulp_ctx)) {
393 		static_port = bnxt_ulp_cntxt_vxlan_port_get(ulp_ctx);
394 		if (static_port) {
395 			ULP_COMP_FLD_IDX_WR(&mapper_params,
396 					    BNXT_ULP_CF_IDX_TUNNEL_PORT,
397 					    static_port);
398 			ULP_BITMAP_SET(mapper_params.cf_bitmap,
399 				       BNXT_ULP_CF_BIT_STATIC_VXLAN_PORT);
400 		} else {
401 			static_port = bnxt_ulp_cntxt_vxlan_ip_port_get(ulp_ctx);
402 			ULP_COMP_FLD_IDX_WR(&mapper_params,
403 					    BNXT_ULP_CF_IDX_TUNNEL_PORT,
404 					    static_port);
405 			ULP_BITMAP_SET(mapper_params.cf_bitmap,
406 				       BNXT_ULP_CF_BIT_STATIC_VXLAN_IP_PORT);
407 		}
408 	}
409 
410 	BNXT_DRV_DBG(DEBUG, "Creating default flow with template id: %u\n",
411 		     ulp_class_tid);
412 
413 	/* Protect flow creation */
414 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
415 		BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n");
416 		goto err1;
417 	}
418 
419 	rc = ulp_flow_db_fid_alloc(ulp_ctx, mapper_params.flow_type,
420 				   mapper_params.func_id, &fid);
421 	if (rc) {
422 		BNXT_DRV_DBG(ERR, "Unable to allocate flow table entry\n");
423 		goto err2;
424 	}
425 
426 	mapper_params.flow_id = fid;
427 	rc = ulp_mapper_flow_create(ulp_ctx, &mapper_params,
428 				    NULL);
429 	if (rc)
430 		goto err3;
431 
432 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
433 	*flow_id = fid;
434 	return 0;
435 
436 err3:
437 	ulp_flow_db_fid_free(ulp_ctx, mapper_params.flow_type, fid);
438 err2:
439 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
440 err1:
441 	BNXT_DRV_DBG(ERR, "Failed to create default flow.\n");
442 	return rc;
443 }
444 
445 /*
446  * Function to destroy default rules for the following paths
447  * 1) Device PORT to DPDK App
448  * 2) DPDK App to Device PORT
449  * 3) VF Representor to VF
450  * 4) VF to VF Representor
451  *
452  * eth_dev [in] Ptr to rte eth device.
453  * flow_id [in] Flow identifier.
454  *
455  * Returns 0 on success or negative number on failure.
456  */
457 int32_t
458 ulp_default_flow_destroy(struct rte_eth_dev *eth_dev, uint32_t flow_id)
459 {
460 	struct bnxt_ulp_context *ulp_ctx;
461 	int rc = 0;
462 
463 	ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(eth_dev);
464 	if (!ulp_ctx) {
465 		BNXT_DRV_DBG(ERR, "ULP context is not initialized\n");
466 		return -EINVAL;
467 	}
468 
469 	if (!flow_id) {
470 		BNXT_DRV_DBG(DEBUG, "invalid flow id zero\n");
471 		return rc;
472 	}
473 
474 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
475 		BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n");
476 		return -EINVAL;
477 	}
478 	rc = ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_DEFAULT,
479 				     flow_id,
480 				     NULL);
481 	if (rc)
482 		BNXT_DRV_DBG(ERR, "Failed to destroy flow.\n");
483 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
484 
485 	return rc;
486 }
487 
488 static void
489 bnxt_ulp_destroy_group_rules(struct bnxt *bp, uint16_t port_id)
490 {
491 	struct bnxt_ulp_grp_rule_info *info;
492 	struct bnxt_ulp_grp_rule_info *grp_rules;
493 	uint16_t idx;
494 
495 	grp_rules = bp->ulp_ctx->cfg_data->df_rule_info[port_id].grp_df_rule;
496 
497 	for (idx = 0; idx < BNXT_ULP_MAX_GROUP_CNT; idx++) {
498 		info = &grp_rules[idx];
499 		if (!info->valid)
500 			continue;
501 		ulp_default_flow_destroy(bp->eth_dev, info->flow_id);
502 		memset(info, 0, sizeof(struct bnxt_ulp_grp_rule_info));
503 	}
504 }
505 
506 void
507 bnxt_ulp_destroy_df_rules(struct bnxt *bp, bool global)
508 {
509 	struct bnxt_ulp_df_rule_info *info;
510 	uint16_t port_id;
511 
512 	if (!BNXT_TRUFLOW_EN(bp) ||
513 	    rte_eth_dev_is_repr(bp->eth_dev))
514 		return;
515 
516 	if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
517 		return;
518 
519 	/* Delete default rules per port */
520 	if (!global) {
521 		port_id = bp->eth_dev->data->port_id;
522 		info = &bp->ulp_ctx->cfg_data->df_rule_info[port_id];
523 		if (!info->valid)
524 			return;
525 
526 		/* Delete the group default rules */
527 		bnxt_ulp_destroy_group_rules(bp, port_id);
528 
529 		ulp_default_flow_destroy(bp->eth_dev,
530 					 info->def_port_flow_id);
531 		if (info->promisc_flow_id)
532 			ulp_default_flow_destroy(bp->eth_dev,
533 						 info->promisc_flow_id);
534 		memset(info, 0, sizeof(struct bnxt_ulp_df_rule_info));
535 		return;
536 	}
537 
538 	/* Delete default rules for all ports */
539 	for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
540 		info = &bp->ulp_ctx->cfg_data->df_rule_info[port_id];
541 		if (!info->valid)
542 			continue;
543 
544 		/* Delete the group default rules */
545 		bnxt_ulp_destroy_group_rules(bp, port_id);
546 
547 		ulp_default_flow_destroy(bp->eth_dev,
548 					 info->def_port_flow_id);
549 		if (info->promisc_flow_id)
550 			ulp_default_flow_destroy(bp->eth_dev,
551 						 info->promisc_flow_id);
552 		memset(info, 0, sizeof(struct bnxt_ulp_df_rule_info));
553 	}
554 }
555 
556 static int32_t
557 bnxt_create_port_app_df_rule(struct bnxt *bp, uint8_t flow_type,
558 			     uint32_t *flow_id)
559 {
560 	uint16_t port_id = bp->eth_dev->data->port_id;
561 	struct ulp_tlv_param param_list[] = {
562 		{
563 			.type = BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID,
564 			.length = 2,
565 			.value = {(port_id >> 8) & 0xff, port_id & 0xff}
566 		},
567 		{
568 			.type = BNXT_ULP_DF_PARAM_TYPE_LAST,
569 			.length = 0,
570 			.value = {0}
571 		}
572 	};
573 
574 	if (!flow_type) {
575 		*flow_id = 0;
576 		return 0;
577 	}
578 	return ulp_default_flow_create(bp->eth_dev, param_list, flow_type,
579 				       port_id, flow_id);
580 }
581 
582 int32_t
583 bnxt_ulp_create_df_rules(struct bnxt *bp)
584 {
585 	struct rte_eth_dev *dev = bp->eth_dev;
586 	struct bnxt_ulp_df_rule_info *info;
587 	uint16_t port_id;
588 	int rc = 0;
589 
590 	if (!BNXT_TRUFLOW_EN(bp) ||
591 	    rte_eth_dev_is_repr(bp->eth_dev) || !bp->ulp_ctx)
592 		return 0;
593 
594 	port_id = bp->eth_dev->data->port_id;
595 	info = &bp->ulp_ctx->cfg_data->df_rule_info[port_id];
596 	rc = bnxt_create_port_app_df_rule(bp,
597 					  BNXT_ULP_DF_TPL_DEFAULT_UPLINK_PORT,
598 					  &info->def_port_flow_id);
599 	if (rc) {
600 		BNXT_DRV_DBG(ERR,
601 			     "Failed to create port to app default rule\n");
602 		return rc;
603 	}
604 
605 	/* If the template already set the bd_action, skip this */
606 	if (!bp->tx_cfa_action) {
607 		rc = ulp_default_flow_db_cfa_action_get(bp->ulp_ctx,
608 							info->def_port_flow_id,
609 							&bp->tx_cfa_action);
610 	}
611 
612 	if (rc || BNXT_TESTPMD_EN(bp))
613 		bp->tx_cfa_action = 0;
614 
615 	/* set or reset the promiscuous rule */
616 	bnxt_ulp_promisc_mode_set(bp, dev->data->promiscuous);
617 
618 	info->valid = true;
619 	return 0;
620 }
621 
622 static int32_t
623 bnxt_create_port_vfr_default_rule(struct bnxt *bp,
624 				  uint8_t flow_type,
625 				  uint16_t vfr_port_id,
626 				  uint32_t *flow_id)
627 {
628 	struct ulp_tlv_param param_list[] = {
629 		{
630 			.type = BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID,
631 			.length = 2,
632 			.value = {(vfr_port_id >> 8) & 0xff, vfr_port_id & 0xff}
633 		},
634 		{
635 			.type = BNXT_ULP_DF_PARAM_TYPE_LAST,
636 			.length = 0,
637 			.value = {0}
638 		}
639 	};
640 	return ulp_default_flow_create(bp->eth_dev, param_list, flow_type,
641 				       vfr_port_id,
642 				       flow_id);
643 }
644 
645 int32_t
646 bnxt_ulp_create_vfr_default_rules(struct rte_eth_dev *vfr_ethdev)
647 {
648 	struct bnxt_ulp_vfr_rule_info *info;
649 	struct bnxt_representor *vfr = vfr_ethdev->data->dev_private;
650 	struct rte_eth_dev *parent_dev = vfr->parent_dev;
651 	struct bnxt *bp = parent_dev->data->dev_private;
652 	uint16_t vfr_port_id = vfr_ethdev->data->port_id;
653 	uint16_t port_id;
654 	int rc;
655 
656 	if (!bp || !BNXT_TRUFLOW_EN(bp))
657 		return 0;
658 
659 	port_id = vfr_ethdev->data->port_id;
660 	info = bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(bp->ulp_ctx, port_id);
661 
662 	if (!info) {
663 		BNXT_DRV_DBG(ERR, "Failed to get vfr ulp context\n");
664 		return -EINVAL;
665 	}
666 
667 	if (info->valid) {
668 		BNXT_DRV_DBG(ERR, "VFR already allocated\n");
669 		return -EINVAL;
670 	}
671 
672 	memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info));
673 	rc = bnxt_create_port_vfr_default_rule(bp, BNXT_ULP_DF_TPL_DEFAULT_VFR,
674 					       vfr_port_id,
675 					       &info->vfr_flow_id);
676 	if (rc) {
677 		BNXT_DRV_DBG(ERR, "Failed to create VFR default rule\n");
678 		goto error;
679 	}
680 
681 	/* If the template already set the bd action, skip this */
682 	if (!vfr->vfr_tx_cfa_action) {
683 		rc = ulp_default_flow_db_cfa_action_get(bp->ulp_ctx,
684 							info->vfr_flow_id,
685 							&vfr->vfr_tx_cfa_action);
686 		if (rc) {
687 			BNXT_DRV_DBG(ERR, "Failed to get the tx cfa action\n");
688 			goto error;
689 		}
690 	}
691 
692 	/* Update the other details */
693 	info->valid = true;
694 	info->parent_port_id =  bp->eth_dev->data->port_id;
695 	return 0;
696 
697 error:
698 	if (info->vfr_flow_id)
699 		ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id);
700 	return rc;
701 }
702 
703 int32_t
704 bnxt_ulp_delete_vfr_default_rules(struct bnxt_representor *vfr)
705 {
706 	struct bnxt_ulp_vfr_rule_info *info;
707 	struct rte_eth_dev *parent_dev = vfr->parent_dev;
708 	struct bnxt *bp = parent_dev->data->dev_private;
709 
710 	if (!bp || !BNXT_TRUFLOW_EN(bp))
711 		return 0;
712 	info = bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(bp->ulp_ctx,
713 						    vfr->dpdk_port_id);
714 	if (!info) {
715 		BNXT_DRV_DBG(ERR, "Failed to get vfr ulp context\n");
716 		return -EINVAL;
717 	}
718 
719 	if (!info->valid) {
720 		BNXT_DRV_DBG(ERR, "VFR already freed\n");
721 		return -EINVAL;
722 	}
723 	ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id);
724 	vfr->vfr_tx_cfa_action = 0;
725 	memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info));
726 	return 0;
727 }
728 
729 static void
730 ulp_l2_custom_tunnel_id_update(struct bnxt *bp,
731 			       struct bnxt_ulp_mapper_parms *params)
732 {
733 	if (!bp->l2_etype_tunnel_cnt)
734 		return;
735 
736 	if (bp->l2_etype_upar_in_use &
737 	    HWRM_TUNNEL_DST_PORT_QUERY_OUTPUT_UPAR_IN_USE_UPAR0) {
738 		ULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_L2_CUSTOM_UPAR_ID,
739 				    ULP_WP_SYM_TUN_HDR_TYPE_UPAR1);
740 	} else if (bp->l2_etype_upar_in_use &
741 		   HWRM_TUNNEL_DST_PORT_QUERY_OUTPUT_UPAR_IN_USE_UPAR1) {
742 		ULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_L2_CUSTOM_UPAR_ID,
743 				    ULP_WP_SYM_TUN_HDR_TYPE_UPAR2);
744 	}
745 }
746 
747 /*
748  * Function to execute a specific template, this does not create flow id
749  *
750  * bp [in] Ptr to bnxt
751  * param_list [in] Ptr to a list of parameters (Currently, only DPDK port_id).
752  * ulp_class_tid [in] Class template ID number.
753  *
754  * Returns 0 on success or negative number on failure.
755  */
756 static int32_t
757 ulp_flow_template_process(struct bnxt *bp,
758 			  struct ulp_tlv_param *param_list,
759 			  uint32_t ulp_class_tid,
760 			  uint16_t port_id,
761 			  uint32_t flow_id)
762 {
763 	struct ulp_rte_hdr_field	hdr_field[BNXT_ULP_PROTO_HDR_MAX];
764 	uint64_t			comp_fld[BNXT_ULP_CF_IDX_LAST];
765 	struct bnxt_ulp_mapper_parms mapper_params = { 0 };
766 	struct ulp_rte_act_prop		act_prop;
767 	struct ulp_rte_act_bitmap	act = { 0 };
768 	struct bnxt_ulp_context		*ulp_ctx;
769 	uint32_t type;
770 	int rc = 0;
771 
772 	memset(&mapper_params, 0, sizeof(mapper_params));
773 	memset(hdr_field, 0, sizeof(hdr_field));
774 	memset(comp_fld, 0, sizeof(comp_fld));
775 	memset(&act_prop, 0, sizeof(act_prop));
776 
777 	mapper_params.hdr_field = hdr_field;
778 	mapper_params.act_bitmap = &act;
779 	mapper_params.act_prop = &act_prop;
780 	mapper_params.comp_fld = comp_fld;
781 	mapper_params.class_tid = ulp_class_tid;
782 	mapper_params.port_id = port_id;
783 
784 	ulp_ctx = bp->ulp_ctx;
785 	if (!ulp_ctx) {
786 		BNXT_DRV_DBG(ERR,
787 			     "ULP is not init'ed. Fail to create dflt flow.\n");
788 		return -EINVAL;
789 	}
790 
791 	type = param_list->type;
792 	while (type != BNXT_ULP_DF_PARAM_TYPE_LAST) {
793 		if (ulp_def_handler_tbl[type].vfr_func) {
794 			rc = ulp_def_handler_tbl[type].vfr_func(ulp_ctx,
795 								param_list,
796 								&mapper_params);
797 			if (rc) {
798 				BNXT_DRV_DBG(ERR,
799 					     "Failed to create default flow\n");
800 				return rc;
801 			}
802 		}
803 
804 		param_list++;
805 		type = param_list->type;
806 	}
807 	/* Protect flow creation */
808 	if (bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx)) {
809 		BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n");
810 		return -EINVAL;
811 	}
812 
813 	mapper_params.flow_id = flow_id;
814 	rc = ulp_mapper_flow_create(ulp_ctx, &mapper_params,
815 				    NULL);
816 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
817 	return rc;
818 }
819 
820 int32_t
821 bnxt_ulp_promisc_mode_set(struct bnxt *bp, uint8_t enable)
822 {
823 	uint32_t flow_type;
824 	struct bnxt_ulp_df_rule_info *info;
825 	uint16_t port_id;
826 	int rc = 0;
827 
828 	if (!BNXT_TRUFLOW_EN(bp) || BNXT_ETH_DEV_IS_REPRESENTOR(bp->eth_dev) ||
829 	    !bp->ulp_ctx)
830 		return rc;
831 
832 	if (!BNXT_CHIP_P5(bp))
833 		return rc;
834 
835 	port_id = bp->eth_dev->data->port_id;
836 	info = &bp->ulp_ctx->cfg_data->df_rule_info[port_id];
837 
838 	/* create the promiscuous rule */
839 	if (enable && !info->promisc_flow_id) {
840 		flow_type = BNXT_ULP_TEMPLATE_PROMISCUOUS_ENABLE;
841 		rc = bnxt_create_port_app_df_rule(bp, flow_type,
842 						  &info->promisc_flow_id);
843 		BNXT_DRV_DBG(DEBUG, "enable ulp promisc mode on port %u:%u\n",
844 			     port_id, info->promisc_flow_id);
845 	} else if (!enable && info->promisc_flow_id) {
846 		struct ulp_tlv_param param_list[] = {
847 			{
848 				.type = BNXT_ULP_DF_PARAM_TYPE_DEV_PORT_ID,
849 				.length = 2,
850 				.value = {(port_id >> 8) & 0xff, port_id & 0xff}
851 			},
852 			{
853 				.type = BNXT_ULP_DF_PARAM_TYPE_LAST,
854 				.length = 0,
855 				.value = {0}
856 			}
857 		};
858 
859 		flow_type = BNXT_ULP_TEMPLATE_PROMISCUOUS_DISABLE;
860 		if (ulp_flow_template_process(bp, param_list, flow_type,
861 					      port_id, 0))
862 			return -EIO;
863 
864 		rc = ulp_default_flow_destroy(bp->eth_dev,
865 					      info->promisc_flow_id);
866 		BNXT_DRV_DBG(DEBUG, "disable ulp promisc mode on port %u:%u\n",
867 			     port_id, info->promisc_flow_id);
868 		info->promisc_flow_id = 0;
869 	}
870 	return rc;
871 }
872 
873 /* Function to create the rte flow for miss action. */
874 int32_t
875 bnxt_ulp_grp_miss_act_set(struct rte_eth_dev *dev,
876 			  const struct rte_flow_attr *attr,
877 			  const struct rte_flow_action actions[],
878 			  uint32_t *flow_id)
879 {
880 	struct bnxt_ulp_mapper_parms mparms = { 0 };
881 	struct ulp_rte_parser_params params;
882 	struct bnxt_ulp_context *ulp_ctx;
883 	int ret = BNXT_TF_RC_ERROR;
884 	uint16_t func_id;
885 	uint32_t fid;
886 	uint32_t group_id;
887 
888 	ulp_ctx = bnxt_ulp_eth_dev_ptr2_cntxt_get(dev);
889 	if (unlikely(!ulp_ctx)) {
890 		BNXT_DRV_DBG(ERR, "ULP context is not initialized\n");
891 		goto flow_error;
892 	}
893 
894 	/* Initialize the parser params */
895 	memset(&params, 0, sizeof(struct ulp_rte_parser_params));
896 	params.ulp_ctx = ulp_ctx;
897 	params.port_id = dev->data->port_id;
898 	/* classid is the group action template*/
899 	params.class_id = BNXT_ULP_TEMPLATE_GROUP_MISS_ACTION;
900 
901 	if (unlikely(bnxt_ulp_cntxt_app_id_get(params.ulp_ctx, &params.app_id))) {
902 		BNXT_DRV_DBG(ERR, "failed to get the app id\n");
903 		goto flow_error;
904 	}
905 
906 	/* Set the flow attributes */
907 	bnxt_ulp_set_dir_attributes(&params, attr);
908 
909 	if (unlikely(bnxt_ulp_set_prio_attribute(&params, attr)))
910 		goto flow_error;
911 
912 	bnxt_ulp_init_parser_cf_defaults(&params, params.port_id);
913 
914 	/* Get the function id */
915 	if (unlikely(ulp_port_db_port_func_id_get(ulp_ctx,
916 						  params.port_id,
917 						  &func_id))) {
918 		BNXT_DRV_DBG(ERR, "conversion of port to func id failed\n");
919 		goto flow_error;
920 	}
921 
922 	/* Protect flow creation */
923 	if (unlikely(bnxt_ulp_cntxt_acquire_fdb_lock(ulp_ctx))) {
924 		BNXT_DRV_DBG(ERR, "Flow db lock acquire failed\n");
925 		goto flow_error;
926 	}
927 
928 	/* Allocate a Flow ID for attaching all resources for the flow to.
929 	 * Once allocated, all errors have to walk the list of resources and
930 	 * free each of them.
931 	 */
932 	ret = ulp_flow_db_fid_alloc(ulp_ctx, BNXT_ULP_FDB_TYPE_DEFAULT,
933 				   func_id, &fid);
934 	if (unlikely(ret)) {
935 		BNXT_DRV_DBG(ERR, "Unable to allocate flow table entry\n");
936 		goto release_lock;
937 	}
938 
939 	/* Update the implied SVIF */
940 	ulp_rte_parser_implicit_match_port_process(&params);
941 
942 	/* Parse the rte flow action */
943 	ret = bnxt_ulp_rte_parser_act_parse(actions, &params);
944 	if (unlikely(ret != BNXT_TF_RC_SUCCESS))
945 		goto free_fid;
946 
947 	/* Verify the jump target group id */
948 	if (ULP_BITMAP_ISSET(params.act_bitmap.bits, BNXT_ULP_ACT_BIT_JUMP)) {
949 		memcpy(&group_id,
950 		       &params.act_prop.act_details[BNXT_ULP_ACT_PROP_IDX_JUMP],
951 		       BNXT_ULP_ACT_PROP_SZ_JUMP);
952 		if (rte_cpu_to_be_32(group_id) == attr->group) {
953 			BNXT_DRV_DBG(ERR, "Jump action cannot jump to its own group.\n");
954 			ret = BNXT_TF_RC_ERROR;
955 			goto free_fid;
956 		}
957 	}
958 
959 	mparms.flow_id = fid;
960 	mparms.func_id = func_id;
961 	mparms.port_id = params.port_id;
962 
963 	/* Perform the rte flow post process */
964 	bnxt_ulp_rte_parser_post_process(&params);
965 
966 #ifdef	RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
967 #ifdef	RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_PARSER
968 	/* Dump the rte flow action */
969 	ulp_parser_act_info_dump(&params);
970 #endif
971 #endif
972 
973 	ret = ulp_matcher_action_match(&params, &params.act_tmpl);
974 	if (unlikely(ret != BNXT_TF_RC_SUCCESS))
975 		goto free_fid;
976 
977 	bnxt_ulp_init_mapper_params(&mparms, &params,
978 				    BNXT_ULP_FDB_TYPE_DEFAULT);
979 	/* Call the ulp mapper to create the flow in the hardware. */
980 	ret = ulp_mapper_flow_create(ulp_ctx, &mparms, NULL);
981 	if (unlikely(ret))
982 		goto free_fid;
983 
984 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
985 
986 	*flow_id = fid;
987 	return 0;
988 
989 free_fid:
990 	ulp_flow_db_fid_free(ulp_ctx, BNXT_ULP_FDB_TYPE_DEFAULT, fid);
991 release_lock:
992 	bnxt_ulp_cntxt_release_fdb_lock(ulp_ctx);
993 flow_error:
994 	return ret;
995 }
996