xref: /dpdk/drivers/net/bnxt/tf_ulp/ulp_tun.c (revision 0c036a1485b9d9163a8fa8059ed5272d060c05e0)
1675e31d8SVenkat Duvvuru /* SPDX-License-Identifier: BSD-3-Clause
2e6e8f03eSRandy Schacher  * Copyright(c) 2014-2023 Broadcom
3675e31d8SVenkat Duvvuru  * All rights reserved.
4675e31d8SVenkat Duvvuru  */
5675e31d8SVenkat Duvvuru 
6bdf4a3c6SKishore Padmanabha #include "bnxt.h"
7bdf4a3c6SKishore Padmanabha #include "bnxt_ulp.h"
8*0c036a14SPeter Spreadborough #include "bnxt_ulp_utils.h"
9675e31d8SVenkat Duvvuru #include "ulp_tun.h"
10bdf4a3c6SKishore Padmanabha #include "ulp_utils.h"
11675e31d8SVenkat Duvvuru 
12bdf4a3c6SKishore Padmanabha /* returns negative on error, 1 if new entry is allocated or zero if old */
13bdf4a3c6SKishore Padmanabha int32_t
14bdf4a3c6SKishore Padmanabha ulp_app_tun_search_entry(struct bnxt_ulp_context *ulp_ctx,
15bdf4a3c6SKishore Padmanabha 			 struct rte_flow_tunnel *app_tunnel,
16bdf4a3c6SKishore Padmanabha 			 struct bnxt_flow_app_tun_ent **tun_entry)
17675e31d8SVenkat Duvvuru {
18bdf4a3c6SKishore Padmanabha 	struct bnxt_flow_app_tun_ent *tun_ent_list;
19bdf4a3c6SKishore Padmanabha 	int32_t i, rc = 0, free_entry = -1;
20675e31d8SVenkat Duvvuru 
21bdf4a3c6SKishore Padmanabha 	tun_ent_list = bnxt_ulp_cntxt_ptr2_app_tun_list_get(ulp_ctx);
22bdf4a3c6SKishore Padmanabha 	if (!tun_ent_list) {
23dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "unable to get the app tunnel list\n");
24bdf4a3c6SKishore Padmanabha 		return -EINVAL;
25675e31d8SVenkat Duvvuru 	}
26675e31d8SVenkat Duvvuru 
27bdf4a3c6SKishore Padmanabha 	for (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) {
28bdf4a3c6SKishore Padmanabha 		if (!tun_ent_list[i].ref_cnt) {
29bdf4a3c6SKishore Padmanabha 			if (free_entry < 0)
30bdf4a3c6SKishore Padmanabha 				free_entry = i;
31bdf4a3c6SKishore Padmanabha 		} else {
32bdf4a3c6SKishore Padmanabha 			if (!memcmp(&tun_ent_list[i].app_tunnel,
33bdf4a3c6SKishore Padmanabha 				    app_tunnel,
34bdf4a3c6SKishore Padmanabha 				    sizeof(struct rte_flow_tunnel))) {
35bdf4a3c6SKishore Padmanabha 				*tun_entry =  &tun_ent_list[i];
36bdf4a3c6SKishore Padmanabha 				tun_ent_list[free_entry].ref_cnt++;
37bdf4a3c6SKishore Padmanabha 				return rc;
38bdf4a3c6SKishore Padmanabha 			}
39bdf4a3c6SKishore Padmanabha 		}
40bdf4a3c6SKishore Padmanabha 	}
41bdf4a3c6SKishore Padmanabha 	if (free_entry >= 0) {
42bdf4a3c6SKishore Padmanabha 		*tun_entry =  &tun_ent_list[free_entry];
43bdf4a3c6SKishore Padmanabha 		memcpy(&tun_ent_list[free_entry].app_tunnel, app_tunnel,
44bdf4a3c6SKishore Padmanabha 		       sizeof(struct rte_flow_tunnel));
45bdf4a3c6SKishore Padmanabha 		tun_ent_list[free_entry].ref_cnt = 1;
46bdf4a3c6SKishore Padmanabha 		rc = 1;
47bdf4a3c6SKishore Padmanabha 	} else {
48dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "ulp app tunnel list is full\n");
49bdf4a3c6SKishore Padmanabha 		return -ENOMEM;
50bdf4a3c6SKishore Padmanabha 	}
51bdf4a3c6SKishore Padmanabha 
52bdf4a3c6SKishore Padmanabha 	return rc;
53bdf4a3c6SKishore Padmanabha }
54bdf4a3c6SKishore Padmanabha 
55bdf4a3c6SKishore Padmanabha void
56bdf4a3c6SKishore Padmanabha ulp_app_tun_entry_delete(struct bnxt_flow_app_tun_ent *tun_entry)
57675e31d8SVenkat Duvvuru {
58bdf4a3c6SKishore Padmanabha 	if (tun_entry) {
59bdf4a3c6SKishore Padmanabha 		if (tun_entry->ref_cnt) {
60bdf4a3c6SKishore Padmanabha 			tun_entry->ref_cnt--;
61bdf4a3c6SKishore Padmanabha 			if (!tun_entry->ref_cnt)
62bdf4a3c6SKishore Padmanabha 				memset(tun_entry, 0,
63bdf4a3c6SKishore Padmanabha 				       sizeof(struct bnxt_flow_app_tun_ent));
64bdf4a3c6SKishore Padmanabha 		}
65ddaf0afaSKishore Padmanabha 	}
66675e31d8SVenkat Duvvuru }
67675e31d8SVenkat Duvvuru 
68bdf4a3c6SKishore Padmanabha int32_t
69bdf4a3c6SKishore Padmanabha ulp_app_tun_entry_set_decap_action(struct bnxt_flow_app_tun_ent *tun_entry)
70675e31d8SVenkat Duvvuru {
71bdf4a3c6SKishore Padmanabha 	if (!tun_entry)
72bdf4a3c6SKishore Padmanabha 		return -EINVAL;
73675e31d8SVenkat Duvvuru 
74bdf4a3c6SKishore Padmanabha 	tun_entry->action.type = (typeof(tun_entry->action.type))
75bdf4a3c6SKishore Padmanabha 			      BNXT_RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
76bdf4a3c6SKishore Padmanabha 	tun_entry->action.conf = tun_entry;
77bdf4a3c6SKishore Padmanabha 	return 0;
78ddaf0afaSKishore Padmanabha }
79675e31d8SVenkat Duvvuru 
80bdf4a3c6SKishore Padmanabha int32_t
81bdf4a3c6SKishore Padmanabha ulp_app_tun_entry_set_decap_item(struct bnxt_flow_app_tun_ent *tun_entry)
82675e31d8SVenkat Duvvuru {
83bdf4a3c6SKishore Padmanabha 	if (!tun_entry)
84bdf4a3c6SKishore Padmanabha 		return -EINVAL;
85675e31d8SVenkat Duvvuru 
86bdf4a3c6SKishore Padmanabha 	tun_entry->item.type = (typeof(tun_entry->item.type))
87bdf4a3c6SKishore Padmanabha 			      BNXT_RTE_FLOW_ITEM_TYPE_VXLAN_DECAP;
88bdf4a3c6SKishore Padmanabha 	tun_entry->item.spec = tun_entry;
89bdf4a3c6SKishore Padmanabha 	tun_entry->item.last = NULL;
90bdf4a3c6SKishore Padmanabha 	tun_entry->item.mask = NULL;
91bdf4a3c6SKishore Padmanabha 	return 0;
92675e31d8SVenkat Duvvuru }
93675e31d8SVenkat Duvvuru 
94bdf4a3c6SKishore Padmanabha struct bnxt_flow_app_tun_ent *
95bdf4a3c6SKishore Padmanabha ulp_app_tun_match_entry(struct bnxt_ulp_context *ulp_ctx,
96bdf4a3c6SKishore Padmanabha 			const void *ctx)
97675e31d8SVenkat Duvvuru {
98bdf4a3c6SKishore Padmanabha 	struct bnxt_flow_app_tun_ent *tun_ent_list;
99bdf4a3c6SKishore Padmanabha 	int32_t i;
100675e31d8SVenkat Duvvuru 
101bdf4a3c6SKishore Padmanabha 	tun_ent_list = bnxt_ulp_cntxt_ptr2_app_tun_list_get(ulp_ctx);
102bdf4a3c6SKishore Padmanabha 	if (!tun_ent_list) {
103dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "unable to get the app tunnel list\n");
104bdf4a3c6SKishore Padmanabha 		return NULL;
105bdf4a3c6SKishore Padmanabha 	}
106675e31d8SVenkat Duvvuru 
107bdf4a3c6SKishore Padmanabha 	for (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) {
108bdf4a3c6SKishore Padmanabha 		if (&tun_ent_list[i] == ctx)
109bdf4a3c6SKishore Padmanabha 			return &tun_ent_list[i];
110bdf4a3c6SKishore Padmanabha 	}
111bdf4a3c6SKishore Padmanabha 	return NULL;
112675e31d8SVenkat Duvvuru }
113675e31d8SVenkat Duvvuru 
114675e31d8SVenkat Duvvuru static int32_t
115675e31d8SVenkat Duvvuru ulp_get_tun_entry(struct ulp_rte_parser_params *params,
116675e31d8SVenkat Duvvuru 		  struct bnxt_tun_cache_entry **tun_entry,
117675e31d8SVenkat Duvvuru 		  uint16_t *tun_idx)
118675e31d8SVenkat Duvvuru {
119bdf4a3c6SKishore Padmanabha 	int32_t i, first_free_entry = BNXT_ULP_TUN_ENTRY_INVALID;
120675e31d8SVenkat Duvvuru 	struct bnxt_tun_cache_entry *tun_tbl;
121bdf4a3c6SKishore Padmanabha 	uint32_t dip_idx, dmac_idx, use_ipv4 = 0;
122675e31d8SVenkat Duvvuru 
123675e31d8SVenkat Duvvuru 	tun_tbl = bnxt_ulp_cntxt_ptr2_tun_tbl_get(params->ulp_ctx);
124bdf4a3c6SKishore Padmanabha 	if (!tun_tbl) {
125dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR, "Error: could not get Tunnel table\n");
126675e31d8SVenkat Duvvuru 		return BNXT_TF_RC_ERROR;
127bdf4a3c6SKishore Padmanabha 	}
128bdf4a3c6SKishore Padmanabha 
129bdf4a3c6SKishore Padmanabha 	/* get the outer destination ip field index */
130bdf4a3c6SKishore Padmanabha 	dip_idx = ULP_COMP_FLD_IDX_RD(params, BNXT_ULP_CF_IDX_TUN_OFF_DIP_ID);
131bdf4a3c6SKishore Padmanabha 	dmac_idx = ULP_COMP_FLD_IDX_RD(params, BNXT_ULP_CF_IDX_TUN_OFF_DMAC_ID);
132bdf4a3c6SKishore Padmanabha 	if (ULP_BITMAP_ISSET(params->hdr_bitmap.bits, BNXT_ULP_HDR_BIT_O_IPV4))
133bdf4a3c6SKishore Padmanabha 		use_ipv4 = 1;
134675e31d8SVenkat Duvvuru 
135675e31d8SVenkat Duvvuru 	for (i = 0; i < BNXT_ULP_MAX_TUN_CACHE_ENTRIES; i++) {
136bdf4a3c6SKishore Padmanabha 		if (!tun_tbl[i].t_dst_ip_valid) {
137bdf4a3c6SKishore Padmanabha 			if (first_free_entry == BNXT_ULP_TUN_ENTRY_INVALID)
138675e31d8SVenkat Duvvuru 				first_free_entry = i;
139bdf4a3c6SKishore Padmanabha 			continue;
140675e31d8SVenkat Duvvuru 		}
141bdf4a3c6SKishore Padmanabha 		/* match on the destination ip of the tunnel */
142bdf4a3c6SKishore Padmanabha 		if ((use_ipv4 && !memcmp(&tun_tbl[i].t_dst_ip,
143bdf4a3c6SKishore Padmanabha 					 params->hdr_field[dip_idx].spec,
144bdf4a3c6SKishore Padmanabha 					 sizeof(rte_be32_t))) ||
145bdf4a3c6SKishore Padmanabha 		    (!use_ipv4 &&
146bdf4a3c6SKishore Padmanabha 		     !memcmp(tun_tbl[i].t_dst_ip6,
147bdf4a3c6SKishore Padmanabha 			     params->hdr_field[dip_idx].spec,
148bdf4a3c6SKishore Padmanabha 			     sizeof(((struct bnxt_tun_cache_entry *)
149bdf4a3c6SKishore Padmanabha 				     NULL)->t_dst_ip6)))) {
150675e31d8SVenkat Duvvuru 			*tun_entry = &tun_tbl[i];
151675e31d8SVenkat Duvvuru 			*tun_idx = i;
152bdf4a3c6SKishore Padmanabha 			return 0;
153675e31d8SVenkat Duvvuru 		}
154bdf4a3c6SKishore Padmanabha 	}
155bdf4a3c6SKishore Padmanabha 	if (first_free_entry == BNXT_ULP_TUN_ENTRY_INVALID) {
156dd0191d5SShuanglin Wang 		BNXT_DRV_DBG(ERR,
157dd0191d5SShuanglin Wang 			     "Error: No entry available in tunnel table\n");
158bdf4a3c6SKishore Padmanabha 		return BNXT_TF_RC_ERROR;
159bdf4a3c6SKishore Padmanabha 	}
160bdf4a3c6SKishore Padmanabha 
161bdf4a3c6SKishore Padmanabha 	*tun_idx = first_free_entry;
162bdf4a3c6SKishore Padmanabha 	*tun_entry = &tun_tbl[first_free_entry];
163bdf4a3c6SKishore Padmanabha 	tun_tbl[first_free_entry].t_dst_ip_valid = true;
164bdf4a3c6SKishore Padmanabha 
165bdf4a3c6SKishore Padmanabha 	/* Update the destination ip and mac */
166bdf4a3c6SKishore Padmanabha 	if (use_ipv4)
167bdf4a3c6SKishore Padmanabha 		memcpy(&tun_tbl[first_free_entry].t_dst_ip,
168bdf4a3c6SKishore Padmanabha 		       params->hdr_field[dip_idx].spec, sizeof(rte_be32_t));
169bdf4a3c6SKishore Padmanabha 	else
170bdf4a3c6SKishore Padmanabha 		memcpy(tun_tbl[first_free_entry].t_dst_ip6,
171bdf4a3c6SKishore Padmanabha 		       params->hdr_field[dip_idx].spec,
172bdf4a3c6SKishore Padmanabha 		       sizeof(((struct bnxt_tun_cache_entry *)
173bdf4a3c6SKishore Padmanabha 				     NULL)->t_dst_ip6));
174bdf4a3c6SKishore Padmanabha 	memcpy(tun_tbl[first_free_entry].t_dmac,
175bdf4a3c6SKishore Padmanabha 	       params->hdr_field[dmac_idx].spec, RTE_ETHER_ADDR_LEN);
176675e31d8SVenkat Duvvuru 
177675e31d8SVenkat Duvvuru 	return 0;
178675e31d8SVenkat Duvvuru }
179675e31d8SVenkat Duvvuru 
180bdf4a3c6SKishore Padmanabha /* Tunnel API to delete the tunnel entry */
181bdf4a3c6SKishore Padmanabha void
182bdf4a3c6SKishore Padmanabha ulp_tunnel_offload_entry_clear(struct bnxt_tun_cache_entry *tun_tbl,
183bdf4a3c6SKishore Padmanabha 			       uint8_t tun_idx)
184675e31d8SVenkat Duvvuru {
185bdf4a3c6SKishore Padmanabha 	memset(&tun_tbl[tun_idx], 0, sizeof(struct bnxt_tun_cache_entry));
186bdf4a3c6SKishore Padmanabha }
187bdf4a3c6SKishore Padmanabha 
188bdf4a3c6SKishore Padmanabha /* Tunnel API to perform tunnel offload process when there is F1/F2 flows */
189bdf4a3c6SKishore Padmanabha int32_t
190bdf4a3c6SKishore Padmanabha ulp_tunnel_offload_process(struct ulp_rte_parser_params *params)
191bdf4a3c6SKishore Padmanabha {
192675e31d8SVenkat Duvvuru 	struct bnxt_tun_cache_entry *tun_entry;
193675e31d8SVenkat Duvvuru 	uint16_t tun_idx;
194bdf4a3c6SKishore Padmanabha 	int32_t rc = BNXT_TF_RC_SUCCESS;
195675e31d8SVenkat Duvvuru 
196bdf4a3c6SKishore Padmanabha 	/* Perform the tunnel offload only for F1 and F2 flows */
197bdf4a3c6SKishore Padmanabha 	if (!ULP_BITMAP_ISSET(params->hdr_bitmap.bits,
198bdf4a3c6SKishore Padmanabha 			      BNXT_ULP_HDR_BIT_F1) &&
199bdf4a3c6SKishore Padmanabha 	    !ULP_BITMAP_ISSET(params->hdr_bitmap.bits,
200bdf4a3c6SKishore Padmanabha 			      BNXT_ULP_HDR_BIT_F2))
201bdf4a3c6SKishore Padmanabha 		return rc;
202675e31d8SVenkat Duvvuru 
203bdf4a3c6SKishore Padmanabha 	/* search for the tunnel entry if not found create one */
204675e31d8SVenkat Duvvuru 	rc = ulp_get_tun_entry(params, &tun_entry, &tun_idx);
205675e31d8SVenkat Duvvuru 	if (rc == BNXT_TF_RC_ERROR)
206675e31d8SVenkat Duvvuru 		return rc;
207675e31d8SVenkat Duvvuru 
208bdf4a3c6SKishore Padmanabha 	/* Tunnel offload for the outer Tunnel flow */
209bdf4a3c6SKishore Padmanabha 	if (ULP_BITMAP_ISSET(params->hdr_bitmap.bits,
210bdf4a3c6SKishore Padmanabha 			     BNXT_ULP_HDR_BIT_F1)) {
211bdf4a3c6SKishore Padmanabha 		/* Reset the JUMP action bit in the action bitmap as we don't
212bdf4a3c6SKishore Padmanabha 		 * offload this action.
213ddaf0afaSKishore Padmanabha 		 */
214bdf4a3c6SKishore Padmanabha 		ULP_BITMAP_RESET(params->act_bitmap.bits,
215bdf4a3c6SKishore Padmanabha 				 BNXT_ULP_ACT_BIT_JUMP);
216bdf4a3c6SKishore Padmanabha 		params->parent_flow = true;
217bdf4a3c6SKishore Padmanabha 		params->tun_idx = tun_idx;
218bdf4a3c6SKishore Padmanabha 		tun_entry->outer_tun_flow_id = params->fid;
219bdf4a3c6SKishore Padmanabha 	} else if (ULP_BITMAP_ISSET(params->hdr_bitmap.bits,
220bdf4a3c6SKishore Padmanabha 			     BNXT_ULP_HDR_BIT_F2)) {
221bdf4a3c6SKishore Padmanabha 		/* add the vxlan decap action for F2 flows */
222bdf4a3c6SKishore Padmanabha 		ULP_BITMAP_SET(params->act_bitmap.bits,
223bdf4a3c6SKishore Padmanabha 			       BNXT_ULP_ACT_BIT_VXLAN_DECAP);
224bdf4a3c6SKishore Padmanabha 		params->child_flow = true;
225bdf4a3c6SKishore Padmanabha 		params->tun_idx = tun_idx;
226bdf4a3c6SKishore Padmanabha 		params->parent_flow = false;
227ddaf0afaSKishore Padmanabha 	}
228bdf4a3c6SKishore Padmanabha 	ULP_COMP_FLD_IDX_WR(params, BNXT_ULP_CF_IDX_TUNNEL_ID, tun_idx);
229bdf4a3c6SKishore Padmanabha 	return rc;
2308665487eSVenkat Duvvuru }
231