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