xref: /dpdk/drivers/net/cnxk/cnxk_lookup.c (revision dc348f2e81a94dd3b8a32c2f882483227796905d)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4 
5 #include <rte_common.h>
6 #include <rte_memzone.h>
7 
8 #include "cnxk_ethdev.h"
9 
10 #define SA_BASE_TBL_SZ	(RTE_MAX_ETHPORTS * sizeof(uintptr_t))
11 #define LOOKUP_ARRAY_SZ (PTYPE_ARRAY_SZ + ERR_ARRAY_SZ + SA_BASE_TBL_SZ)
12 const uint32_t *
13 cnxk_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev)
14 {
15 	RTE_SET_USED(eth_dev);
16 
17 	static const uint32_t ptypes[] = {
18 		RTE_PTYPE_L2_ETHER_QINQ,      /* LB */
19 		RTE_PTYPE_L2_ETHER_VLAN,      /* LB */
20 		RTE_PTYPE_L2_ETHER_TIMESYNC,  /* LB */
21 		RTE_PTYPE_L2_ETHER_ARP,	      /* LC */
22 		RTE_PTYPE_L2_ETHER_NSH,	      /* LC */
23 		RTE_PTYPE_L2_ETHER_FCOE,      /* LC */
24 		RTE_PTYPE_L2_ETHER_MPLS,      /* LC */
25 		RTE_PTYPE_L3_IPV4,	      /* LC */
26 		RTE_PTYPE_L3_IPV4_EXT,	      /* LC */
27 		RTE_PTYPE_L3_IPV6,	      /* LC */
28 		RTE_PTYPE_L3_IPV6_EXT,	      /* LC */
29 		RTE_PTYPE_L4_TCP,	      /* LD */
30 		RTE_PTYPE_L4_UDP,	      /* LD */
31 		RTE_PTYPE_L4_SCTP,	      /* LD */
32 		RTE_PTYPE_L4_ICMP,	      /* LD */
33 		RTE_PTYPE_L4_IGMP,	      /* LD */
34 		RTE_PTYPE_TUNNEL_GRE,	      /* LD */
35 		RTE_PTYPE_TUNNEL_ESP,	      /* LD */
36 		RTE_PTYPE_TUNNEL_NVGRE,	      /* LD */
37 		RTE_PTYPE_TUNNEL_VXLAN,	      /* LE */
38 		RTE_PTYPE_TUNNEL_GENEVE,      /* LE */
39 		RTE_PTYPE_TUNNEL_GTPC,	      /* LE */
40 		RTE_PTYPE_TUNNEL_GTPU,	      /* LE */
41 		RTE_PTYPE_TUNNEL_VXLAN_GPE,   /* LE */
42 		RTE_PTYPE_TUNNEL_MPLS_IN_GRE, /* LE */
43 		RTE_PTYPE_TUNNEL_MPLS_IN_UDP, /* LE */
44 		RTE_PTYPE_INNER_L2_ETHER,     /* LF */
45 		RTE_PTYPE_INNER_L3_IPV4,      /* LG */
46 		RTE_PTYPE_INNER_L3_IPV6,      /* LG */
47 		RTE_PTYPE_INNER_L4_TCP,	      /* LH */
48 		RTE_PTYPE_INNER_L4_UDP,	      /* LH */
49 		RTE_PTYPE_INNER_L4_SCTP,      /* LH */
50 		RTE_PTYPE_INNER_L4_ICMP,      /* LH */
51 		RTE_PTYPE_UNKNOWN,
52 	};
53 
54 	return ptypes;
55 }
56 
57 /*
58  * +------------------ +------------------ +
59  * |  | IL4 | IL3| IL2 | TU | L4 | L3 | L2 |
60  * +-------------------+-------------------+
61  *
62  * +-------------------+------------------ +
63  * |  | LH | LG  | LF  | LE | LD | LC | LB |
64  * +-------------------+-------------------+
65  *
66  * ptype       [LE - LD - LC - LB]  = TU  - L4 -  L3  - T2
67  * ptype_tunnel[LH - LG - LF]  = IL4 - IL3 - IL2 - TU
68  *
69  */
70 static void
71 nix_create_non_tunnel_ptype_array(uint16_t *ptype)
72 {
73 	uint8_t lb, lc, ld, le;
74 	uint16_t val;
75 	uint32_t idx;
76 
77 	for (idx = 0; idx < PTYPE_NON_TUNNEL_ARRAY_SZ; idx++) {
78 		lb = idx & 0xF;
79 		lc = (idx & 0xF0) >> 4;
80 		ld = (idx & 0xF00) >> 8;
81 		le = (idx & 0xF000) >> 12;
82 		val = RTE_PTYPE_UNKNOWN;
83 
84 		switch (lb) {
85 		case NPC_LT_LB_STAG_QINQ:
86 			val |= RTE_PTYPE_L2_ETHER_QINQ;
87 			break;
88 		case NPC_LT_LB_CTAG:
89 			val |= RTE_PTYPE_L2_ETHER_VLAN;
90 			break;
91 		}
92 
93 		switch (lc) {
94 		case NPC_LT_LC_ARP:
95 			val |= RTE_PTYPE_L2_ETHER_ARP;
96 			break;
97 		case NPC_LT_LC_NSH:
98 			val |= RTE_PTYPE_L2_ETHER_NSH;
99 			break;
100 		case NPC_LT_LC_FCOE:
101 			val |= RTE_PTYPE_L2_ETHER_FCOE;
102 			break;
103 		case NPC_LT_LC_MPLS:
104 			val |= RTE_PTYPE_L2_ETHER_MPLS;
105 			break;
106 		case NPC_LT_LC_IP:
107 			val |= RTE_PTYPE_L3_IPV4;
108 			break;
109 		case NPC_LT_LC_IP_OPT:
110 			val |= RTE_PTYPE_L3_IPV4_EXT;
111 			break;
112 		case NPC_LT_LC_IP6:
113 			val |= RTE_PTYPE_L3_IPV6;
114 			break;
115 		case NPC_LT_LC_IP6_EXT:
116 			val |= RTE_PTYPE_L3_IPV6_EXT;
117 			break;
118 		case NPC_LT_LC_PTP:
119 			val |= RTE_PTYPE_L2_ETHER_TIMESYNC;
120 			break;
121 		}
122 
123 		switch (ld) {
124 		case NPC_LT_LD_TCP:
125 			val |= RTE_PTYPE_L4_TCP;
126 			break;
127 		case NPC_LT_LD_UDP:
128 			val |= RTE_PTYPE_L4_UDP;
129 			break;
130 		case NPC_LT_LD_SCTP:
131 			val |= RTE_PTYPE_L4_SCTP;
132 			break;
133 		case NPC_LT_LD_ICMP:
134 		case NPC_LT_LD_ICMP6:
135 			val |= RTE_PTYPE_L4_ICMP;
136 			break;
137 		case NPC_LT_LD_IGMP:
138 			val |= RTE_PTYPE_L4_IGMP;
139 			break;
140 		case NPC_LT_LD_GRE:
141 			val |= RTE_PTYPE_TUNNEL_GRE;
142 			break;
143 		case NPC_LT_LD_NVGRE:
144 			val |= RTE_PTYPE_TUNNEL_NVGRE;
145 			break;
146 		}
147 
148 		switch (le) {
149 		case NPC_LT_LE_VXLAN:
150 			val |= RTE_PTYPE_TUNNEL_VXLAN;
151 			break;
152 		case NPC_LT_LE_ESP:
153 			val |= RTE_PTYPE_TUNNEL_ESP;
154 			break;
155 		case NPC_LT_LE_VXLANGPE:
156 			val |= RTE_PTYPE_TUNNEL_VXLAN_GPE;
157 			break;
158 		case NPC_LT_LE_GENEVE:
159 			val |= RTE_PTYPE_TUNNEL_GENEVE;
160 			break;
161 		case NPC_LT_LE_GTPC:
162 			val |= RTE_PTYPE_TUNNEL_GTPC;
163 			break;
164 		case NPC_LT_LE_GTPU:
165 			val |= RTE_PTYPE_TUNNEL_GTPU;
166 			break;
167 		case NPC_LT_LE_TU_MPLS_IN_GRE:
168 			val |= RTE_PTYPE_TUNNEL_MPLS_IN_GRE;
169 			break;
170 		case NPC_LT_LE_TU_MPLS_IN_UDP:
171 			val |= RTE_PTYPE_TUNNEL_MPLS_IN_UDP;
172 			break;
173 		}
174 		ptype[idx] = val;
175 	}
176 }
177 
178 #define TU_SHIFT(x) ((x) >> PTYPE_NON_TUNNEL_WIDTH)
179 static void
180 nix_create_tunnel_ptype_array(uint16_t *ptype)
181 {
182 	uint8_t lf, lg, lh;
183 	uint16_t val;
184 	uint32_t idx;
185 
186 	/* Skip non tunnel ptype array memory */
187 	ptype = ptype + PTYPE_NON_TUNNEL_ARRAY_SZ;
188 
189 	for (idx = 0; idx < PTYPE_TUNNEL_ARRAY_SZ; idx++) {
190 		lf = idx & 0xF;
191 		lg = (idx & 0xF0) >> 4;
192 		lh = (idx & 0xF00) >> 8;
193 		val = RTE_PTYPE_UNKNOWN;
194 
195 		switch (lf) {
196 		case NPC_LT_LF_TU_ETHER:
197 			val |= TU_SHIFT(RTE_PTYPE_INNER_L2_ETHER);
198 			break;
199 		}
200 		switch (lg) {
201 		case NPC_LT_LG_TU_IP:
202 			val |= TU_SHIFT(RTE_PTYPE_INNER_L3_IPV4);
203 			break;
204 		case NPC_LT_LG_TU_IP6:
205 			val |= TU_SHIFT(RTE_PTYPE_INNER_L3_IPV6);
206 			break;
207 		}
208 		switch (lh) {
209 		case NPC_LT_LH_TU_TCP:
210 			val |= TU_SHIFT(RTE_PTYPE_INNER_L4_TCP);
211 			break;
212 		case NPC_LT_LH_TU_UDP:
213 			val |= TU_SHIFT(RTE_PTYPE_INNER_L4_UDP);
214 			break;
215 		case NPC_LT_LH_TU_SCTP:
216 			val |= TU_SHIFT(RTE_PTYPE_INNER_L4_SCTP);
217 			break;
218 		case NPC_LT_LH_TU_ICMP:
219 		case NPC_LT_LH_TU_ICMP6:
220 			val |= TU_SHIFT(RTE_PTYPE_INNER_L4_ICMP);
221 			break;
222 		}
223 
224 		ptype[idx] = val;
225 	}
226 }
227 
228 static void
229 nix_create_rx_ol_flags_array(void *mem)
230 {
231 	uint16_t idx, errcode, errlev;
232 	uint32_t val, *ol_flags;
233 
234 	/* Skip ptype array memory */
235 	ol_flags = (uint32_t *)((uint8_t *)mem + PTYPE_ARRAY_SZ);
236 
237 	for (idx = 0; idx < BIT(ERRCODE_ERRLEN_WIDTH); idx++) {
238 		errlev = idx & 0xf;
239 		errcode = (idx & 0xff0) >> 4;
240 
241 		val = RTE_MBUF_F_RX_IP_CKSUM_UNKNOWN;
242 		val |= RTE_MBUF_F_RX_L4_CKSUM_UNKNOWN;
243 		val |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_UNKNOWN;
244 
245 		switch (errlev) {
246 		case NPC_ERRLEV_RE:
247 			/* Mark all errors as BAD checksum errors
248 			 * including Outer L2 length mismatch error
249 			 */
250 			if (errcode) {
251 				val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
252 				val |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
253 			} else {
254 				val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
255 				val |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
256 			}
257 			break;
258 		case NPC_ERRLEV_LC:
259 			if (errcode == NPC_EC_OIP4_CSUM ||
260 			    errcode == NPC_EC_IP_FRAG_OFFSET_1) {
261 				val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
262 				val |= RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD;
263 			} else {
264 				val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
265 			}
266 			break;
267 		case NPC_ERRLEV_LG:
268 			if (errcode == NPC_EC_IIP4_CSUM)
269 				val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
270 			else
271 				val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
272 			break;
273 		case NPC_ERRLEV_NIX:
274 			if (errcode == NIX_RX_PERRCODE_OL4_CHK ||
275 			    errcode == NIX_RX_PERRCODE_OL4_LEN ||
276 			    errcode == NIX_RX_PERRCODE_OL4_PORT) {
277 				val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
278 				val |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
279 				val |= RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD;
280 			} else if (errcode == NIX_RX_PERRCODE_IL4_CHK ||
281 				   errcode == NIX_RX_PERRCODE_IL4_LEN ||
282 				   errcode == NIX_RX_PERRCODE_IL4_PORT) {
283 				val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
284 				val |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
285 			} else if (errcode == NIX_RX_PERRCODE_IL3_LEN ||
286 				   errcode == NIX_RX_PERRCODE_OL3_LEN) {
287 				val |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
288 			} else {
289 				val |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
290 				val |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
291 			}
292 			break;
293 		}
294 		ol_flags[idx] = val;
295 	}
296 }
297 
298 void *
299 cnxk_nix_fastpath_lookup_mem_get(void)
300 {
301 	const char name[] = CNXK_NIX_FASTPATH_LOOKUP_MEM;
302 	const struct rte_memzone *mz;
303 	void *mem;
304 
305 	mz = rte_memzone_lookup(name);
306 	if (mz != NULL)
307 		return mz->addr;
308 
309 	/* Request for the first time */
310 	mz = rte_memzone_reserve_aligned(name, LOOKUP_ARRAY_SZ, SOCKET_ID_ANY,
311 					 0, ROC_ALIGN);
312 	if (mz != NULL) {
313 		mem = mz->addr;
314 		/* Form the ptype array lookup memory */
315 		nix_create_non_tunnel_ptype_array(mem);
316 		nix_create_tunnel_ptype_array(mem);
317 		/* Form the rx ol_flags based on errcode */
318 		nix_create_rx_ol_flags_array(mem);
319 		return mem;
320 	}
321 	return NULL;
322 }
323 
324 int
325 cnxk_nix_lookup_mem_sa_base_set(struct cnxk_eth_dev *dev)
326 {
327 	void *lookup_mem = cnxk_nix_fastpath_lookup_mem_get();
328 	uint16_t port = dev->eth_dev->data->port_id;
329 	uintptr_t sa_base_tbl;
330 	uintptr_t sa_base;
331 	uint8_t sa_w;
332 
333 	if (!lookup_mem)
334 		return -EIO;
335 
336 	sa_base = roc_nix_inl_inb_sa_base_get(&dev->nix, dev->inb.inl_dev);
337 	if (!sa_base)
338 		return -ENOTSUP;
339 
340 	sa_w = plt_log2_u32(dev->nix.ipsec_in_max_spi + 1 -
341 			    dev->nix.ipsec_in_min_spi);
342 
343 	/* Set SA Base in lookup mem */
344 	sa_base_tbl = (uintptr_t)lookup_mem;
345 	sa_base_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ;
346 	*((uintptr_t *)sa_base_tbl + port) = sa_base | sa_w;
347 	return 0;
348 }
349 
350 int
351 cnxk_nix_lookup_mem_sa_base_clear(struct cnxk_eth_dev *dev)
352 {
353 	void *lookup_mem = cnxk_nix_fastpath_lookup_mem_get();
354 	uint16_t port = dev->eth_dev->data->port_id;
355 	uintptr_t sa_base_tbl;
356 
357 	if (!lookup_mem)
358 		return -EIO;
359 
360 	/* Set SA Base in lookup mem */
361 	sa_base_tbl = (uintptr_t)lookup_mem;
362 	sa_base_tbl += PTYPE_ARRAY_SZ + ERR_ARRAY_SZ;
363 	*((uintptr_t *)sa_base_tbl + port) = 0;
364 	return 0;
365 }
366