xref: /dpdk/drivers/net/sfc/sfc_mae.c (revision 0cd91fd3)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2021 Xilinx, Inc.
4  * Copyright(c) 2019 Solarflare Communications Inc.
5  *
6  * This software was jointly developed between OKTET Labs (under contract
7  * for Solarflare) and Solarflare Communications, Inc.
8  */
9 
10 #include <stdbool.h>
11 
12 #include <rte_bitops.h>
13 #include <rte_common.h>
14 #include <rte_vxlan.h>
15 
16 #include "efx.h"
17 
18 #include "sfc.h"
19 #include "sfc_flow_tunnel.h"
20 #include "sfc_mae_counter.h"
21 #include "sfc_log.h"
22 #include "sfc_switch.h"
23 #include "sfc_service.h"
24 
25 static int
26 sfc_mae_assign_ethdev_mport(struct sfc_adapter *sa,
27 			    efx_mport_sel_t *mportp)
28 {
29 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
30 
31 	return efx_mae_mport_by_pcie_function(encp->enc_pf, encp->enc_vf,
32 					      mportp);
33 }
34 
35 static int
36 sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
37 			    efx_mport_sel_t *mportp)
38 {
39 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
40 	int rc = 0;
41 
42 	if (encp->enc_mae_admin) {
43 		/*
44 		 * This ethdev sits on MAE admin PF. The represented
45 		 * entity is the network port assigned to that PF.
46 		 */
47 		rc = efx_mae_mport_by_phy_port(encp->enc_assigned_port, mportp);
48 	} else {
49 		/*
50 		 * This ethdev sits on unprivileged PF / VF. The entity
51 		 * represented by the ethdev can change dynamically
52 		 * as MAE admin changes default traffic rules.
53 		 *
54 		 * For the sake of simplicity, do not fill in the m-port
55 		 * and assume that flow rules should not be allowed to
56 		 * reference the entity represented by this ethdev.
57 		 */
58 		efx_mae_mport_invalid(mportp);
59 	}
60 
61 	return rc;
62 }
63 
64 static int
65 sfc_mae_counter_registry_init(struct sfc_mae_counter_registry *registry,
66 			      uint32_t nb_counters_max)
67 {
68 	return sfc_mae_counters_init(&registry->counters, nb_counters_max);
69 }
70 
71 static void
72 sfc_mae_counter_registry_fini(struct sfc_mae_counter_registry *registry)
73 {
74 	sfc_mae_counters_fini(&registry->counters);
75 }
76 
77 static int
78 sfc_mae_internal_rule_find_empty_slot(struct sfc_adapter *sa,
79 				      struct sfc_mae_rule **rule)
80 {
81 	struct sfc_mae *mae = &sa->mae;
82 	struct sfc_mae_internal_rules *internal_rules = &mae->internal_rules;
83 	unsigned int entry;
84 	int rc;
85 
86 	for (entry = 0; entry < SFC_MAE_NB_RULES_MAX; entry++) {
87 		if (internal_rules->rules[entry].spec == NULL)
88 			break;
89 	}
90 
91 	if (entry == SFC_MAE_NB_RULES_MAX) {
92 		rc = ENOSPC;
93 		sfc_err(sa, "failed too many rules (%u rules used)", entry);
94 		goto fail_too_many_rules;
95 	}
96 
97 	*rule = &internal_rules->rules[entry];
98 
99 	return 0;
100 
101 fail_too_many_rules:
102 	return rc;
103 }
104 
105 int
106 sfc_mae_rule_add_mport_match_deliver(struct sfc_adapter *sa,
107 				     const efx_mport_sel_t *mport_match,
108 				     const efx_mport_sel_t *mport_deliver,
109 				     int prio, struct sfc_mae_rule **rulep)
110 {
111 	struct sfc_mae *mae = &sa->mae;
112 	struct sfc_mae_rule *rule;
113 	int rc;
114 
115 	sfc_log_init(sa, "entry");
116 
117 	if (prio > 0 && (unsigned int)prio >= mae->nb_action_rule_prios_max) {
118 		rc = EINVAL;
119 		sfc_err(sa, "failed: invalid priority %d (max %u)", prio,
120 			mae->nb_action_rule_prios_max);
121 		goto fail_invalid_prio;
122 	}
123 	if (prio < 0)
124 		prio = mae->nb_action_rule_prios_max - 1;
125 
126 	rc = sfc_mae_internal_rule_find_empty_slot(sa, &rule);
127 	if (rc != 0)
128 		goto fail_find_empty_slot;
129 
130 	sfc_log_init(sa, "init MAE match spec");
131 	rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
132 				     (uint32_t)prio, &rule->spec);
133 	if (rc != 0) {
134 		sfc_err(sa, "failed to init MAE match spec");
135 		goto fail_match_init;
136 	}
137 
138 	rc = efx_mae_match_spec_mport_set(rule->spec, mport_match, NULL);
139 	if (rc != 0) {
140 		sfc_err(sa, "failed to get MAE match mport selector");
141 		goto fail_mport_set;
142 	}
143 
144 	rc = efx_mae_action_set_spec_init(sa->nic, &rule->actions);
145 	if (rc != 0) {
146 		sfc_err(sa, "failed to init MAE action set");
147 		goto fail_action_init;
148 	}
149 
150 	rc = efx_mae_action_set_populate_deliver(rule->actions,
151 						 mport_deliver);
152 	if (rc != 0) {
153 		sfc_err(sa, "failed to populate deliver action");
154 		goto fail_populate_deliver;
155 	}
156 
157 	rc = efx_mae_action_set_alloc(sa->nic, rule->actions,
158 				      &rule->action_set);
159 	if (rc != 0) {
160 		sfc_err(sa, "failed to allocate action set");
161 		goto fail_action_set_alloc;
162 	}
163 
164 	rc = efx_mae_action_rule_insert(sa->nic, rule->spec, NULL,
165 					&rule->action_set,
166 					&rule->rule_id);
167 	if (rc != 0) {
168 		sfc_err(sa, "failed to insert action rule");
169 		goto fail_rule_insert;
170 	}
171 
172 	*rulep = rule;
173 
174 	sfc_log_init(sa, "done");
175 
176 	return 0;
177 
178 fail_rule_insert:
179 	efx_mae_action_set_free(sa->nic, &rule->action_set);
180 
181 fail_action_set_alloc:
182 fail_populate_deliver:
183 	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
184 
185 fail_action_init:
186 fail_mport_set:
187 	efx_mae_match_spec_fini(sa->nic, rule->spec);
188 
189 fail_match_init:
190 fail_find_empty_slot:
191 fail_invalid_prio:
192 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
193 	return rc;
194 }
195 
196 void
197 sfc_mae_rule_del(struct sfc_adapter *sa, struct sfc_mae_rule *rule)
198 {
199 	if (rule == NULL || rule->spec == NULL)
200 		return;
201 
202 	efx_mae_action_rule_remove(sa->nic, &rule->rule_id);
203 	efx_mae_action_set_free(sa->nic, &rule->action_set);
204 	efx_mae_action_set_spec_fini(sa->nic, rule->actions);
205 	efx_mae_match_spec_fini(sa->nic, rule->spec);
206 
207 	rule->spec = NULL;
208 }
209 
210 int
211 sfc_mae_attach(struct sfc_adapter *sa)
212 {
213 	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
214 	struct sfc_mae_switch_port_request switch_port_request = {0};
215 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
216 	efx_mport_sel_t ethdev_mport;
217 	efx_mport_sel_t entity_mport;
218 	struct sfc_mae *mae = &sa->mae;
219 	struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
220 	efx_mae_limits_t limits;
221 	int rc;
222 
223 	sfc_log_init(sa, "entry");
224 
225 	if (!encp->enc_mae_supported) {
226 		mae->status = SFC_MAE_STATUS_UNSUPPORTED;
227 		return 0;
228 	}
229 
230 	if (encp->enc_mae_admin) {
231 		sfc_log_init(sa, "init MAE");
232 		rc = efx_mae_init(sa->nic);
233 		if (rc != 0)
234 			goto fail_mae_init;
235 
236 		sfc_log_init(sa, "get MAE limits");
237 		rc = efx_mae_get_limits(sa->nic, &limits);
238 		if (rc != 0)
239 			goto fail_mae_get_limits;
240 
241 		sfc_log_init(sa, "init MAE counter registry");
242 		rc = sfc_mae_counter_registry_init(&mae->counter_registry,
243 						   limits.eml_max_n_counters);
244 		if (rc != 0) {
245 			sfc_err(sa, "failed to init MAE counters registry for %u entries: %s",
246 				limits.eml_max_n_counters, rte_strerror(rc));
247 			goto fail_counter_registry_init;
248 		}
249 	}
250 
251 	sfc_log_init(sa, "assign ethdev MPORT");
252 	rc = sfc_mae_assign_ethdev_mport(sa, &ethdev_mport);
253 	if (rc != 0)
254 		goto fail_mae_assign_ethdev_mport;
255 
256 	sfc_log_init(sa, "assign entity MPORT");
257 	rc = sfc_mae_assign_entity_mport(sa, &entity_mport);
258 	if (rc != 0)
259 		goto fail_mae_assign_entity_mport;
260 
261 	sfc_log_init(sa, "assign RTE switch domain");
262 	rc = sfc_mae_assign_switch_domain(sa, &mae->switch_domain_id);
263 	if (rc != 0)
264 		goto fail_mae_assign_switch_domain;
265 
266 	sfc_log_init(sa, "assign RTE switch port");
267 	switch_port_request.type = SFC_MAE_SWITCH_PORT_INDEPENDENT;
268 	switch_port_request.ethdev_mportp = &ethdev_mport;
269 	switch_port_request.entity_mportp = &entity_mport;
270 	switch_port_request.ethdev_port_id = sas->port_id;
271 	switch_port_request.port_data.indep.mae_admin =
272 		encp->enc_mae_admin == B_TRUE;
273 	rc = sfc_mae_assign_switch_port(mae->switch_domain_id,
274 					&switch_port_request,
275 					&mae->switch_port_id);
276 	if (rc != 0)
277 		goto fail_mae_assign_switch_port;
278 
279 	if (encp->enc_mae_admin) {
280 		sfc_log_init(sa, "allocate encap. header bounce buffer");
281 		bounce_eh->buf_size = limits.eml_encap_header_size_limit;
282 		bounce_eh->buf = rte_malloc("sfc_mae_bounce_eh",
283 					    bounce_eh->buf_size, 0);
284 		if (bounce_eh->buf == NULL)
285 			goto fail_mae_alloc_bounce_eh;
286 
287 		mae->nb_outer_rule_prios_max = limits.eml_max_n_outer_prios;
288 		mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
289 		mae->encap_types_supported = limits.eml_encap_types_supported;
290 	}
291 
292 	TAILQ_INIT(&mae->outer_rules);
293 	TAILQ_INIT(&mae->encap_headers);
294 	TAILQ_INIT(&mae->action_sets);
295 
296 	if (encp->enc_mae_admin)
297 		mae->status = SFC_MAE_STATUS_ADMIN;
298 	else
299 		mae->status = SFC_MAE_STATUS_SUPPORTED;
300 
301 	sfc_log_init(sa, "done");
302 
303 	return 0;
304 
305 fail_mae_alloc_bounce_eh:
306 fail_mae_assign_switch_port:
307 fail_mae_assign_switch_domain:
308 fail_mae_assign_entity_mport:
309 fail_mae_assign_ethdev_mport:
310 	if (encp->enc_mae_admin)
311 		sfc_mae_counter_registry_fini(&mae->counter_registry);
312 
313 fail_counter_registry_init:
314 fail_mae_get_limits:
315 	if (encp->enc_mae_admin)
316 		efx_mae_fini(sa->nic);
317 
318 fail_mae_init:
319 	sfc_log_init(sa, "failed %d", rc);
320 
321 	return rc;
322 }
323 
324 void
325 sfc_mae_detach(struct sfc_adapter *sa)
326 {
327 	struct sfc_mae *mae = &sa->mae;
328 	enum sfc_mae_status status_prev = mae->status;
329 
330 	sfc_log_init(sa, "entry");
331 
332 	mae->nb_action_rule_prios_max = 0;
333 	mae->status = SFC_MAE_STATUS_UNKNOWN;
334 
335 	if (status_prev != SFC_MAE_STATUS_ADMIN)
336 		return;
337 
338 	rte_free(mae->bounce_eh.buf);
339 	sfc_mae_counter_registry_fini(&mae->counter_registry);
340 
341 	efx_mae_fini(sa->nic);
342 
343 	sfc_log_init(sa, "done");
344 }
345 
346 static struct sfc_mae_outer_rule *
347 sfc_mae_outer_rule_attach(struct sfc_adapter *sa,
348 			  const efx_mae_match_spec_t *match_spec,
349 			  efx_tunnel_protocol_t encap_type)
350 {
351 	struct sfc_mae_outer_rule *rule;
352 	struct sfc_mae *mae = &sa->mae;
353 
354 	SFC_ASSERT(sfc_adapter_is_locked(sa));
355 
356 	TAILQ_FOREACH(rule, &mae->outer_rules, entries) {
357 		if (efx_mae_match_specs_equal(rule->match_spec, match_spec) &&
358 		    rule->encap_type == encap_type) {
359 			sfc_dbg(sa, "attaching to outer_rule=%p", rule);
360 			++(rule->refcnt);
361 			return rule;
362 		}
363 	}
364 
365 	return NULL;
366 }
367 
368 static int
369 sfc_mae_outer_rule_add(struct sfc_adapter *sa,
370 		       efx_mae_match_spec_t *match_spec,
371 		       efx_tunnel_protocol_t encap_type,
372 		       struct sfc_mae_outer_rule **rulep)
373 {
374 	struct sfc_mae_outer_rule *rule;
375 	struct sfc_mae *mae = &sa->mae;
376 
377 	SFC_ASSERT(sfc_adapter_is_locked(sa));
378 
379 	rule = rte_zmalloc("sfc_mae_outer_rule", sizeof(*rule), 0);
380 	if (rule == NULL)
381 		return ENOMEM;
382 
383 	rule->refcnt = 1;
384 	rule->match_spec = match_spec;
385 	rule->encap_type = encap_type;
386 
387 	rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
388 
389 	TAILQ_INSERT_TAIL(&mae->outer_rules, rule, entries);
390 
391 	*rulep = rule;
392 
393 	sfc_dbg(sa, "added outer_rule=%p", rule);
394 
395 	return 0;
396 }
397 
398 static void
399 sfc_mae_outer_rule_del(struct sfc_adapter *sa,
400 		       struct sfc_mae_outer_rule *rule)
401 {
402 	struct sfc_mae *mae = &sa->mae;
403 
404 	SFC_ASSERT(sfc_adapter_is_locked(sa));
405 	SFC_ASSERT(rule->refcnt != 0);
406 
407 	--(rule->refcnt);
408 
409 	if (rule->refcnt != 0)
410 		return;
411 
412 	if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||
413 	    rule->fw_rsrc.refcnt != 0) {
414 		sfc_err(sa, "deleting outer_rule=%p abandons its FW resource: OR_ID=0x%08x, refcnt=%u",
415 			rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);
416 	}
417 
418 	efx_mae_match_spec_fini(sa->nic, rule->match_spec);
419 
420 	TAILQ_REMOVE(&mae->outer_rules, rule, entries);
421 	rte_free(rule);
422 
423 	sfc_dbg(sa, "deleted outer_rule=%p", rule);
424 }
425 
426 static int
427 sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
428 			  struct sfc_mae_outer_rule *rule,
429 			  efx_mae_match_spec_t *match_spec_action)
430 {
431 	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
432 	int rc;
433 
434 	SFC_ASSERT(sfc_adapter_is_locked(sa));
435 
436 	if (fw_rsrc->refcnt == 0) {
437 		SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
438 		SFC_ASSERT(rule->match_spec != NULL);
439 
440 		rc = efx_mae_outer_rule_insert(sa->nic, rule->match_spec,
441 					       rule->encap_type,
442 					       &fw_rsrc->rule_id);
443 		if (rc != 0) {
444 			sfc_err(sa, "failed to enable outer_rule=%p: %s",
445 				rule, strerror(rc));
446 			return rc;
447 		}
448 	}
449 
450 	if (match_spec_action == NULL)
451 		goto skip_action_rule;
452 
453 	rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
454 						  &fw_rsrc->rule_id);
455 	if (rc != 0) {
456 		if (fw_rsrc->refcnt == 0) {
457 			(void)efx_mae_outer_rule_remove(sa->nic,
458 							&fw_rsrc->rule_id);
459 			fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
460 		}
461 
462 		sfc_err(sa, "can't match on outer rule ID: %s", strerror(rc));
463 
464 		return rc;
465 	}
466 
467 skip_action_rule:
468 	if (fw_rsrc->refcnt == 0) {
469 		sfc_dbg(sa, "enabled outer_rule=%p: OR_ID=0x%08x",
470 			rule, fw_rsrc->rule_id.id);
471 	}
472 
473 	++(fw_rsrc->refcnt);
474 
475 	return 0;
476 }
477 
478 static void
479 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
480 			   struct sfc_mae_outer_rule *rule)
481 {
482 	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
483 	int rc;
484 
485 	SFC_ASSERT(sfc_adapter_is_locked(sa));
486 
487 	if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
488 	    fw_rsrc->refcnt == 0) {
489 		sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
490 			rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);
491 		return;
492 	}
493 
494 	if (fw_rsrc->refcnt == 1) {
495 		rc = efx_mae_outer_rule_remove(sa->nic, &fw_rsrc->rule_id);
496 		if (rc == 0) {
497 			sfc_dbg(sa, "disabled outer_rule=%p with OR_ID=0x%08x",
498 				rule, fw_rsrc->rule_id.id);
499 		} else {
500 			sfc_err(sa, "failed to disable outer_rule=%p with OR_ID=0x%08x: %s",
501 				rule, fw_rsrc->rule_id.id, strerror(rc));
502 		}
503 		fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
504 	}
505 
506 	--(fw_rsrc->refcnt);
507 }
508 
509 static struct sfc_mae_encap_header *
510 sfc_mae_encap_header_attach(struct sfc_adapter *sa,
511 			    const struct sfc_mae_bounce_eh *bounce_eh)
512 {
513 	struct sfc_mae_encap_header *encap_header;
514 	struct sfc_mae *mae = &sa->mae;
515 
516 	SFC_ASSERT(sfc_adapter_is_locked(sa));
517 
518 	TAILQ_FOREACH(encap_header, &mae->encap_headers, entries) {
519 		if (encap_header->size == bounce_eh->size &&
520 		    memcmp(encap_header->buf, bounce_eh->buf,
521 			   bounce_eh->size) == 0) {
522 			sfc_dbg(sa, "attaching to encap_header=%p",
523 				encap_header);
524 			++(encap_header->refcnt);
525 			return encap_header;
526 		}
527 	}
528 
529 	return NULL;
530 }
531 
532 static int
533 sfc_mae_encap_header_add(struct sfc_adapter *sa,
534 			 const struct sfc_mae_bounce_eh *bounce_eh,
535 			 struct sfc_mae_encap_header **encap_headerp)
536 {
537 	struct sfc_mae_encap_header *encap_header;
538 	struct sfc_mae *mae = &sa->mae;
539 
540 	SFC_ASSERT(sfc_adapter_is_locked(sa));
541 
542 	encap_header = rte_zmalloc("sfc_mae_encap_header",
543 				   sizeof(*encap_header), 0);
544 	if (encap_header == NULL)
545 		return ENOMEM;
546 
547 	encap_header->size = bounce_eh->size;
548 
549 	encap_header->buf = rte_malloc("sfc_mae_encap_header_buf",
550 				       encap_header->size, 0);
551 	if (encap_header->buf == NULL) {
552 		rte_free(encap_header);
553 		return ENOMEM;
554 	}
555 
556 	rte_memcpy(encap_header->buf, bounce_eh->buf, bounce_eh->size);
557 
558 	encap_header->refcnt = 1;
559 	encap_header->type = bounce_eh->type;
560 	encap_header->fw_rsrc.eh_id.id = EFX_MAE_RSRC_ID_INVALID;
561 
562 	TAILQ_INSERT_TAIL(&mae->encap_headers, encap_header, entries);
563 
564 	*encap_headerp = encap_header;
565 
566 	sfc_dbg(sa, "added encap_header=%p", encap_header);
567 
568 	return 0;
569 }
570 
571 static void
572 sfc_mae_encap_header_del(struct sfc_adapter *sa,
573 		       struct sfc_mae_encap_header *encap_header)
574 {
575 	struct sfc_mae *mae = &sa->mae;
576 
577 	if (encap_header == NULL)
578 		return;
579 
580 	SFC_ASSERT(sfc_adapter_is_locked(sa));
581 	SFC_ASSERT(encap_header->refcnt != 0);
582 
583 	--(encap_header->refcnt);
584 
585 	if (encap_header->refcnt != 0)
586 		return;
587 
588 	if (encap_header->fw_rsrc.eh_id.id != EFX_MAE_RSRC_ID_INVALID ||
589 	    encap_header->fw_rsrc.refcnt != 0) {
590 		sfc_err(sa, "deleting encap_header=%p abandons its FW resource: EH_ID=0x%08x, refcnt=%u",
591 			encap_header, encap_header->fw_rsrc.eh_id.id,
592 			encap_header->fw_rsrc.refcnt);
593 	}
594 
595 	TAILQ_REMOVE(&mae->encap_headers, encap_header, entries);
596 	rte_free(encap_header->buf);
597 	rte_free(encap_header);
598 
599 	sfc_dbg(sa, "deleted encap_header=%p", encap_header);
600 }
601 
602 static int
603 sfc_mae_encap_header_enable(struct sfc_adapter *sa,
604 			    struct sfc_mae_encap_header *encap_header,
605 			    efx_mae_actions_t *action_set_spec)
606 {
607 	struct sfc_mae_fw_rsrc *fw_rsrc;
608 	int rc;
609 
610 	if (encap_header == NULL)
611 		return 0;
612 
613 	SFC_ASSERT(sfc_adapter_is_locked(sa));
614 
615 	fw_rsrc = &encap_header->fw_rsrc;
616 
617 	if (fw_rsrc->refcnt == 0) {
618 		SFC_ASSERT(fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID);
619 		SFC_ASSERT(encap_header->buf != NULL);
620 		SFC_ASSERT(encap_header->size != 0);
621 
622 		rc = efx_mae_encap_header_alloc(sa->nic, encap_header->type,
623 						encap_header->buf,
624 						encap_header->size,
625 						&fw_rsrc->eh_id);
626 		if (rc != 0) {
627 			sfc_err(sa, "failed to enable encap_header=%p: %s",
628 				encap_header, strerror(rc));
629 			return rc;
630 		}
631 	}
632 
633 	rc = efx_mae_action_set_fill_in_eh_id(action_set_spec,
634 					      &fw_rsrc->eh_id);
635 	if (rc != 0) {
636 		if (fw_rsrc->refcnt == 0) {
637 			(void)efx_mae_encap_header_free(sa->nic,
638 							&fw_rsrc->eh_id);
639 			fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID;
640 		}
641 
642 		sfc_err(sa, "can't fill in encap. header ID: %s", strerror(rc));
643 
644 		return rc;
645 	}
646 
647 	if (fw_rsrc->refcnt == 0) {
648 		sfc_dbg(sa, "enabled encap_header=%p: EH_ID=0x%08x",
649 			encap_header, fw_rsrc->eh_id.id);
650 	}
651 
652 	++(fw_rsrc->refcnt);
653 
654 	return 0;
655 }
656 
657 static void
658 sfc_mae_encap_header_disable(struct sfc_adapter *sa,
659 			     struct sfc_mae_encap_header *encap_header)
660 {
661 	struct sfc_mae_fw_rsrc *fw_rsrc;
662 	int rc;
663 
664 	if (encap_header == NULL)
665 		return;
666 
667 	SFC_ASSERT(sfc_adapter_is_locked(sa));
668 
669 	fw_rsrc = &encap_header->fw_rsrc;
670 
671 	if (fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID ||
672 	    fw_rsrc->refcnt == 0) {
673 		sfc_err(sa, "failed to disable encap_header=%p: already disabled; EH_ID=0x%08x, refcnt=%u",
674 			encap_header, fw_rsrc->eh_id.id, fw_rsrc->refcnt);
675 		return;
676 	}
677 
678 	if (fw_rsrc->refcnt == 1) {
679 		rc = efx_mae_encap_header_free(sa->nic, &fw_rsrc->eh_id);
680 		if (rc == 0) {
681 			sfc_dbg(sa, "disabled encap_header=%p with EH_ID=0x%08x",
682 				encap_header, fw_rsrc->eh_id.id);
683 		} else {
684 			sfc_err(sa, "failed to disable encap_header=%p with EH_ID=0x%08x: %s",
685 				encap_header, fw_rsrc->eh_id.id, strerror(rc));
686 		}
687 		fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID;
688 	}
689 
690 	--(fw_rsrc->refcnt);
691 }
692 
693 static int
694 sfc_mae_counters_enable(struct sfc_adapter *sa,
695 			struct sfc_mae_counter_id *counters,
696 			unsigned int n_counters,
697 			efx_mae_actions_t *action_set_spec)
698 {
699 	int rc;
700 
701 	sfc_log_init(sa, "entry");
702 
703 	if (n_counters == 0) {
704 		sfc_log_init(sa, "no counters - skip");
705 		return 0;
706 	}
707 
708 	SFC_ASSERT(sfc_adapter_is_locked(sa));
709 	SFC_ASSERT(n_counters == 1);
710 
711 	rc = sfc_mae_counter_enable(sa, &counters[0]);
712 	if (rc != 0) {
713 		sfc_err(sa, "failed to enable MAE counter %u: %s",
714 			counters[0].mae_id.id, rte_strerror(rc));
715 		goto fail_counter_add;
716 	}
717 
718 	rc = efx_mae_action_set_fill_in_counter_id(action_set_spec,
719 						   &counters[0].mae_id);
720 	if (rc != 0) {
721 		sfc_err(sa, "failed to fill in MAE counter %u in action set: %s",
722 			counters[0].mae_id.id, rte_strerror(rc));
723 		goto fail_fill_in_id;
724 	}
725 
726 	return 0;
727 
728 fail_fill_in_id:
729 	(void)sfc_mae_counter_disable(sa, &counters[0]);
730 
731 fail_counter_add:
732 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
733 	return rc;
734 }
735 
736 static int
737 sfc_mae_counters_disable(struct sfc_adapter *sa,
738 			 struct sfc_mae_counter_id *counters,
739 			 unsigned int n_counters)
740 {
741 	if (n_counters == 0)
742 		return 0;
743 
744 	SFC_ASSERT(sfc_adapter_is_locked(sa));
745 	SFC_ASSERT(n_counters == 1);
746 
747 	if (counters[0].mae_id.id == EFX_MAE_RSRC_ID_INVALID) {
748 		sfc_err(sa, "failed to disable: already disabled");
749 		return EALREADY;
750 	}
751 
752 	return sfc_mae_counter_disable(sa, &counters[0]);
753 }
754 
755 static struct sfc_mae_action_set *
756 sfc_mae_action_set_attach(struct sfc_adapter *sa,
757 			  const struct sfc_mae_encap_header *encap_header,
758 			  unsigned int n_count,
759 			  const efx_mae_actions_t *spec)
760 {
761 	struct sfc_mae_action_set *action_set;
762 	struct sfc_mae *mae = &sa->mae;
763 
764 	SFC_ASSERT(sfc_adapter_is_locked(sa));
765 
766 	TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
767 		/*
768 		 * Shared counters are not supported, hence action sets with
769 		 * COUNT are not attachable.
770 		 */
771 		if (action_set->encap_header == encap_header &&
772 		    n_count == 0 &&
773 		    efx_mae_action_set_specs_equal(action_set->spec, spec)) {
774 			sfc_dbg(sa, "attaching to action_set=%p", action_set);
775 			++(action_set->refcnt);
776 			return action_set;
777 		}
778 	}
779 
780 	return NULL;
781 }
782 
783 static int
784 sfc_mae_action_set_add(struct sfc_adapter *sa,
785 		       const struct rte_flow_action actions[],
786 		       efx_mae_actions_t *spec,
787 		       struct sfc_mae_encap_header *encap_header,
788 		       uint64_t *ft_group_hit_counter,
789 		       struct sfc_flow_tunnel *ft,
790 		       unsigned int n_counters,
791 		       struct sfc_mae_action_set **action_setp)
792 {
793 	struct sfc_mae_action_set *action_set;
794 	struct sfc_mae *mae = &sa->mae;
795 	unsigned int i;
796 
797 	SFC_ASSERT(sfc_adapter_is_locked(sa));
798 
799 	action_set = rte_zmalloc("sfc_mae_action_set", sizeof(*action_set), 0);
800 	if (action_set == NULL) {
801 		sfc_err(sa, "failed to alloc action set");
802 		return ENOMEM;
803 	}
804 
805 	if (n_counters > 0) {
806 		const struct rte_flow_action *action;
807 
808 		action_set->counters = rte_malloc("sfc_mae_counter_ids",
809 			sizeof(action_set->counters[0]) * n_counters, 0);
810 		if (action_set->counters == NULL) {
811 			rte_free(action_set);
812 			sfc_err(sa, "failed to alloc counters");
813 			return ENOMEM;
814 		}
815 
816 		for (i = 0; i < n_counters; ++i) {
817 			action_set->counters[i].rte_id_valid = B_FALSE;
818 			action_set->counters[i].mae_id.id =
819 				EFX_MAE_RSRC_ID_INVALID;
820 
821 			action_set->counters[i].ft_group_hit_counter =
822 				ft_group_hit_counter;
823 			action_set->counters[i].ft = ft;
824 		}
825 
826 		for (action = actions, i = 0;
827 		     action->type != RTE_FLOW_ACTION_TYPE_END && i < n_counters;
828 		     ++action) {
829 			const struct rte_flow_action_count *conf;
830 
831 			if (action->type != RTE_FLOW_ACTION_TYPE_COUNT)
832 				continue;
833 
834 			conf = action->conf;
835 
836 			action_set->counters[i].rte_id_valid = B_TRUE;
837 			action_set->counters[i].rte_id = conf->id;
838 			i++;
839 		}
840 		action_set->n_counters = n_counters;
841 	}
842 
843 	action_set->refcnt = 1;
844 	action_set->spec = spec;
845 	action_set->encap_header = encap_header;
846 
847 	action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
848 
849 	TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
850 
851 	*action_setp = action_set;
852 
853 	sfc_dbg(sa, "added action_set=%p", action_set);
854 
855 	return 0;
856 }
857 
858 static void
859 sfc_mae_action_set_del(struct sfc_adapter *sa,
860 		       struct sfc_mae_action_set *action_set)
861 {
862 	struct sfc_mae *mae = &sa->mae;
863 
864 	SFC_ASSERT(sfc_adapter_is_locked(sa));
865 	SFC_ASSERT(action_set->refcnt != 0);
866 
867 	--(action_set->refcnt);
868 
869 	if (action_set->refcnt != 0)
870 		return;
871 
872 	if (action_set->fw_rsrc.aset_id.id != EFX_MAE_RSRC_ID_INVALID ||
873 	    action_set->fw_rsrc.refcnt != 0) {
874 		sfc_err(sa, "deleting action_set=%p abandons its FW resource: AS_ID=0x%08x, refcnt=%u",
875 			action_set, action_set->fw_rsrc.aset_id.id,
876 			action_set->fw_rsrc.refcnt);
877 	}
878 
879 	efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
880 	sfc_mae_encap_header_del(sa, action_set->encap_header);
881 	if (action_set->n_counters > 0) {
882 		SFC_ASSERT(action_set->n_counters == 1);
883 		SFC_ASSERT(action_set->counters[0].mae_id.id ==
884 			   EFX_MAE_RSRC_ID_INVALID);
885 		rte_free(action_set->counters);
886 	}
887 	TAILQ_REMOVE(&mae->action_sets, action_set, entries);
888 	rte_free(action_set);
889 
890 	sfc_dbg(sa, "deleted action_set=%p", action_set);
891 }
892 
893 static int
894 sfc_mae_action_set_enable(struct sfc_adapter *sa,
895 			  struct sfc_mae_action_set *action_set)
896 {
897 	struct sfc_mae_encap_header *encap_header = action_set->encap_header;
898 	struct sfc_mae_counter_id *counters = action_set->counters;
899 	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
900 	int rc;
901 
902 	SFC_ASSERT(sfc_adapter_is_locked(sa));
903 
904 	if (fw_rsrc->refcnt == 0) {
905 		SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
906 		SFC_ASSERT(action_set->spec != NULL);
907 
908 		rc = sfc_mae_encap_header_enable(sa, encap_header,
909 						 action_set->spec);
910 		if (rc != 0)
911 			return rc;
912 
913 		rc = sfc_mae_counters_enable(sa, counters,
914 					     action_set->n_counters,
915 					     action_set->spec);
916 		if (rc != 0) {
917 			sfc_err(sa, "failed to enable %u MAE counters: %s",
918 				action_set->n_counters, rte_strerror(rc));
919 
920 			sfc_mae_encap_header_disable(sa, encap_header);
921 			return rc;
922 		}
923 
924 		rc = efx_mae_action_set_alloc(sa->nic, action_set->spec,
925 					      &fw_rsrc->aset_id);
926 		if (rc != 0) {
927 			sfc_err(sa, "failed to enable action_set=%p: %s",
928 				action_set, strerror(rc));
929 
930 			(void)sfc_mae_counters_disable(sa, counters,
931 						       action_set->n_counters);
932 			sfc_mae_encap_header_disable(sa, encap_header);
933 			return rc;
934 		}
935 
936 		sfc_dbg(sa, "enabled action_set=%p: AS_ID=0x%08x",
937 			action_set, fw_rsrc->aset_id.id);
938 	}
939 
940 	++(fw_rsrc->refcnt);
941 
942 	return 0;
943 }
944 
945 static void
946 sfc_mae_action_set_disable(struct sfc_adapter *sa,
947 			   struct sfc_mae_action_set *action_set)
948 {
949 	struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
950 	int rc;
951 
952 	SFC_ASSERT(sfc_adapter_is_locked(sa));
953 
954 	if (fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID ||
955 	    fw_rsrc->refcnt == 0) {
956 		sfc_err(sa, "failed to disable action_set=%p: already disabled; AS_ID=0x%08x, refcnt=%u",
957 			action_set, fw_rsrc->aset_id.id, fw_rsrc->refcnt);
958 		return;
959 	}
960 
961 	if (fw_rsrc->refcnt == 1) {
962 		rc = efx_mae_action_set_free(sa->nic, &fw_rsrc->aset_id);
963 		if (rc == 0) {
964 			sfc_dbg(sa, "disabled action_set=%p with AS_ID=0x%08x",
965 				action_set, fw_rsrc->aset_id.id);
966 		} else {
967 			sfc_err(sa, "failed to disable action_set=%p with AS_ID=0x%08x: %s",
968 				action_set, fw_rsrc->aset_id.id, strerror(rc));
969 		}
970 		fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
971 
972 		rc = sfc_mae_counters_disable(sa, action_set->counters,
973 					      action_set->n_counters);
974 		if (rc != 0) {
975 			sfc_err(sa, "failed to disable %u MAE counters: %s",
976 				action_set->n_counters, rte_strerror(rc));
977 		}
978 
979 		sfc_mae_encap_header_disable(sa, action_set->encap_header);
980 	}
981 
982 	--(fw_rsrc->refcnt);
983 }
984 
985 void
986 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
987 		     struct rte_flow *flow)
988 {
989 	struct sfc_flow_spec *spec;
990 	struct sfc_flow_spec_mae *spec_mae;
991 
992 	if (flow == NULL)
993 		return;
994 
995 	spec = &flow->spec;
996 
997 	if (spec == NULL)
998 		return;
999 
1000 	spec_mae = &spec->mae;
1001 
1002 	if (spec_mae->ft != NULL) {
1003 		if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP)
1004 			spec_mae->ft->jump_rule_is_set = B_FALSE;
1005 
1006 		SFC_ASSERT(spec_mae->ft->refcnt != 0);
1007 		--(spec_mae->ft->refcnt);
1008 	}
1009 
1010 	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
1011 
1012 	if (spec_mae->outer_rule != NULL)
1013 		sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
1014 
1015 	if (spec_mae->action_set != NULL)
1016 		sfc_mae_action_set_del(sa, spec_mae->action_set);
1017 
1018 	if (spec_mae->match_spec != NULL)
1019 		efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
1020 }
1021 
1022 static int
1023 sfc_mae_set_ethertypes(struct sfc_mae_parse_ctx *ctx)
1024 {
1025 	struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
1026 	const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
1027 	const efx_mae_field_id_t field_ids[] = {
1028 		EFX_MAE_FIELD_VLAN0_PROTO_BE,
1029 		EFX_MAE_FIELD_VLAN1_PROTO_BE,
1030 	};
1031 	const struct sfc_mae_ethertype *et;
1032 	unsigned int i;
1033 	int rc;
1034 
1035 	/*
1036 	 * In accordance with RTE flow API convention, the innermost L2
1037 	 * item's "type" ("inner_type") is a L3 EtherType. If there is
1038 	 * no L3 item, it's 0x0000/0x0000.
1039 	 */
1040 	et = &pdata->ethertypes[pdata->nb_vlan_tags];
1041 	rc = efx_mae_match_spec_field_set(ctx->match_spec,
1042 					  fremap[EFX_MAE_FIELD_ETHER_TYPE_BE],
1043 					  sizeof(et->value),
1044 					  (const uint8_t *)&et->value,
1045 					  sizeof(et->mask),
1046 					  (const uint8_t *)&et->mask);
1047 	if (rc != 0)
1048 		return rc;
1049 
1050 	/*
1051 	 * sfc_mae_rule_parse_item_vlan() has already made sure
1052 	 * that pdata->nb_vlan_tags does not exceed this figure.
1053 	 */
1054 	RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
1055 
1056 	for (i = 0; i < pdata->nb_vlan_tags; ++i) {
1057 		et = &pdata->ethertypes[i];
1058 
1059 		rc = efx_mae_match_spec_field_set(ctx->match_spec,
1060 						  fremap[field_ids[i]],
1061 						  sizeof(et->value),
1062 						  (const uint8_t *)&et->value,
1063 						  sizeof(et->mask),
1064 						  (const uint8_t *)&et->mask);
1065 		if (rc != 0)
1066 			return rc;
1067 	}
1068 
1069 	return 0;
1070 }
1071 
1072 static int
1073 sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
1074 				  struct rte_flow_error *error)
1075 {
1076 	const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
1077 	struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
1078 	struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
1079 	const rte_be16_t supported_tpids[] = {
1080 		/* VLAN standard TPID (always the first element) */
1081 		RTE_BE16(RTE_ETHER_TYPE_VLAN),
1082 
1083 		/* Double-tagging TPIDs */
1084 		RTE_BE16(RTE_ETHER_TYPE_QINQ),
1085 		RTE_BE16(RTE_ETHER_TYPE_QINQ1),
1086 		RTE_BE16(RTE_ETHER_TYPE_QINQ2),
1087 		RTE_BE16(RTE_ETHER_TYPE_QINQ3),
1088 	};
1089 	bool enforce_tag_presence[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {0};
1090 	unsigned int nb_supported_tpids = RTE_DIM(supported_tpids);
1091 	unsigned int ethertype_idx;
1092 	const uint8_t *valuep;
1093 	const uint8_t *maskp;
1094 	int rc;
1095 
1096 	if (pdata->innermost_ethertype_restriction.mask != 0 &&
1097 	    pdata->nb_vlan_tags < SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
1098 		/*
1099 		 * If a single item VLAN is followed by a L3 item, value
1100 		 * of "type" in item ETH can't be a double-tagging TPID.
1101 		 */
1102 		nb_supported_tpids = 1;
1103 	}
1104 
1105 	/*
1106 	 * sfc_mae_rule_parse_item_vlan() has already made sure
1107 	 * that pdata->nb_vlan_tags does not exceed this figure.
1108 	 */
1109 	RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
1110 
1111 	for (ethertype_idx = 0;
1112 	     ethertype_idx < pdata->nb_vlan_tags; ++ethertype_idx) {
1113 		rte_be16_t tpid_v = ethertypes[ethertype_idx].value;
1114 		rte_be16_t tpid_m = ethertypes[ethertype_idx].mask;
1115 		unsigned int tpid_idx;
1116 
1117 		/*
1118 		 * This loop can have only two iterations. On the second one,
1119 		 * drop outer tag presence enforcement bit because the inner
1120 		 * tag presence automatically assumes that for the outer tag.
1121 		 */
1122 		enforce_tag_presence[0] = B_FALSE;
1123 
1124 		if (tpid_m == RTE_BE16(0)) {
1125 			if (pdata->tci_masks[ethertype_idx] == RTE_BE16(0))
1126 				enforce_tag_presence[ethertype_idx] = B_TRUE;
1127 
1128 			/* No match on this field, and no value check. */
1129 			nb_supported_tpids = 1;
1130 			continue;
1131 		}
1132 
1133 		/* Exact match is supported only. */
1134 		if (tpid_m != RTE_BE16(0xffff)) {
1135 			sfc_err(ctx->sa, "TPID mask must be 0x0 or 0xffff; got 0x%04x",
1136 				rte_be_to_cpu_16(tpid_m));
1137 			rc = EINVAL;
1138 			goto fail;
1139 		}
1140 
1141 		for (tpid_idx = pdata->nb_vlan_tags - ethertype_idx - 1;
1142 		     tpid_idx < nb_supported_tpids; ++tpid_idx) {
1143 			if (tpid_v == supported_tpids[tpid_idx])
1144 				break;
1145 		}
1146 
1147 		if (tpid_idx == nb_supported_tpids) {
1148 			sfc_err(ctx->sa, "TPID 0x%04x is unsupported",
1149 				rte_be_to_cpu_16(tpid_v));
1150 			rc = EINVAL;
1151 			goto fail;
1152 		}
1153 
1154 		nb_supported_tpids = 1;
1155 	}
1156 
1157 	if (pdata->innermost_ethertype_restriction.mask == RTE_BE16(0xffff)) {
1158 		struct sfc_mae_ethertype *et = &ethertypes[ethertype_idx];
1159 		rte_be16_t enforced_et;
1160 
1161 		enforced_et = pdata->innermost_ethertype_restriction.value;
1162 
1163 		if (et->mask == 0) {
1164 			et->mask = RTE_BE16(0xffff);
1165 			et->value = enforced_et;
1166 		} else if (et->mask != RTE_BE16(0xffff) ||
1167 			   et->value != enforced_et) {
1168 			sfc_err(ctx->sa, "L3 EtherType must be 0x0/0x0 or 0x%04x/0xffff; got 0x%04x/0x%04x",
1169 				rte_be_to_cpu_16(enforced_et),
1170 				rte_be_to_cpu_16(et->value),
1171 				rte_be_to_cpu_16(et->mask));
1172 			rc = EINVAL;
1173 			goto fail;
1174 		}
1175 	}
1176 
1177 	/*
1178 	 * Now, when the number of VLAN tags is known, set fields
1179 	 * ETHER_TYPE, VLAN0_PROTO and VLAN1_PROTO so that the first
1180 	 * one is either a valid L3 EtherType (or 0x0000/0x0000),
1181 	 * and the last two are valid TPIDs (or 0x0000/0x0000).
1182 	 */
1183 	rc = sfc_mae_set_ethertypes(ctx);
1184 	if (rc != 0)
1185 		goto fail;
1186 
1187 	if (pdata->l3_next_proto_restriction_mask == 0xff) {
1188 		if (pdata->l3_next_proto_mask == 0) {
1189 			pdata->l3_next_proto_mask = 0xff;
1190 			pdata->l3_next_proto_value =
1191 				pdata->l3_next_proto_restriction_value;
1192 		} else if (pdata->l3_next_proto_mask != 0xff ||
1193 			   pdata->l3_next_proto_value !=
1194 			   pdata->l3_next_proto_restriction_value) {
1195 			sfc_err(ctx->sa, "L3 next protocol must be 0x0/0x0 or 0x%02x/0xff; got 0x%02x/0x%02x",
1196 				pdata->l3_next_proto_restriction_value,
1197 				pdata->l3_next_proto_value,
1198 				pdata->l3_next_proto_mask);
1199 			rc = EINVAL;
1200 			goto fail;
1201 		}
1202 	}
1203 
1204 	if (enforce_tag_presence[0] || pdata->has_ovlan_mask) {
1205 		rc = efx_mae_match_spec_bit_set(ctx->match_spec,
1206 						fremap[EFX_MAE_FIELD_HAS_OVLAN],
1207 						enforce_tag_presence[0] ||
1208 						pdata->has_ovlan_value);
1209 		if (rc != 0)
1210 			goto fail;
1211 	}
1212 
1213 	if (enforce_tag_presence[1] || pdata->has_ivlan_mask) {
1214 		rc = efx_mae_match_spec_bit_set(ctx->match_spec,
1215 						fremap[EFX_MAE_FIELD_HAS_IVLAN],
1216 						enforce_tag_presence[1] ||
1217 						pdata->has_ivlan_value);
1218 		if (rc != 0)
1219 			goto fail;
1220 	}
1221 
1222 	valuep = (const uint8_t *)&pdata->l3_next_proto_value;
1223 	maskp = (const uint8_t *)&pdata->l3_next_proto_mask;
1224 	rc = efx_mae_match_spec_field_set(ctx->match_spec,
1225 					  fremap[EFX_MAE_FIELD_IP_PROTO],
1226 					  sizeof(pdata->l3_next_proto_value),
1227 					  valuep,
1228 					  sizeof(pdata->l3_next_proto_mask),
1229 					  maskp);
1230 	if (rc != 0)
1231 		goto fail;
1232 
1233 	return 0;
1234 
1235 fail:
1236 	return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1237 				  "Failed to process pattern data");
1238 }
1239 
1240 static int
1241 sfc_mae_rule_parse_item_mark(const struct rte_flow_item *item,
1242 			     struct sfc_flow_parse_ctx *ctx,
1243 			     struct rte_flow_error *error)
1244 {
1245 	const struct rte_flow_item_mark *spec = item->spec;
1246 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1247 
1248 	if (spec == NULL) {
1249 		return rte_flow_error_set(error, EINVAL,
1250 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1251 				"NULL spec in item MARK");
1252 	}
1253 
1254 	/*
1255 	 * This item is used in tunnel offload support only.
1256 	 * It must go before any network header items. This
1257 	 * way, sfc_mae_rule_preparse_item_mark() must have
1258 	 * already parsed it. Only one item MARK is allowed.
1259 	 */
1260 	if (ctx_mae->ft_rule_type != SFC_FT_RULE_GROUP ||
1261 	    spec->id != (uint32_t)SFC_FT_ID_TO_MARK(ctx_mae->ft->id)) {
1262 		return rte_flow_error_set(error, EINVAL,
1263 					  RTE_FLOW_ERROR_TYPE_ITEM,
1264 					  item, "invalid item MARK");
1265 	}
1266 
1267 	return 0;
1268 }
1269 
1270 static int
1271 sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
1272 				struct sfc_flow_parse_ctx *ctx,
1273 				struct rte_flow_error *error)
1274 {
1275 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1276 	const struct rte_flow_item_port_id supp_mask = {
1277 		.id = 0xffffffff,
1278 	};
1279 	const void *def_mask = &rte_flow_item_port_id_mask;
1280 	const struct rte_flow_item_port_id *spec = NULL;
1281 	const struct rte_flow_item_port_id *mask = NULL;
1282 	efx_mport_sel_t mport_sel;
1283 	int rc;
1284 
1285 	if (ctx_mae->match_mport_set) {
1286 		return rte_flow_error_set(error, ENOTSUP,
1287 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1288 				"Can't handle multiple traffic source items");
1289 	}
1290 
1291 	rc = sfc_flow_parse_init(item,
1292 				 (const void **)&spec, (const void **)&mask,
1293 				 (const void *)&supp_mask, def_mask,
1294 				 sizeof(struct rte_flow_item_port_id), error);
1295 	if (rc != 0)
1296 		return rc;
1297 
1298 	if (mask->id != supp_mask.id) {
1299 		return rte_flow_error_set(error, EINVAL,
1300 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1301 				"Bad mask in the PORT_ID pattern item");
1302 	}
1303 
1304 	/* If "spec" is not set, could be any port ID */
1305 	if (spec == NULL)
1306 		return 0;
1307 
1308 	if (spec->id > UINT16_MAX) {
1309 		return rte_flow_error_set(error, EOVERFLOW,
1310 					  RTE_FLOW_ERROR_TYPE_ITEM, item,
1311 					  "The port ID is too large");
1312 	}
1313 
1314 	rc = sfc_mae_switch_get_ethdev_mport(ctx_mae->sa->mae.switch_domain_id,
1315 					     spec->id, &mport_sel);
1316 	if (rc != 0) {
1317 		return rte_flow_error_set(error, rc,
1318 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1319 				"Can't get m-port for the given ethdev");
1320 	}
1321 
1322 	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec,
1323 					  &mport_sel, NULL);
1324 	if (rc != 0) {
1325 		return rte_flow_error_set(error, rc,
1326 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1327 				"Failed to set MPORT for the port ID");
1328 	}
1329 
1330 	ctx_mae->match_mport_set = B_TRUE;
1331 
1332 	return 0;
1333 }
1334 
1335 static int
1336 sfc_mae_rule_parse_item_ethdev_based(const struct rte_flow_item *item,
1337 				     struct sfc_flow_parse_ctx *ctx,
1338 				     struct rte_flow_error *error)
1339 {
1340 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1341 	const struct rte_flow_item_ethdev supp_mask = {
1342 		.port_id = 0xffff,
1343 	};
1344 	const void *def_mask = &rte_flow_item_ethdev_mask;
1345 	const struct rte_flow_item_ethdev *spec = NULL;
1346 	const struct rte_flow_item_ethdev *mask = NULL;
1347 	efx_mport_sel_t mport_sel;
1348 	int rc;
1349 
1350 	if (ctx_mae->match_mport_set) {
1351 		return rte_flow_error_set(error, ENOTSUP,
1352 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1353 				"Can't handle multiple traffic source items");
1354 	}
1355 
1356 	rc = sfc_flow_parse_init(item,
1357 				 (const void **)&spec, (const void **)&mask,
1358 				 (const void *)&supp_mask, def_mask,
1359 				 sizeof(struct rte_flow_item_ethdev), error);
1360 	if (rc != 0)
1361 		return rc;
1362 
1363 	if (mask->port_id != supp_mask.port_id) {
1364 		return rte_flow_error_set(error, EINVAL,
1365 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1366 				"Bad mask in the ethdev-based pattern item");
1367 	}
1368 
1369 	/* If "spec" is not set, could be any port ID */
1370 	if (spec == NULL)
1371 		return 0;
1372 
1373 	switch (item->type) {
1374 	case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR:
1375 		rc = sfc_mae_switch_get_ethdev_mport(
1376 				ctx_mae->sa->mae.switch_domain_id,
1377 				spec->port_id, &mport_sel);
1378 		if (rc != 0) {
1379 			return rte_flow_error_set(error, rc,
1380 					RTE_FLOW_ERROR_TYPE_ITEM, item,
1381 					"Can't get m-port for the given ethdev");
1382 		}
1383 		break;
1384 	case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT:
1385 		rc = sfc_mae_switch_get_entity_mport(
1386 				ctx_mae->sa->mae.switch_domain_id,
1387 				spec->port_id, &mport_sel);
1388 		if (rc != 0) {
1389 			return rte_flow_error_set(error, rc,
1390 					RTE_FLOW_ERROR_TYPE_ITEM, item,
1391 					"Can't get m-port for the given ethdev");
1392 		}
1393 		break;
1394 	default:
1395 		return rte_flow_error_set(error, EINVAL,
1396 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1397 				"Unsupported ethdev-based flow item");
1398 	}
1399 
1400 	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec,
1401 					  &mport_sel, NULL);
1402 	if (rc != 0) {
1403 		return rte_flow_error_set(error, rc,
1404 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1405 				"Failed to set MPORT for the port ID");
1406 	}
1407 
1408 	ctx_mae->match_mport_set = B_TRUE;
1409 
1410 	return 0;
1411 }
1412 
1413 static int
1414 sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
1415 				 struct sfc_flow_parse_ctx *ctx,
1416 				 struct rte_flow_error *error)
1417 {
1418 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1419 	const struct rte_flow_item_phy_port supp_mask = {
1420 		.index = 0xffffffff,
1421 	};
1422 	const void *def_mask = &rte_flow_item_phy_port_mask;
1423 	const struct rte_flow_item_phy_port *spec = NULL;
1424 	const struct rte_flow_item_phy_port *mask = NULL;
1425 	efx_mport_sel_t mport_v;
1426 	int rc;
1427 
1428 	if (ctx_mae->match_mport_set) {
1429 		return rte_flow_error_set(error, ENOTSUP,
1430 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1431 				"Can't handle multiple traffic source items");
1432 	}
1433 
1434 	rc = sfc_flow_parse_init(item,
1435 				 (const void **)&spec, (const void **)&mask,
1436 				 (const void *)&supp_mask, def_mask,
1437 				 sizeof(struct rte_flow_item_phy_port), error);
1438 	if (rc != 0)
1439 		return rc;
1440 
1441 	if (mask->index != supp_mask.index) {
1442 		return rte_flow_error_set(error, EINVAL,
1443 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1444 				"Bad mask in the PHY_PORT pattern item");
1445 	}
1446 
1447 	/* If "spec" is not set, could be any physical port */
1448 	if (spec == NULL)
1449 		return 0;
1450 
1451 	rc = efx_mae_mport_by_phy_port(spec->index, &mport_v);
1452 	if (rc != 0) {
1453 		return rte_flow_error_set(error, rc,
1454 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1455 				"Failed to convert the PHY_PORT index");
1456 	}
1457 
1458 	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
1459 	if (rc != 0) {
1460 		return rte_flow_error_set(error, rc,
1461 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1462 				"Failed to set MPORT for the PHY_PORT");
1463 	}
1464 
1465 	ctx_mae->match_mport_set = B_TRUE;
1466 
1467 	return 0;
1468 }
1469 
1470 static int
1471 sfc_mae_rule_parse_item_pf(const struct rte_flow_item *item,
1472 			   struct sfc_flow_parse_ctx *ctx,
1473 			   struct rte_flow_error *error)
1474 {
1475 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1476 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
1477 	efx_mport_sel_t mport_v;
1478 	int rc;
1479 
1480 	if (ctx_mae->match_mport_set) {
1481 		return rte_flow_error_set(error, ENOTSUP,
1482 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1483 				"Can't handle multiple traffic source items");
1484 	}
1485 
1486 	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
1487 					    &mport_v);
1488 	if (rc != 0) {
1489 		return rte_flow_error_set(error, rc,
1490 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1491 				"Failed to convert the PF ID");
1492 	}
1493 
1494 	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
1495 	if (rc != 0) {
1496 		return rte_flow_error_set(error, rc,
1497 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1498 				"Failed to set MPORT for the PF");
1499 	}
1500 
1501 	ctx_mae->match_mport_set = B_TRUE;
1502 
1503 	return 0;
1504 }
1505 
1506 static int
1507 sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item,
1508 			   struct sfc_flow_parse_ctx *ctx,
1509 			   struct rte_flow_error *error)
1510 {
1511 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1512 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
1513 	const struct rte_flow_item_vf supp_mask = {
1514 		.id = 0xffffffff,
1515 	};
1516 	const void *def_mask = &rte_flow_item_vf_mask;
1517 	const struct rte_flow_item_vf *spec = NULL;
1518 	const struct rte_flow_item_vf *mask = NULL;
1519 	efx_mport_sel_t mport_v;
1520 	int rc;
1521 
1522 	if (ctx_mae->match_mport_set) {
1523 		return rte_flow_error_set(error, ENOTSUP,
1524 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1525 				"Can't handle multiple traffic source items");
1526 	}
1527 
1528 	rc = sfc_flow_parse_init(item,
1529 				 (const void **)&spec, (const void **)&mask,
1530 				 (const void *)&supp_mask, def_mask,
1531 				 sizeof(struct rte_flow_item_vf), error);
1532 	if (rc != 0)
1533 		return rc;
1534 
1535 	if (mask->id != supp_mask.id) {
1536 		return rte_flow_error_set(error, EINVAL,
1537 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1538 				"Bad mask in the VF pattern item");
1539 	}
1540 
1541 	/*
1542 	 * If "spec" is not set, the item requests any VF related to the
1543 	 * PF of the current DPDK port (but not the PF itself).
1544 	 * Reject this match criterion as unsupported.
1545 	 */
1546 	if (spec == NULL) {
1547 		return rte_flow_error_set(error, EINVAL,
1548 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1549 				"Bad spec in the VF pattern item");
1550 	}
1551 
1552 	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, spec->id, &mport_v);
1553 	if (rc != 0) {
1554 		return rte_flow_error_set(error, rc,
1555 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1556 				"Failed to convert the PF + VF IDs");
1557 	}
1558 
1559 	rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
1560 	if (rc != 0) {
1561 		return rte_flow_error_set(error, rc,
1562 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1563 				"Failed to set MPORT for the PF + VF");
1564 	}
1565 
1566 	ctx_mae->match_mport_set = B_TRUE;
1567 
1568 	return 0;
1569 }
1570 
1571 /*
1572  * Having this field ID in a field locator means that this
1573  * locator cannot be used to actually set the field at the
1574  * time when the corresponding item gets encountered. Such
1575  * fields get stashed in the parsing context instead. This
1576  * is required to resolve dependencies between the stashed
1577  * fields. See sfc_mae_rule_process_pattern_data().
1578  */
1579 #define SFC_MAE_FIELD_HANDLING_DEFERRED	EFX_MAE_FIELD_NIDS
1580 
1581 struct sfc_mae_field_locator {
1582 	efx_mae_field_id_t		field_id;
1583 	size_t				size;
1584 	/* Field offset in the corresponding rte_flow_item_ struct */
1585 	size_t				ofst;
1586 };
1587 
1588 static void
1589 sfc_mae_item_build_supp_mask(const struct sfc_mae_field_locator *field_locators,
1590 			     unsigned int nb_field_locators, void *mask_ptr,
1591 			     size_t mask_size)
1592 {
1593 	unsigned int i;
1594 
1595 	memset(mask_ptr, 0, mask_size);
1596 
1597 	for (i = 0; i < nb_field_locators; ++i) {
1598 		const struct sfc_mae_field_locator *fl = &field_locators[i];
1599 
1600 		SFC_ASSERT(fl->ofst + fl->size <= mask_size);
1601 		memset(RTE_PTR_ADD(mask_ptr, fl->ofst), 0xff, fl->size);
1602 	}
1603 }
1604 
1605 static int
1606 sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
1607 		   unsigned int nb_field_locators, const uint8_t *spec,
1608 		   const uint8_t *mask, struct sfc_mae_parse_ctx *ctx,
1609 		   struct rte_flow_error *error)
1610 {
1611 	const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
1612 	unsigned int i;
1613 	int rc = 0;
1614 
1615 	for (i = 0; i < nb_field_locators; ++i) {
1616 		const struct sfc_mae_field_locator *fl = &field_locators[i];
1617 
1618 		if (fl->field_id == SFC_MAE_FIELD_HANDLING_DEFERRED)
1619 			continue;
1620 
1621 		rc = efx_mae_match_spec_field_set(ctx->match_spec,
1622 						  fremap[fl->field_id],
1623 						  fl->size, spec + fl->ofst,
1624 						  fl->size, mask + fl->ofst);
1625 		if (rc != 0)
1626 			break;
1627 	}
1628 
1629 	if (rc != 0) {
1630 		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
1631 				NULL, "Failed to process item fields");
1632 	}
1633 
1634 	return rc;
1635 }
1636 
1637 static const struct sfc_mae_field_locator flocs_eth[] = {
1638 	{
1639 		/*
1640 		 * This locator is used only for building supported fields mask.
1641 		 * The field is handled by sfc_mae_rule_process_pattern_data().
1642 		 */
1643 		SFC_MAE_FIELD_HANDLING_DEFERRED,
1644 		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, type),
1645 		offsetof(struct rte_flow_item_eth, type),
1646 	},
1647 	{
1648 		EFX_MAE_FIELD_ETH_DADDR_BE,
1649 		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, dst),
1650 		offsetof(struct rte_flow_item_eth, dst),
1651 	},
1652 	{
1653 		EFX_MAE_FIELD_ETH_SADDR_BE,
1654 		RTE_SIZEOF_FIELD(struct rte_flow_item_eth, src),
1655 		offsetof(struct rte_flow_item_eth, src),
1656 	},
1657 };
1658 
1659 static int
1660 sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
1661 			    struct sfc_flow_parse_ctx *ctx,
1662 			    struct rte_flow_error *error)
1663 {
1664 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1665 	struct rte_flow_item_eth override_mask;
1666 	struct rte_flow_item_eth supp_mask;
1667 	const uint8_t *spec = NULL;
1668 	const uint8_t *mask = NULL;
1669 	int rc;
1670 
1671 	sfc_mae_item_build_supp_mask(flocs_eth, RTE_DIM(flocs_eth),
1672 				     &supp_mask, sizeof(supp_mask));
1673 	supp_mask.has_vlan = 1;
1674 
1675 	rc = sfc_flow_parse_init(item,
1676 				 (const void **)&spec, (const void **)&mask,
1677 				 (const void *)&supp_mask,
1678 				 &rte_flow_item_eth_mask,
1679 				 sizeof(struct rte_flow_item_eth), error);
1680 	if (rc != 0)
1681 		return rc;
1682 
1683 	if (ctx_mae->ft_rule_type == SFC_FT_RULE_JUMP && mask != NULL) {
1684 		/*
1685 		 * The HW/FW hasn't got support for match on MAC addresses in
1686 		 * outer rules yet (this will change). Match on VLAN presence
1687 		 * isn't supported either. Ignore these match criteria.
1688 		 */
1689 		memcpy(&override_mask, mask, sizeof(override_mask));
1690 		memset(&override_mask.hdr.dst_addr, 0,
1691 		       sizeof(override_mask.hdr.dst_addr));
1692 		memset(&override_mask.hdr.src_addr, 0,
1693 		       sizeof(override_mask.hdr.src_addr));
1694 		override_mask.has_vlan = 0;
1695 
1696 		mask = (const uint8_t *)&override_mask;
1697 	}
1698 
1699 	if (spec != NULL) {
1700 		struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1701 		struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
1702 		const struct rte_flow_item_eth *item_spec;
1703 		const struct rte_flow_item_eth *item_mask;
1704 
1705 		item_spec = (const struct rte_flow_item_eth *)spec;
1706 		item_mask = (const struct rte_flow_item_eth *)mask;
1707 
1708 		/*
1709 		 * Remember various match criteria in the parsing context.
1710 		 * sfc_mae_rule_process_pattern_data() will consider them
1711 		 * altogether when the rest of the items have been parsed.
1712 		 */
1713 		ethertypes[0].value = item_spec->type;
1714 		ethertypes[0].mask = item_mask->type;
1715 		if (item_mask->has_vlan) {
1716 			pdata->has_ovlan_mask = B_TRUE;
1717 			if (item_spec->has_vlan)
1718 				pdata->has_ovlan_value = B_TRUE;
1719 		}
1720 	} else {
1721 		/*
1722 		 * The specification is empty. The overall pattern
1723 		 * validity will be enforced at the end of parsing.
1724 		 * See sfc_mae_rule_process_pattern_data().
1725 		 */
1726 		return 0;
1727 	}
1728 
1729 	return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask,
1730 				  ctx_mae, error);
1731 }
1732 
1733 static const struct sfc_mae_field_locator flocs_vlan[] = {
1734 	/* Outermost tag */
1735 	{
1736 		EFX_MAE_FIELD_VLAN0_TCI_BE,
1737 		RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci),
1738 		offsetof(struct rte_flow_item_vlan, tci),
1739 	},
1740 	{
1741 		/*
1742 		 * This locator is used only for building supported fields mask.
1743 		 * The field is handled by sfc_mae_rule_process_pattern_data().
1744 		 */
1745 		SFC_MAE_FIELD_HANDLING_DEFERRED,
1746 		RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type),
1747 		offsetof(struct rte_flow_item_vlan, inner_type),
1748 	},
1749 
1750 	/* Innermost tag */
1751 	{
1752 		EFX_MAE_FIELD_VLAN1_TCI_BE,
1753 		RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci),
1754 		offsetof(struct rte_flow_item_vlan, tci),
1755 	},
1756 	{
1757 		/*
1758 		 * This locator is used only for building supported fields mask.
1759 		 * The field is handled by sfc_mae_rule_process_pattern_data().
1760 		 */
1761 		SFC_MAE_FIELD_HANDLING_DEFERRED,
1762 		RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type),
1763 		offsetof(struct rte_flow_item_vlan, inner_type),
1764 	},
1765 };
1766 
1767 static int
1768 sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
1769 			     struct sfc_flow_parse_ctx *ctx,
1770 			     struct rte_flow_error *error)
1771 {
1772 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1773 	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1774 	boolean_t *has_vlan_mp_by_nb_tags[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {
1775 		&pdata->has_ovlan_mask,
1776 		&pdata->has_ivlan_mask,
1777 	};
1778 	boolean_t *has_vlan_vp_by_nb_tags[SFC_MAE_MATCH_VLAN_MAX_NTAGS] = {
1779 		&pdata->has_ovlan_value,
1780 		&pdata->has_ivlan_value,
1781 	};
1782 	boolean_t *cur_tag_presence_bit_mp;
1783 	boolean_t *cur_tag_presence_bit_vp;
1784 	const struct sfc_mae_field_locator *flocs;
1785 	struct rte_flow_item_vlan supp_mask;
1786 	const uint8_t *spec = NULL;
1787 	const uint8_t *mask = NULL;
1788 	unsigned int nb_flocs;
1789 	int rc;
1790 
1791 	RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
1792 
1793 	if (pdata->nb_vlan_tags == SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
1794 		return rte_flow_error_set(error, ENOTSUP,
1795 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1796 				"Can't match that many VLAN tags");
1797 	}
1798 
1799 	cur_tag_presence_bit_mp = has_vlan_mp_by_nb_tags[pdata->nb_vlan_tags];
1800 	cur_tag_presence_bit_vp = has_vlan_vp_by_nb_tags[pdata->nb_vlan_tags];
1801 
1802 	if (*cur_tag_presence_bit_mp == B_TRUE &&
1803 	    *cur_tag_presence_bit_vp == B_FALSE) {
1804 		return rte_flow_error_set(error, EINVAL,
1805 				RTE_FLOW_ERROR_TYPE_ITEM, item,
1806 				"The previous item enforces no (more) VLAN, "
1807 				"so the current item (VLAN) must not exist");
1808 	}
1809 
1810 	nb_flocs = RTE_DIM(flocs_vlan) / SFC_MAE_MATCH_VLAN_MAX_NTAGS;
1811 	flocs = flocs_vlan + pdata->nb_vlan_tags * nb_flocs;
1812 
1813 	sfc_mae_item_build_supp_mask(flocs, nb_flocs,
1814 				     &supp_mask, sizeof(supp_mask));
1815 	/*
1816 	 * This only means that the field is supported by the driver and libefx.
1817 	 * Support on NIC level will be checked when all items have been parsed.
1818 	 */
1819 	supp_mask.has_more_vlan = 1;
1820 
1821 	rc = sfc_flow_parse_init(item,
1822 				 (const void **)&spec, (const void **)&mask,
1823 				 (const void *)&supp_mask,
1824 				 &rte_flow_item_vlan_mask,
1825 				 sizeof(struct rte_flow_item_vlan), error);
1826 	if (rc != 0)
1827 		return rc;
1828 
1829 	if (spec != NULL) {
1830 		struct sfc_mae_ethertype *et = pdata->ethertypes;
1831 		const struct rte_flow_item_vlan *item_spec;
1832 		const struct rte_flow_item_vlan *item_mask;
1833 
1834 		item_spec = (const struct rte_flow_item_vlan *)spec;
1835 		item_mask = (const struct rte_flow_item_vlan *)mask;
1836 
1837 		/*
1838 		 * Remember various match criteria in the parsing context.
1839 		 * sfc_mae_rule_process_pattern_data() will consider them
1840 		 * altogether when the rest of the items have been parsed.
1841 		 */
1842 		et[pdata->nb_vlan_tags + 1].value = item_spec->inner_type;
1843 		et[pdata->nb_vlan_tags + 1].mask = item_mask->inner_type;
1844 		pdata->tci_masks[pdata->nb_vlan_tags] = item_mask->tci;
1845 		if (item_mask->has_more_vlan) {
1846 			if (pdata->nb_vlan_tags ==
1847 			    SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
1848 				return rte_flow_error_set(error, ENOTSUP,
1849 					RTE_FLOW_ERROR_TYPE_ITEM, item,
1850 					"Can't use 'has_more_vlan' in "
1851 					"the second item VLAN");
1852 			}
1853 			pdata->has_ivlan_mask = B_TRUE;
1854 			if (item_spec->has_more_vlan)
1855 				pdata->has_ivlan_value = B_TRUE;
1856 		}
1857 
1858 		/* Convert TCI to MAE representation right now. */
1859 		rc = sfc_mae_parse_item(flocs, nb_flocs, spec, mask,
1860 					ctx_mae, error);
1861 		if (rc != 0)
1862 			return rc;
1863 	}
1864 
1865 	++(pdata->nb_vlan_tags);
1866 
1867 	return 0;
1868 }
1869 
1870 static const struct sfc_mae_field_locator flocs_ipv4[] = {
1871 	{
1872 		EFX_MAE_FIELD_SRC_IP4_BE,
1873 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
1874 		offsetof(struct rte_flow_item_ipv4, hdr.src_addr),
1875 	},
1876 	{
1877 		EFX_MAE_FIELD_DST_IP4_BE,
1878 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
1879 		offsetof(struct rte_flow_item_ipv4, hdr.dst_addr),
1880 	},
1881 	{
1882 		/*
1883 		 * This locator is used only for building supported fields mask.
1884 		 * The field is handled by sfc_mae_rule_process_pattern_data().
1885 		 */
1886 		SFC_MAE_FIELD_HANDLING_DEFERRED,
1887 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.next_proto_id),
1888 		offsetof(struct rte_flow_item_ipv4, hdr.next_proto_id),
1889 	},
1890 	{
1891 		EFX_MAE_FIELD_IP_TOS,
1892 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4,
1893 				 hdr.type_of_service),
1894 		offsetof(struct rte_flow_item_ipv4, hdr.type_of_service),
1895 	},
1896 	{
1897 		EFX_MAE_FIELD_IP_TTL,
1898 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.time_to_live),
1899 		offsetof(struct rte_flow_item_ipv4, hdr.time_to_live),
1900 	},
1901 };
1902 
1903 static int
1904 sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item,
1905 			     struct sfc_flow_parse_ctx *ctx,
1906 			     struct rte_flow_error *error)
1907 {
1908 	rte_be16_t ethertype_ipv4_be = RTE_BE16(RTE_ETHER_TYPE_IPV4);
1909 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1910 	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1911 	struct rte_flow_item_ipv4 supp_mask;
1912 	const uint8_t *spec = NULL;
1913 	const uint8_t *mask = NULL;
1914 	int rc;
1915 
1916 	sfc_mae_item_build_supp_mask(flocs_ipv4, RTE_DIM(flocs_ipv4),
1917 				     &supp_mask, sizeof(supp_mask));
1918 
1919 	rc = sfc_flow_parse_init(item,
1920 				 (const void **)&spec, (const void **)&mask,
1921 				 (const void *)&supp_mask,
1922 				 &rte_flow_item_ipv4_mask,
1923 				 sizeof(struct rte_flow_item_ipv4), error);
1924 	if (rc != 0)
1925 		return rc;
1926 
1927 	pdata->innermost_ethertype_restriction.value = ethertype_ipv4_be;
1928 	pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
1929 
1930 	if (spec != NULL) {
1931 		const struct rte_flow_item_ipv4 *item_spec;
1932 		const struct rte_flow_item_ipv4 *item_mask;
1933 
1934 		item_spec = (const struct rte_flow_item_ipv4 *)spec;
1935 		item_mask = (const struct rte_flow_item_ipv4 *)mask;
1936 
1937 		pdata->l3_next_proto_value = item_spec->hdr.next_proto_id;
1938 		pdata->l3_next_proto_mask = item_mask->hdr.next_proto_id;
1939 	} else {
1940 		return 0;
1941 	}
1942 
1943 	return sfc_mae_parse_item(flocs_ipv4, RTE_DIM(flocs_ipv4), spec, mask,
1944 				  ctx_mae, error);
1945 }
1946 
1947 static const struct sfc_mae_field_locator flocs_ipv6[] = {
1948 	{
1949 		EFX_MAE_FIELD_SRC_IP6_BE,
1950 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
1951 		offsetof(struct rte_flow_item_ipv6, hdr.src_addr),
1952 	},
1953 	{
1954 		EFX_MAE_FIELD_DST_IP6_BE,
1955 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
1956 		offsetof(struct rte_flow_item_ipv6, hdr.dst_addr),
1957 	},
1958 	{
1959 		/*
1960 		 * This locator is used only for building supported fields mask.
1961 		 * The field is handled by sfc_mae_rule_process_pattern_data().
1962 		 */
1963 		SFC_MAE_FIELD_HANDLING_DEFERRED,
1964 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.proto),
1965 		offsetof(struct rte_flow_item_ipv6, hdr.proto),
1966 	},
1967 	{
1968 		EFX_MAE_FIELD_IP_TTL,
1969 		RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.hop_limits),
1970 		offsetof(struct rte_flow_item_ipv6, hdr.hop_limits),
1971 	},
1972 };
1973 
1974 static int
1975 sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
1976 			     struct sfc_flow_parse_ctx *ctx,
1977 			     struct rte_flow_error *error)
1978 {
1979 	rte_be16_t ethertype_ipv6_be = RTE_BE16(RTE_ETHER_TYPE_IPV6);
1980 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1981 	const efx_mae_field_id_t *fremap = ctx_mae->field_ids_remap;
1982 	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1983 	struct rte_flow_item_ipv6 supp_mask;
1984 	const uint8_t *spec = NULL;
1985 	const uint8_t *mask = NULL;
1986 	rte_be32_t vtc_flow_be;
1987 	uint32_t vtc_flow;
1988 	uint8_t tc_value;
1989 	uint8_t tc_mask;
1990 	int rc;
1991 
1992 	sfc_mae_item_build_supp_mask(flocs_ipv6, RTE_DIM(flocs_ipv6),
1993 				     &supp_mask, sizeof(supp_mask));
1994 
1995 	vtc_flow_be = RTE_BE32(RTE_IPV6_HDR_TC_MASK);
1996 	memcpy(&supp_mask, &vtc_flow_be, sizeof(vtc_flow_be));
1997 
1998 	rc = sfc_flow_parse_init(item,
1999 				 (const void **)&spec, (const void **)&mask,
2000 				 (const void *)&supp_mask,
2001 				 &rte_flow_item_ipv6_mask,
2002 				 sizeof(struct rte_flow_item_ipv6), error);
2003 	if (rc != 0)
2004 		return rc;
2005 
2006 	pdata->innermost_ethertype_restriction.value = ethertype_ipv6_be;
2007 	pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
2008 
2009 	if (spec != NULL) {
2010 		const struct rte_flow_item_ipv6 *item_spec;
2011 		const struct rte_flow_item_ipv6 *item_mask;
2012 
2013 		item_spec = (const struct rte_flow_item_ipv6 *)spec;
2014 		item_mask = (const struct rte_flow_item_ipv6 *)mask;
2015 
2016 		pdata->l3_next_proto_value = item_spec->hdr.proto;
2017 		pdata->l3_next_proto_mask = item_mask->hdr.proto;
2018 	} else {
2019 		return 0;
2020 	}
2021 
2022 	rc = sfc_mae_parse_item(flocs_ipv6, RTE_DIM(flocs_ipv6), spec, mask,
2023 				ctx_mae, error);
2024 	if (rc != 0)
2025 		return rc;
2026 
2027 	memcpy(&vtc_flow_be, spec, sizeof(vtc_flow_be));
2028 	vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
2029 	tc_value = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
2030 
2031 	memcpy(&vtc_flow_be, mask, sizeof(vtc_flow_be));
2032 	vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
2033 	tc_mask = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
2034 
2035 	rc = efx_mae_match_spec_field_set(ctx_mae->match_spec,
2036 					  fremap[EFX_MAE_FIELD_IP_TOS],
2037 					  sizeof(tc_value), &tc_value,
2038 					  sizeof(tc_mask), &tc_mask);
2039 	if (rc != 0) {
2040 		return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
2041 				NULL, "Failed to process item fields");
2042 	}
2043 
2044 	return 0;
2045 }
2046 
2047 static const struct sfc_mae_field_locator flocs_tcp[] = {
2048 	{
2049 		EFX_MAE_FIELD_L4_SPORT_BE,
2050 		RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.src_port),
2051 		offsetof(struct rte_flow_item_tcp, hdr.src_port),
2052 	},
2053 	{
2054 		EFX_MAE_FIELD_L4_DPORT_BE,
2055 		RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.dst_port),
2056 		offsetof(struct rte_flow_item_tcp, hdr.dst_port),
2057 	},
2058 	{
2059 		EFX_MAE_FIELD_TCP_FLAGS_BE,
2060 		/*
2061 		 * The values have been picked intentionally since the
2062 		 * target MAE field is oversize (16 bit). This mapping
2063 		 * relies on the fact that the MAE field is big-endian.
2064 		 */
2065 		RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.data_off) +
2066 		RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.tcp_flags),
2067 		offsetof(struct rte_flow_item_tcp, hdr.data_off),
2068 	},
2069 };
2070 
2071 static int
2072 sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item,
2073 			    struct sfc_flow_parse_ctx *ctx,
2074 			    struct rte_flow_error *error)
2075 {
2076 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
2077 	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
2078 	struct rte_flow_item_tcp supp_mask;
2079 	const uint8_t *spec = NULL;
2080 	const uint8_t *mask = NULL;
2081 	int rc;
2082 
2083 	/*
2084 	 * When encountered among outermost items, item TCP is invalid.
2085 	 * Check which match specification is being constructed now.
2086 	 */
2087 	if (ctx_mae->match_spec != ctx_mae->match_spec_action) {
2088 		return rte_flow_error_set(error, EINVAL,
2089 					  RTE_FLOW_ERROR_TYPE_ITEM, item,
2090 					  "TCP in outer frame is invalid");
2091 	}
2092 
2093 	sfc_mae_item_build_supp_mask(flocs_tcp, RTE_DIM(flocs_tcp),
2094 				     &supp_mask, sizeof(supp_mask));
2095 
2096 	rc = sfc_flow_parse_init(item,
2097 				 (const void **)&spec, (const void **)&mask,
2098 				 (const void *)&supp_mask,
2099 				 &rte_flow_item_tcp_mask,
2100 				 sizeof(struct rte_flow_item_tcp), error);
2101 	if (rc != 0)
2102 		return rc;
2103 
2104 	pdata->l3_next_proto_restriction_value = IPPROTO_TCP;
2105 	pdata->l3_next_proto_restriction_mask = 0xff;
2106 
2107 	if (spec == NULL)
2108 		return 0;
2109 
2110 	return sfc_mae_parse_item(flocs_tcp, RTE_DIM(flocs_tcp), spec, mask,
2111 				  ctx_mae, error);
2112 }
2113 
2114 static const struct sfc_mae_field_locator flocs_udp[] = {
2115 	{
2116 		EFX_MAE_FIELD_L4_SPORT_BE,
2117 		RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.src_port),
2118 		offsetof(struct rte_flow_item_udp, hdr.src_port),
2119 	},
2120 	{
2121 		EFX_MAE_FIELD_L4_DPORT_BE,
2122 		RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.dst_port),
2123 		offsetof(struct rte_flow_item_udp, hdr.dst_port),
2124 	},
2125 };
2126 
2127 static int
2128 sfc_mae_rule_parse_item_udp(const struct rte_flow_item *item,
2129 			    struct sfc_flow_parse_ctx *ctx,
2130 			    struct rte_flow_error *error)
2131 {
2132 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
2133 	struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
2134 	struct rte_flow_item_udp supp_mask;
2135 	const uint8_t *spec = NULL;
2136 	const uint8_t *mask = NULL;
2137 	int rc;
2138 
2139 	sfc_mae_item_build_supp_mask(flocs_udp, RTE_DIM(flocs_udp),
2140 				     &supp_mask, sizeof(supp_mask));
2141 
2142 	rc = sfc_flow_parse_init(item,
2143 				 (const void **)&spec, (const void **)&mask,
2144 				 (const void *)&supp_mask,
2145 				 &rte_flow_item_udp_mask,
2146 				 sizeof(struct rte_flow_item_udp), error);
2147 	if (rc != 0)
2148 		return rc;
2149 
2150 	pdata->l3_next_proto_restriction_value = IPPROTO_UDP;
2151 	pdata->l3_next_proto_restriction_mask = 0xff;
2152 
2153 	if (spec == NULL)
2154 		return 0;
2155 
2156 	return sfc_mae_parse_item(flocs_udp, RTE_DIM(flocs_udp), spec, mask,
2157 				  ctx_mae, error);
2158 }
2159 
2160 static const struct sfc_mae_field_locator flocs_tunnel[] = {
2161 	{
2162 		/*
2163 		 * The size and offset values are relevant
2164 		 * for Geneve and NVGRE, too.
2165 		 */
2166 		.size = RTE_SIZEOF_FIELD(struct rte_flow_item_vxlan, vni),
2167 		.ofst = offsetof(struct rte_flow_item_vxlan, vni),
2168 	},
2169 };
2170 
2171 /*
2172  * An auxiliary registry which allows using non-encap. field IDs
2173  * directly when building a match specification of type ACTION.
2174  *
2175  * See sfc_mae_rule_parse_pattern() and sfc_mae_rule_parse_item_tunnel().
2176  */
2177 static const efx_mae_field_id_t field_ids_no_remap[] = {
2178 #define FIELD_ID_NO_REMAP(_field) \
2179 	[EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_##_field
2180 
2181 	FIELD_ID_NO_REMAP(ETHER_TYPE_BE),
2182 	FIELD_ID_NO_REMAP(ETH_SADDR_BE),
2183 	FIELD_ID_NO_REMAP(ETH_DADDR_BE),
2184 	FIELD_ID_NO_REMAP(VLAN0_TCI_BE),
2185 	FIELD_ID_NO_REMAP(VLAN0_PROTO_BE),
2186 	FIELD_ID_NO_REMAP(VLAN1_TCI_BE),
2187 	FIELD_ID_NO_REMAP(VLAN1_PROTO_BE),
2188 	FIELD_ID_NO_REMAP(SRC_IP4_BE),
2189 	FIELD_ID_NO_REMAP(DST_IP4_BE),
2190 	FIELD_ID_NO_REMAP(IP_PROTO),
2191 	FIELD_ID_NO_REMAP(IP_TOS),
2192 	FIELD_ID_NO_REMAP(IP_TTL),
2193 	FIELD_ID_NO_REMAP(SRC_IP6_BE),
2194 	FIELD_ID_NO_REMAP(DST_IP6_BE),
2195 	FIELD_ID_NO_REMAP(L4_SPORT_BE),
2196 	FIELD_ID_NO_REMAP(L4_DPORT_BE),
2197 	FIELD_ID_NO_REMAP(TCP_FLAGS_BE),
2198 	FIELD_ID_NO_REMAP(HAS_OVLAN),
2199 	FIELD_ID_NO_REMAP(HAS_IVLAN),
2200 
2201 #undef FIELD_ID_NO_REMAP
2202 };
2203 
2204 /*
2205  * An auxiliary registry which allows using "ENC" field IDs
2206  * when building a match specification of type OUTER.
2207  *
2208  * See sfc_mae_rule_encap_parse_init().
2209  */
2210 static const efx_mae_field_id_t field_ids_remap_to_encap[] = {
2211 #define FIELD_ID_REMAP_TO_ENCAP(_field) \
2212 	[EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_ENC_##_field
2213 
2214 	FIELD_ID_REMAP_TO_ENCAP(ETHER_TYPE_BE),
2215 	FIELD_ID_REMAP_TO_ENCAP(ETH_SADDR_BE),
2216 	FIELD_ID_REMAP_TO_ENCAP(ETH_DADDR_BE),
2217 	FIELD_ID_REMAP_TO_ENCAP(VLAN0_TCI_BE),
2218 	FIELD_ID_REMAP_TO_ENCAP(VLAN0_PROTO_BE),
2219 	FIELD_ID_REMAP_TO_ENCAP(VLAN1_TCI_BE),
2220 	FIELD_ID_REMAP_TO_ENCAP(VLAN1_PROTO_BE),
2221 	FIELD_ID_REMAP_TO_ENCAP(SRC_IP4_BE),
2222 	FIELD_ID_REMAP_TO_ENCAP(DST_IP4_BE),
2223 	FIELD_ID_REMAP_TO_ENCAP(IP_PROTO),
2224 	FIELD_ID_REMAP_TO_ENCAP(IP_TOS),
2225 	FIELD_ID_REMAP_TO_ENCAP(IP_TTL),
2226 	FIELD_ID_REMAP_TO_ENCAP(SRC_IP6_BE),
2227 	FIELD_ID_REMAP_TO_ENCAP(DST_IP6_BE),
2228 	FIELD_ID_REMAP_TO_ENCAP(L4_SPORT_BE),
2229 	FIELD_ID_REMAP_TO_ENCAP(L4_DPORT_BE),
2230 	FIELD_ID_REMAP_TO_ENCAP(HAS_OVLAN),
2231 	FIELD_ID_REMAP_TO_ENCAP(HAS_IVLAN),
2232 
2233 #undef FIELD_ID_REMAP_TO_ENCAP
2234 };
2235 
2236 static int
2237 sfc_mae_rule_parse_item_tunnel(const struct rte_flow_item *item,
2238 			       struct sfc_flow_parse_ctx *ctx,
2239 			       struct rte_flow_error *error)
2240 {
2241 	struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
2242 	uint8_t vnet_id_v[sizeof(uint32_t)] = {0};
2243 	uint8_t vnet_id_m[sizeof(uint32_t)] = {0};
2244 	const struct rte_flow_item_vxlan *vxp;
2245 	uint8_t supp_mask[sizeof(uint64_t)];
2246 	const uint8_t *spec = NULL;
2247 	const uint8_t *mask = NULL;
2248 	int rc;
2249 
2250 	if (ctx_mae->ft_rule_type == SFC_FT_RULE_GROUP) {
2251 		/*
2252 		 * As a workaround, pattern processing has started from
2253 		 * this (tunnel) item. No pattern data to process yet.
2254 		 */
2255 	} else {
2256 		/*
2257 		 * We're about to start processing inner frame items.
2258 		 * Process pattern data that has been deferred so far
2259 		 * and reset pattern data storage.
2260 		 */
2261 		rc = sfc_mae_rule_process_pattern_data(ctx_mae, error);
2262 		if (rc != 0)
2263 			return rc;
2264 	}
2265 
2266 	memset(&ctx_mae->pattern_data, 0, sizeof(ctx_mae->pattern_data));
2267 
2268 	sfc_mae_item_build_supp_mask(flocs_tunnel, RTE_DIM(flocs_tunnel),
2269 				     &supp_mask, sizeof(supp_mask));
2270 
2271 	/*
2272 	 * This tunnel item was preliminarily detected by
2273 	 * sfc_mae_rule_encap_parse_init(). Default mask
2274 	 * was also picked by that helper. Use it here.
2275 	 */
2276 	rc = sfc_flow_parse_init(item,
2277 				 (const void **)&spec, (const void **)&mask,
2278 				 (const void *)&supp_mask,
2279 				 ctx_mae->tunnel_def_mask,
2280 				 ctx_mae->tunnel_def_mask_size,  error);
2281 	if (rc != 0)
2282 		return rc;
2283 
2284 	/*
2285 	 * This item and later ones comprise a
2286 	 * match specification of type ACTION.
2287 	 */
2288 	ctx_mae->match_spec = ctx_mae->match_spec_action;
2289 
2290 	/* This item and later ones use non-encap. EFX MAE field IDs. */
2291 	ctx_mae->field_ids_remap = field_ids_no_remap;
2292 
2293 	if (spec == NULL)
2294 		return 0;
2295 
2296 	/*
2297 	 * Field EFX_MAE_FIELD_ENC_VNET_ID_BE is a 32-bit one.
2298 	 * Copy 24-bit VNI, which is BE, at offset 1 in it.
2299 	 * The extra byte is 0 both in the mask and in the value.
2300 	 */
2301 	vxp = (const struct rte_flow_item_vxlan *)spec;
2302 	memcpy(vnet_id_v + 1, &vxp->vni, sizeof(vxp->vni));
2303 
2304 	vxp = (const struct rte_flow_item_vxlan *)mask;
2305 	memcpy(vnet_id_m + 1, &vxp->vni, sizeof(vxp->vni));
2306 
2307 	rc = efx_mae_match_spec_field_set(ctx_mae->match_spec,
2308 					  EFX_MAE_FIELD_ENC_VNET_ID_BE,
2309 					  sizeof(vnet_id_v), vnet_id_v,
2310 					  sizeof(vnet_id_m), vnet_id_m);
2311 	if (rc != 0) {
2312 		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
2313 					item, "Failed to set VXLAN VNI");
2314 	}
2315 
2316 	return rc;
2317 }
2318 
2319 static const struct sfc_flow_item sfc_flow_items[] = {
2320 	{
2321 		.type = RTE_FLOW_ITEM_TYPE_MARK,
2322 		.name = "MARK",
2323 		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
2324 		.layer = SFC_FLOW_ITEM_ANY_LAYER,
2325 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2326 		.parse = sfc_mae_rule_parse_item_mark,
2327 	},
2328 	{
2329 		.type = RTE_FLOW_ITEM_TYPE_PORT_ID,
2330 		.name = "PORT_ID",
2331 		/*
2332 		 * In terms of RTE flow, this item is a META one,
2333 		 * and its position in the pattern is don't care.
2334 		 */
2335 		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
2336 		.layer = SFC_FLOW_ITEM_ANY_LAYER,
2337 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2338 		.parse = sfc_mae_rule_parse_item_port_id,
2339 	},
2340 	{
2341 		.type = RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR,
2342 		.name = "PORT_REPRESENTOR",
2343 		/*
2344 		 * In terms of RTE flow, this item is a META one,
2345 		 * and its position in the pattern is don't care.
2346 		 */
2347 		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
2348 		.layer = SFC_FLOW_ITEM_ANY_LAYER,
2349 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2350 		.parse = sfc_mae_rule_parse_item_ethdev_based,
2351 	},
2352 	{
2353 		.type = RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT,
2354 		.name = "REPRESENTED_PORT",
2355 		/*
2356 		 * In terms of RTE flow, this item is a META one,
2357 		 * and its position in the pattern is don't care.
2358 		 */
2359 		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
2360 		.layer = SFC_FLOW_ITEM_ANY_LAYER,
2361 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2362 		.parse = sfc_mae_rule_parse_item_ethdev_based,
2363 	},
2364 	{
2365 		.type = RTE_FLOW_ITEM_TYPE_PHY_PORT,
2366 		.name = "PHY_PORT",
2367 		/*
2368 		 * In terms of RTE flow, this item is a META one,
2369 		 * and its position in the pattern is don't care.
2370 		 */
2371 		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
2372 		.layer = SFC_FLOW_ITEM_ANY_LAYER,
2373 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2374 		.parse = sfc_mae_rule_parse_item_phy_port,
2375 	},
2376 	{
2377 		.type = RTE_FLOW_ITEM_TYPE_PF,
2378 		.name = "PF",
2379 		/*
2380 		 * In terms of RTE flow, this item is a META one,
2381 		 * and its position in the pattern is don't care.
2382 		 */
2383 		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
2384 		.layer = SFC_FLOW_ITEM_ANY_LAYER,
2385 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2386 		.parse = sfc_mae_rule_parse_item_pf,
2387 	},
2388 	{
2389 		.type = RTE_FLOW_ITEM_TYPE_VF,
2390 		.name = "VF",
2391 		/*
2392 		 * In terms of RTE flow, this item is a META one,
2393 		 * and its position in the pattern is don't care.
2394 		 */
2395 		.prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
2396 		.layer = SFC_FLOW_ITEM_ANY_LAYER,
2397 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2398 		.parse = sfc_mae_rule_parse_item_vf,
2399 	},
2400 	{
2401 		.type = RTE_FLOW_ITEM_TYPE_ETH,
2402 		.name = "ETH",
2403 		.prev_layer = SFC_FLOW_ITEM_START_LAYER,
2404 		.layer = SFC_FLOW_ITEM_L2,
2405 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2406 		.parse = sfc_mae_rule_parse_item_eth,
2407 	},
2408 	{
2409 		.type = RTE_FLOW_ITEM_TYPE_VLAN,
2410 		.name = "VLAN",
2411 		.prev_layer = SFC_FLOW_ITEM_L2,
2412 		.layer = SFC_FLOW_ITEM_L2,
2413 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2414 		.parse = sfc_mae_rule_parse_item_vlan,
2415 	},
2416 	{
2417 		.type = RTE_FLOW_ITEM_TYPE_IPV4,
2418 		.name = "IPV4",
2419 		.prev_layer = SFC_FLOW_ITEM_L2,
2420 		.layer = SFC_FLOW_ITEM_L3,
2421 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2422 		.parse = sfc_mae_rule_parse_item_ipv4,
2423 	},
2424 	{
2425 		.type = RTE_FLOW_ITEM_TYPE_IPV6,
2426 		.name = "IPV6",
2427 		.prev_layer = SFC_FLOW_ITEM_L2,
2428 		.layer = SFC_FLOW_ITEM_L3,
2429 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2430 		.parse = sfc_mae_rule_parse_item_ipv6,
2431 	},
2432 	{
2433 		.type = RTE_FLOW_ITEM_TYPE_TCP,
2434 		.name = "TCP",
2435 		.prev_layer = SFC_FLOW_ITEM_L3,
2436 		.layer = SFC_FLOW_ITEM_L4,
2437 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2438 		.parse = sfc_mae_rule_parse_item_tcp,
2439 	},
2440 	{
2441 		.type = RTE_FLOW_ITEM_TYPE_UDP,
2442 		.name = "UDP",
2443 		.prev_layer = SFC_FLOW_ITEM_L3,
2444 		.layer = SFC_FLOW_ITEM_L4,
2445 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2446 		.parse = sfc_mae_rule_parse_item_udp,
2447 	},
2448 	{
2449 		.type = RTE_FLOW_ITEM_TYPE_VXLAN,
2450 		.name = "VXLAN",
2451 		.prev_layer = SFC_FLOW_ITEM_L4,
2452 		.layer = SFC_FLOW_ITEM_START_LAYER,
2453 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2454 		.parse = sfc_mae_rule_parse_item_tunnel,
2455 	},
2456 	{
2457 		.type = RTE_FLOW_ITEM_TYPE_GENEVE,
2458 		.name = "GENEVE",
2459 		.prev_layer = SFC_FLOW_ITEM_L4,
2460 		.layer = SFC_FLOW_ITEM_START_LAYER,
2461 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2462 		.parse = sfc_mae_rule_parse_item_tunnel,
2463 	},
2464 	{
2465 		.type = RTE_FLOW_ITEM_TYPE_NVGRE,
2466 		.name = "NVGRE",
2467 		.prev_layer = SFC_FLOW_ITEM_L3,
2468 		.layer = SFC_FLOW_ITEM_START_LAYER,
2469 		.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
2470 		.parse = sfc_mae_rule_parse_item_tunnel,
2471 	},
2472 };
2473 
2474 static int
2475 sfc_mae_rule_process_outer(struct sfc_adapter *sa,
2476 			   struct sfc_mae_parse_ctx *ctx,
2477 			   struct sfc_mae_outer_rule **rulep,
2478 			   struct rte_flow_error *error)
2479 {
2480 	efx_mae_rule_id_t invalid_rule_id = { .id = EFX_MAE_RSRC_ID_INVALID };
2481 	int rc;
2482 
2483 	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
2484 		*rulep = NULL;
2485 		goto no_or_id;
2486 	}
2487 
2488 	SFC_ASSERT(ctx->match_spec_outer != NULL);
2489 
2490 	if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) {
2491 		return rte_flow_error_set(error, ENOTSUP,
2492 					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
2493 					  "Inconsistent pattern (outer)");
2494 	}
2495 
2496 	*rulep = sfc_mae_outer_rule_attach(sa, ctx->match_spec_outer,
2497 					   ctx->encap_type);
2498 	if (*rulep != NULL) {
2499 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
2500 	} else {
2501 		rc = sfc_mae_outer_rule_add(sa, ctx->match_spec_outer,
2502 					    ctx->encap_type, rulep);
2503 		if (rc != 0) {
2504 			return rte_flow_error_set(error, rc,
2505 					RTE_FLOW_ERROR_TYPE_ITEM, NULL,
2506 					"Failed to process the pattern");
2507 		}
2508 	}
2509 
2510 	/* The spec has now been tracked by the outer rule entry. */
2511 	ctx->match_spec_outer = NULL;
2512 
2513 no_or_id:
2514 	switch (ctx->ft_rule_type) {
2515 	case SFC_FT_RULE_NONE:
2516 		break;
2517 	case SFC_FT_RULE_JUMP:
2518 		/* No action rule */
2519 		return 0;
2520 	case SFC_FT_RULE_GROUP:
2521 		/*
2522 		 * Match on recirculation ID rather than
2523 		 * on the outer rule allocation handle.
2524 		 */
2525 		rc = efx_mae_match_spec_recirc_id_set(ctx->match_spec_action,
2526 					SFC_FT_ID_TO_TUNNEL_MARK(ctx->ft->id));
2527 		if (rc != 0) {
2528 			return rte_flow_error_set(error, rc,
2529 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2530 					"tunnel offload: GROUP: AR: failed to request match on RECIRC_ID");
2531 		}
2532 		return 0;
2533 	default:
2534 		SFC_ASSERT(B_FALSE);
2535 	}
2536 
2537 	/*
2538 	 * In MAE, lookup sequence comprises outer parse, outer rule lookup,
2539 	 * inner parse (when some outer rule is hit) and action rule lookup.
2540 	 * If the currently processed flow does not come with an outer rule,
2541 	 * its action rule must be available only for packets which miss in
2542 	 * outer rule table. Set OR_ID match field to 0xffffffff/0xffffffff
2543 	 * in the action rule specification; this ensures correct behaviour.
2544 	 *
2545 	 * If, on the other hand, this flow does have an outer rule, its ID
2546 	 * may be unknown at the moment (not yet allocated), but OR_ID mask
2547 	 * has to be set to 0xffffffff anyway for correct class comparisons.
2548 	 * When the outer rule has been allocated, this match field will be
2549 	 * overridden by sfc_mae_outer_rule_enable() to use the right value.
2550 	 */
2551 	rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
2552 						  &invalid_rule_id);
2553 	if (rc != 0) {
2554 		if (*rulep != NULL)
2555 			sfc_mae_outer_rule_del(sa, *rulep);
2556 
2557 		*rulep = NULL;
2558 
2559 		return rte_flow_error_set(error, rc,
2560 					  RTE_FLOW_ERROR_TYPE_ITEM, NULL,
2561 					  "Failed to process the pattern");
2562 	}
2563 
2564 	return 0;
2565 }
2566 
2567 static int
2568 sfc_mae_rule_preparse_item_mark(const struct rte_flow_item_mark *spec,
2569 				struct sfc_mae_parse_ctx *ctx)
2570 {
2571 	struct sfc_flow_tunnel *ft;
2572 	uint32_t user_mark;
2573 
2574 	if (spec == NULL) {
2575 		sfc_err(ctx->sa, "tunnel offload: GROUP: NULL spec in item MARK");
2576 		return EINVAL;
2577 	}
2578 
2579 	ft = sfc_flow_tunnel_pick(ctx->sa, spec->id);
2580 	if (ft == NULL) {
2581 		sfc_err(ctx->sa, "tunnel offload: GROUP: invalid tunnel");
2582 		return EINVAL;
2583 	}
2584 
2585 	if (ft->refcnt == 0) {
2586 		sfc_err(ctx->sa, "tunnel offload: GROUP: tunnel=%u does not exist",
2587 			ft->id);
2588 		return ENOENT;
2589 	}
2590 
2591 	user_mark = SFC_FT_GET_USER_MARK(spec->id);
2592 	if (user_mark != 0) {
2593 		sfc_err(ctx->sa, "tunnel offload: GROUP: invalid item MARK");
2594 		return EINVAL;
2595 	}
2596 
2597 	sfc_dbg(ctx->sa, "tunnel offload: GROUP: detected");
2598 
2599 	ctx->ft_rule_type = SFC_FT_RULE_GROUP;
2600 	ctx->ft = ft;
2601 
2602 	return 0;
2603 }
2604 
2605 static int
2606 sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
2607 			      struct sfc_mae_parse_ctx *ctx,
2608 			      struct rte_flow_error *error)
2609 {
2610 	const struct rte_flow_item *pattern = ctx->pattern;
2611 	struct sfc_mae *mae = &sa->mae;
2612 	uint8_t recirc_id = 0;
2613 	int rc;
2614 
2615 	if (pattern == NULL) {
2616 		rte_flow_error_set(error, EINVAL,
2617 				   RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
2618 				   "NULL pattern");
2619 		return -rte_errno;
2620 	}
2621 
2622 	for (;;) {
2623 		switch (pattern->type) {
2624 		case RTE_FLOW_ITEM_TYPE_MARK:
2625 			rc = sfc_mae_rule_preparse_item_mark(pattern->spec,
2626 							     ctx);
2627 			if (rc != 0) {
2628 				return rte_flow_error_set(error, rc,
2629 						  RTE_FLOW_ERROR_TYPE_ITEM,
2630 						  pattern, "tunnel offload: GROUP: invalid item MARK");
2631 			}
2632 			++pattern;
2633 			continue;
2634 		case RTE_FLOW_ITEM_TYPE_VXLAN:
2635 			ctx->encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
2636 			ctx->tunnel_def_mask = &rte_flow_item_vxlan_mask;
2637 			ctx->tunnel_def_mask_size =
2638 				sizeof(rte_flow_item_vxlan_mask);
2639 			break;
2640 		case RTE_FLOW_ITEM_TYPE_GENEVE:
2641 			ctx->encap_type = EFX_TUNNEL_PROTOCOL_GENEVE;
2642 			ctx->tunnel_def_mask = &rte_flow_item_geneve_mask;
2643 			ctx->tunnel_def_mask_size =
2644 				sizeof(rte_flow_item_geneve_mask);
2645 			break;
2646 		case RTE_FLOW_ITEM_TYPE_NVGRE:
2647 			ctx->encap_type = EFX_TUNNEL_PROTOCOL_NVGRE;
2648 			ctx->tunnel_def_mask = &rte_flow_item_nvgre_mask;
2649 			ctx->tunnel_def_mask_size =
2650 				sizeof(rte_flow_item_nvgre_mask);
2651 			break;
2652 		case RTE_FLOW_ITEM_TYPE_END:
2653 			break;
2654 		default:
2655 			++pattern;
2656 			continue;
2657 		};
2658 
2659 		break;
2660 	}
2661 
2662 	switch (ctx->ft_rule_type) {
2663 	case SFC_FT_RULE_NONE:
2664 		if (pattern->type == RTE_FLOW_ITEM_TYPE_END)
2665 			return 0;
2666 		break;
2667 	case SFC_FT_RULE_JUMP:
2668 		if (pattern->type != RTE_FLOW_ITEM_TYPE_END) {
2669 			return rte_flow_error_set(error, ENOTSUP,
2670 						  RTE_FLOW_ERROR_TYPE_ITEM,
2671 						  pattern, "tunnel offload: JUMP: invalid item");
2672 		}
2673 		ctx->encap_type = ctx->ft->encap_type;
2674 		break;
2675 	case SFC_FT_RULE_GROUP:
2676 		if (pattern->type == RTE_FLOW_ITEM_TYPE_END) {
2677 			return rte_flow_error_set(error, EINVAL,
2678 						  RTE_FLOW_ERROR_TYPE_ITEM,
2679 						  NULL, "tunnel offload: GROUP: missing tunnel item");
2680 		} else if (ctx->encap_type != ctx->ft->encap_type) {
2681 			return rte_flow_error_set(error, EINVAL,
2682 						  RTE_FLOW_ERROR_TYPE_ITEM,
2683 						  pattern, "tunnel offload: GROUP: tunnel type mismatch");
2684 		}
2685 
2686 		/*
2687 		 * The HW/FW hasn't got support for the use of "ENC" fields in
2688 		 * action rules (except the VNET_ID one) yet. As a workaround,
2689 		 * start parsing the pattern from the tunnel item.
2690 		 */
2691 		ctx->pattern = pattern;
2692 		break;
2693 	default:
2694 		SFC_ASSERT(B_FALSE);
2695 		break;
2696 	}
2697 
2698 	if ((mae->encap_types_supported & (1U << ctx->encap_type)) == 0) {
2699 		return rte_flow_error_set(error, ENOTSUP,
2700 					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2701 					  "OR: unsupported tunnel type");
2702 	}
2703 
2704 	switch (ctx->ft_rule_type) {
2705 	case SFC_FT_RULE_JUMP:
2706 		recirc_id = SFC_FT_ID_TO_TUNNEL_MARK(ctx->ft->id);
2707 		/* FALLTHROUGH */
2708 	case SFC_FT_RULE_NONE:
2709 		if (ctx->priority >= mae->nb_outer_rule_prios_max) {
2710 			return rte_flow_error_set(error, ENOTSUP,
2711 					RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
2712 					NULL, "OR: unsupported priority level");
2713 		}
2714 
2715 		rc = efx_mae_match_spec_init(sa->nic,
2716 					     EFX_MAE_RULE_OUTER, ctx->priority,
2717 					     &ctx->match_spec_outer);
2718 		if (rc != 0) {
2719 			return rte_flow_error_set(error, rc,
2720 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2721 				"OR: failed to initialise the match specification");
2722 		}
2723 
2724 		/*
2725 		 * Outermost items comprise a match
2726 		 * specification of type OUTER.
2727 		 */
2728 		ctx->match_spec = ctx->match_spec_outer;
2729 
2730 		/* Outermost items use "ENC" EFX MAE field IDs. */
2731 		ctx->field_ids_remap = field_ids_remap_to_encap;
2732 
2733 		rc = efx_mae_outer_rule_recirc_id_set(ctx->match_spec,
2734 						      recirc_id);
2735 		if (rc != 0) {
2736 			return rte_flow_error_set(error, rc,
2737 					RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2738 					"OR: failed to initialise RECIRC_ID");
2739 		}
2740 		break;
2741 	case SFC_FT_RULE_GROUP:
2742 		/* Outermost items -> "ENC" match fields in the action rule. */
2743 		ctx->field_ids_remap = field_ids_remap_to_encap;
2744 		ctx->match_spec = ctx->match_spec_action;
2745 
2746 		/* No own outer rule; match on JUMP OR's RECIRC_ID is used. */
2747 		ctx->encap_type = EFX_TUNNEL_PROTOCOL_NONE;
2748 		break;
2749 	default:
2750 		SFC_ASSERT(B_FALSE);
2751 		break;
2752 	}
2753 
2754 	return 0;
2755 }
2756 
2757 static void
2758 sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
2759 			      struct sfc_mae_parse_ctx *ctx)
2760 {
2761 	if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE)
2762 		return;
2763 
2764 	if (ctx->match_spec_outer != NULL)
2765 		efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
2766 }
2767 
2768 int
2769 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
2770 			   const struct rte_flow_item pattern[],
2771 			   struct sfc_flow_spec_mae *spec,
2772 			   struct rte_flow_error *error)
2773 {
2774 	struct sfc_mae_parse_ctx ctx_mae;
2775 	unsigned int priority_shift = 0;
2776 	struct sfc_flow_parse_ctx ctx;
2777 	int rc;
2778 
2779 	memset(&ctx_mae, 0, sizeof(ctx_mae));
2780 	ctx_mae.ft_rule_type = spec->ft_rule_type;
2781 	ctx_mae.priority = spec->priority;
2782 	ctx_mae.ft = spec->ft;
2783 	ctx_mae.sa = sa;
2784 
2785 	switch (ctx_mae.ft_rule_type) {
2786 	case SFC_FT_RULE_JUMP:
2787 		/*
2788 		 * By design, this flow should be represented solely by the
2789 		 * outer rule. But the HW/FW hasn't got support for setting
2790 		 * Rx mark from RECIRC_ID on outer rule lookup yet. Neither
2791 		 * does it support outer rule counters. As a workaround, an
2792 		 * action rule of lower priority is used to do the job.
2793 		 */
2794 		priority_shift = 1;
2795 
2796 		/* FALLTHROUGH */
2797 	case SFC_FT_RULE_GROUP:
2798 		if (ctx_mae.priority != 0) {
2799 			/*
2800 			 * Because of the above workaround, deny the
2801 			 * use of priorities to JUMP and GROUP rules.
2802 			 */
2803 			rc = rte_flow_error_set(error, ENOTSUP,
2804 				RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
2805 				"tunnel offload: priorities are not supported");
2806 			goto fail_priority_check;
2807 		}
2808 
2809 		/* FALLTHROUGH */
2810 	case SFC_FT_RULE_NONE:
2811 		rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
2812 					     spec->priority + priority_shift,
2813 					     &ctx_mae.match_spec_action);
2814 		if (rc != 0) {
2815 			rc = rte_flow_error_set(error, rc,
2816 				RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
2817 				"AR: failed to initialise the match specification");
2818 			goto fail_init_match_spec_action;
2819 		}
2820 		break;
2821 	default:
2822 		SFC_ASSERT(B_FALSE);
2823 		break;
2824 	}
2825 
2826 	/*
2827 	 * As a preliminary setting, assume that there is no encapsulation
2828 	 * in the pattern. That is, pattern items are about to comprise a
2829 	 * match specification of type ACTION and use non-encap. field IDs.
2830 	 *
2831 	 * sfc_mae_rule_encap_parse_init() below may override this.
2832 	 */
2833 	ctx_mae.encap_type = EFX_TUNNEL_PROTOCOL_NONE;
2834 	ctx_mae.match_spec = ctx_mae.match_spec_action;
2835 	ctx_mae.field_ids_remap = field_ids_no_remap;
2836 	ctx_mae.pattern = pattern;
2837 
2838 	ctx.type = SFC_FLOW_PARSE_CTX_MAE;
2839 	ctx.mae = &ctx_mae;
2840 
2841 	rc = sfc_mae_rule_encap_parse_init(sa, &ctx_mae, error);
2842 	if (rc != 0)
2843 		goto fail_encap_parse_init;
2844 
2845 	/*
2846 	 * sfc_mae_rule_encap_parse_init() may have detected tunnel offload
2847 	 * GROUP rule. Remember its properties for later use.
2848 	 */
2849 	spec->ft_rule_type = ctx_mae.ft_rule_type;
2850 	spec->ft = ctx_mae.ft;
2851 
2852 	rc = sfc_flow_parse_pattern(sa, sfc_flow_items, RTE_DIM(sfc_flow_items),
2853 				    ctx_mae.pattern, &ctx, error);
2854 	if (rc != 0)
2855 		goto fail_parse_pattern;
2856 
2857 	rc = sfc_mae_rule_process_pattern_data(&ctx_mae, error);
2858 	if (rc != 0)
2859 		goto fail_process_pattern_data;
2860 
2861 	rc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error);
2862 	if (rc != 0)
2863 		goto fail_process_outer;
2864 
2865 	if (ctx_mae.match_spec_action != NULL &&
2866 	    !efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {
2867 		rc = rte_flow_error_set(error, ENOTSUP,
2868 					RTE_FLOW_ERROR_TYPE_ITEM, NULL,
2869 					"Inconsistent pattern");
2870 		goto fail_validate_match_spec_action;
2871 	}
2872 
2873 	spec->match_spec = ctx_mae.match_spec_action;
2874 
2875 	return 0;
2876 
2877 fail_validate_match_spec_action:
2878 fail_process_outer:
2879 fail_process_pattern_data:
2880 fail_parse_pattern:
2881 	sfc_mae_rule_encap_parse_fini(sa, &ctx_mae);
2882 
2883 fail_encap_parse_init:
2884 	if (ctx_mae.match_spec_action != NULL)
2885 		efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
2886 
2887 fail_init_match_spec_action:
2888 fail_priority_check:
2889 	return rc;
2890 }
2891 
2892 /*
2893  * An action supported by MAE may correspond to a bundle of RTE flow actions,
2894  * in example, VLAN_PUSH = OF_PUSH_VLAN + OF_VLAN_SET_VID + OF_VLAN_SET_PCP.
2895  * That is, related RTE flow actions need to be tracked as parts of a whole
2896  * so that they can be combined into a single action and submitted to MAE
2897  * representation of a given rule's action set.
2898  *
2899  * Each RTE flow action provided by an application gets classified as
2900  * one belonging to some bundle type. If an action is not supposed to
2901  * belong to any bundle, or if this action is END, it is described as
2902  * one belonging to a dummy bundle of type EMPTY.
2903  *
2904  * A currently tracked bundle will be submitted if a repeating
2905  * action or an action of different bundle type follows.
2906  */
2907 
2908 enum sfc_mae_actions_bundle_type {
2909 	SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
2910 	SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
2911 };
2912 
2913 struct sfc_mae_actions_bundle {
2914 	enum sfc_mae_actions_bundle_type	type;
2915 
2916 	/* Indicates actions already tracked by the current bundle */
2917 	uint64_t				actions_mask;
2918 
2919 	/* Parameters used by SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH */
2920 	rte_be16_t				vlan_push_tpid;
2921 	rte_be16_t				vlan_push_tci;
2922 };
2923 
2924 /*
2925  * Combine configuration of RTE flow actions tracked by the bundle into a
2926  * single action and submit the result to MAE action set specification.
2927  * Do nothing in the case of dummy action bundle.
2928  */
2929 static int
2930 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
2931 			      efx_mae_actions_t *spec)
2932 {
2933 	int rc = 0;
2934 
2935 	switch (bundle->type) {
2936 	case SFC_MAE_ACTIONS_BUNDLE_EMPTY:
2937 		break;
2938 	case SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH:
2939 		rc = efx_mae_action_set_populate_vlan_push(
2940 			spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
2941 		break;
2942 	default:
2943 		SFC_ASSERT(B_FALSE);
2944 		break;
2945 	}
2946 
2947 	return rc;
2948 }
2949 
2950 /*
2951  * Given the type of the next RTE flow action in the line, decide
2952  * whether a new bundle is about to start, and, if this is the case,
2953  * submit and reset the current bundle.
2954  */
2955 static int
2956 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
2957 			    struct sfc_mae_actions_bundle *bundle,
2958 			    efx_mae_actions_t *spec,
2959 			    struct rte_flow_error *error)
2960 {
2961 	enum sfc_mae_actions_bundle_type bundle_type_new;
2962 	int rc;
2963 
2964 	switch (action->type) {
2965 	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
2966 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
2967 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
2968 		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
2969 		break;
2970 	default:
2971 		/*
2972 		 * Self-sufficient actions, including END, are handled in this
2973 		 * case. No checks for unsupported actions are needed here
2974 		 * because parsing doesn't occur at this point.
2975 		 */
2976 		bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_EMPTY;
2977 		break;
2978 	}
2979 
2980 	if (bundle_type_new != bundle->type ||
2981 	    (bundle->actions_mask & (1ULL << action->type)) != 0) {
2982 		rc = sfc_mae_actions_bundle_submit(bundle, spec);
2983 		if (rc != 0)
2984 			goto fail_submit;
2985 
2986 		memset(bundle, 0, sizeof(*bundle));
2987 	}
2988 
2989 	bundle->type = bundle_type_new;
2990 
2991 	return 0;
2992 
2993 fail_submit:
2994 	return rte_flow_error_set(error, rc,
2995 			RTE_FLOW_ERROR_TYPE_ACTION, NULL,
2996 			"Failed to request the (group of) action(s)");
2997 }
2998 
2999 static void
3000 sfc_mae_rule_parse_action_of_push_vlan(
3001 			    const struct rte_flow_action_of_push_vlan *conf,
3002 			    struct sfc_mae_actions_bundle *bundle)
3003 {
3004 	bundle->vlan_push_tpid = conf->ethertype;
3005 }
3006 
3007 static void
3008 sfc_mae_rule_parse_action_of_set_vlan_vid(
3009 			    const struct rte_flow_action_of_set_vlan_vid *conf,
3010 			    struct sfc_mae_actions_bundle *bundle)
3011 {
3012 	bundle->vlan_push_tci |= (conf->vlan_vid &
3013 				  rte_cpu_to_be_16(RTE_LEN2MASK(12, uint16_t)));
3014 }
3015 
3016 static void
3017 sfc_mae_rule_parse_action_of_set_vlan_pcp(
3018 			    const struct rte_flow_action_of_set_vlan_pcp *conf,
3019 			    struct sfc_mae_actions_bundle *bundle)
3020 {
3021 	uint16_t vlan_tci_pcp = (uint16_t)(conf->vlan_pcp &
3022 					   RTE_LEN2MASK(3, uint8_t)) << 13;
3023 
3024 	bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp);
3025 }
3026 
3027 struct sfc_mae_parsed_item {
3028 	const struct rte_flow_item	*item;
3029 	size_t				proto_header_ofst;
3030 	size_t				proto_header_size;
3031 };
3032 
3033 /*
3034  * For each 16-bit word of the given header, override
3035  * bits enforced by the corresponding 16-bit mask.
3036  */
3037 static void
3038 sfc_mae_header_force_item_masks(uint8_t *header_buf,
3039 				const struct sfc_mae_parsed_item *parsed_items,
3040 				unsigned int nb_parsed_items)
3041 {
3042 	unsigned int item_idx;
3043 
3044 	for (item_idx = 0; item_idx < nb_parsed_items; ++item_idx) {
3045 		const struct sfc_mae_parsed_item *parsed_item;
3046 		const struct rte_flow_item *item;
3047 		size_t proto_header_size;
3048 		size_t ofst;
3049 
3050 		parsed_item = &parsed_items[item_idx];
3051 		proto_header_size = parsed_item->proto_header_size;
3052 		item = parsed_item->item;
3053 
3054 		for (ofst = 0; ofst < proto_header_size;
3055 		     ofst += sizeof(rte_be16_t)) {
3056 			rte_be16_t *wp = RTE_PTR_ADD(header_buf, ofst);
3057 			const rte_be16_t *w_maskp;
3058 			const rte_be16_t *w_specp;
3059 
3060 			w_maskp = RTE_PTR_ADD(item->mask, ofst);
3061 			w_specp = RTE_PTR_ADD(item->spec, ofst);
3062 
3063 			*wp &= ~(*w_maskp);
3064 			*wp |= (*w_specp & *w_maskp);
3065 		}
3066 
3067 		header_buf += proto_header_size;
3068 	}
3069 }
3070 
3071 #define SFC_IPV4_TTL_DEF	0x40
3072 #define SFC_IPV6_VTC_FLOW_DEF	0x60000000
3073 #define SFC_IPV6_HOP_LIMITS_DEF	0xff
3074 #define SFC_VXLAN_FLAGS_DEF	0x08000000
3075 
3076 static int
3077 sfc_mae_rule_parse_action_vxlan_encap(
3078 			    struct sfc_mae *mae,
3079 			    const struct rte_flow_action_vxlan_encap *conf,
3080 			    efx_mae_actions_t *spec,
3081 			    struct rte_flow_error *error)
3082 {
3083 	struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
3084 	struct rte_flow_item *pattern = conf->definition;
3085 	uint8_t *buf = bounce_eh->buf;
3086 
3087 	/* This array will keep track of non-VOID pattern items. */
3088 	struct sfc_mae_parsed_item parsed_items[1 /* Ethernet */ +
3089 						2 /* VLAN tags */ +
3090 						1 /* IPv4 or IPv6 */ +
3091 						1 /* UDP */ +
3092 						1 /* VXLAN */];
3093 	unsigned int nb_parsed_items = 0;
3094 
3095 	size_t eth_ethertype_ofst = offsetof(struct rte_ether_hdr, ether_type);
3096 	uint8_t dummy_buf[RTE_MAX(sizeof(struct rte_ipv4_hdr),
3097 				  sizeof(struct rte_ipv6_hdr))];
3098 	struct rte_ipv4_hdr *ipv4 = (void *)dummy_buf;
3099 	struct rte_ipv6_hdr *ipv6 = (void *)dummy_buf;
3100 	struct rte_vxlan_hdr *vxlan = NULL;
3101 	struct rte_udp_hdr *udp = NULL;
3102 	unsigned int nb_vlan_tags = 0;
3103 	size_t next_proto_ofst = 0;
3104 	size_t ethertype_ofst = 0;
3105 	uint64_t exp_items;
3106 	int rc;
3107 
3108 	if (pattern == NULL) {
3109 		return rte_flow_error_set(error, EINVAL,
3110 				RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3111 				"The encap. header definition is NULL");
3112 	}
3113 
3114 	bounce_eh->type = EFX_TUNNEL_PROTOCOL_VXLAN;
3115 	bounce_eh->size = 0;
3116 
3117 	/*
3118 	 * Process pattern items and remember non-VOID ones.
3119 	 * Defer applying masks until after the complete header
3120 	 * has been built from the pattern items.
3121 	 */
3122 	exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_ETH);
3123 
3124 	for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; ++pattern) {
3125 		struct sfc_mae_parsed_item *parsed_item;
3126 		const uint64_t exp_items_extra_vlan[] = {
3127 			RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN), 0
3128 		};
3129 		size_t proto_header_size;
3130 		rte_be16_t *ethertypep;
3131 		uint8_t *next_protop;
3132 		uint8_t *buf_cur;
3133 
3134 		if (pattern->spec == NULL) {
3135 			return rte_flow_error_set(error, EINVAL,
3136 					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3137 					"NULL item spec in the encap. header");
3138 		}
3139 
3140 		if (pattern->mask == NULL) {
3141 			return rte_flow_error_set(error, EINVAL,
3142 					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3143 					"NULL item mask in the encap. header");
3144 		}
3145 
3146 		if (pattern->last != NULL) {
3147 			/* This is not a match pattern, so disallow range. */
3148 			return rte_flow_error_set(error, EINVAL,
3149 					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3150 					"Range item in the encap. header");
3151 		}
3152 
3153 		if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID) {
3154 			/* Handle VOID separately, for clarity. */
3155 			continue;
3156 		}
3157 
3158 		if ((exp_items & RTE_BIT64(pattern->type)) == 0) {
3159 			return rte_flow_error_set(error, ENOTSUP,
3160 					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3161 					"Unexpected item in the encap. header");
3162 		}
3163 
3164 		parsed_item = &parsed_items[nb_parsed_items];
3165 		buf_cur = buf + bounce_eh->size;
3166 
3167 		switch (pattern->type) {
3168 		case RTE_FLOW_ITEM_TYPE_ETH:
3169 			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_ETH,
3170 					       exp_items);
3171 			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_eth,
3172 						  hdr) != 0);
3173 
3174 			proto_header_size = sizeof(struct rte_ether_hdr);
3175 
3176 			ethertype_ofst = eth_ethertype_ofst;
3177 
3178 			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN) |
3179 				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
3180 				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
3181 			break;
3182 		case RTE_FLOW_ITEM_TYPE_VLAN:
3183 			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VLAN,
3184 					       exp_items);
3185 			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vlan,
3186 						  hdr) != 0);
3187 
3188 			proto_header_size = sizeof(struct rte_vlan_hdr);
3189 
3190 			ethertypep = RTE_PTR_ADD(buf, eth_ethertype_ofst);
3191 			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_QINQ);
3192 
3193 			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
3194 			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_VLAN);
3195 
3196 			ethertype_ofst =
3197 			    bounce_eh->size +
3198 			    offsetof(struct rte_vlan_hdr, eth_proto);
3199 
3200 			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
3201 				    RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
3202 			exp_items |= exp_items_extra_vlan[nb_vlan_tags];
3203 
3204 			++nb_vlan_tags;
3205 			break;
3206 		case RTE_FLOW_ITEM_TYPE_IPV4:
3207 			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV4,
3208 					       exp_items);
3209 			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv4,
3210 						  hdr) != 0);
3211 
3212 			proto_header_size = sizeof(struct rte_ipv4_hdr);
3213 
3214 			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
3215 			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV4);
3216 
3217 			next_proto_ofst =
3218 			    bounce_eh->size +
3219 			    offsetof(struct rte_ipv4_hdr, next_proto_id);
3220 
3221 			ipv4 = (struct rte_ipv4_hdr *)buf_cur;
3222 
3223 			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
3224 			break;
3225 		case RTE_FLOW_ITEM_TYPE_IPV6:
3226 			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV6,
3227 					       exp_items);
3228 			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv6,
3229 						  hdr) != 0);
3230 
3231 			proto_header_size = sizeof(struct rte_ipv6_hdr);
3232 
3233 			ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
3234 			*ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV6);
3235 
3236 			next_proto_ofst = bounce_eh->size +
3237 					  offsetof(struct rte_ipv6_hdr, proto);
3238 
3239 			ipv6 = (struct rte_ipv6_hdr *)buf_cur;
3240 
3241 			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
3242 			break;
3243 		case RTE_FLOW_ITEM_TYPE_UDP:
3244 			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_UDP,
3245 					       exp_items);
3246 			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_udp,
3247 						  hdr) != 0);
3248 
3249 			proto_header_size = sizeof(struct rte_udp_hdr);
3250 
3251 			next_protop = RTE_PTR_ADD(buf, next_proto_ofst);
3252 			*next_protop = IPPROTO_UDP;
3253 
3254 			udp = (struct rte_udp_hdr *)buf_cur;
3255 
3256 			exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VXLAN);
3257 			break;
3258 		case RTE_FLOW_ITEM_TYPE_VXLAN:
3259 			SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VXLAN,
3260 					       exp_items);
3261 			RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vxlan,
3262 						  hdr) != 0);
3263 
3264 			proto_header_size = sizeof(struct rte_vxlan_hdr);
3265 
3266 			vxlan = (struct rte_vxlan_hdr *)buf_cur;
3267 
3268 			udp->dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT);
3269 			udp->dgram_len = RTE_BE16(sizeof(*udp) +
3270 						  sizeof(*vxlan));
3271 			udp->dgram_cksum = 0;
3272 
3273 			exp_items = 0;
3274 			break;
3275 		default:
3276 			return rte_flow_error_set(error, ENOTSUP,
3277 					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3278 					"Unknown item in the encap. header");
3279 		}
3280 
3281 		if (bounce_eh->size + proto_header_size > bounce_eh->buf_size) {
3282 			return rte_flow_error_set(error, E2BIG,
3283 					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3284 					"The encap. header is too big");
3285 		}
3286 
3287 		if ((proto_header_size & 1) != 0) {
3288 			return rte_flow_error_set(error, EINVAL,
3289 					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3290 					"Odd layer size in the encap. header");
3291 		}
3292 
3293 		rte_memcpy(buf_cur, pattern->spec, proto_header_size);
3294 		bounce_eh->size += proto_header_size;
3295 
3296 		parsed_item->item = pattern;
3297 		parsed_item->proto_header_size = proto_header_size;
3298 		++nb_parsed_items;
3299 	}
3300 
3301 	if (exp_items != 0) {
3302 		/* Parsing item VXLAN would have reset exp_items to 0. */
3303 		return rte_flow_error_set(error, ENOTSUP,
3304 					RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
3305 					"No item VXLAN in the encap. header");
3306 	}
3307 
3308 	/* One of the pointers (ipv4, ipv6) refers to a dummy area. */
3309 	ipv4->version_ihl = RTE_IPV4_VHL_DEF;
3310 	ipv4->time_to_live = SFC_IPV4_TTL_DEF;
3311 	ipv4->total_length = RTE_BE16(sizeof(*ipv4) + sizeof(*udp) +
3312 				      sizeof(*vxlan));
3313 	/* The HW cannot compute this checksum. */
3314 	ipv4->hdr_checksum = 0;
3315 	ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
3316 
3317 	ipv6->vtc_flow = RTE_BE32(SFC_IPV6_VTC_FLOW_DEF);
3318 	ipv6->hop_limits = SFC_IPV6_HOP_LIMITS_DEF;
3319 	ipv6->payload_len = udp->dgram_len;
3320 
3321 	vxlan->vx_flags = RTE_BE32(SFC_VXLAN_FLAGS_DEF);
3322 
3323 	/* Take care of the masks. */
3324 	sfc_mae_header_force_item_masks(buf, parsed_items, nb_parsed_items);
3325 
3326 	rc = efx_mae_action_set_populate_encap(spec);
3327 	if (rc != 0) {
3328 		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
3329 				NULL, "failed to request action ENCAP");
3330 	}
3331 
3332 	return rc;
3333 }
3334 
3335 static int
3336 sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
3337 			       const struct rte_flow_action_mark *conf,
3338 			       const struct sfc_flow_spec_mae *spec_mae,
3339 			       efx_mae_actions_t *spec)
3340 {
3341 	int rc;
3342 
3343 	if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
3344 		/* Workaround. See sfc_flow_parse_rte_to_mae() */
3345 	} else if (conf->id > SFC_FT_USER_MARK_MASK) {
3346 		sfc_err(sa, "the mark value is too large");
3347 		return EINVAL;
3348 	}
3349 
3350 	rc = efx_mae_action_set_populate_mark(spec, conf->id);
3351 	if (rc != 0)
3352 		sfc_err(sa, "failed to request action MARK: %s", strerror(rc));
3353 
3354 	return rc;
3355 }
3356 
3357 static int
3358 sfc_mae_rule_parse_action_count(struct sfc_adapter *sa,
3359 				const struct rte_flow_action_count *conf
3360 					__rte_unused,
3361 				efx_mae_actions_t *spec)
3362 {
3363 	int rc;
3364 
3365 	if ((sa->counter_rxq.state & SFC_COUNTER_RXQ_INITIALIZED) == 0) {
3366 		sfc_err(sa,
3367 			"counter queue is not configured for COUNT action");
3368 		rc = EINVAL;
3369 		goto fail_counter_queue_uninit;
3370 	}
3371 
3372 	if (sfc_get_service_lcore(SOCKET_ID_ANY) == RTE_MAX_LCORE) {
3373 		rc = EINVAL;
3374 		goto fail_no_service_core;
3375 	}
3376 
3377 	rc = efx_mae_action_set_populate_count(spec);
3378 	if (rc != 0) {
3379 		sfc_err(sa,
3380 			"failed to populate counters in MAE action set: %s",
3381 			rte_strerror(rc));
3382 		goto fail_populate_count;
3383 	}
3384 
3385 	return 0;
3386 
3387 fail_populate_count:
3388 fail_no_service_core:
3389 fail_counter_queue_uninit:
3390 
3391 	return rc;
3392 }
3393 
3394 static int
3395 sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
3396 				   const struct rte_flow_action_phy_port *conf,
3397 				   efx_mae_actions_t *spec)
3398 {
3399 	efx_mport_sel_t mport;
3400 	uint32_t phy_port;
3401 	int rc;
3402 
3403 	if (conf->original != 0)
3404 		phy_port = efx_nic_cfg_get(sa->nic)->enc_assigned_port;
3405 	else
3406 		phy_port = conf->index;
3407 
3408 	rc = efx_mae_mport_by_phy_port(phy_port, &mport);
3409 	if (rc != 0) {
3410 		sfc_err(sa, "failed to convert phys. port ID %u to m-port selector: %s",
3411 			phy_port, strerror(rc));
3412 		return rc;
3413 	}
3414 
3415 	rc = efx_mae_action_set_populate_deliver(spec, &mport);
3416 	if (rc != 0) {
3417 		sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
3418 			mport.sel, strerror(rc));
3419 	}
3420 
3421 	return rc;
3422 }
3423 
3424 static int
3425 sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
3426 				const struct rte_flow_action_vf *vf_conf,
3427 				efx_mae_actions_t *spec)
3428 {
3429 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
3430 	efx_mport_sel_t mport;
3431 	uint32_t vf;
3432 	int rc;
3433 
3434 	if (vf_conf == NULL)
3435 		vf = EFX_PCI_VF_INVALID;
3436 	else if (vf_conf->original != 0)
3437 		vf = encp->enc_vf;
3438 	else
3439 		vf = vf_conf->id;
3440 
3441 	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, vf, &mport);
3442 	if (rc != 0) {
3443 		sfc_err(sa, "failed to convert PF %u VF %d to m-port: %s",
3444 			encp->enc_pf, (vf != EFX_PCI_VF_INVALID) ? (int)vf : -1,
3445 			strerror(rc));
3446 		return rc;
3447 	}
3448 
3449 	rc = efx_mae_action_set_populate_deliver(spec, &mport);
3450 	if (rc != 0) {
3451 		sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
3452 			mport.sel, strerror(rc));
3453 	}
3454 
3455 	return rc;
3456 }
3457 
3458 static int
3459 sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
3460 				  const struct rte_flow_action_port_id *conf,
3461 				  efx_mae_actions_t *spec)
3462 {
3463 	struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
3464 	struct sfc_mae *mae = &sa->mae;
3465 	efx_mport_sel_t mport;
3466 	uint16_t port_id;
3467 	int rc;
3468 
3469 	if (conf->id > UINT16_MAX)
3470 		return EOVERFLOW;
3471 
3472 	port_id = (conf->original != 0) ? sas->port_id : conf->id;
3473 
3474 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
3475 					     port_id, &mport);
3476 	if (rc != 0) {
3477 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
3478 			port_id, strerror(rc));
3479 		return rc;
3480 	}
3481 
3482 	rc = efx_mae_action_set_populate_deliver(spec, &mport);
3483 	if (rc != 0) {
3484 		sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
3485 			mport.sel, strerror(rc));
3486 	}
3487 
3488 	return rc;
3489 }
3490 
3491 static int
3492 sfc_mae_rule_parse_action_port_representor(struct sfc_adapter *sa,
3493 		const struct rte_flow_action_ethdev *conf,
3494 		efx_mae_actions_t *spec)
3495 {
3496 	struct sfc_mae *mae = &sa->mae;
3497 	efx_mport_sel_t mport;
3498 	int rc;
3499 
3500 	rc = sfc_mae_switch_get_ethdev_mport(mae->switch_domain_id,
3501 					     conf->port_id, &mport);
3502 	if (rc != 0) {
3503 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
3504 			conf->port_id, strerror(rc));
3505 		return rc;
3506 	}
3507 
3508 	rc = efx_mae_action_set_populate_deliver(spec, &mport);
3509 	if (rc != 0) {
3510 		sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
3511 			mport.sel, strerror(rc));
3512 	}
3513 
3514 	return rc;
3515 }
3516 
3517 static int
3518 sfc_mae_rule_parse_action_represented_port(struct sfc_adapter *sa,
3519 		const struct rte_flow_action_ethdev *conf,
3520 		efx_mae_actions_t *spec)
3521 {
3522 	struct sfc_mae *mae = &sa->mae;
3523 	efx_mport_sel_t mport;
3524 	int rc;
3525 
3526 	rc = sfc_mae_switch_get_entity_mport(mae->switch_domain_id,
3527 					     conf->port_id, &mport);
3528 	if (rc != 0) {
3529 		sfc_err(sa, "failed to get m-port for the given ethdev (port_id=%u): %s",
3530 			conf->port_id, strerror(rc));
3531 		return rc;
3532 	}
3533 
3534 	rc = efx_mae_action_set_populate_deliver(spec, &mport);
3535 	if (rc != 0) {
3536 		sfc_err(sa, "failed to request action DELIVER with m-port selector 0x%08x: %s",
3537 			mport.sel, strerror(rc));
3538 	}
3539 
3540 	return rc;
3541 }
3542 
3543 static const char * const action_names[] = {
3544 	[RTE_FLOW_ACTION_TYPE_VXLAN_DECAP] = "VXLAN_DECAP",
3545 	[RTE_FLOW_ACTION_TYPE_OF_POP_VLAN] = "OF_POP_VLAN",
3546 	[RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN] = "OF_PUSH_VLAN",
3547 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID] = "OF_SET_VLAN_VID",
3548 	[RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP] = "OF_SET_VLAN_PCP",
3549 	[RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP] = "VXLAN_ENCAP",
3550 	[RTE_FLOW_ACTION_TYPE_FLAG] = "FLAG",
3551 	[RTE_FLOW_ACTION_TYPE_MARK] = "MARK",
3552 	[RTE_FLOW_ACTION_TYPE_PHY_PORT] = "PHY_PORT",
3553 	[RTE_FLOW_ACTION_TYPE_PF] = "PF",
3554 	[RTE_FLOW_ACTION_TYPE_VF] = "VF",
3555 	[RTE_FLOW_ACTION_TYPE_PORT_ID] = "PORT_ID",
3556 	[RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR] = "PORT_REPRESENTOR",
3557 	[RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT] = "REPRESENTED_PORT",
3558 	[RTE_FLOW_ACTION_TYPE_DROP] = "DROP",
3559 	[RTE_FLOW_ACTION_TYPE_JUMP] = "JUMP",
3560 };
3561 
3562 static int
3563 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
3564 			  const struct rte_flow_action *action,
3565 			  const struct sfc_flow_spec_mae *spec_mae,
3566 			  struct sfc_mae_actions_bundle *bundle,
3567 			  efx_mae_actions_t *spec,
3568 			  struct rte_flow_error *error)
3569 {
3570 	const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
3571 	const uint64_t rx_metadata = sa->negotiated_rx_metadata;
3572 	bool custom_error = B_FALSE;
3573 	int rc = 0;
3574 
3575 	switch (action->type) {
3576 	case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
3577 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
3578 				       bundle->actions_mask);
3579 		if (outer_rule == NULL ||
3580 		    outer_rule->encap_type != EFX_TUNNEL_PROTOCOL_VXLAN)
3581 			rc = EINVAL;
3582 		else
3583 			rc = efx_mae_action_set_populate_decap(spec);
3584 		break;
3585 	case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
3586 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_POP_VLAN,
3587 				       bundle->actions_mask);
3588 		rc = efx_mae_action_set_populate_vlan_pop(spec);
3589 		break;
3590 	case RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL:
3591 	case RTE_FLOW_ACTION_TYPE_DEC_TTL:
3592 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL,
3593 				       bundle->actions_mask);
3594 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DEC_TTL,
3595 				       bundle->actions_mask);
3596 		rc = efx_mae_action_set_populate_decr_ip_ttl(spec);
3597 		break;
3598 	case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
3599 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
3600 				       bundle->actions_mask);
3601 		sfc_mae_rule_parse_action_of_push_vlan(action->conf, bundle);
3602 		break;
3603 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
3604 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID,
3605 				       bundle->actions_mask);
3606 		sfc_mae_rule_parse_action_of_set_vlan_vid(action->conf, bundle);
3607 		break;
3608 	case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
3609 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP,
3610 				       bundle->actions_mask);
3611 		sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle);
3612 		break;
3613 	case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
3614 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP,
3615 				       bundle->actions_mask);
3616 		rc = sfc_mae_rule_parse_action_vxlan_encap(&sa->mae,
3617 							   action->conf,
3618 							   spec, error);
3619 		custom_error = B_TRUE;
3620 		break;
3621 	case RTE_FLOW_ACTION_TYPE_COUNT:
3622 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_COUNT,
3623 				       bundle->actions_mask);
3624 		rc = sfc_mae_rule_parse_action_count(sa, action->conf, spec);
3625 		break;
3626 	case RTE_FLOW_ACTION_TYPE_FLAG:
3627 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
3628 				       bundle->actions_mask);
3629 		if ((rx_metadata & RTE_ETH_RX_METADATA_USER_FLAG) != 0) {
3630 			rc = efx_mae_action_set_populate_flag(spec);
3631 		} else {
3632 			rc = rte_flow_error_set(error, ENOTSUP,
3633 						RTE_FLOW_ERROR_TYPE_ACTION,
3634 						action,
3635 						"flag delivery has not been negotiated");
3636 			custom_error = B_TRUE;
3637 		}
3638 		break;
3639 	case RTE_FLOW_ACTION_TYPE_MARK:
3640 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
3641 				       bundle->actions_mask);
3642 		if ((rx_metadata & RTE_ETH_RX_METADATA_USER_MARK) != 0 ||
3643 		    spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
3644 			rc = sfc_mae_rule_parse_action_mark(sa, action->conf,
3645 							    spec_mae, spec);
3646 		} else {
3647 			rc = rte_flow_error_set(error, ENOTSUP,
3648 						RTE_FLOW_ERROR_TYPE_ACTION,
3649 						action,
3650 						"mark delivery has not been negotiated");
3651 			custom_error = B_TRUE;
3652 		}
3653 		break;
3654 	case RTE_FLOW_ACTION_TYPE_PHY_PORT:
3655 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT,
3656 				       bundle->actions_mask);
3657 		rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
3658 		break;
3659 	case RTE_FLOW_ACTION_TYPE_PF:
3660 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PF,
3661 				       bundle->actions_mask);
3662 		rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec);
3663 		break;
3664 	case RTE_FLOW_ACTION_TYPE_VF:
3665 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VF,
3666 				       bundle->actions_mask);
3667 		rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec);
3668 		break;
3669 	case RTE_FLOW_ACTION_TYPE_PORT_ID:
3670 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_ID,
3671 				       bundle->actions_mask);
3672 		rc = sfc_mae_rule_parse_action_port_id(sa, action->conf, spec);
3673 		break;
3674 	case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR:
3675 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR,
3676 				       bundle->actions_mask);
3677 		rc = sfc_mae_rule_parse_action_port_representor(sa,
3678 				action->conf, spec);
3679 		break;
3680 	case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT:
3681 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT,
3682 				       bundle->actions_mask);
3683 		rc = sfc_mae_rule_parse_action_represented_port(sa,
3684 				action->conf, spec);
3685 		break;
3686 	case RTE_FLOW_ACTION_TYPE_DROP:
3687 		SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
3688 				       bundle->actions_mask);
3689 		rc = efx_mae_action_set_populate_drop(spec);
3690 		break;
3691 	case RTE_FLOW_ACTION_TYPE_JUMP:
3692 		if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
3693 			/* Workaround. See sfc_flow_parse_rte_to_mae() */
3694 			break;
3695 		}
3696 		/* FALLTHROUGH */
3697 	default:
3698 		return rte_flow_error_set(error, ENOTSUP,
3699 				RTE_FLOW_ERROR_TYPE_ACTION, NULL,
3700 				"Unsupported action");
3701 	}
3702 
3703 	if (rc == 0) {
3704 		bundle->actions_mask |= (1ULL << action->type);
3705 	} else if (!custom_error) {
3706 		if (action->type < RTE_DIM(action_names)) {
3707 			const char *action_name = action_names[action->type];
3708 
3709 			if (action_name != NULL) {
3710 				sfc_err(sa, "action %s was rejected: %s",
3711 					action_name, strerror(rc));
3712 			}
3713 		}
3714 		rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
3715 				NULL, "Failed to request the action");
3716 	}
3717 
3718 	return rc;
3719 }
3720 
3721 static void
3722 sfc_mae_bounce_eh_invalidate(struct sfc_mae_bounce_eh *bounce_eh)
3723 {
3724 	bounce_eh->type = EFX_TUNNEL_PROTOCOL_NONE;
3725 }
3726 
3727 static int
3728 sfc_mae_process_encap_header(struct sfc_adapter *sa,
3729 			     const struct sfc_mae_bounce_eh *bounce_eh,
3730 			     struct sfc_mae_encap_header **encap_headerp)
3731 {
3732 	if (bounce_eh->type == EFX_TUNNEL_PROTOCOL_NONE) {
3733 		encap_headerp = NULL;
3734 		return 0;
3735 	}
3736 
3737 	*encap_headerp = sfc_mae_encap_header_attach(sa, bounce_eh);
3738 	if (*encap_headerp != NULL)
3739 		return 0;
3740 
3741 	return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
3742 }
3743 
3744 int
3745 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
3746 			   const struct rte_flow_action actions[],
3747 			   struct sfc_flow_spec_mae *spec_mae,
3748 			   struct rte_flow_error *error)
3749 {
3750 	struct sfc_mae_encap_header *encap_header = NULL;
3751 	struct sfc_mae_actions_bundle bundle = {0};
3752 	struct sfc_flow_tunnel *counter_ft = NULL;
3753 	uint64_t *ft_group_hit_counter = NULL;
3754 	const struct rte_flow_action *action;
3755 	struct sfc_mae *mae = &sa->mae;
3756 	unsigned int n_count = 0;
3757 	efx_mae_actions_t *spec;
3758 	int rc;
3759 
3760 	rte_errno = 0;
3761 
3762 	if (actions == NULL) {
3763 		return rte_flow_error_set(error, EINVAL,
3764 				RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
3765 				"NULL actions");
3766 	}
3767 
3768 	rc = efx_mae_action_set_spec_init(sa->nic, &spec);
3769 	if (rc != 0)
3770 		goto fail_action_set_spec_init;
3771 
3772 	for (action = actions;
3773 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
3774 		if (action->type == RTE_FLOW_ACTION_TYPE_COUNT)
3775 			++n_count;
3776 	}
3777 
3778 	if (spec_mae->ft_rule_type == SFC_FT_RULE_GROUP) {
3779 		/* JUMP rules don't decapsulate packets. GROUP rules do. */
3780 		rc = efx_mae_action_set_populate_decap(spec);
3781 		if (rc != 0)
3782 			goto fail_enforce_ft_decap;
3783 
3784 		if (n_count == 0 && sfc_mae_counter_stream_enabled(sa)) {
3785 			/*
3786 			 * The user opted not to use action COUNT in this rule,
3787 			 * but the counter should be enabled implicitly because
3788 			 * packets hitting this rule contribute to the tunnel's
3789 			 * total number of hits. See sfc_mae_counter_get().
3790 			 */
3791 			rc = efx_mae_action_set_populate_count(spec);
3792 			if (rc != 0)
3793 				goto fail_enforce_ft_count;
3794 
3795 			n_count = 1;
3796 		}
3797 	}
3798 
3799 	/* Cleanup after previous encap. header bounce buffer usage. */
3800 	sfc_mae_bounce_eh_invalidate(&mae->bounce_eh);
3801 
3802 	for (action = actions;
3803 	     action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
3804 		rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error);
3805 		if (rc != 0)
3806 			goto fail_rule_parse_action;
3807 
3808 		rc = sfc_mae_rule_parse_action(sa, action, spec_mae,
3809 					       &bundle, spec, error);
3810 		if (rc != 0)
3811 			goto fail_rule_parse_action;
3812 	}
3813 
3814 	rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error);
3815 	if (rc != 0)
3816 		goto fail_rule_parse_action;
3817 
3818 	rc = sfc_mae_process_encap_header(sa, &mae->bounce_eh, &encap_header);
3819 	if (rc != 0)
3820 		goto fail_process_encap_header;
3821 
3822 	if (n_count > 1) {
3823 		rc = ENOTSUP;
3824 		sfc_err(sa, "too many count actions requested: %u", n_count);
3825 		goto fail_nb_count;
3826 	}
3827 
3828 	switch (spec_mae->ft_rule_type) {
3829 	case SFC_FT_RULE_NONE:
3830 		break;
3831 	case SFC_FT_RULE_JUMP:
3832 		/* Workaround. See sfc_flow_parse_rte_to_mae() */
3833 		rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec);
3834 		if (rc != 0)
3835 			goto fail_workaround_jump_delivery;
3836 
3837 		counter_ft = spec_mae->ft;
3838 		break;
3839 	case SFC_FT_RULE_GROUP:
3840 		/*
3841 		 * Packets that go to the rule's AR have FT mark set (from the
3842 		 * JUMP rule OR's RECIRC_ID). Remove this mark in matching
3843 		 * packets. The user may have provided their own action
3844 		 * MARK above, so don't check the return value here.
3845 		 */
3846 		(void)efx_mae_action_set_populate_mark(spec, 0);
3847 
3848 		ft_group_hit_counter = &spec_mae->ft->group_hit_counter;
3849 		break;
3850 	default:
3851 		SFC_ASSERT(B_FALSE);
3852 	}
3853 
3854 	spec_mae->action_set = sfc_mae_action_set_attach(sa, encap_header,
3855 							 n_count, spec);
3856 	if (spec_mae->action_set != NULL) {
3857 		sfc_mae_encap_header_del(sa, encap_header);
3858 		efx_mae_action_set_spec_fini(sa->nic, spec);
3859 		return 0;
3860 	}
3861 
3862 	rc = sfc_mae_action_set_add(sa, actions, spec, encap_header,
3863 				    ft_group_hit_counter, counter_ft, n_count,
3864 				    &spec_mae->action_set);
3865 	if (rc != 0)
3866 		goto fail_action_set_add;
3867 
3868 	return 0;
3869 
3870 fail_action_set_add:
3871 fail_workaround_jump_delivery:
3872 fail_nb_count:
3873 	sfc_mae_encap_header_del(sa, encap_header);
3874 
3875 fail_process_encap_header:
3876 fail_rule_parse_action:
3877 	efx_mae_action_set_spec_fini(sa->nic, spec);
3878 
3879 fail_enforce_ft_count:
3880 fail_enforce_ft_decap:
3881 fail_action_set_spec_init:
3882 	if (rc > 0 && rte_errno == 0) {
3883 		rc = rte_flow_error_set(error, rc,
3884 			RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
3885 			NULL, "Failed to process the action");
3886 	}
3887 	return rc;
3888 }
3889 
3890 static bool
3891 sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
3892 			const efx_mae_match_spec_t *left,
3893 			const efx_mae_match_spec_t *right)
3894 {
3895 	bool have_same_class;
3896 	int rc;
3897 
3898 	rc = efx_mae_match_specs_class_cmp(sa->nic, left, right,
3899 					   &have_same_class);
3900 
3901 	return (rc == 0) ? have_same_class : false;
3902 }
3903 
3904 static int
3905 sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
3906 				struct sfc_mae_outer_rule *rule)
3907 {
3908 	struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
3909 	struct sfc_mae_outer_rule *entry;
3910 	struct sfc_mae *mae = &sa->mae;
3911 
3912 	if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
3913 		/* An active rule is reused. It's class is wittingly valid. */
3914 		return 0;
3915 	}
3916 
3917 	TAILQ_FOREACH_REVERSE(entry, &mae->outer_rules,
3918 			      sfc_mae_outer_rules, entries) {
3919 		const efx_mae_match_spec_t *left = entry->match_spec;
3920 		const efx_mae_match_spec_t *right = rule->match_spec;
3921 
3922 		if (entry == rule)
3923 			continue;
3924 
3925 		if (sfc_mae_rules_class_cmp(sa, left, right))
3926 			return 0;
3927 	}
3928 
3929 	sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
3930 		 "support for outer frame pattern items is not guaranteed; "
3931 		 "other than that, the items are valid from SW standpoint");
3932 	return 0;
3933 }
3934 
3935 static int
3936 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
3937 				 struct sfc_flow_spec_mae *spec)
3938 {
3939 	const struct rte_flow *entry;
3940 
3941 	if (spec->match_spec == NULL)
3942 		return 0;
3943 
3944 	TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {
3945 		const struct sfc_flow_spec *entry_spec = &entry->spec;
3946 		const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;
3947 		const efx_mae_match_spec_t *left = es_mae->match_spec;
3948 		const efx_mae_match_spec_t *right = spec->match_spec;
3949 
3950 		switch (entry_spec->type) {
3951 		case SFC_FLOW_SPEC_FILTER:
3952 			/* Ignore VNIC-level flows */
3953 			break;
3954 		case SFC_FLOW_SPEC_MAE:
3955 			if (sfc_mae_rules_class_cmp(sa, left, right))
3956 				return 0;
3957 			break;
3958 		default:
3959 			SFC_ASSERT(false);
3960 		}
3961 	}
3962 
3963 	sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
3964 		 "support for inner frame pattern items is not guaranteed; "
3965 		 "other than that, the items are valid from SW standpoint");
3966 	return 0;
3967 }
3968 
3969 /**
3970  * Confirm that a given flow can be accepted by the FW.
3971  *
3972  * @param sa
3973  *   Software adapter context
3974  * @param flow
3975  *   Flow to be verified
3976  * @return
3977  *   Zero on success and non-zero in the case of error.
3978  *   A special value of EAGAIN indicates that the adapter is
3979  *   not in started state. This state is compulsory because
3980  *   it only makes sense to compare the rule class of the flow
3981  *   being validated with classes of the active rules.
3982  *   Such classes are wittingly supported by the FW.
3983  */
3984 int
3985 sfc_mae_flow_verify(struct sfc_adapter *sa,
3986 		    struct rte_flow *flow)
3987 {
3988 	struct sfc_flow_spec *spec = &flow->spec;
3989 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
3990 	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
3991 	int rc;
3992 
3993 	SFC_ASSERT(sfc_adapter_is_locked(sa));
3994 
3995 	if (sa->state != SFC_ETHDEV_STARTED)
3996 		return EAGAIN;
3997 
3998 	if (outer_rule != NULL) {
3999 		rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
4000 		if (rc != 0)
4001 			return rc;
4002 	}
4003 
4004 	return sfc_mae_action_rule_class_verify(sa, spec_mae);
4005 }
4006 
4007 int
4008 sfc_mae_flow_insert(struct sfc_adapter *sa,
4009 		    struct rte_flow *flow)
4010 {
4011 	struct sfc_flow_spec *spec = &flow->spec;
4012 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
4013 	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
4014 	struct sfc_mae_action_set *action_set = spec_mae->action_set;
4015 	struct sfc_mae_fw_rsrc *fw_rsrc;
4016 	int rc;
4017 
4018 	SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
4019 
4020 	if (outer_rule != NULL) {
4021 		rc = sfc_mae_outer_rule_enable(sa, outer_rule,
4022 					       spec_mae->match_spec);
4023 		if (rc != 0)
4024 			goto fail_outer_rule_enable;
4025 	}
4026 
4027 	if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
4028 		spec_mae->ft->reset_jump_hit_counter =
4029 			spec_mae->ft->group_hit_counter;
4030 	}
4031 
4032 	if (action_set == NULL) {
4033 		sfc_dbg(sa, "enabled flow=%p (no AR)", flow);
4034 		return 0;
4035 	}
4036 
4037 	rc = sfc_mae_action_set_enable(sa, action_set);
4038 	if (rc != 0)
4039 		goto fail_action_set_enable;
4040 
4041 	if (action_set->n_counters > 0) {
4042 		rc = sfc_mae_counter_start(sa);
4043 		if (rc != 0) {
4044 			sfc_err(sa, "failed to start MAE counters support: %s",
4045 				rte_strerror(rc));
4046 			goto fail_mae_counter_start;
4047 		}
4048 	}
4049 
4050 	fw_rsrc = &action_set->fw_rsrc;
4051 
4052 	rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
4053 					NULL, &fw_rsrc->aset_id,
4054 					&spec_mae->rule_id);
4055 	if (rc != 0)
4056 		goto fail_action_rule_insert;
4057 
4058 	sfc_dbg(sa, "enabled flow=%p: AR_ID=0x%08x",
4059 		flow, spec_mae->rule_id.id);
4060 
4061 	return 0;
4062 
4063 fail_action_rule_insert:
4064 fail_mae_counter_start:
4065 	sfc_mae_action_set_disable(sa, action_set);
4066 
4067 fail_action_set_enable:
4068 	if (outer_rule != NULL)
4069 		sfc_mae_outer_rule_disable(sa, outer_rule);
4070 
4071 fail_outer_rule_enable:
4072 	return rc;
4073 }
4074 
4075 int
4076 sfc_mae_flow_remove(struct sfc_adapter *sa,
4077 		    struct rte_flow *flow)
4078 {
4079 	struct sfc_flow_spec *spec = &flow->spec;
4080 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
4081 	struct sfc_mae_action_set *action_set = spec_mae->action_set;
4082 	struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
4083 	int rc;
4084 
4085 	if (action_set == NULL) {
4086 		sfc_dbg(sa, "disabled flow=%p (no AR)", flow);
4087 		goto skip_action_rule;
4088 	}
4089 
4090 	SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
4091 
4092 	rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
4093 	if (rc != 0) {
4094 		sfc_err(sa, "failed to disable flow=%p with AR_ID=0x%08x: %s",
4095 			flow, spec_mae->rule_id.id, strerror(rc));
4096 	}
4097 	sfc_dbg(sa, "disabled flow=%p with AR_ID=0x%08x",
4098 		flow, spec_mae->rule_id.id);
4099 	spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
4100 
4101 	sfc_mae_action_set_disable(sa, action_set);
4102 
4103 skip_action_rule:
4104 	if (outer_rule != NULL)
4105 		sfc_mae_outer_rule_disable(sa, outer_rule);
4106 
4107 	return 0;
4108 }
4109 
4110 static int
4111 sfc_mae_query_counter(struct sfc_adapter *sa,
4112 		      struct sfc_flow_spec_mae *spec,
4113 		      const struct rte_flow_action *action,
4114 		      struct rte_flow_query_count *data,
4115 		      struct rte_flow_error *error)
4116 {
4117 	struct sfc_mae_action_set *action_set = spec->action_set;
4118 	const struct rte_flow_action_count *conf = action->conf;
4119 	unsigned int i;
4120 	int rc;
4121 
4122 	if (action_set == NULL || action_set->n_counters == 0) {
4123 		return rte_flow_error_set(error, EINVAL,
4124 			RTE_FLOW_ERROR_TYPE_ACTION, action,
4125 			"Queried flow rule does not have count actions");
4126 	}
4127 
4128 	for (i = 0; i < action_set->n_counters; i++) {
4129 		/*
4130 		 * Get the first available counter of the flow rule if
4131 		 * counter ID is not specified, provided that this
4132 		 * counter is not an automatic (implicit) one.
4133 		 */
4134 		if (conf != NULL && action_set->counters[i].rte_id != conf->id)
4135 			continue;
4136 
4137 		rc = sfc_mae_counter_get(&sa->mae.counter_registry.counters,
4138 					 &action_set->counters[i], data);
4139 		if (rc != 0) {
4140 			return rte_flow_error_set(error, EINVAL,
4141 				RTE_FLOW_ERROR_TYPE_ACTION, action,
4142 				"Queried flow rule counter action is invalid");
4143 		}
4144 
4145 		return 0;
4146 	}
4147 
4148 	return rte_flow_error_set(error, ENOENT,
4149 				  RTE_FLOW_ERROR_TYPE_ACTION, action,
4150 				  "no such flow rule action or such count ID");
4151 }
4152 
4153 int
4154 sfc_mae_flow_query(struct rte_eth_dev *dev,
4155 		   struct rte_flow *flow,
4156 		   const struct rte_flow_action *action,
4157 		   void *data,
4158 		   struct rte_flow_error *error)
4159 {
4160 	struct sfc_adapter *sa = sfc_adapter_by_eth_dev(dev);
4161 	struct sfc_flow_spec *spec = &flow->spec;
4162 	struct sfc_flow_spec_mae *spec_mae = &spec->mae;
4163 
4164 	switch (action->type) {
4165 	case RTE_FLOW_ACTION_TYPE_COUNT:
4166 		return sfc_mae_query_counter(sa, spec_mae, action,
4167 					     data, error);
4168 	default:
4169 		return rte_flow_error_set(error, ENOTSUP,
4170 			RTE_FLOW_ERROR_TYPE_ACTION, NULL,
4171 			"Query for action of this type is not supported");
4172 	}
4173 }
4174 
4175 int
4176 sfc_mae_switchdev_init(struct sfc_adapter *sa)
4177 {
4178 	const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
4179 	struct sfc_mae *mae = &sa->mae;
4180 	efx_mport_sel_t pf;
4181 	efx_mport_sel_t phy;
4182 	int rc;
4183 
4184 	sfc_log_init(sa, "entry");
4185 
4186 	if (!sa->switchdev) {
4187 		sfc_log_init(sa, "switchdev is not enabled - skip");
4188 		return 0;
4189 	}
4190 
4191 	if (mae->status != SFC_MAE_STATUS_ADMIN) {
4192 		rc = ENOTSUP;
4193 		sfc_err(sa, "failed to init switchdev - no admin MAE privilege");
4194 		goto fail_no_mae;
4195 	}
4196 
4197 	rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
4198 					    &pf);
4199 	if (rc != 0) {
4200 		sfc_err(sa, "failed get PF mport");
4201 		goto fail_pf_get;
4202 	}
4203 
4204 	rc = efx_mae_mport_by_phy_port(encp->enc_assigned_port, &phy);
4205 	if (rc != 0) {
4206 		sfc_err(sa, "failed get PHY mport");
4207 		goto fail_phy_get;
4208 	}
4209 
4210 	rc = sfc_mae_rule_add_mport_match_deliver(sa, &pf, &phy,
4211 			SFC_MAE_RULE_PRIO_LOWEST,
4212 			&mae->switchdev_rule_pf_to_ext);
4213 	if (rc != 0) {
4214 		sfc_err(sa, "failed add MAE rule to forward from PF to PHY");
4215 		goto fail_pf_add;
4216 	}
4217 
4218 	rc = sfc_mae_rule_add_mport_match_deliver(sa, &phy, &pf,
4219 			SFC_MAE_RULE_PRIO_LOWEST,
4220 			&mae->switchdev_rule_ext_to_pf);
4221 	if (rc != 0) {
4222 		sfc_err(sa, "failed add MAE rule to forward from PHY to PF");
4223 		goto fail_phy_add;
4224 	}
4225 
4226 	sfc_log_init(sa, "done");
4227 
4228 	return 0;
4229 
4230 fail_phy_add:
4231 	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
4232 
4233 fail_pf_add:
4234 fail_phy_get:
4235 fail_pf_get:
4236 fail_no_mae:
4237 	sfc_log_init(sa, "failed: %s", rte_strerror(rc));
4238 	return rc;
4239 }
4240 
4241 void
4242 sfc_mae_switchdev_fini(struct sfc_adapter *sa)
4243 {
4244 	struct sfc_mae *mae = &sa->mae;
4245 
4246 	if (!sa->switchdev)
4247 		return;
4248 
4249 	sfc_mae_rule_del(sa, mae->switchdev_rule_pf_to_ext);
4250 	sfc_mae_rule_del(sa, mae->switchdev_rule_ext_to_pf);
4251 }
4252