xref: /dpdk/drivers/net/bnxt/tf_ulp/bnxt_tf_pmd_shim.c (revision a089734a026a316994674e3f405ee4d56a114efc)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021-2023 Broadcom
3  * All rights reserved.
4  */
5 
6 #include <glob.h>
7 #include <libgen.h>
8 #include <stdio.h>
9 #include <net/if.h>
10 #include <sys/ioctl.h>
11 #include <sys/socket.h>
12 #include <unistd.h>
13 
14 #include "bnxt.h"
15 #include "bnxt_vnic.h"
16 #include "bnxt_hwrm.h"
17 #include "bnxt_tf_common.h"
18 #include "bnxt_tf_pmd_shim.h"
19 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
20 #include "ulp_template_debug_proto.h"
21 #endif
22 
23 
24 int
25 bnxt_tunnel_dst_port_free(struct bnxt *bp,
26 			  uint16_t port,
27 			  uint8_t type)
28 {
29 	return bnxt_hwrm_tunnel_dst_port_free(bp,
30 					      port,
31 					      type);
32 }
33 
34 int
35 bnxt_tunnel_dst_port_alloc(struct bnxt *bp,
36 			   uint16_t port,
37 			   uint8_t type)
38 {
39 	int rc = 0;
40 	rc = bnxt_hwrm_tunnel_dst_port_alloc(bp,
41 					       port,
42 					       type);
43 	if (rc) {
44 		PMD_DRV_LOG_LINE(ERR, "Tunnel type:%d alloc failed for port:%d error:%s",
45 				 type, port,
46 				 (rc ==
47 				  HWRM_TUNNEL_DST_PORT_ALLOC_OUTPUT_ERROR_INFO_ERR_ALLOCATED) ?
48 				 "already allocated" : "no resource");
49 	}
50 	return rc;
51 }
52 
53 int
54 bnxt_tunnel_upar_id_get(struct bnxt *bp,
55 			uint8_t type,
56 			uint8_t *upar_id)
57 {
58 	return bnxt_hwrm_tunnel_upar_id_get(bp,
59 					    upar_id,
60 					    type);
61 }
62 
63 int32_t bnxt_rss_config_action_apply(struct bnxt_ulp_mapper_parms *parms)
64 {
65 	struct bnxt_vnic_info *vnic = NULL;
66 	struct bnxt *bp = NULL;
67 	uint64_t rss_types;
68 	uint16_t hwrm_type;
69 	uint32_t rss_level, key_len;
70 	uint8_t *rss_key;
71 	struct ulp_rte_act_prop *ap = parms->act_prop;
72 	int32_t rc = -EINVAL;
73 	uint8_t rss_func;
74 
75 	bp = bnxt_pmd_get_bp(parms->port_id);
76 	if (bp == NULL) {
77 		BNXT_DRV_DBG(ERR, "Invalid bp for port_id %u\n",
78 			     parms->port_id);
79 		return rc;
80 	}
81 	vnic = bnxt_get_default_vnic(bp);
82 	if (vnic == NULL) {
83 		BNXT_DRV_DBG(ERR, "default vnic not available for %u\n",
84 			     parms->port_id);
85 		return rc;
86 	}
87 
88 	/* get the details */
89 	memcpy(&rss_func, &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_FUNC],
90 	       BNXT_ULP_ACT_PROP_SZ_RSS_FUNC);
91 	memcpy(&rss_types, &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_TYPES],
92 	       BNXT_ULP_ACT_PROP_SZ_RSS_TYPES);
93 	memcpy(&rss_level, &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_LEVEL],
94 	       BNXT_ULP_ACT_PROP_SZ_RSS_LEVEL);
95 	memcpy(&key_len, &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_KEY_LEN],
96 	       BNXT_ULP_ACT_PROP_SZ_RSS_KEY_LEN);
97 	rss_key = &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_KEY];
98 
99 	rc = bnxt_rte_flow_to_hwrm_ring_select_mode((enum rte_eth_hash_function)rss_func,
100 						    rss_types, bp, vnic);
101 	if (rc != 0) {
102 		BNXT_DRV_DBG(ERR, "Error unsupported rss hash func\n");
103 		return rc;
104 	}
105 
106 	hwrm_type = bnxt_rte_to_hwrm_hash_types(rss_types);
107 	if (!hwrm_type) {
108 		BNXT_DRV_DBG(ERR, "Error unsupported rss config type\n");
109 		return rc;
110 	}
111 	/* Configure RSS only if the queue count is > 1 */
112 	if (vnic->rx_queue_cnt > 1) {
113 		vnic->hash_type = hwrm_type;
114 		vnic->hash_mode =
115 			bnxt_rte_to_hwrm_hash_level(bp, rss_types, rss_level);
116 		memcpy(vnic->rss_hash_key, rss_key,
117 		       BNXT_ULP_ACT_PROP_SZ_RSS_KEY);
118 		rc = bnxt_hwrm_vnic_rss_cfg(bp, vnic);
119 		if (rc) {
120 			BNXT_DRV_DBG(ERR, "Error configuring vnic RSS config\n");
121 			return rc;
122 		}
123 		BNXT_DRV_DBG(INFO, "Rss config successfully applied\n");
124 	}
125 	return 0;
126 }
127 
128 #define PARENT_PHY_INTF_PATH "/sys/bus/pci/devices/%s/physfn/net/*"
129 #define ULP_PRT_MAC_PATH "/sys/bus/pci/devices/%s/physfn/net/%s/address"
130 
131 #define ULP_FILE_PATH_SIZE 256
132 
133 static int32_t glob_error_fn(const char *epath, int32_t eerrno)
134 {
135 	BNXT_DRV_DBG(ERR, "path %s error %d\n", epath, eerrno);
136 	return 0;
137 }
138 
139 static int32_t ulp_pmd_get_mac_by_pci(const char *pci_name, uint8_t *mac)
140 {
141 	char path[ULP_FILE_PATH_SIZE], dev_str[ULP_FILE_PATH_SIZE];
142 	char *intf_name;
143 	glob_t gres;
144 	FILE *fp;
145 	int32_t rc = -EINVAL;
146 
147 	memset(path, 0, sizeof(path));
148 	sprintf(path, PARENT_PHY_INTF_PATH, pci_name);
149 
150 	/* There can be only one, no more, no less */
151 	if (glob(path, 0, glob_error_fn, &gres) == 0) {
152 		if (gres.gl_pathc != 1)
153 			return rc;
154 
155 		/* Replace the PCI address with interface name and get index */
156 		intf_name = basename(gres.gl_pathv[0]);
157 		sprintf(path, ULP_PRT_MAC_PATH, pci_name, intf_name);
158 
159 		fp = fopen(path, "r");
160 		if (!fp) {
161 			BNXT_DRV_DBG(ERR, "Error in getting bond mac address\n");
162 			return rc;
163 		}
164 
165 		memset(dev_str, 0, sizeof(dev_str));
166 		if (fgets(dev_str, sizeof(dev_str), fp) == NULL) {
167 			BNXT_DRV_DBG(ERR, "Error in reading %s\n", path);
168 			fclose(fp);
169 			return rc;
170 		}
171 
172 		if (sscanf(dev_str, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx\n",
173 			   &mac[0], &mac[1], &mac[2],
174 			   &mac[3], &mac[4], &mac[5]) == 6)
175 			rc = 0;
176 		fclose(fp);
177 	}
178 	return rc;
179 }
180 
181 int32_t bnxt_pmd_get_parent_mac_addr(struct bnxt_ulp_mapper_parms *parms,
182 				     uint8_t *mac)
183 {
184 	struct bnxt *bp = NULL;
185 	int32_t rc = -EINVAL;
186 
187 	bp = bnxt_pmd_get_bp(parms->port_id);
188 	if (bp == NULL) {
189 		BNXT_DRV_DBG(ERR, "Invalid bp for port_id %u\n",
190 			     parms->port_id);
191 		return rc;
192 	}
193 	return ulp_pmd_get_mac_by_pci(bp->pdev->name, &mac[2]);
194 }
195 
196 uint16_t
197 bnxt_pmd_get_svif(uint16_t port_id, bool func_svif,
198 	      enum bnxt_ulp_intf_type type)
199 {
200 	struct rte_eth_dev *eth_dev;
201 	struct bnxt *bp;
202 
203 	eth_dev = &rte_eth_devices[port_id];
204 	if (rte_eth_dev_is_repr(eth_dev)) {
205 		struct bnxt_representor *vfr = eth_dev->data->dev_private;
206 		if (!vfr)
207 			return 0;
208 
209 		if (type == BNXT_ULP_INTF_TYPE_VF_REP)
210 			return vfr->svif;
211 
212 		eth_dev = vfr->parent_dev;
213 	}
214 
215 	bp = eth_dev->data->dev_private;
216 
217 	return func_svif ? bp->func_svif : bp->port_svif;
218 }
219 
220 void
221 bnxt_pmd_get_iface_mac(uint16_t port, enum bnxt_ulp_intf_type type,
222 		       uint8_t *mac, uint8_t *parent_mac)
223 {
224 	struct rte_eth_dev *eth_dev;
225 	struct bnxt *bp;
226 
227 	if (type != BNXT_ULP_INTF_TYPE_TRUSTED_VF &&
228 	    type != BNXT_ULP_INTF_TYPE_PF)
229 		return;
230 
231 	eth_dev = &rte_eth_devices[port];
232 	bp = eth_dev->data->dev_private;
233 	memcpy(mac, bp->mac_addr, RTE_ETHER_ADDR_LEN);
234 
235 	if (type == BNXT_ULP_INTF_TYPE_TRUSTED_VF)
236 		memcpy(parent_mac, bp->parent->mac_addr, RTE_ETHER_ADDR_LEN);
237 }
238 
239 uint16_t
240 bnxt_pmd_get_parent_vnic_id(uint16_t port, enum bnxt_ulp_intf_type type)
241 {
242 	struct rte_eth_dev *eth_dev;
243 	struct bnxt *bp;
244 
245 	if (type != BNXT_ULP_INTF_TYPE_TRUSTED_VF)
246 		return 0;
247 
248 	eth_dev = &rte_eth_devices[port];
249 	bp = eth_dev->data->dev_private;
250 
251 	return bp->parent->vnic;
252 }
253 
254 uint16_t
255 bnxt_pmd_get_vnic_id(uint16_t port, enum bnxt_ulp_intf_type type)
256 {
257 	struct rte_eth_dev *eth_dev;
258 	struct bnxt_vnic_info *vnic;
259 	struct bnxt *bp;
260 
261 	eth_dev = &rte_eth_devices[port];
262 	if (rte_eth_dev_is_repr(eth_dev)) {
263 		struct bnxt_representor *vfr = eth_dev->data->dev_private;
264 		if (!vfr)
265 			return 0;
266 
267 		if (type == BNXT_ULP_INTF_TYPE_VF_REP)
268 			return vfr->dflt_vnic_id;
269 
270 		eth_dev = vfr->parent_dev;
271 	}
272 
273 	bp = eth_dev->data->dev_private;
274 
275 	vnic = bnxt_get_default_vnic(bp);
276 
277 	return vnic->fw_vnic_id;
278 }
279 
280 uint16_t
281 bnxt_pmd_get_fw_func_id(uint16_t port, enum bnxt_ulp_intf_type type)
282 {
283 	struct rte_eth_dev *eth_dev;
284 	struct bnxt *bp;
285 
286 	eth_dev = &rte_eth_devices[port];
287 	if (rte_eth_dev_is_repr(eth_dev)) {
288 		struct bnxt_representor *vfr = eth_dev->data->dev_private;
289 		if (!vfr)
290 			return 0;
291 
292 		if (type == BNXT_ULP_INTF_TYPE_VF_REP)
293 			return vfr->fw_fid;
294 
295 		eth_dev = vfr->parent_dev;
296 	}
297 
298 	bp = eth_dev->data->dev_private;
299 
300 	return bp->fw_fid;
301 }
302 
303 enum bnxt_ulp_intf_type
304 bnxt_pmd_get_interface_type(uint16_t port)
305 {
306 	struct rte_eth_dev *eth_dev;
307 	struct bnxt *bp;
308 
309 	eth_dev = &rte_eth_devices[port];
310 	if (rte_eth_dev_is_repr(eth_dev))
311 		return BNXT_ULP_INTF_TYPE_VF_REP;
312 
313 	bp = eth_dev->data->dev_private;
314 	if (BNXT_PF(bp))
315 		return BNXT_ULP_INTF_TYPE_PF;
316 	else if (BNXT_VF_IS_TRUSTED(bp))
317 		return BNXT_ULP_INTF_TYPE_TRUSTED_VF;
318 	else if (BNXT_VF(bp))
319 		return BNXT_ULP_INTF_TYPE_VF;
320 
321 	return BNXT_ULP_INTF_TYPE_INVALID;
322 }
323 
324 uint16_t
325 bnxt_pmd_get_phy_port_id(uint16_t port_id)
326 {
327 	struct bnxt_representor *vfr;
328 	struct rte_eth_dev *eth_dev;
329 	struct bnxt *bp;
330 
331 	eth_dev = &rte_eth_devices[port_id];
332 	if (rte_eth_dev_is_repr(eth_dev)) {
333 		vfr = eth_dev->data->dev_private;
334 		if (!vfr)
335 			return 0;
336 
337 		eth_dev = vfr->parent_dev;
338 	}
339 
340 	bp = eth_dev->data->dev_private;
341 
342 	return BNXT_PF(bp) ? bp->pf->port_id : bp->parent->port_id;
343 }
344 
345 uint16_t
346 bnxt_pmd_get_parif(uint16_t port_id, enum bnxt_ulp_intf_type type)
347 {
348 	struct rte_eth_dev *eth_dev;
349 	struct bnxt *bp;
350 
351 	eth_dev = &rte_eth_devices[port_id];
352 	if (rte_eth_dev_is_repr(eth_dev)) {
353 		struct bnxt_representor *vfr = eth_dev->data->dev_private;
354 		if (!vfr)
355 			return 0;
356 
357 		if (type == BNXT_ULP_INTF_TYPE_VF_REP)
358 			return vfr->fw_fid - 1;
359 
360 		eth_dev = vfr->parent_dev;
361 	}
362 
363 	bp = eth_dev->data->dev_private;
364 
365 	return BNXT_PF(bp) ? bp->fw_fid - 1 : bp->parent->fid - 1;
366 }
367 
368 uint16_t
369 bnxt_pmd_get_vport(uint16_t port_id)
370 {
371 	return (1 << bnxt_pmd_get_phy_port_id(port_id));
372 }
373 
374 int32_t
375 bnxt_pmd_set_unicast_rxmask(struct rte_eth_dev *eth_dev)
376 {
377 	struct bnxt *bp = eth_dev->data->dev_private;
378 	struct bnxt_vnic_info *vnic;
379 	uint32_t old_flags;
380 	int32_t rc;
381 
382 	rc = is_bnxt_in_error(bp);
383 	if (rc)
384 		return rc;
385 
386 	/* Filter settings will get applied when port is started */
387 	if (!eth_dev->data->dev_started)
388 		return 0;
389 
390 	if (bp->vnic_info == NULL)
391 		return 0;
392 
393 	vnic = bnxt_get_default_vnic(bp);
394 
395 	old_flags = vnic->flags;
396 	vnic->flags |= BNXT_VNIC_INFO_UCAST;
397 	vnic->flags &= ~BNXT_VNIC_INFO_PROMISC;
398 	vnic->flags &= ~BNXT_VNIC_INFO_ALLMULTI;
399 	vnic->flags &= ~BNXT_VNIC_INFO_BCAST;
400 	rc = bnxt_hwrm_cfa_l2_set_rx_mask(bp, vnic, 0, NULL);
401 	if (rc != 0)
402 		vnic->flags = old_flags;
403 
404 	return rc;
405 }
406 
407 int32_t bnxt_pmd_queue_action_create(struct bnxt_ulp_mapper_parms *parms,
408 				     uint16_t *vnic_idx, uint16_t *vnic_id)
409 {
410 	struct bnxt *bp = NULL;
411 	uint16_t q_index;
412 	struct ulp_rte_act_prop *ap = parms->act_prop;
413 
414 	bp = bnxt_pmd_get_bp(parms->port_id);
415 	if (bp == NULL) {
416 		BNXT_DRV_DBG(ERR, "Invalid bp for port_id %u\n",
417 			     parms->port_id);
418 		return -EINVAL;
419 	}
420 
421 	memcpy(&q_index, &ap->act_details[BNXT_ULP_ACT_PROP_IDX_QUEUE_INDEX],
422 	       BNXT_ULP_ACT_PROP_SZ_QUEUE_INDEX);
423 
424 	return bnxt_vnic_queue_action_alloc(bp, q_index, vnic_idx, vnic_id);
425 }
426 
427 int32_t bnxt_pmd_queue_action_delete(struct bnxt *bp, uint16_t vnic_idx)
428 {
429 	return bnxt_vnic_queue_action_free(bp, vnic_idx);
430 }
431 
432 int32_t bnxt_pmd_rss_action_create(struct bnxt_ulp_mapper_parms *parms,
433 				   uint16_t *vnic_idx, uint16_t *vnic_id)
434 {
435 	struct bnxt *bp = NULL;
436 	struct bnxt_vnic_rss_info rss_info = {0};
437 	struct ulp_rte_act_prop *ap = parms->act_prop;
438 
439 	bp = bnxt_pmd_get_bp(parms->port_id);
440 	if (bp == NULL) {
441 		BNXT_DRV_DBG(ERR, "Invalid bp for port_id %u\n",
442 			     parms->port_id);
443 		return -EINVAL;
444 	}
445 
446 	/* get the details */
447 	memset(&rss_info, 0, sizeof(rss_info));
448 	memcpy(&rss_info.rss_func,
449 	       &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_FUNC],
450 	       BNXT_ULP_ACT_PROP_SZ_RSS_FUNC);
451 	memcpy(&rss_info.rss_types,
452 	       &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_TYPES],
453 	       BNXT_ULP_ACT_PROP_SZ_RSS_TYPES);
454 	memcpy(&rss_info.rss_level,
455 	       &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_LEVEL],
456 	       BNXT_ULP_ACT_PROP_SZ_RSS_LEVEL);
457 	memcpy(&rss_info.key_len,
458 	       &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_KEY_LEN],
459 	       BNXT_ULP_ACT_PROP_SZ_RSS_KEY_LEN);
460 	if (rss_info.key_len)
461 		rss_info.key = &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_KEY];
462 	memcpy(&rss_info.queue_num,
463 	       &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_QUEUE_NUM],
464 	       BNXT_ULP_ACT_PROP_SZ_RSS_QUEUE_NUM);
465 
466 	/* Validate the size of the queue list */
467 	if (sizeof(rss_info.queue_list) < BNXT_ULP_ACT_PROP_SZ_RSS_QUEUE) {
468 		BNXT_DRV_DBG(ERR, "Mismatch of RSS queue size in template\n");
469 		return -EINVAL;
470 	}
471 	memcpy(rss_info.queue_list,
472 	       &ap->act_details[BNXT_ULP_ACT_PROP_IDX_RSS_QUEUE],
473 	       BNXT_ULP_ACT_PROP_SZ_RSS_QUEUE);
474 
475 	return bnxt_vnic_rss_action_alloc(bp, &rss_info, vnic_idx, vnic_id);
476 }
477 
478 int32_t bnxt_pmd_rss_action_delete(struct bnxt *bp, uint16_t vnic_idx)
479 {
480 	return bnxt_vnic_rss_action_free(bp, vnic_idx);
481 }
482 
483 #define ULP_GLOBAL_TUNNEL_UDP_PORT_SHIFT  32
484 #define ULP_GLOBAL_TUNNEL_UDP_PORT_MASK   ((uint16_t)0xffff)
485 #define ULP_GLOBAL_TUNNEL_PORT_ID_SHIFT  16
486 #define ULP_GLOBAL_TUNNEL_PORT_ID_MASK   ((uint16_t)0xffff)
487 #define ULP_GLOBAL_TUNNEL_UPARID_SHIFT   8
488 #define ULP_GLOBAL_TUNNEL_UPARID_MASK    ((uint16_t)0xff)
489 #define ULP_GLOBAL_TUNNEL_TYPE_SHIFT     0
490 #define ULP_GLOBAL_TUNNEL_TYPE_MASK      ((uint16_t)0xff)
491 
492 /* Extracts the dpdk port id and tunnel type from the handle */
493 static void
494 bnxt_pmd_global_reg_hndl_to_data(uint64_t handle, uint16_t *port,
495 				 uint8_t *upar_id, uint8_t *type,
496 				 uint16_t *udp_port)
497 {
498 	*type    = (handle >> ULP_GLOBAL_TUNNEL_TYPE_SHIFT) &
499 		   ULP_GLOBAL_TUNNEL_TYPE_MASK;
500 	*upar_id = (handle >> ULP_GLOBAL_TUNNEL_UPARID_SHIFT) &
501 		   ULP_GLOBAL_TUNNEL_UPARID_MASK;
502 	*port    = (handle >> ULP_GLOBAL_TUNNEL_PORT_ID_SHIFT) &
503 		   ULP_GLOBAL_TUNNEL_PORT_ID_MASK;
504 	*udp_port = (handle >> ULP_GLOBAL_TUNNEL_UDP_PORT_SHIFT) &
505 		   ULP_GLOBAL_TUNNEL_UDP_PORT_MASK;
506 }
507 
508 /* Packs the dpdk port id and tunnel type in the handle */
509 static void
510 bnxt_pmd_global_reg_data_to_hndl(uint16_t port_id, uint8_t upar_id,
511 				 uint8_t type, uint16_t udp_port,
512 				 uint64_t *handle)
513 {
514 	*handle = 0;
515 	*handle	|=  (udp_port & ULP_GLOBAL_TUNNEL_UDP_PORT_MASK);
516 	*handle	<<= ULP_GLOBAL_TUNNEL_UDP_PORT_SHIFT;
517 	*handle	|=  (port_id & ULP_GLOBAL_TUNNEL_PORT_ID_MASK) <<
518 		ULP_GLOBAL_TUNNEL_PORT_ID_SHIFT;
519 	*handle	|= (upar_id & ULP_GLOBAL_TUNNEL_UPARID_MASK) <<
520 		ULP_GLOBAL_TUNNEL_UPARID_SHIFT;
521 	*handle |= (type & ULP_GLOBAL_TUNNEL_TYPE_MASK);
522 }
523 
524 /* Sets or resets the tunnel ports.
525  * If dport == 0, then the port_id and type are retrieved from the handle.
526  * otherwise, the incoming port_id, type, and dport are used.
527  * The type is enum ulp_mapper_ulp_global_tunnel_type
528  */
529 int32_t
530 bnxt_pmd_global_tunnel_set(struct bnxt_ulp_context *ulp_ctx,
531 			   uint16_t port_id, uint8_t type,
532 			   uint16_t udp_port, uint64_t *handle)
533 {
534 	uint8_t hwtype = 0, ltype, lupar_id = 0;
535 	struct rte_eth_dev *eth_dev;
536 	struct rte_eth_udp_tunnel udp_tunnel = { 0 };
537 	uint32_t *ulp_flags;
538 	struct bnxt *bp;
539 	int32_t rc = 0;
540 	uint16_t ludp_port = udp_port;
541 
542 	if (!udp_port) {
543 		/* Free based on the handle */
544 		if (!handle) {
545 			BNXT_DRV_DBG(ERR, "Free with invalid handle\n");
546 			return -EINVAL;
547 		}
548 		bnxt_pmd_global_reg_hndl_to_data(*handle, &port_id,
549 						 &lupar_id, &ltype, &ludp_port);
550 	}
551 
552 	/* convert to HWRM type */
553 	switch (type) {
554 	case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_VXLAN:
555 		udp_tunnel.prot_type = RTE_ETH_TUNNEL_TYPE_VXLAN;
556 		break;
557 	case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_ECPRI:
558 		udp_tunnel.prot_type = RTE_ETH_TUNNEL_TYPE_ECPRI;
559 		break;
560 	case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_VXLAN_GPE:
561 		udp_tunnel.prot_type = RTE_ETH_TUNNEL_TYPE_VXLAN_GPE;
562 		break;
563 	case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_GENEVE:
564 		udp_tunnel.prot_type = RTE_ETH_TUNNEL_TYPE_GENEVE;
565 		break;
566 	case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_VXLAN_GPE_V6:
567 		hwtype = HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_GPE_V6;
568 		break;
569 	case BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_VXLAN_IP:
570 		hwtype = HWRM_TUNNEL_DST_PORT_ALLOC_INPUT_TUNNEL_TYPE_VXLAN_V4;
571 		break;
572 	default:
573 		BNXT_DRV_DBG(ERR, "Tunnel Type (%d) invalid\n", type);
574 		return -EINVAL;
575 	}
576 
577 	if (udp_tunnel.prot_type) {
578 		udp_tunnel.udp_port = ludp_port;
579 		if (!rte_eth_dev_is_valid_port(port_id)) {
580 			PMD_DRV_LOG_LINE(ERR, "Invalid port %d", port_id);
581 			return -EINVAL;
582 		}
583 
584 		eth_dev = &rte_eth_devices[port_id];
585 		if (!is_bnxt_supported(eth_dev)) {
586 			PMD_DRV_LOG_LINE(ERR, "Device %d not supported", port_id);
587 			return -EINVAL;
588 		}
589 
590 		if (udp_port) {
591 			rc = bnxt_udp_tunnel_port_add_op(eth_dev, &udp_tunnel);
592 		} else {
593 			/* TODO: Make the counters shareable so the resource
594 			 * free can be synced up between core dpdk path and
595 			 * the tf path.
596 			 */
597 			if (eth_dev->data->dev_started != 0)
598 				rc = bnxt_udp_tunnel_port_del_op(eth_dev, &udp_tunnel);
599 		}
600 	} else {
601 		bp = bnxt_pmd_get_bp(port_id);
602 		if (!bp) {
603 			BNXT_DRV_DBG(ERR, "Unable to get dev by port %d\n",
604 				     port_id);
605 			return -EINVAL;
606 		}
607 		if (udp_port)
608 			rc = bnxt_hwrm_tunnel_dst_port_alloc(bp, udp_port,
609 							     hwtype);
610 		else
611 			rc = bnxt_hwrm_tunnel_dst_port_free(bp, ludp_port,
612 							    hwtype);
613 	}
614 
615 	if (rc) {
616 		PMD_DRV_LOG_LINE(ERR, "Tunnel set failed for port:%d error:%d",
617 			    port_id, rc);
618 		return rc;
619 	}
620 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
621 	ulp_mapper_global_register_tbl_dump(type, udp_port);
622 #endif
623 	if (udp_port)
624 		bnxt_pmd_global_reg_data_to_hndl(port_id, lupar_id,
625 						 type, udp_port, handle);
626 
627 	if (type == BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_VXLAN ||
628 	    type == BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_VXLAN_IP) {
629 		ulp_flags = &ulp_ctx->cfg_data->ulp_flags;
630 		if (udp_port)
631 			*ulp_flags |= BNXT_ULP_DYNAMIC_VXLAN_PORT;
632 		else
633 			*ulp_flags &= ~BNXT_ULP_DYNAMIC_VXLAN_PORT;
634 	}
635 	if (type == BNXT_ULP_RESOURCE_SUB_TYPE_GLOBAL_REGISTER_CUST_GENEVE) {
636 		ulp_flags = &ulp_ctx->cfg_data->ulp_flags;
637 		if (udp_port)
638 			*ulp_flags |= BNXT_ULP_DYNAMIC_GENEVE_PORT;
639 		else
640 			*ulp_flags &= ~BNXT_ULP_DYNAMIC_GENEVE_PORT;
641 	}
642 
643 	return rc;
644 }
645 
646 #define BNXT_ULP_HOT_UP_DYNAMIC_ENV_VAR "BNXT_ULP_T_HA_SUPPORT"
647 /* This function queries the linux shell variable to determine
648  * whether Hot upgrade should be disabled or not.
649  * If BNXT_ULP_T_HA_SUPPORT is set to zero explicitly then
650  * hotupgrade is disabled.
651  */
652 static bool bnxt_pmd_get_hot_upgrade_env(void)
653 {
654 	char *env;
655 	bool hot_up = 1;
656 
657 	env = getenv(BNXT_ULP_HOT_UP_DYNAMIC_ENV_VAR);
658 	if (env && strcmp(env, "0") == 0)
659 		hot_up = 0;
660 	return hot_up;
661 }
662 
663 int32_t bnxt_pmd_bd_act_set(uint16_t port_id, uint32_t act)
664 {
665 	struct rte_eth_dev *eth_dev;
666 	int32_t rc = -EINVAL;
667 
668 	eth_dev = &rte_eth_devices[port_id];
669 	if (BNXT_ETH_DEV_IS_REPRESENTOR(eth_dev)) {
670 		struct bnxt_representor *vfr = eth_dev->data->dev_private;
671 		if (!vfr)
672 			return rc;
673 		vfr->vfr_tx_cfa_action = act;
674 	} else {
675 		struct bnxt *bp = eth_dev->data->dev_private;
676 		bp->tx_cfa_action = act;
677 	}
678 
679 	return 0;
680 }
681 
682 static bool hot_up_api;
683 static bool hot_up_configured_by_api;
684 /* There are two ways to configure hot upgrade.
685  * By either calling this bnxt_pmd_configure_hot_upgrade API or
686  * setting the BNXT_ULP_T_HA_SUPPORT environment variable.
687  * bnxt_pmd_configure_hot_upgrade takes precedence over the
688  * environment variable way. Once the setting is done through
689  * bnxt_pmd_configure_hot_upgrade, can't switch back to env
690  * variable.
691  *
692  * bnxt_pmd_configure_hot_upgrade must be called before
693  * dev_start eth_dev_ops is called for the configuration to
694  * take effect.
695  */
696 void bnxt_pmd_configure_hot_upgrade(bool enable)
697 {
698 	hot_up_configured_by_api = true;
699 	hot_up_api = enable;
700 }
701 
702 bool bnxt_pmd_get_hot_up_config(void)
703 {
704 	if (hot_up_configured_by_api)
705 		return hot_up_api;
706 
707 	return bnxt_pmd_get_hot_upgrade_env();
708 }
709