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