Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : : #include "roc_api.h"
5 : : #include "roc_priv.h"
6 : :
7 : : const struct roc_npc_item_info *
8 : 0 : npc_parse_skip_void_and_any_items(const struct roc_npc_item_info *pattern)
9 : : {
10 [ # # ]: 0 : while ((pattern->type == ROC_NPC_ITEM_TYPE_VOID) ||
11 : : (pattern->type == ROC_NPC_ITEM_TYPE_ANY))
12 : 0 : pattern++;
13 : :
14 : 0 : return pattern;
15 : : }
16 : :
17 : : int
18 : 0 : npc_parse_meta_items(struct npc_parse_state *pst)
19 : : {
20 : : PLT_SET_USED(pst);
21 : 0 : return 0;
22 : : }
23 : :
24 : : int
25 : 0 : npc_parse_mark_item(struct npc_parse_state *pst)
26 : : {
27 [ # # ]: 0 : if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MARK) {
28 [ # # ]: 0 : if (pst->flow->nix_intf != NIX_INTF_RX)
29 : : return -EINVAL;
30 : :
31 : 0 : pst->is_second_pass_rule = true;
32 : 0 : pst->pattern++;
33 : : }
34 : :
35 : : return 0;
36 : : }
37 : :
38 : : static int
39 [ # # ]: 0 : npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
40 : : const struct roc_npc_flow_item_raw *raw_mask,
41 : : struct npc_parse_item_info *info, uint8_t *spec_buf,
42 : : uint8_t *mask_buf)
43 : : {
44 : :
45 : : memset(spec_buf, 0, NPC_MAX_RAW_ITEM_LEN);
46 : : memset(mask_buf, 0, NPC_MAX_RAW_ITEM_LEN);
47 : :
48 : 0 : memcpy(spec_buf + raw_spec->offset, raw_spec->pattern,
49 [ # # ]: 0 : raw_spec->length);
50 : :
51 [ # # # # ]: 0 : if (raw_mask && raw_mask->pattern) {
52 : 0 : memcpy(mask_buf + raw_spec->offset, raw_mask->pattern,
53 : 0 : raw_spec->length);
54 : : } else {
55 : 0 : memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length);
56 : : }
57 : :
58 : 0 : info->len = NPC_MAX_RAW_ITEM_LEN;
59 : 0 : info->spec = spec_buf;
60 : 0 : info->mask = mask_buf;
61 : 0 : return 0;
62 : : }
63 : :
64 : : int
65 : 0 : npc_parse_pre_l2(struct npc_parse_state *pst)
66 : : {
67 : 0 : uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN] = {0};
68 : 0 : uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN] = {0};
69 : 0 : uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN] = {0};
70 : : const struct roc_npc_flow_item_raw *raw_spec;
71 : : struct npc_parse_item_info info;
72 : : int lid, lt, len;
73 : : int rc;
74 : :
75 [ # # ]: 0 : if (pst->npc->switch_header_type != ROC_PRIV_FLAGS_PRE_L2)
76 : : return 0;
77 : :
78 : : /* Identify the pattern type into lid, lt */
79 [ # # ]: 0 : if (pst->pattern->type != ROC_NPC_ITEM_TYPE_RAW)
80 : : return 0;
81 : :
82 : : lid = NPC_LID_LA;
83 : : lt = NPC_LT_LA_CUSTOM_PRE_L2_ETHER;
84 : 0 : info.hw_hdr_len = 0;
85 : :
86 : 0 : raw_spec = pst->pattern->spec;
87 : 0 : len = raw_spec->length + raw_spec->offset;
88 [ # # ]: 0 : if (len > NPC_MAX_RAW_ITEM_LEN)
89 : : return -EINVAL;
90 : :
91 [ # # # # : 0 : if (raw_spec->relative == 0 || raw_spec->search || raw_spec->limit ||
# # ]
92 : : raw_spec->offset < 0)
93 : : return -EINVAL;
94 : :
95 : 0 : npc_flow_raw_item_prepare(
96 : : (const struct roc_npc_flow_item_raw *)pst->pattern->spec,
97 : 0 : (const struct roc_npc_flow_item_raw *)pst->pattern->mask, &info,
98 : : raw_spec_buf, raw_mask_buf);
99 : :
100 : 0 : info.def_mask = NULL;
101 : 0 : info.hw_mask = &hw_mask;
102 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
103 : :
104 : : /* Basic validation of item parameters */
105 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
106 [ # # ]: 0 : if (rc)
107 : : return rc;
108 : :
109 : : /* Update pst if not validate only? clash check? */
110 : 0 : return npc_update_parse_state(pst, &info, lid, lt, 0);
111 : : }
112 : :
113 : : int
114 : 0 : npc_parse_cpt_hdr(struct npc_parse_state *pst)
115 : : {
116 : : uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
117 : : struct npc_parse_item_info info;
118 : : int lid, lt;
119 : : int rc;
120 : :
121 : : /* Identify the pattern type into lid, lt */
122 [ # # ]: 0 : if (pst->pattern->type != ROC_NPC_ITEM_TYPE_CPT_HDR)
123 : : return 0;
124 : :
125 : : lid = NPC_LID_LA;
126 : : lt = NPC_LT_LA_CPT_HDR;
127 : 0 : info.hw_hdr_len = 0;
128 : :
129 : : /* Prepare for parsing the item */
130 : 0 : info.def_mask = NULL;
131 : 0 : info.hw_mask = &hw_mask;
132 : 0 : info.len = pst->pattern->size;
133 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
134 : 0 : info.spec = NULL;
135 : 0 : info.mask = NULL;
136 : :
137 : : /* Basic validation of item parameters */
138 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
139 [ # # ]: 0 : if (rc)
140 : : return rc;
141 : :
142 : : /* Update pst if not validate only? clash check? */
143 : 0 : return npc_update_parse_state(pst, &info, lid, lt, 0);
144 : : }
145 : :
146 : : int
147 : 0 : npc_parse_higig2_hdr(struct npc_parse_state *pst)
148 : : {
149 : : uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
150 : : struct npc_parse_item_info info;
151 : : int lid, lt;
152 : : int rc;
153 : :
154 : : /* Identify the pattern type into lid, lt */
155 [ # # ]: 0 : if (pst->pattern->type != ROC_NPC_ITEM_TYPE_HIGIG2)
156 : : return 0;
157 : :
158 : : lid = NPC_LID_LA;
159 : : lt = NPC_LT_LA_HIGIG2_ETHER;
160 : 0 : info.hw_hdr_len = 0;
161 : :
162 [ # # ]: 0 : if (pst->flow->nix_intf == NIX_INTF_TX) {
163 : : lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
164 : 0 : info.hw_hdr_len = NPC_IH_LENGTH;
165 : : }
166 : :
167 : : /* Prepare for parsing the item */
168 : 0 : info.def_mask = NULL;
169 : 0 : info.hw_mask = &hw_mask;
170 : 0 : info.len = pst->pattern->size;
171 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
172 : 0 : info.spec = NULL;
173 : 0 : info.mask = NULL;
174 : :
175 : : /* Basic validation of item parameters */
176 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
177 [ # # ]: 0 : if (rc)
178 : : return rc;
179 : :
180 : : /* Update pst if not validate only? clash check? */
181 : 0 : return npc_update_parse_state(pst, &info, lid, lt, 0);
182 : : }
183 : :
184 : : int
185 [ # # ]: 0 : npc_parse_tx_queue(struct npc_parse_state *pst)
186 : : {
187 : : struct nix_inst_hdr_s nix_inst_hdr, nix_inst_hdr_mask;
188 : : uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
189 : : struct npc_parse_item_info parse_info;
190 : : const uint16_t *send_queue;
191 : : int lid, lt, rc = 0;
192 : :
193 : : memset(&nix_inst_hdr, 0, sizeof(nix_inst_hdr));
194 : : memset(&nix_inst_hdr_mask, 0, sizeof(nix_inst_hdr_mask));
195 : : memset(&parse_info, 0, sizeof(parse_info));
196 : :
197 [ # # ]: 0 : if (pst->pattern->type != ROC_NPC_ITEM_TYPE_TX_QUEUE)
198 : : return 0;
199 : :
200 [ # # ]: 0 : if (pst->flow->nix_intf != NIX_INTF_TX)
201 : : return NPC_ERR_INVALID_SPEC;
202 : :
203 : : lid = NPC_LID_LA;
204 : : lt = NPC_LT_LA_IH_NIX_ETHER;
205 : 0 : send_queue = (const uint16_t *)pst->pattern->spec;
206 : :
207 [ # # ]: 0 : if (*send_queue >= pst->nb_tx_queues)
208 : : return NPC_ERR_INVALID_SPEC;
209 : :
210 : 0 : nix_inst_hdr.sq = *send_queue;
211 : 0 : nix_inst_hdr_mask.sq = 0xFFFF;
212 : :
213 : : parse_info.def_mask = NULL;
214 : 0 : parse_info.spec = &nix_inst_hdr;
215 : 0 : parse_info.mask = &nix_inst_hdr_mask;
216 : 0 : parse_info.len = sizeof(nix_inst_hdr);
217 : : parse_info.def_mask = NULL;
218 : : parse_info.hw_hdr_len = 0;
219 : :
220 : : memset(hw_mask, 0, sizeof(hw_mask));
221 : :
222 : 0 : parse_info.hw_mask = &hw_mask;
223 : 0 : npc_get_hw_supp_mask(pst, &parse_info, lid, lt);
224 : :
225 : 0 : rc = npc_mask_is_supported(parse_info.mask, parse_info.hw_mask, parse_info.len);
226 [ # # ]: 0 : if (!rc)
227 : : return NPC_ERR_INVALID_MASK;
228 : :
229 : 0 : rc = npc_update_parse_state(pst, &parse_info, lid, lt, 0);
230 [ # # ]: 0 : if (rc)
231 : 0 : return rc;
232 : :
233 : : return 0;
234 : : }
235 : :
236 : : int
237 : 0 : npc_parse_la(struct npc_parse_state *pst)
238 : : {
239 : : const struct roc_npc_flow_item_eth *eth_item;
240 : : uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
241 : : struct npc_parse_item_info info;
242 : : int lid, lt;
243 : : int rc;
244 : :
245 : : /* Identify the pattern type into lid, lt */
246 [ # # ]: 0 : if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
247 : : return 0;
248 : :
249 : 0 : pst->has_eth_type = true;
250 : 0 : eth_item = pst->pattern->spec;
251 : :
252 : : lid = NPC_LID_LA;
253 : : lt = NPC_LT_LA_ETHER;
254 : 0 : info.hw_hdr_len = 0;
255 : :
256 [ # # ]: 0 : if (pst->flow->nix_intf == NIX_INTF_TX) {
257 : : lt = NPC_LT_LA_IH_NIX_ETHER;
258 : 0 : info.hw_hdr_len = NPC_IH_LENGTH;
259 [ # # ]: 0 : if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
260 : : lt = NPC_LT_LA_IH_NIX_HIGIG2_ETHER;
261 : 0 : info.hw_hdr_len += NPC_HIGIG2_LENGTH;
262 : : }
263 : : } else {
264 [ # # ]: 0 : if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_HIGIG) {
265 : : lt = NPC_LT_LA_HIGIG2_ETHER;
266 : 0 : info.hw_hdr_len = NPC_HIGIG2_LENGTH;
267 : : }
268 : : }
269 : :
270 : : /* Prepare for parsing the item */
271 : 0 : info.def_mask = NULL;
272 : 0 : info.hw_mask = &hw_mask;
273 : 0 : info.len = sizeof(eth_item->hdr);
274 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
275 : 0 : info.spec = NULL;
276 : 0 : info.mask = NULL;
277 : :
278 : : /* Basic validation of item parameters */
279 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
280 [ # # ]: 0 : if (rc)
281 : : return rc;
282 : :
283 : 0 : rc = npc_update_parse_state(pst, &info, lid, lt, 0);
284 [ # # ]: 0 : if (rc)
285 : : return rc;
286 : :
287 [ # # # # ]: 0 : if (eth_item && eth_item->has_vlan)
288 : 0 : pst->set_vlan_ltype_mask = true;
289 : :
290 : : return 0;
291 : : }
292 : :
293 : : #define NPC_MAX_SUPPORTED_VLANS 3
294 : :
295 : : static int
296 : 0 : npc_parse_vlan_count(const struct roc_npc_item_info *pattern,
297 : : const struct roc_npc_item_info **pattern_list,
298 : : const struct roc_npc_flow_item_vlan **vlan_items, int *vlan_count)
299 : : {
300 : 0 : *vlan_count = 0;
301 [ # # ]: 0 : while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
302 [ # # ]: 0 : if (*vlan_count > NPC_MAX_SUPPORTED_VLANS - 1)
303 : : return NPC_ERR_PATTERN_NOTSUP;
304 : :
305 : : /* Don't support ranges */
306 [ # # ]: 0 : if (pattern->last != NULL)
307 : : return NPC_ERR_INVALID_RANGE;
308 : :
309 : : /* If spec is NULL, both mask and last must be NULL, this
310 : : * makes it to match ANY value (eq to mask = 0).
311 : : * Setting either mask or last without spec is an error
312 : : */
313 : : if (pattern->spec == NULL) {
314 : : if (pattern->last != NULL && pattern->mask != NULL)
315 : : return NPC_ERR_INVALID_SPEC;
316 : : }
317 : :
318 : 0 : pattern_list[*vlan_count] = pattern;
319 : 0 : vlan_items[*vlan_count] = pattern->spec;
320 : 0 : (*vlan_count)++;
321 : :
322 : 0 : pattern++;
323 : 0 : pattern = npc_parse_skip_void_and_any_items(pattern);
324 : : }
325 : :
326 : : return 0;
327 : : }
328 : :
329 : : static int
330 : 0 : npc_parse_vlan_ltype_get(struct npc_parse_state *pst,
331 : : const struct roc_npc_flow_item_vlan **vlan_item, int vlan_count,
332 : : int *ltype, int *lflags)
333 : : {
334 [ # # # # ]: 0 : switch (vlan_count) {
335 : 0 : case 1:
336 : 0 : *ltype = NPC_LT_LB_CTAG;
337 [ # # # # ]: 0 : if (vlan_item[0] && vlan_item[0]->has_more_vlan)
338 : 0 : *ltype = NPC_LT_LB_STAG_QINQ;
339 : : break;
340 : 0 : case 2:
341 [ # # # # ]: 0 : if (vlan_item[1] && vlan_item[1]->has_more_vlan) {
342 [ # # ]: 0 : if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] &
343 : : 0x3ULL << NPC_LFLAG_LB_OFFSET))
344 : : return NPC_ERR_PATTERN_NOTSUP;
345 : :
346 : : /* This lflag value will match either one of
347 : : * NPC_F_LB_L_WITH_STAG_STAG,
348 : : * NPC_F_LB_L_WITH_QINQ_CTAG,
349 : : * NPC_F_LB_L_WITH_QINQ_QINQ and
350 : : * NPC_F_LB_L_WITH_ITAG (0b0100 to 0b0111). For
351 : : * NPC_F_LB_L_WITH_ITAG, ltype is NPC_LT_LB_ETAG
352 : : * hence will not match.
353 : : */
354 : :
355 : 0 : *lflags = NPC_F_LB_L_WITH_QINQ_CTAG & NPC_F_LB_L_WITH_QINQ_QINQ &
356 : : NPC_F_LB_L_WITH_STAG_STAG;
357 : : }
358 : 0 : *ltype = NPC_LT_LB_STAG_QINQ;
359 : 0 : break;
360 : 0 : case 3:
361 [ # # # # ]: 0 : if (vlan_item[2] && vlan_item[2]->has_more_vlan)
362 : : return NPC_ERR_PATTERN_NOTSUP;
363 [ # # ]: 0 : if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] & 0x3ULL << NPC_LFLAG_LB_OFFSET))
364 : : return NPC_ERR_PATTERN_NOTSUP;
365 : 0 : *ltype = NPC_LT_LB_STAG_QINQ;
366 : 0 : *lflags = NPC_F_STAG_STAG_CTAG;
367 : 0 : break;
368 : : default:
369 : : return NPC_ERR_PATTERN_NOTSUP;
370 : : }
371 : :
372 : : return 0;
373 : : }
374 : :
375 : : static int
376 : 0 : npc_update_vlan_parse_state(struct npc_parse_state *pst, const struct roc_npc_item_info *pattern,
377 : : int lid, int lt, uint8_t lflags, int vlan_count)
378 : : {
379 : : uint8_t vlan_spec[NPC_MAX_SUPPORTED_VLANS * sizeof(struct roc_vlan_hdr)];
380 : : uint8_t vlan_mask[NPC_MAX_SUPPORTED_VLANS * sizeof(struct roc_vlan_hdr)];
381 : : int rc = 0, i, offset = NPC_TPID_LENGTH;
382 : : struct npc_parse_item_info parse_info;
383 : : char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
384 : :
385 : : memset(vlan_spec, 0, sizeof(struct roc_vlan_hdr) * NPC_MAX_SUPPORTED_VLANS);
386 : : memset(vlan_mask, 0, sizeof(struct roc_vlan_hdr) * NPC_MAX_SUPPORTED_VLANS);
387 : : memset(&parse_info, 0, sizeof(parse_info));
388 : :
389 : : if (vlan_count > 2)
390 : : vlan_count = 2;
391 : :
392 [ # # ]: 0 : for (i = 0; i < vlan_count; i++) {
393 [ # # ]: 0 : if (pattern[i].spec)
394 : 0 : memcpy(vlan_spec + offset, pattern[i].spec, sizeof(struct roc_vlan_hdr));
395 [ # # ]: 0 : if (pattern[i].mask)
396 : 0 : memcpy(vlan_mask + offset, pattern[i].mask, sizeof(struct roc_vlan_hdr));
397 : :
398 : 0 : offset += 4;
399 : : }
400 : :
401 : : parse_info.def_mask = NULL;
402 : 0 : parse_info.spec = vlan_spec;
403 : 0 : parse_info.mask = vlan_mask;
404 : : parse_info.def_mask = NULL;
405 : : parse_info.hw_hdr_len = 0;
406 : :
407 : : lid = NPC_LID_LB;
408 : 0 : parse_info.hw_mask = hw_mask;
409 : :
410 [ # # ]: 0 : if (lt == NPC_LT_LB_CTAG)
411 : 0 : parse_info.len = sizeof(struct roc_vlan_hdr) + NPC_TPID_LENGTH;
412 : :
413 [ # # ]: 0 : if (lt == NPC_LT_LB_STAG_QINQ)
414 : 0 : parse_info.len = sizeof(struct roc_vlan_hdr) * 2 + NPC_TPID_LENGTH;
415 : :
416 : : memset(hw_mask, 0, sizeof(hw_mask));
417 : :
418 : : parse_info.hw_mask = &hw_mask;
419 : 0 : npc_get_hw_supp_mask(pst, &parse_info, lid, lt);
420 : :
421 : 0 : rc = npc_mask_is_supported(parse_info.mask, parse_info.hw_mask, parse_info.len);
422 [ # # ]: 0 : if (!rc)
423 : : return NPC_ERR_INVALID_MASK;
424 : :
425 : : /* Point pattern to last item consumed */
426 : 0 : pst->pattern = pattern;
427 : 0 : return npc_update_parse_state(pst, &parse_info, lid, lt, lflags);
428 : : }
429 : :
430 : : static int
431 : 0 : npc_parse_lb_vlan(struct npc_parse_state *pst)
432 : : {
433 : : const struct roc_npc_flow_item_vlan *vlan_items[NPC_MAX_SUPPORTED_VLANS];
434 : : const struct roc_npc_item_info *pattern_list[NPC_MAX_SUPPORTED_VLANS];
435 : : const struct roc_npc_item_info *last_pattern;
436 : 0 : int vlan_count = 0, rc = 0;
437 : : int lid, lt, lflags;
438 : :
439 : : lid = NPC_LID_LB;
440 : 0 : lflags = 0;
441 : 0 : last_pattern = pst->pattern;
442 : :
443 : 0 : rc = npc_parse_vlan_count(pst->pattern, pattern_list, vlan_items, &vlan_count);
444 [ # # ]: 0 : if (rc)
445 : : return rc;
446 : :
447 : 0 : rc = npc_parse_vlan_ltype_get(pst, vlan_items, vlan_count, <, &lflags);
448 [ # # ]: 0 : if (rc)
449 : : return rc;
450 : :
451 [ # # ]: 0 : if (vlan_count == 3) {
452 [ # # # # ]: 0 : if (pattern_list[2]->spec != NULL && pattern_list[2]->mask != NULL &&
453 [ # # ]: 0 : pattern_list[2]->last != NULL)
454 : : return NPC_ERR_PATTERN_NOTSUP;
455 : :
456 : : /* Matching can be done only for two tags. */
457 : 0 : vlan_count = 2;
458 : 0 : last_pattern++;
459 : : }
460 : :
461 : 0 : rc = npc_update_vlan_parse_state(pst, pattern_list[0], lid, lt, lflags, vlan_count);
462 [ # # ]: 0 : if (rc)
463 : : return rc;
464 : :
465 [ # # ]: 0 : if (vlan_count > 1)
466 : 0 : pst->pattern = last_pattern + vlan_count;
467 : :
468 : : return 0;
469 : : }
470 : :
471 : : int
472 : 0 : npc_parse_lb(struct npc_parse_state *pst)
473 : : {
474 : 0 : const struct roc_npc_item_info *pattern = pst->pattern;
475 : : const struct roc_npc_item_info *last_pattern;
476 : : const struct roc_npc_flow_item_raw *raw_spec;
477 : : uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
478 : : uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
479 : : char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
480 : : struct npc_parse_item_info info;
481 : : int lid, lt, lflags, len = 0;
482 : : int rc;
483 : :
484 : 0 : info.def_mask = NULL;
485 : 0 : info.spec = NULL;
486 : 0 : info.mask = NULL;
487 : : info.def_mask = NULL;
488 : 0 : info.hw_hdr_len = NPC_TPID_LENGTH;
489 : :
490 : : lid = NPC_LID_LB;
491 : : lflags = 0;
492 : : last_pattern = pattern;
493 : :
494 [ # # ]: 0 : if (pst->pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
495 : : /* RTE vlan is either 802.1q or 802.1ad,
496 : : * this maps to either CTAG/STAG. We need to decide
497 : : * based on number of VLANS present. Matching is
498 : : * supported on first two tags.
499 : : */
500 : :
501 : 0 : return npc_parse_lb_vlan(pst);
502 [ # # ]: 0 : } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_E_TAG) {
503 : : /* we can support ETAG and match a subsequent CTAG
504 : : * without any matching support.
505 : : */
506 : : lt = NPC_LT_LB_ETAG;
507 : : lflags = 0;
508 : :
509 : : last_pattern = pst->pattern;
510 : 0 : pattern = npc_parse_skip_void_and_any_items(pst->pattern + 1);
511 [ # # ]: 0 : if (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
512 : : /* set supported mask to NULL for vlan tag */
513 : 0 : info.hw_mask = NULL;
514 : 0 : info.len = pattern->size;
515 : 0 : rc = npc_parse_item_basic(pattern, &info);
516 [ # # ]: 0 : if (rc != 0)
517 : : return rc;
518 : :
519 : : lflags = NPC_F_ETAG_CTAG;
520 : : last_pattern = pattern;
521 : : }
522 : 0 : info.len = pattern->size;
523 [ # # ]: 0 : } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_QINQ) {
524 : : info.hw_mask = NULL;
525 : 0 : info.len = pattern->size;
526 : : lt = NPC_LT_LB_STAG_QINQ;
527 : : lflags = NPC_F_STAG_CTAG;
528 [ # # ]: 0 : } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_PPPOES) {
529 : : info.hw_mask = NULL;
530 : 0 : info.len = pattern->size;
531 : : info.hw_hdr_len = 2;
532 : : lt = NPC_LT_LB_PPPOE;
533 [ # # ]: 0 : } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) {
534 : 0 : raw_spec = pst->pattern->spec;
535 [ # # ]: 0 : if (raw_spec->relative)
536 : : return 0;
537 : 0 : len = raw_spec->length + raw_spec->offset;
538 [ # # ]: 0 : if (len > NPC_MAX_RAW_ITEM_LEN)
539 : : return -EINVAL;
540 : :
541 [ # # ]: 0 : if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
542 : : lt = NPC_LT_LB_VLAN_EXDSA;
543 [ # # ]: 0 : } else if (pst->npc->switch_header_type ==
544 : : ROC_PRIV_FLAGS_EXDSA) {
545 : : lt = NPC_LT_LB_EXDSA;
546 : : } else {
547 : : return -EINVAL;
548 : : }
549 : :
550 : 0 : npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
551 : : pst->pattern->spec,
552 : : (const struct roc_npc_flow_item_raw *)
553 : 0 : pst->pattern->mask,
554 : : &info, raw_spec_buf, raw_mask_buf);
555 : :
556 : 0 : info.hw_hdr_len = 0;
557 : : } else {
558 : : return 0;
559 : : }
560 : :
561 : 0 : info.hw_mask = &hw_mask;
562 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
563 : :
564 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
565 [ # # ]: 0 : if (rc != 0)
566 : : return rc;
567 : :
568 : : /* Point pattern to last item consumed */
569 : 0 : pst->pattern = last_pattern;
570 : 0 : return npc_update_parse_state(pst, &info, lid, lt, lflags);
571 : : }
572 : :
573 : : static int
574 : 0 : npc_parse_mpls_label_stack(struct npc_parse_state *pst, int *flag)
575 : : {
576 : 0 : uint8_t flag_list[] = {0, NPC_F_MPLS_2_LABELS, NPC_F_MPLS_3_LABELS,
577 : : NPC_F_MPLS_4_LABELS};
578 : 0 : const struct roc_npc_item_info *pattern = pst->pattern;
579 : : struct npc_parse_item_info info;
580 : : int nr_labels = 0;
581 : : int rc;
582 : :
583 : : /*
584 : : * pst->pattern points to first MPLS label. We only check
585 : : * that subsequent labels do not have anything to match.
586 : : */
587 : 0 : info.def_mask = NULL;
588 : 0 : info.hw_mask = NULL;
589 : 0 : info.len = pattern->size;
590 : 0 : info.spec = NULL;
591 : 0 : info.mask = NULL;
592 : 0 : info.hw_hdr_len = 0;
593 : :
594 [ # # ]: 0 : while (pattern->type == ROC_NPC_ITEM_TYPE_MPLS) {
595 : 0 : nr_labels++;
596 : :
597 : : /* Basic validation of Second/Third/Fourth mpls item */
598 [ # # ]: 0 : if (nr_labels > 1) {
599 : 0 : rc = npc_parse_item_basic(pattern, &info);
600 [ # # ]: 0 : if (rc != 0)
601 : 0 : return rc;
602 : : }
603 : 0 : pst->last_pattern = pattern;
604 : 0 : pattern++;
605 : 0 : pattern = npc_parse_skip_void_and_any_items(pattern);
606 : : }
607 : :
608 [ # # ]: 0 : if (nr_labels < 1 || nr_labels > 4)
609 : : return NPC_ERR_PATTERN_NOTSUP;
610 : :
611 : 0 : *flag = flag_list[nr_labels - 1];
612 : 0 : return 0;
613 : : }
614 : :
615 : : static int
616 : 0 : npc_parse_mpls(struct npc_parse_state *pst, int lid)
617 : : {
618 : : /* Find number of MPLS labels */
619 : : uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
620 : : struct npc_parse_item_info info;
621 : : int lt, lflags;
622 : : int rc;
623 : :
624 : 0 : lflags = 0;
625 : :
626 [ # # ]: 0 : if (lid == NPC_LID_LC)
627 : : lt = NPC_LT_LC_MPLS;
628 [ # # ]: 0 : else if (lid == NPC_LID_LD)
629 : : lt = NPC_LT_LD_TU_MPLS_IN_IP;
630 : : else
631 : : lt = NPC_LT_LE_TU_MPLS_IN_UDP;
632 : :
633 : : /* Prepare for parsing the first item */
634 : 0 : info.hw_mask = &hw_mask;
635 : 0 : info.len = pst->pattern->size;
636 : 0 : info.spec = NULL;
637 : 0 : info.mask = NULL;
638 : 0 : info.def_mask = NULL;
639 : 0 : info.hw_hdr_len = 0;
640 : :
641 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
642 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
643 [ # # ]: 0 : if (rc != 0)
644 : : return rc;
645 : :
646 : : /*
647 : : * Parse for more labels.
648 : : * This sets lflags and pst->last_pattern correctly.
649 : : */
650 : 0 : rc = npc_parse_mpls_label_stack(pst, &lflags);
651 [ # # ]: 0 : if (rc != 0)
652 : : return rc;
653 : :
654 : 0 : pst->tunnel = 1;
655 : 0 : pst->pattern = pst->last_pattern;
656 : :
657 : 0 : return npc_update_parse_state(pst, &info, lid, lt, lflags);
658 : : }
659 : :
660 : : static inline void
661 : 0 : npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
662 : : {
663 : 0 : const struct roc_npc_item_info *pattern = pst->pattern + 1;
664 : :
665 : 0 : pattern = npc_parse_skip_void_and_any_items(pattern);
666 [ # # ]: 0 : if (pattern->type == ROC_NPC_ITEM_TYPE_MPLS ||
667 [ # # ]: 0 : pattern->type == ROC_NPC_ITEM_TYPE_IPV4 ||
668 : : pattern->type == ROC_NPC_ITEM_TYPE_IPV6)
669 : 0 : pst->tunnel = 1;
670 : 0 : }
671 : :
672 : : static int
673 : 0 : npc_handle_ipv6ext_attr(const struct roc_npc_flow_item_ipv6 *ipv6_spec,
674 : : struct npc_parse_state *pst, uint8_t *flags)
675 : : {
676 : : int flags_count = 0;
677 : :
678 [ # # ]: 0 : if (ipv6_spec->has_hop_ext) {
679 : 0 : *flags = NPC_F_LC_L_EXT_HOP;
680 : : flags_count++;
681 : : }
682 [ # # ]: 0 : if (ipv6_spec->has_route_ext) {
683 : 0 : *flags = NPC_F_LC_L_EXT_ROUT;
684 : 0 : flags_count++;
685 : : }
686 [ # # ]: 0 : if (ipv6_spec->has_frag_ext) {
687 : 0 : *flags = NPC_F_LC_U_IP6_FRAG;
688 : 0 : flags_count++;
689 : : }
690 [ # # ]: 0 : if (ipv6_spec->has_dest_ext) {
691 : 0 : *flags = NPC_F_LC_L_EXT_DEST;
692 : 0 : flags_count++;
693 : : }
694 [ # # ]: 0 : if (ipv6_spec->has_mobil_ext) {
695 : 0 : *flags = NPC_F_LC_L_EXT_MOBILITY;
696 : 0 : flags_count++;
697 : : }
698 [ # # ]: 0 : if (ipv6_spec->has_hip_ext) {
699 : 0 : *flags = NPC_F_LC_L_EXT_HOSTID;
700 : 0 : flags_count++;
701 : : }
702 [ # # ]: 0 : if (ipv6_spec->has_shim6_ext) {
703 : 0 : *flags = NPC_F_LC_L_EXT_SHIM6;
704 : 0 : flags_count++;
705 : : }
706 [ # # ]: 0 : if (ipv6_spec->has_auth_ext) {
707 : 0 : pst->lt[NPC_LID_LD] = NPC_LT_LD_AH;
708 : 0 : flags_count++;
709 : : }
710 [ # # ]: 0 : if (ipv6_spec->has_esp_ext) {
711 : 0 : pst->lt[NPC_LID_LE] = NPC_LT_LE_ESP;
712 : 0 : flags_count++;
713 : : }
714 : :
715 [ # # ]: 0 : if (flags_count > 1)
716 : : return -EINVAL;
717 : :
718 [ # # ]: 0 : if (flags_count)
719 : 0 : pst->set_ipv6ext_ltype_mask = true;
720 : :
721 : : return 0;
722 : : }
723 : :
724 : : static int
725 : 0 : npc_process_ipv6_item(struct npc_parse_state *pst)
726 : : {
727 : : uint8_t ipv6_hdr_mask[2 * sizeof(struct roc_ipv6_hdr)];
728 : : uint8_t ipv6_hdr_buf[2 * sizeof(struct roc_ipv6_hdr)];
729 : : const struct roc_npc_flow_item_ipv6 *ipv6_spec, *ipv6_mask;
730 : 0 : const struct roc_npc_item_info *pattern = pst->pattern;
731 : : int offset = 0, rc = 0, lid, item_count = 0;
732 : : struct npc_parse_item_info parse_info;
733 : : char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
734 [ # # ]: 0 : uint8_t flags = 0, ltype;
735 : :
736 : : memset(ipv6_hdr_buf, 0, sizeof(ipv6_hdr_buf));
737 : : memset(ipv6_hdr_mask, 0, sizeof(ipv6_hdr_mask));
738 : :
739 : 0 : ipv6_spec = pst->pattern->spec;
740 : 0 : ipv6_mask = pst->pattern->mask;
741 : :
742 : 0 : parse_info.def_mask = NULL;
743 : 0 : parse_info.spec = ipv6_hdr_buf;
744 : 0 : parse_info.mask = ipv6_hdr_mask;
745 : : parse_info.def_mask = NULL;
746 : 0 : parse_info.hw_hdr_len = 0;
747 : 0 : parse_info.len = sizeof(ipv6_spec->hdr);
748 : :
749 : 0 : pst->set_ipv6ext_ltype_mask = true;
750 : :
751 : : lid = NPC_LID_LC;
752 : : ltype = NPC_LT_LC_IP6;
753 : :
754 [ # # ]: 0 : if (pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
755 : : item_count++;
756 [ # # ]: 0 : if (ipv6_spec) {
757 : 0 : memcpy(ipv6_hdr_buf, &ipv6_spec->hdr, sizeof(struct roc_ipv6_hdr));
758 : 0 : rc = npc_handle_ipv6ext_attr(ipv6_spec, pst, &flags);
759 [ # # ]: 0 : if (rc)
760 : : return rc;
761 : : }
762 [ # # ]: 0 : if (ipv6_mask)
763 : 0 : memcpy(ipv6_hdr_mask, &ipv6_mask->hdr, sizeof(struct roc_ipv6_hdr));
764 : : }
765 : :
766 : : offset = sizeof(struct roc_ipv6_hdr);
767 : :
768 [ # # ]: 0 : while (pattern->type != ROC_NPC_ITEM_TYPE_END) {
769 : : /* Don't support ranges */
770 [ # # ]: 0 : if (pattern->last != NULL)
771 : : return NPC_ERR_INVALID_RANGE;
772 : :
773 : : /* If spec is NULL, both mask and last must be NULL, this
774 : : * makes it to match ANY value (eq to mask = 0).
775 : : * Setting either mask or last without spec is
776 : : * an error
777 : : */
778 : 0 : if (pattern->spec == NULL) {
779 : : if (pattern->last != NULL && pattern->mask != NULL)
780 : : return NPC_ERR_INVALID_SPEC;
781 : : }
782 : : /* Either one ROC_NPC_ITEM_TYPE_IPV6_EXT or
783 : : * one ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT is supported
784 : : * following an ROC_NPC_ITEM_TYPE_IPV6 item.
785 : : */
786 [ # # ]: 0 : if (pattern->type == ROC_NPC_ITEM_TYPE_IPV6_EXT) {
787 : 0 : item_count++;
788 : : ltype = NPC_LT_LC_IP6_EXT;
789 : 0 : parse_info.len =
790 : : sizeof(struct roc_ipv6_hdr) + sizeof(struct roc_flow_item_ipv6_ext);
791 [ # # ]: 0 : if (pattern->spec)
792 : : memcpy(ipv6_hdr_buf + offset, pattern->spec,
793 : : sizeof(struct roc_flow_item_ipv6_ext));
794 [ # # ]: 0 : if (pattern->mask)
795 : : memcpy(ipv6_hdr_mask + offset, pattern->mask,
796 : : sizeof(struct roc_flow_item_ipv6_ext));
797 : : break;
798 [ # # ]: 0 : } else if (pattern->type == ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT) {
799 : 0 : item_count++;
800 : : ltype = NPC_LT_LC_IP6_EXT;
801 : 0 : flags = NPC_F_LC_U_IP6_FRAG;
802 : 0 : parse_info.len =
803 : : sizeof(struct roc_ipv6_hdr) + sizeof(struct roc_ipv6_fragment_ext);
804 [ # # ]: 0 : if (pattern->spec)
805 : : memcpy(ipv6_hdr_buf + offset, pattern->spec,
806 : : sizeof(struct roc_ipv6_fragment_ext));
807 [ # # ]: 0 : if (pattern->mask)
808 : : memcpy(ipv6_hdr_mask + offset, pattern->mask,
809 : : sizeof(struct roc_ipv6_fragment_ext));
810 : :
811 : : break;
812 [ # # ]: 0 : } else if (pattern->type == ROC_NPC_ITEM_TYPE_IPV6_ROUTING_EXT) {
813 : 0 : item_count++;
814 : : ltype = NPC_LT_LC_IP6_EXT;
815 : 0 : parse_info.len = sizeof(struct roc_ipv6_hdr) + pattern->size;
816 : :
817 [ # # ]: 0 : if (pattern->spec)
818 : 0 : memcpy(ipv6_hdr_buf + offset, pattern->spec, pattern->size);
819 [ # # ]: 0 : if (pattern->mask)
820 : 0 : memcpy(ipv6_hdr_mask + offset, pattern->mask, pattern->size);
821 : : break;
822 : : }
823 : :
824 : 0 : pattern++;
825 : 0 : pattern = npc_parse_skip_void_and_any_items(pattern);
826 : : }
827 : :
828 : : memset(hw_mask, 0, sizeof(hw_mask));
829 : :
830 : 0 : parse_info.hw_mask = &hw_mask;
831 : 0 : npc_get_hw_supp_mask(pst, &parse_info, lid, ltype);
832 : :
833 : 0 : rc = npc_mask_is_supported(parse_info.mask, parse_info.hw_mask, parse_info.len);
834 [ # # ]: 0 : if (!rc)
835 : : return NPC_ERR_INVALID_MASK;
836 : :
837 : 0 : rc = npc_update_parse_state(pst, &parse_info, lid, ltype, flags);
838 [ # # ]: 0 : if (rc)
839 : : return rc;
840 : :
841 [ # # ]: 0 : if (pst->npc->hash_extract_cap) {
842 : 0 : rc = npc_process_ipv6_field_hash(parse_info.spec, parse_info.mask, pst, ltype);
843 [ # # ]: 0 : if (rc)
844 : : return rc;
845 : : }
846 : :
847 : : /* npc_update_parse_state() increments pattern once.
848 : : * Check if additional increment is required.
849 : : */
850 [ # # ]: 0 : if (item_count == 2)
851 : 0 : pst->pattern++;
852 : :
853 : : return 0;
854 : : }
855 : :
856 : : int
857 : 0 : npc_parse_lc(struct npc_parse_state *pst)
858 : : {
859 : : const struct roc_npc_flow_item_raw *raw_spec;
860 : : uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
861 : : uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
862 : : uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
863 : : struct npc_parse_item_info info;
864 : : int rc, lid, lt, len = 0;
865 : : uint8_t flags = 0;
866 : :
867 [ # # ]: 0 : if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
868 : 0 : return npc_parse_mpls(pst, NPC_LID_LC);
869 : :
870 : 0 : info.def_mask = NULL;
871 : 0 : info.hw_mask = &hw_mask;
872 : 0 : info.spec = NULL;
873 : 0 : info.mask = NULL;
874 : 0 : info.hw_hdr_len = 0;
875 : : lid = NPC_LID_LC;
876 : :
877 [ # # # # : 0 : switch (pst->pattern->type) {
# # ]
878 : 0 : case ROC_NPC_ITEM_TYPE_IPV4:
879 : : lt = NPC_LT_LC_IP;
880 : 0 : info.len = pst->pattern->size;
881 : 0 : break;
882 : 0 : case ROC_NPC_ITEM_TYPE_IPV6:
883 : : case ROC_NPC_ITEM_TYPE_IPV6_EXT:
884 : : case ROC_NPC_ITEM_TYPE_IPV6_FRAG_EXT:
885 : : case ROC_NPC_ITEM_TYPE_IPV6_ROUTING_EXT:
886 : 0 : return npc_process_ipv6_item(pst);
887 : 0 : case ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4:
888 : : lt = NPC_LT_LC_ARP;
889 : 0 : info.len = pst->pattern->size;
890 : 0 : break;
891 : 0 : case ROC_NPC_ITEM_TYPE_L3_CUSTOM:
892 : : lt = NPC_LT_LC_CUSTOM0;
893 : 0 : info.len = pst->pattern->size;
894 : 0 : break;
895 : 0 : case ROC_NPC_ITEM_TYPE_RAW:
896 : 0 : raw_spec = pst->pattern->spec;
897 [ # # ]: 0 : if (!raw_spec->relative)
898 : : return 0;
899 : :
900 : 0 : len = raw_spec->length + raw_spec->offset;
901 [ # # ]: 0 : if (len > NPC_MAX_RAW_ITEM_LEN)
902 : : return -EINVAL;
903 : :
904 : 0 : npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
905 : : pst->pattern->spec,
906 : : (const struct roc_npc_flow_item_raw *)
907 : 0 : pst->pattern->mask,
908 : : &info, raw_spec_buf, raw_mask_buf);
909 : :
910 : : lid = NPC_LID_LC;
911 : : lt = NPC_LT_LC_NGIO;
912 : : info.hw_mask = &hw_mask;
913 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
914 : 0 : break;
915 : : default:
916 : : /* No match at this layer */
917 : : return 0;
918 : : }
919 : :
920 : : /* Identify if IP tunnels MPLS or IPv4/v6 */
921 : 0 : npc_check_lc_ip_tunnel(pst);
922 : :
923 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
924 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
925 : :
926 [ # # ]: 0 : if (rc != 0)
927 : : return rc;
928 : :
929 : 0 : return npc_update_parse_state(pst, &info, lid, lt, flags);
930 : : }
931 : :
932 : : int
933 : 0 : npc_parse_ld(struct npc_parse_state *pst)
934 : : {
935 : : char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
936 : : struct npc_parse_item_info info;
937 : : int lid, lt, lflags;
938 : : int rc;
939 : :
940 [ # # ]: 0 : if (pst->tunnel) {
941 : : /* We have already parsed MPLS or IPv4/v6 followed
942 : : * by MPLS or IPv4/v6. Subsequent TCP/UDP etc
943 : : * would be parsed as tunneled versions. Skip
944 : : * this layer, except for tunneled MPLS. If LC is
945 : : * MPLS, we have anyway skipped all stacked MPLS
946 : : * labels.
947 : : */
948 [ # # ]: 0 : if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
949 : 0 : return npc_parse_mpls(pst, NPC_LID_LD);
950 : : return 0;
951 : : }
952 : 0 : info.def_mask = NULL;
953 : 0 : info.hw_mask = &hw_mask;
954 : 0 : info.spec = NULL;
955 : 0 : info.mask = NULL;
956 : : info.len = 0;
957 : 0 : info.hw_hdr_len = 0;
958 : :
959 : : lid = NPC_LID_LD;
960 : : lflags = 0;
961 : :
962 [ # # # # : 0 : switch (pst->pattern->type) {
# # # #
# ]
963 : 0 : case ROC_NPC_ITEM_TYPE_ICMP:
964 [ # # ]: 0 : if (pst->lt[NPC_LID_LC] == NPC_LT_LC_IP6)
965 : : lt = NPC_LT_LD_ICMP6;
966 : : else
967 : : lt = NPC_LT_LD_ICMP;
968 : 0 : info.len = pst->pattern->size;
969 : 0 : break;
970 : 0 : case ROC_NPC_ITEM_TYPE_UDP:
971 : : lt = NPC_LT_LD_UDP;
972 : 0 : info.len = pst->pattern->size;
973 : 0 : break;
974 : 0 : case ROC_NPC_ITEM_TYPE_IGMP:
975 : : lt = NPC_LT_LD_IGMP;
976 : 0 : info.len = pst->pattern->size;
977 : 0 : break;
978 : 0 : case ROC_NPC_ITEM_TYPE_TCP:
979 : : lt = NPC_LT_LD_TCP;
980 : 0 : info.len = pst->pattern->size;
981 : 0 : break;
982 : 0 : case ROC_NPC_ITEM_TYPE_SCTP:
983 : : lt = NPC_LT_LD_SCTP;
984 : 0 : info.len = pst->pattern->size;
985 : 0 : break;
986 : 0 : case ROC_NPC_ITEM_TYPE_GRE:
987 : : lt = NPC_LT_LD_GRE;
988 : 0 : info.len = pst->pattern->size;
989 : 0 : pst->tunnel = 1;
990 : 0 : break;
991 : 0 : case ROC_NPC_ITEM_TYPE_GRE_KEY:
992 : : lt = NPC_LT_LD_GRE;
993 : 0 : info.len = pst->pattern->size;
994 : 0 : info.hw_hdr_len = 4;
995 : 0 : pst->tunnel = 1;
996 : 0 : break;
997 : 0 : case ROC_NPC_ITEM_TYPE_NVGRE:
998 : : lt = NPC_LT_LD_NVGRE;
999 : : lflags = NPC_F_GRE_NVGRE;
1000 : 0 : info.len = pst->pattern->size;
1001 : : /* Further IP/Ethernet are parsed as tunneled */
1002 : 0 : pst->tunnel = 1;
1003 : 0 : break;
1004 : : default:
1005 : : return 0;
1006 : : }
1007 : :
1008 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
1009 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
1010 [ # # ]: 0 : if (rc != 0)
1011 : : return rc;
1012 : :
1013 : 0 : return npc_update_parse_state(pst, &info, lid, lt, lflags);
1014 : : }
1015 : :
1016 : : int
1017 : 0 : npc_parse_le(struct npc_parse_state *pst)
1018 : : {
1019 : 0 : const struct roc_npc_item_info *pattern = pst->pattern;
1020 : : const struct roc_npc_item_esp_hdr *esp = NULL;
1021 : : char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
1022 : : struct npc_parse_item_info info;
1023 : : int lid, lt, lflags;
1024 : : int rc;
1025 : :
1026 [ # # ]: 0 : if (pst->tunnel)
1027 : : return 0;
1028 : :
1029 [ # # ]: 0 : if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
1030 : 0 : return npc_parse_mpls(pst, NPC_LID_LE);
1031 : :
1032 : 0 : info.spec = NULL;
1033 : 0 : info.mask = NULL;
1034 : 0 : info.hw_mask = NULL;
1035 : 0 : info.def_mask = NULL;
1036 : 0 : info.len = 0;
1037 : 0 : info.hw_hdr_len = 0;
1038 : : lid = NPC_LID_LE;
1039 : : lflags = 0;
1040 : :
1041 : : /* Ensure we are not matching anything in UDP */
1042 : 0 : rc = npc_parse_item_basic(pattern, &info);
1043 [ # # ]: 0 : if (rc)
1044 : : return rc;
1045 : :
1046 : 0 : info.hw_mask = &hw_mask;
1047 : 0 : pattern = npc_parse_skip_void_and_any_items(pattern);
1048 [ # # # # : 0 : switch (pattern->type) {
# # # ]
1049 : 0 : case ROC_NPC_ITEM_TYPE_VXLAN:
1050 : : lflags = NPC_F_UDP_VXLAN;
1051 : 0 : info.len = pattern->size;
1052 : : lt = NPC_LT_LE_VXLAN;
1053 : 0 : break;
1054 : 0 : case ROC_NPC_ITEM_TYPE_GTPC:
1055 : : lflags = NPC_F_UDP_GTP_GTPC;
1056 : 0 : info.len = pattern->size;
1057 : : lt = NPC_LT_LE_GTPC;
1058 : 0 : break;
1059 : 0 : case ROC_NPC_ITEM_TYPE_GTPU:
1060 : : lflags = NPC_F_UDP_GTP_GTPU_G_PDU;
1061 : 0 : info.len = pattern->size;
1062 : : lt = NPC_LT_LE_GTPU;
1063 : 0 : break;
1064 : 0 : case ROC_NPC_ITEM_TYPE_GENEVE:
1065 : : lflags = NPC_F_UDP_GENEVE;
1066 : 0 : info.len = pattern->size;
1067 : : lt = NPC_LT_LE_GENEVE;
1068 : 0 : break;
1069 : 0 : case ROC_NPC_ITEM_TYPE_VXLAN_GPE:
1070 : : lflags = NPC_F_UDP_VXLANGPE;
1071 : 0 : info.len = pattern->size;
1072 : : lt = NPC_LT_LE_VXLANGPE;
1073 : 0 : break;
1074 : 0 : case ROC_NPC_ITEM_TYPE_ESP:
1075 : : lt = NPC_LT_LE_ESP;
1076 : 0 : info.len = pst->pattern->size;
1077 : 0 : esp = (const struct roc_npc_item_esp_hdr *)pattern->spec;
1078 [ # # ]: 0 : if (esp)
1079 : 0 : pst->flow->spi_to_sa_info.spi = esp->spi;
1080 : : break;
1081 : : default:
1082 : : return 0;
1083 : : }
1084 : :
1085 : 0 : pst->tunnel = 1;
1086 : :
1087 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
1088 : 0 : rc = npc_parse_item_basic(pattern, &info);
1089 [ # # ]: 0 : if (rc != 0)
1090 : : return rc;
1091 : :
1092 : 0 : return npc_update_parse_state(pst, &info, lid, lt, lflags);
1093 : : }
1094 : :
1095 : : int
1096 : 0 : npc_parse_lf(struct npc_parse_state *pst)
1097 : : {
1098 : : const struct roc_npc_item_info *pattern, *last_pattern;
1099 : : char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
1100 : : const struct roc_npc_flow_item_eth *eth_item;
1101 : : struct npc_parse_item_info info;
1102 : : int lid, lt, lflags;
1103 : : int nr_vlans = 0;
1104 : : int rc;
1105 : :
1106 : : /* We hit this layer if there is a tunneling protocol */
1107 [ # # ]: 0 : if (!pst->tunnel)
1108 : : return 0;
1109 : :
1110 [ # # ]: 0 : if (pst->pattern->type != ROC_NPC_ITEM_TYPE_ETH)
1111 : : return 0;
1112 : :
1113 : : lid = NPC_LID_LF;
1114 : : lt = NPC_LT_LF_TU_ETHER;
1115 : : lflags = 0;
1116 : :
1117 : 0 : eth_item = pst->pattern->spec;
1118 : :
1119 : : /* No match support for vlan tags */
1120 : 0 : info.def_mask = NULL;
1121 : 0 : info.hw_mask = NULL;
1122 : 0 : info.len = sizeof(eth_item->hdr);
1123 : 0 : info.spec = NULL;
1124 : 0 : info.mask = NULL;
1125 : 0 : info.hw_hdr_len = 0;
1126 : :
1127 : : /* Look ahead and find out any VLAN tags. These can be
1128 : : * detected but no data matching is available.
1129 : : */
1130 : : last_pattern = pst->pattern;
1131 : 0 : pattern = pst->pattern + 1;
1132 : 0 : pattern = npc_parse_skip_void_and_any_items(pattern);
1133 [ # # ]: 0 : while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
1134 : 0 : nr_vlans++;
1135 : : last_pattern = pattern;
1136 : 0 : pattern++;
1137 : 0 : pattern = npc_parse_skip_void_and_any_items(pattern);
1138 : : }
1139 : : switch (nr_vlans) {
1140 : : case 0:
1141 : : break;
1142 : : case 1:
1143 : : lflags = NPC_F_TU_ETHER_CTAG;
1144 : : break;
1145 : : case 2:
1146 : : lflags = NPC_F_TU_ETHER_STAG_CTAG;
1147 : : break;
1148 : : default:
1149 : : return NPC_ERR_PATTERN_NOTSUP;
1150 : : }
1151 : :
1152 : 0 : info.hw_mask = &hw_mask;
1153 : 0 : info.len = sizeof(eth_item->hdr);
1154 : 0 : info.hw_hdr_len = 0;
1155 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
1156 : 0 : info.spec = NULL;
1157 : 0 : info.mask = NULL;
1158 : :
1159 [ # # # # ]: 0 : if (eth_item && eth_item->has_vlan)
1160 : 0 : pst->set_vlan_ltype_mask = true;
1161 : :
1162 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
1163 [ # # ]: 0 : if (rc != 0)
1164 : : return rc;
1165 : :
1166 : 0 : pst->pattern = last_pattern;
1167 : :
1168 : 0 : return npc_update_parse_state(pst, &info, lid, lt, lflags);
1169 : : }
1170 : :
1171 : : int
1172 : 0 : npc_parse_lg(struct npc_parse_state *pst)
1173 : : {
1174 : : char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
1175 : : struct npc_parse_item_info info;
1176 : : int lid, lt;
1177 : : int rc;
1178 : :
1179 [ # # ]: 0 : if (!pst->tunnel)
1180 : : return 0;
1181 : :
1182 : 0 : info.def_mask = NULL;
1183 : 0 : info.hw_mask = &hw_mask;
1184 : 0 : info.spec = NULL;
1185 : 0 : info.mask = NULL;
1186 : 0 : info.hw_hdr_len = 0;
1187 : : lid = NPC_LID_LG;
1188 : :
1189 [ # # ]: 0 : if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV4) {
1190 : : lt = NPC_LT_LG_TU_IP;
1191 : 0 : info.len = pst->pattern->size;
1192 [ # # ]: 0 : } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_IPV6) {
1193 : : lt = NPC_LT_LG_TU_IP6;
1194 : 0 : info.len = pst->pattern->size;
1195 : : } else {
1196 : : /* There is no tunneled IP header */
1197 : : return 0;
1198 : : }
1199 : :
1200 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
1201 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
1202 [ # # ]: 0 : if (rc != 0)
1203 : : return rc;
1204 : :
1205 : 0 : return npc_update_parse_state(pst, &info, lid, lt, 0);
1206 : : }
1207 : :
1208 : : int
1209 : 0 : npc_parse_lh(struct npc_parse_state *pst)
1210 : : {
1211 : : char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
1212 : : struct npc_parse_item_info info;
1213 : : int lid, lt;
1214 : : int rc;
1215 : :
1216 [ # # ]: 0 : if (!pst->tunnel)
1217 : : return 0;
1218 : :
1219 : 0 : info.def_mask = NULL;
1220 : 0 : info.hw_mask = &hw_mask;
1221 : 0 : info.spec = NULL;
1222 : 0 : info.mask = NULL;
1223 : 0 : info.hw_hdr_len = 0;
1224 : : lid = NPC_LID_LH;
1225 : :
1226 [ # # # # : 0 : switch (pst->pattern->type) {
# ]
1227 : 0 : case ROC_NPC_ITEM_TYPE_UDP:
1228 : : lt = NPC_LT_LH_TU_UDP;
1229 : 0 : info.len = pst->pattern->size;
1230 : 0 : break;
1231 : 0 : case ROC_NPC_ITEM_TYPE_TCP:
1232 : : lt = NPC_LT_LH_TU_TCP;
1233 : 0 : info.len = pst->pattern->size;
1234 : 0 : break;
1235 : 0 : case ROC_NPC_ITEM_TYPE_SCTP:
1236 : : lt = NPC_LT_LH_TU_SCTP;
1237 : 0 : info.len = pst->pattern->size;
1238 : 0 : break;
1239 : 0 : case ROC_NPC_ITEM_TYPE_ESP:
1240 : : lt = NPC_LT_LH_TU_ESP;
1241 : 0 : info.len = pst->pattern->size;
1242 : 0 : break;
1243 : : default:
1244 : : return 0;
1245 : : }
1246 : :
1247 : 0 : npc_get_hw_supp_mask(pst, &info, lid, lt);
1248 : 0 : rc = npc_parse_item_basic(pst->pattern, &info);
1249 [ # # ]: 0 : if (rc != 0)
1250 : : return rc;
1251 : :
1252 : 0 : return npc_update_parse_state(pst, &info, lid, lt, 0);
1253 : : }
|