net/octeontx2: support packet type
[dpdk.git] / drivers / net / octeontx2 / otx2_lookup.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_common.h>
6 #include <rte_memzone.h>
7
8 #include "otx2_ethdev.h"
9
10 /* NIX_RX_PARSE_S's ERRCODE + ERRLEV (12 bits) */
11 #define ERRCODE_ERRLEN_WIDTH            12
12 #define ERR_ARRAY_SZ                    ((BIT(ERRCODE_ERRLEN_WIDTH)) *\
13                                         sizeof(uint32_t))
14
15 #define LOOKUP_ARRAY_SZ                 (PTYPE_ARRAY_SZ + ERR_ARRAY_SZ)
16
17 const uint32_t *
18 otx2_nix_supported_ptypes_get(struct rte_eth_dev *eth_dev)
19 {
20         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
21
22         static const uint32_t ptypes[] = {
23                 RTE_PTYPE_L2_ETHER_QINQ, /* LB */
24                 RTE_PTYPE_L2_ETHER_VLAN, /* LB */
25                 RTE_PTYPE_L2_ETHER_TIMESYNC, /* LB */
26                 RTE_PTYPE_L2_ETHER_ARP,  /* LC */
27                 RTE_PTYPE_L2_ETHER_NSH,  /* LC */
28                 RTE_PTYPE_L2_ETHER_FCOE, /* LC */
29                 RTE_PTYPE_L2_ETHER_MPLS, /* LC */
30                 RTE_PTYPE_L3_IPV4,       /* LC */
31                 RTE_PTYPE_L3_IPV4_EXT,   /* LC */
32                 RTE_PTYPE_L3_IPV6,       /* LC */
33                 RTE_PTYPE_L3_IPV6_EXT,   /* LC */
34                 RTE_PTYPE_L4_TCP,        /* LD */
35                 RTE_PTYPE_L4_UDP,        /* LD */
36                 RTE_PTYPE_L4_SCTP,       /* LD */
37                 RTE_PTYPE_L4_ICMP,       /* LD */
38                 RTE_PTYPE_L4_IGMP,       /* LD */
39                 RTE_PTYPE_TUNNEL_GRE,    /* LD */
40                 RTE_PTYPE_TUNNEL_ESP,    /* LD */
41                 RTE_PTYPE_TUNNEL_NVGRE,  /* LD */
42                 RTE_PTYPE_TUNNEL_VXLAN,  /* LE */
43                 RTE_PTYPE_TUNNEL_GENEVE, /* LE */
44                 RTE_PTYPE_TUNNEL_GTPC,   /* LE */
45                 RTE_PTYPE_TUNNEL_GTPU,   /* LE */
46                 RTE_PTYPE_TUNNEL_VXLAN_GPE,   /* LE */
47                 RTE_PTYPE_TUNNEL_MPLS_IN_GRE, /* LE */
48                 RTE_PTYPE_TUNNEL_MPLS_IN_UDP, /* LE */
49                 RTE_PTYPE_INNER_L2_ETHER,/* LF */
50                 RTE_PTYPE_INNER_L3_IPV4, /* LG */
51                 RTE_PTYPE_INNER_L3_IPV6, /* LG */
52                 RTE_PTYPE_INNER_L4_TCP,  /* LH */
53                 RTE_PTYPE_INNER_L4_UDP,  /* LH */
54                 RTE_PTYPE_INNER_L4_SCTP, /* LH */
55                 RTE_PTYPE_INNER_L4_ICMP, /* LH */
56         };
57
58         if (dev->rx_offload_flags & NIX_RX_OFFLOAD_PTYPE_F)
59                 return ptypes;
60         else
61                 return NULL;
62 }
63
64 /*
65  * +------------------ +------------------ +
66  * |  | IL4 | IL3| IL2 | TU | L4 | L3 | L2 |
67  * +-------------------+-------------------+
68  *
69  * +-------------------+------------------ +
70  * |  | LH | LG  | LF  | LE | LD | LC | LB |
71  * +-------------------+-------------------+
72  *
73  * ptype       [LE - LD - LC - LB]  = TU  - L4 -  L3  - T2
74  * ptype_tunnel[LH - LG - LF]  = IL4 - IL3 - IL2 - TU
75  *
76  */
77 static void
78 nix_create_non_tunnel_ptype_array(uint16_t *ptype)
79 {
80         uint8_t lb, lc, ld, le;
81         uint16_t idx, val;
82
83         for (idx = 0; idx < PTYPE_NON_TUNNEL_ARRAY_SZ; idx++) {
84                 lb = idx & 0xF;
85                 lc = (idx & 0xF0) >> 4;
86                 ld = (idx & 0xF00) >> 8;
87                 le = (idx & 0xF000) >> 12;
88                 val = RTE_PTYPE_UNKNOWN;
89
90                 switch (lb) {
91                 case NPC_LT_LB_QINQ:
92                         val |= RTE_PTYPE_L2_ETHER_QINQ;
93                         break;
94                 case NPC_LT_LB_CTAG:
95                         val |= RTE_PTYPE_L2_ETHER_VLAN;
96                         break;
97                 }
98
99                 switch (lc) {
100                 case NPC_LT_LC_ARP:
101                         val |= RTE_PTYPE_L2_ETHER_ARP;
102                         break;
103                 case NPC_LT_LC_NSH:
104                         val |= RTE_PTYPE_L2_ETHER_NSH;
105                         break;
106                 case NPC_LT_LC_FCOE:
107                         val |= RTE_PTYPE_L2_ETHER_FCOE;
108                         break;
109                 case NPC_LT_LC_MPLS:
110                         val |= RTE_PTYPE_L2_ETHER_MPLS;
111                         break;
112                 case NPC_LT_LC_IP:
113                         val |= RTE_PTYPE_L3_IPV4;
114                         break;
115                 case NPC_LT_LC_IP_OPT:
116                         val |= RTE_PTYPE_L3_IPV4_EXT;
117                         break;
118                 case NPC_LT_LC_IP6:
119                         val |= RTE_PTYPE_L3_IPV6;
120                         break;
121                 case NPC_LT_LC_IP6_EXT:
122                         val |= RTE_PTYPE_L3_IPV6_EXT;
123                         break;
124                 case NPC_LT_LC_PTP:
125                         val |= RTE_PTYPE_L2_ETHER_TIMESYNC;
126                         break;
127                 }
128
129                 switch (ld) {
130                 case NPC_LT_LD_TCP:
131                         val |= RTE_PTYPE_L4_TCP;
132                         break;
133                 case NPC_LT_LD_UDP:
134                         val |= RTE_PTYPE_L4_UDP;
135                         break;
136                 case NPC_LT_LD_SCTP:
137                         val |= RTE_PTYPE_L4_SCTP;
138                         break;
139                 case NPC_LT_LD_ICMP:
140                         val |= RTE_PTYPE_L4_ICMP;
141                         break;
142                 case NPC_LT_LD_IGMP:
143                         val |= RTE_PTYPE_L4_IGMP;
144                         break;
145                 case NPC_LT_LD_GRE:
146                         val |= RTE_PTYPE_TUNNEL_GRE;
147                         break;
148                 case NPC_LT_LD_NVGRE:
149                         val |= RTE_PTYPE_TUNNEL_NVGRE;
150                         break;
151                 case NPC_LT_LD_ESP:
152                         val |= RTE_PTYPE_TUNNEL_ESP;
153                         break;
154                 }
155
156                 switch (le) {
157                 case NPC_LT_LE_VXLAN:
158                         val |= RTE_PTYPE_TUNNEL_VXLAN;
159                         break;
160                 case NPC_LT_LE_VXLANGPE:
161                         val |= RTE_PTYPE_TUNNEL_VXLAN_GPE;
162                         break;
163                 case NPC_LT_LE_GENEVE:
164                         val |= RTE_PTYPE_TUNNEL_GENEVE;
165                         break;
166                 case NPC_LT_LE_GTPC:
167                         val |= RTE_PTYPE_TUNNEL_GTPC;
168                         break;
169                 case NPC_LT_LE_GTPU:
170                         val |= RTE_PTYPE_TUNNEL_GTPU;
171                         break;
172                 case NPC_LT_LE_TU_MPLS_IN_GRE:
173                         val |= RTE_PTYPE_TUNNEL_MPLS_IN_GRE;
174                         break;
175                 case NPC_LT_LE_TU_MPLS_IN_UDP:
176                         val |= RTE_PTYPE_TUNNEL_MPLS_IN_UDP;
177                         break;
178                 }
179                 ptype[idx] = val;
180         }
181 }
182
183 #define TU_SHIFT(x) ((x) >> PTYPE_WIDTH)
184 static void
185 nix_create_tunnel_ptype_array(uint16_t *ptype)
186 {
187         uint8_t le, lf, lg;
188         uint16_t idx, val;
189
190         /* Skip non tunnel ptype array memory */
191         ptype = ptype + PTYPE_NON_TUNNEL_ARRAY_SZ;
192
193         for (idx = 0; idx < PTYPE_TUNNEL_ARRAY_SZ; idx++) {
194                 le = idx & 0xF;
195                 lf = (idx & 0xF0) >> 4;
196                 lg = (idx & 0xF00) >> 8;
197                 val = RTE_PTYPE_UNKNOWN;
198
199                 switch (le) {
200                 case NPC_LT_LF_TU_ETHER:
201                         val |= TU_SHIFT(RTE_PTYPE_INNER_L2_ETHER);
202                         break;
203                 }
204                 switch (lf) {
205                 case NPC_LT_LG_TU_IP:
206                         val |= TU_SHIFT(RTE_PTYPE_INNER_L3_IPV4);
207                         break;
208                 case NPC_LT_LG_TU_IP6:
209                         val |= TU_SHIFT(RTE_PTYPE_INNER_L3_IPV6);
210                         break;
211                 }
212                 switch (lg) {
213                 case NPC_LT_LH_TU_TCP:
214                         val |= TU_SHIFT(RTE_PTYPE_INNER_L4_TCP);
215                         break;
216                 case NPC_LT_LH_TU_UDP:
217                         val |= TU_SHIFT(RTE_PTYPE_INNER_L4_UDP);
218                         break;
219                 case NPC_LT_LH_TU_SCTP:
220                         val |= TU_SHIFT(RTE_PTYPE_INNER_L4_SCTP);
221                         break;
222                 case NPC_LT_LH_TU_ICMP:
223                         val |= TU_SHIFT(RTE_PTYPE_INNER_L4_ICMP);
224                         break;
225                 }
226
227                 ptype[idx] = val;
228         }
229 }
230
231 static void
232 nix_create_rx_ol_flags_array(void *mem)
233 {
234         uint16_t idx, errcode, errlev;
235         uint32_t val, *ol_flags;
236
237         /* Skip ptype array memory */
238         ol_flags = (uint32_t *)((uint8_t *)mem + PTYPE_ARRAY_SZ);
239
240         for (idx = 0; idx < BIT(ERRCODE_ERRLEN_WIDTH); idx++) {
241                 errlev = idx & 0xf;
242                 errcode = (idx & 0xff0) >> 4;
243
244                 val = PKT_RX_IP_CKSUM_UNKNOWN;
245                 val |= PKT_RX_L4_CKSUM_UNKNOWN;
246                 val |= PKT_RX_OUTER_L4_CKSUM_UNKNOWN;
247
248                 switch (errlev) {
249                 case NPC_ERRLEV_RE:
250                         /* Mark all errors as BAD checksum errors */
251                         if (errcode) {
252                                 val |= PKT_RX_IP_CKSUM_BAD;
253                                 val |= PKT_RX_L4_CKSUM_BAD;
254                         } else {
255                                 val |= PKT_RX_IP_CKSUM_GOOD;
256                                 val |= PKT_RX_L4_CKSUM_GOOD;
257                         }
258                         break;
259                 case NPC_ERRLEV_LC:
260                         if (errcode == NPC_EC_OIP4_CSUM ||
261                             errcode == NPC_EC_IP_FRAG_OFFSET_1) {
262                                 val |= PKT_RX_IP_CKSUM_BAD;
263                                 val |= PKT_RX_EIP_CKSUM_BAD;
264                         } else {
265                                 val |= PKT_RX_IP_CKSUM_GOOD;
266                         }
267                         break;
268                 case NPC_ERRLEV_LG:
269                         if (errcode == NPC_EC_IIP4_CSUM)
270                                 val |= PKT_RX_IP_CKSUM_BAD;
271                         else
272                                 val |= PKT_RX_IP_CKSUM_GOOD;
273                         break;
274                 case NPC_ERRLEV_NIX:
275                         if (errcode == NIX_RX_PERRCODE_OL4_CHK) {
276                                 val |= PKT_RX_OUTER_L4_CKSUM_BAD;
277                                 val |= PKT_RX_L4_CKSUM_BAD;
278                         } else if (errcode == NIX_RX_PERRCODE_IL4_CHK) {
279                                 val |= PKT_RX_L4_CKSUM_BAD;
280                         } else {
281                                 val |= PKT_RX_IP_CKSUM_GOOD;
282                                 val |= PKT_RX_L4_CKSUM_GOOD;
283                         }
284                         break;
285                 }
286
287                 ol_flags[idx] = val;
288         }
289 }
290
291 void *
292 otx2_nix_fastpath_lookup_mem_get(void)
293 {
294         const char name[] = "otx2_nix_fastpath_lookup_mem";
295         const struct rte_memzone *mz;
296         void *mem;
297
298         mz = rte_memzone_lookup(name);
299         if (mz != NULL)
300                 return mz->addr;
301
302         /* Request for the first time */
303         mz = rte_memzone_reserve_aligned(name, LOOKUP_ARRAY_SZ,
304                                          SOCKET_ID_ANY, 0, OTX2_ALIGN);
305         if (mz != NULL) {
306                 mem = mz->addr;
307                 /* Form the ptype array lookup memory */
308                 nix_create_non_tunnel_ptype_array(mem);
309                 nix_create_tunnel_ptype_array(mem);
310                 /* Form the rx ol_flags based on errcode */
311                 nix_create_rx_ol_flags_array(mem);
312                 return mem;
313         }
314         return NULL;
315 }