1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2019 Solarflare Communications Inc.
6 * This software was jointly developed between OKTET Labs (under contract
7 * for Solarflare) and Solarflare Communications, Inc.
12 #include <rte_bitops.h>
13 #include <rte_common.h>
14 #include <rte_vxlan.h>
20 #include "sfc_switch.h"
23 sfc_mae_assign_entity_mport(struct sfc_adapter *sa,
24 efx_mport_sel_t *mportp)
26 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
28 return efx_mae_mport_by_pcie_function(encp->enc_pf, encp->enc_vf,
33 sfc_mae_attach(struct sfc_adapter *sa)
35 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
36 struct sfc_mae_switch_port_request switch_port_request = {0};
37 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
38 efx_mport_sel_t entity_mport;
39 struct sfc_mae *mae = &sa->mae;
40 struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
41 efx_mae_limits_t limits;
44 sfc_log_init(sa, "entry");
46 if (!encp->enc_mae_supported) {
47 mae->status = SFC_MAE_STATUS_UNSUPPORTED;
51 sfc_log_init(sa, "init MAE");
52 rc = efx_mae_init(sa->nic);
56 sfc_log_init(sa, "get MAE limits");
57 rc = efx_mae_get_limits(sa->nic, &limits);
59 goto fail_mae_get_limits;
61 sfc_log_init(sa, "assign entity MPORT");
62 rc = sfc_mae_assign_entity_mport(sa, &entity_mport);
64 goto fail_mae_assign_entity_mport;
66 sfc_log_init(sa, "assign RTE switch domain");
67 rc = sfc_mae_assign_switch_domain(sa, &mae->switch_domain_id);
69 goto fail_mae_assign_switch_domain;
71 sfc_log_init(sa, "assign RTE switch port");
72 switch_port_request.type = SFC_MAE_SWITCH_PORT_INDEPENDENT;
73 switch_port_request.entity_mportp = &entity_mport;
75 * As of now, the driver does not support representors, so
76 * RTE ethdev MPORT simply matches that of the entity.
78 switch_port_request.ethdev_mportp = &entity_mport;
79 switch_port_request.ethdev_port_id = sas->port_id;
80 rc = sfc_mae_assign_switch_port(mae->switch_domain_id,
82 &mae->switch_port_id);
84 goto fail_mae_assign_switch_port;
86 sfc_log_init(sa, "allocate encap. header bounce buffer");
87 bounce_eh->buf_size = limits.eml_encap_header_size_limit;
88 bounce_eh->buf = rte_malloc("sfc_mae_bounce_eh",
89 bounce_eh->buf_size, 0);
90 if (bounce_eh->buf == NULL)
91 goto fail_mae_alloc_bounce_eh;
93 mae->status = SFC_MAE_STATUS_SUPPORTED;
94 mae->nb_outer_rule_prios_max = limits.eml_max_n_outer_prios;
95 mae->nb_action_rule_prios_max = limits.eml_max_n_action_prios;
96 mae->encap_types_supported = limits.eml_encap_types_supported;
97 TAILQ_INIT(&mae->outer_rules);
98 TAILQ_INIT(&mae->encap_headers);
99 TAILQ_INIT(&mae->action_sets);
101 sfc_log_init(sa, "done");
105 fail_mae_alloc_bounce_eh:
106 fail_mae_assign_switch_port:
107 fail_mae_assign_switch_domain:
108 fail_mae_assign_entity_mport:
110 efx_mae_fini(sa->nic);
113 sfc_log_init(sa, "failed %d", rc);
119 sfc_mae_detach(struct sfc_adapter *sa)
121 struct sfc_mae *mae = &sa->mae;
122 enum sfc_mae_status status_prev = mae->status;
124 sfc_log_init(sa, "entry");
126 mae->nb_action_rule_prios_max = 0;
127 mae->status = SFC_MAE_STATUS_UNKNOWN;
129 if (status_prev != SFC_MAE_STATUS_SUPPORTED)
132 rte_free(mae->bounce_eh.buf);
134 efx_mae_fini(sa->nic);
136 sfc_log_init(sa, "done");
139 static struct sfc_mae_outer_rule *
140 sfc_mae_outer_rule_attach(struct sfc_adapter *sa,
141 const efx_mae_match_spec_t *match_spec,
142 efx_tunnel_protocol_t encap_type)
144 struct sfc_mae_outer_rule *rule;
145 struct sfc_mae *mae = &sa->mae;
147 SFC_ASSERT(sfc_adapter_is_locked(sa));
149 TAILQ_FOREACH(rule, &mae->outer_rules, entries) {
150 if (efx_mae_match_specs_equal(rule->match_spec, match_spec) &&
151 rule->encap_type == encap_type) {
161 sfc_mae_outer_rule_add(struct sfc_adapter *sa,
162 efx_mae_match_spec_t *match_spec,
163 efx_tunnel_protocol_t encap_type,
164 struct sfc_mae_outer_rule **rulep)
166 struct sfc_mae_outer_rule *rule;
167 struct sfc_mae *mae = &sa->mae;
169 SFC_ASSERT(sfc_adapter_is_locked(sa));
171 rule = rte_zmalloc("sfc_mae_outer_rule", sizeof(*rule), 0);
176 rule->match_spec = match_spec;
177 rule->encap_type = encap_type;
179 rule->fw_rsrc.rule_id.id = EFX_MAE_RSRC_ID_INVALID;
181 TAILQ_INSERT_TAIL(&mae->outer_rules, rule, entries);
189 sfc_mae_outer_rule_del(struct sfc_adapter *sa,
190 struct sfc_mae_outer_rule *rule)
192 struct sfc_mae *mae = &sa->mae;
194 SFC_ASSERT(sfc_adapter_is_locked(sa));
195 SFC_ASSERT(rule->refcnt != 0);
199 if (rule->refcnt != 0)
202 if (rule->fw_rsrc.rule_id.id != EFX_MAE_RSRC_ID_INVALID ||
203 rule->fw_rsrc.refcnt != 0) {
204 sfc_err(sa, "deleting outer_rule=%p abandons its FW resource: OR_ID=0x%08x, refcnt=%u",
205 rule, rule->fw_rsrc.rule_id.id, rule->fw_rsrc.refcnt);
208 efx_mae_match_spec_fini(sa->nic, rule->match_spec);
210 TAILQ_REMOVE(&mae->outer_rules, rule, entries);
215 sfc_mae_outer_rule_enable(struct sfc_adapter *sa,
216 struct sfc_mae_outer_rule *rule,
217 efx_mae_match_spec_t *match_spec_action)
219 struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
222 SFC_ASSERT(sfc_adapter_is_locked(sa));
224 if (fw_rsrc->refcnt == 0) {
225 SFC_ASSERT(fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
226 SFC_ASSERT(rule->match_spec != NULL);
228 rc = efx_mae_outer_rule_insert(sa->nic, rule->match_spec,
235 rc = efx_mae_match_spec_outer_rule_id_set(match_spec_action,
238 if (fw_rsrc->refcnt == 0) {
239 (void)efx_mae_outer_rule_remove(sa->nic,
241 fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
252 sfc_mae_outer_rule_disable(struct sfc_adapter *sa,
253 struct sfc_mae_outer_rule *rule)
255 struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
258 SFC_ASSERT(sfc_adapter_is_locked(sa));
260 if (fw_rsrc->rule_id.id == EFX_MAE_RSRC_ID_INVALID ||
261 fw_rsrc->refcnt == 0) {
262 sfc_err(sa, "failed to disable outer_rule=%p: already disabled; OR_ID=0x%08x, refcnt=%u",
263 rule, fw_rsrc->rule_id.id, fw_rsrc->refcnt);
267 if (fw_rsrc->refcnt == 1) {
268 rc = efx_mae_outer_rule_remove(sa->nic, &fw_rsrc->rule_id);
270 sfc_err(sa, "failed to disable outer_rule=%p with OR_ID=0x%08x: %s",
271 rule, fw_rsrc->rule_id.id, strerror(rc));
273 fw_rsrc->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
279 static struct sfc_mae_encap_header *
280 sfc_mae_encap_header_attach(struct sfc_adapter *sa,
281 const struct sfc_mae_bounce_eh *bounce_eh)
283 struct sfc_mae_encap_header *encap_header;
284 struct sfc_mae *mae = &sa->mae;
286 SFC_ASSERT(sfc_adapter_is_locked(sa));
288 TAILQ_FOREACH(encap_header, &mae->encap_headers, entries) {
289 if (encap_header->size == bounce_eh->size &&
290 memcmp(encap_header->buf, bounce_eh->buf,
291 bounce_eh->size) == 0) {
292 ++(encap_header->refcnt);
301 sfc_mae_encap_header_add(struct sfc_adapter *sa,
302 const struct sfc_mae_bounce_eh *bounce_eh,
303 struct sfc_mae_encap_header **encap_headerp)
305 struct sfc_mae_encap_header *encap_header;
306 struct sfc_mae *mae = &sa->mae;
308 SFC_ASSERT(sfc_adapter_is_locked(sa));
310 encap_header = rte_zmalloc("sfc_mae_encap_header",
311 sizeof(*encap_header), 0);
312 if (encap_header == NULL)
315 encap_header->size = bounce_eh->size;
317 encap_header->buf = rte_malloc("sfc_mae_encap_header_buf",
318 encap_header->size, 0);
319 if (encap_header->buf == NULL) {
320 rte_free(encap_header);
324 rte_memcpy(encap_header->buf, bounce_eh->buf, bounce_eh->size);
326 encap_header->refcnt = 1;
327 encap_header->type = bounce_eh->type;
328 encap_header->fw_rsrc.eh_id.id = EFX_MAE_RSRC_ID_INVALID;
330 TAILQ_INSERT_TAIL(&mae->encap_headers, encap_header, entries);
332 *encap_headerp = encap_header;
338 sfc_mae_encap_header_del(struct sfc_adapter *sa,
339 struct sfc_mae_encap_header *encap_header)
341 struct sfc_mae *mae = &sa->mae;
343 if (encap_header == NULL)
346 SFC_ASSERT(sfc_adapter_is_locked(sa));
347 SFC_ASSERT(encap_header->refcnt != 0);
349 --(encap_header->refcnt);
351 if (encap_header->refcnt != 0)
354 if (encap_header->fw_rsrc.eh_id.id != EFX_MAE_RSRC_ID_INVALID ||
355 encap_header->fw_rsrc.refcnt != 0) {
356 sfc_err(sa, "deleting encap_header=%p abandons its FW resource: EH_ID=0x%08x, refcnt=%u",
357 encap_header, encap_header->fw_rsrc.eh_id.id,
358 encap_header->fw_rsrc.refcnt);
361 TAILQ_REMOVE(&mae->encap_headers, encap_header, entries);
362 rte_free(encap_header->buf);
363 rte_free(encap_header);
367 sfc_mae_encap_header_enable(struct sfc_adapter *sa,
368 struct sfc_mae_encap_header *encap_header,
369 efx_mae_actions_t *action_set_spec)
371 struct sfc_mae_fw_rsrc *fw_rsrc;
374 if (encap_header == NULL)
377 SFC_ASSERT(sfc_adapter_is_locked(sa));
379 fw_rsrc = &encap_header->fw_rsrc;
381 if (fw_rsrc->refcnt == 0) {
382 SFC_ASSERT(fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID);
383 SFC_ASSERT(encap_header->buf != NULL);
384 SFC_ASSERT(encap_header->size != 0);
386 rc = efx_mae_encap_header_alloc(sa->nic, encap_header->type,
394 rc = efx_mae_action_set_fill_in_eh_id(action_set_spec,
397 if (fw_rsrc->refcnt == 0) {
398 (void)efx_mae_encap_header_free(sa->nic,
400 fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID;
411 sfc_mae_encap_header_disable(struct sfc_adapter *sa,
412 struct sfc_mae_encap_header *encap_header)
414 struct sfc_mae_fw_rsrc *fw_rsrc;
417 if (encap_header == NULL)
420 SFC_ASSERT(sfc_adapter_is_locked(sa));
422 fw_rsrc = &encap_header->fw_rsrc;
424 if (fw_rsrc->eh_id.id == EFX_MAE_RSRC_ID_INVALID ||
425 fw_rsrc->refcnt == 0) {
426 sfc_err(sa, "failed to disable encap_header=%p: already disabled; EH_ID=0x%08x, refcnt=%u",
427 encap_header, fw_rsrc->eh_id.id, fw_rsrc->refcnt);
431 if (fw_rsrc->refcnt == 1) {
432 rc = efx_mae_encap_header_free(sa->nic, &fw_rsrc->eh_id);
434 sfc_err(sa, "failed to disable encap_header=%p with EH_ID=0x%08x: %s",
435 encap_header, fw_rsrc->eh_id.id, strerror(rc));
437 fw_rsrc->eh_id.id = EFX_MAE_RSRC_ID_INVALID;
443 static struct sfc_mae_action_set *
444 sfc_mae_action_set_attach(struct sfc_adapter *sa,
445 const struct sfc_mae_encap_header *encap_header,
446 const efx_mae_actions_t *spec)
448 struct sfc_mae_action_set *action_set;
449 struct sfc_mae *mae = &sa->mae;
451 SFC_ASSERT(sfc_adapter_is_locked(sa));
453 TAILQ_FOREACH(action_set, &mae->action_sets, entries) {
454 if (action_set->encap_header == encap_header &&
455 efx_mae_action_set_specs_equal(action_set->spec, spec)) {
456 ++(action_set->refcnt);
465 sfc_mae_action_set_add(struct sfc_adapter *sa,
466 efx_mae_actions_t *spec,
467 struct sfc_mae_encap_header *encap_header,
468 struct sfc_mae_action_set **action_setp)
470 struct sfc_mae_action_set *action_set;
471 struct sfc_mae *mae = &sa->mae;
473 SFC_ASSERT(sfc_adapter_is_locked(sa));
475 action_set = rte_zmalloc("sfc_mae_action_set", sizeof(*action_set), 0);
476 if (action_set == NULL)
479 action_set->refcnt = 1;
480 action_set->spec = spec;
481 action_set->encap_header = encap_header;
483 action_set->fw_rsrc.aset_id.id = EFX_MAE_RSRC_ID_INVALID;
485 TAILQ_INSERT_TAIL(&mae->action_sets, action_set, entries);
487 *action_setp = action_set;
493 sfc_mae_action_set_del(struct sfc_adapter *sa,
494 struct sfc_mae_action_set *action_set)
496 struct sfc_mae *mae = &sa->mae;
498 SFC_ASSERT(sfc_adapter_is_locked(sa));
499 SFC_ASSERT(action_set->refcnt != 0);
501 --(action_set->refcnt);
503 if (action_set->refcnt != 0)
506 if (action_set->fw_rsrc.aset_id.id != EFX_MAE_RSRC_ID_INVALID ||
507 action_set->fw_rsrc.refcnt != 0) {
508 sfc_err(sa, "deleting action_set=%p abandons its FW resource: AS_ID=0x%08x, refcnt=%u",
509 action_set, action_set->fw_rsrc.aset_id.id,
510 action_set->fw_rsrc.refcnt);
513 efx_mae_action_set_spec_fini(sa->nic, action_set->spec);
514 sfc_mae_encap_header_del(sa, action_set->encap_header);
515 TAILQ_REMOVE(&mae->action_sets, action_set, entries);
516 rte_free(action_set);
520 sfc_mae_action_set_enable(struct sfc_adapter *sa,
521 struct sfc_mae_action_set *action_set)
523 struct sfc_mae_encap_header *encap_header = action_set->encap_header;
524 struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
527 SFC_ASSERT(sfc_adapter_is_locked(sa));
529 if (fw_rsrc->refcnt == 0) {
530 SFC_ASSERT(fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID);
531 SFC_ASSERT(action_set->spec != NULL);
533 rc = sfc_mae_encap_header_enable(sa, encap_header,
538 rc = efx_mae_action_set_alloc(sa->nic, action_set->spec,
541 sfc_mae_encap_header_disable(sa, encap_header);
553 sfc_mae_action_set_disable(struct sfc_adapter *sa,
554 struct sfc_mae_action_set *action_set)
556 struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
559 SFC_ASSERT(sfc_adapter_is_locked(sa));
561 if (fw_rsrc->aset_id.id == EFX_MAE_RSRC_ID_INVALID ||
562 fw_rsrc->refcnt == 0) {
563 sfc_err(sa, "failed to disable action_set=%p: already disabled; AS_ID=0x%08x, refcnt=%u",
564 action_set, fw_rsrc->aset_id.id, fw_rsrc->refcnt);
568 if (fw_rsrc->refcnt == 1) {
569 rc = efx_mae_action_set_free(sa->nic, &fw_rsrc->aset_id);
571 sfc_err(sa, "failed to disable action_set=%p with AS_ID=0x%08x: %s",
572 action_set, fw_rsrc->aset_id.id, strerror(rc));
574 fw_rsrc->aset_id.id = EFX_MAE_RSRC_ID_INVALID;
576 sfc_mae_encap_header_disable(sa, action_set->encap_header);
583 sfc_mae_flow_cleanup(struct sfc_adapter *sa,
584 struct rte_flow *flow)
586 struct sfc_flow_spec *spec;
587 struct sfc_flow_spec_mae *spec_mae;
597 spec_mae = &spec->mae;
599 SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
601 if (spec_mae->outer_rule != NULL)
602 sfc_mae_outer_rule_del(sa, spec_mae->outer_rule);
604 if (spec_mae->action_set != NULL)
605 sfc_mae_action_set_del(sa, spec_mae->action_set);
607 if (spec_mae->match_spec != NULL)
608 efx_mae_match_spec_fini(sa->nic, spec_mae->match_spec);
612 sfc_mae_set_ethertypes(struct sfc_mae_parse_ctx *ctx)
614 struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
615 const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
616 const efx_mae_field_id_t field_ids[] = {
617 EFX_MAE_FIELD_VLAN0_PROTO_BE,
618 EFX_MAE_FIELD_VLAN1_PROTO_BE,
620 const struct sfc_mae_ethertype *et;
625 * In accordance with RTE flow API convention, the innermost L2
626 * item's "type" ("inner_type") is a L3 EtherType. If there is
627 * no L3 item, it's 0x0000/0x0000.
629 et = &pdata->ethertypes[pdata->nb_vlan_tags];
630 rc = efx_mae_match_spec_field_set(ctx->match_spec,
631 fremap[EFX_MAE_FIELD_ETHER_TYPE_BE],
633 (const uint8_t *)&et->value,
635 (const uint8_t *)&et->mask);
640 * sfc_mae_rule_parse_item_vlan() has already made sure
641 * that pdata->nb_vlan_tags does not exceed this figure.
643 RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
645 for (i = 0; i < pdata->nb_vlan_tags; ++i) {
646 et = &pdata->ethertypes[i];
648 rc = efx_mae_match_spec_field_set(ctx->match_spec,
649 fremap[field_ids[i]],
651 (const uint8_t *)&et->value,
653 (const uint8_t *)&et->mask);
662 sfc_mae_rule_process_pattern_data(struct sfc_mae_parse_ctx *ctx,
663 struct rte_flow_error *error)
665 const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
666 struct sfc_mae_pattern_data *pdata = &ctx->pattern_data;
667 struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
668 const rte_be16_t supported_tpids[] = {
669 /* VLAN standard TPID (always the first element) */
670 RTE_BE16(RTE_ETHER_TYPE_VLAN),
672 /* Double-tagging TPIDs */
673 RTE_BE16(RTE_ETHER_TYPE_QINQ),
674 RTE_BE16(RTE_ETHER_TYPE_QINQ1),
675 RTE_BE16(RTE_ETHER_TYPE_QINQ2),
676 RTE_BE16(RTE_ETHER_TYPE_QINQ3),
678 unsigned int nb_supported_tpids = RTE_DIM(supported_tpids);
679 unsigned int ethertype_idx;
680 const uint8_t *valuep;
681 const uint8_t *maskp;
684 if (pdata->innermost_ethertype_restriction.mask != 0 &&
685 pdata->nb_vlan_tags < SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
687 * If a single item VLAN is followed by a L3 item, value
688 * of "type" in item ETH can't be a double-tagging TPID.
690 nb_supported_tpids = 1;
694 * sfc_mae_rule_parse_item_vlan() has already made sure
695 * that pdata->nb_vlan_tags does not exceed this figure.
697 RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
699 for (ethertype_idx = 0;
700 ethertype_idx < pdata->nb_vlan_tags; ++ethertype_idx) {
701 unsigned int tpid_idx;
703 /* Exact match is supported only. */
704 if (ethertypes[ethertype_idx].mask != RTE_BE16(0xffff)) {
709 for (tpid_idx = pdata->nb_vlan_tags - ethertype_idx - 1;
710 tpid_idx < nb_supported_tpids; ++tpid_idx) {
711 if (ethertypes[ethertype_idx].value ==
712 supported_tpids[tpid_idx])
716 if (tpid_idx == nb_supported_tpids) {
721 nb_supported_tpids = 1;
724 if (pdata->innermost_ethertype_restriction.mask == RTE_BE16(0xffff)) {
725 struct sfc_mae_ethertype *et = ðertypes[ethertype_idx];
728 et->mask = RTE_BE16(0xffff);
730 pdata->innermost_ethertype_restriction.value;
731 } else if (et->mask != RTE_BE16(0xffff) ||
733 pdata->innermost_ethertype_restriction.value) {
740 * Now, when the number of VLAN tags is known, set fields
741 * ETHER_TYPE, VLAN0_PROTO and VLAN1_PROTO so that the first
742 * one is either a valid L3 EtherType (or 0x0000/0x0000),
743 * and the last two are valid TPIDs (or 0x0000/0x0000).
745 rc = sfc_mae_set_ethertypes(ctx);
749 if (pdata->l3_next_proto_restriction_mask == 0xff) {
750 if (pdata->l3_next_proto_mask == 0) {
751 pdata->l3_next_proto_mask = 0xff;
752 pdata->l3_next_proto_value =
753 pdata->l3_next_proto_restriction_value;
754 } else if (pdata->l3_next_proto_mask != 0xff ||
755 pdata->l3_next_proto_value !=
756 pdata->l3_next_proto_restriction_value) {
762 valuep = (const uint8_t *)&pdata->l3_next_proto_value;
763 maskp = (const uint8_t *)&pdata->l3_next_proto_mask;
764 rc = efx_mae_match_spec_field_set(ctx->match_spec,
765 fremap[EFX_MAE_FIELD_IP_PROTO],
766 sizeof(pdata->l3_next_proto_value),
768 sizeof(pdata->l3_next_proto_mask),
776 return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
777 "Failed to process pattern data");
781 sfc_mae_rule_parse_item_port_id(const struct rte_flow_item *item,
782 struct sfc_flow_parse_ctx *ctx,
783 struct rte_flow_error *error)
785 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
786 const struct rte_flow_item_port_id supp_mask = {
789 const void *def_mask = &rte_flow_item_port_id_mask;
790 const struct rte_flow_item_port_id *spec = NULL;
791 const struct rte_flow_item_port_id *mask = NULL;
792 efx_mport_sel_t mport_sel;
795 if (ctx_mae->match_mport_set) {
796 return rte_flow_error_set(error, ENOTSUP,
797 RTE_FLOW_ERROR_TYPE_ITEM, item,
798 "Can't handle multiple traffic source items");
801 rc = sfc_flow_parse_init(item,
802 (const void **)&spec, (const void **)&mask,
803 (const void *)&supp_mask, def_mask,
804 sizeof(struct rte_flow_item_port_id), error);
808 if (mask->id != supp_mask.id) {
809 return rte_flow_error_set(error, EINVAL,
810 RTE_FLOW_ERROR_TYPE_ITEM, item,
811 "Bad mask in the PORT_ID pattern item");
814 /* If "spec" is not set, could be any port ID */
818 if (spec->id > UINT16_MAX) {
819 return rte_flow_error_set(error, EOVERFLOW,
820 RTE_FLOW_ERROR_TYPE_ITEM, item,
821 "The port ID is too large");
824 rc = sfc_mae_switch_port_by_ethdev(ctx_mae->sa->mae.switch_domain_id,
825 spec->id, &mport_sel);
827 return rte_flow_error_set(error, rc,
828 RTE_FLOW_ERROR_TYPE_ITEM, item,
829 "Can't find RTE ethdev by the port ID");
832 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec,
835 return rte_flow_error_set(error, rc,
836 RTE_FLOW_ERROR_TYPE_ITEM, item,
837 "Failed to set MPORT for the port ID");
840 ctx_mae->match_mport_set = B_TRUE;
846 sfc_mae_rule_parse_item_phy_port(const struct rte_flow_item *item,
847 struct sfc_flow_parse_ctx *ctx,
848 struct rte_flow_error *error)
850 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
851 const struct rte_flow_item_phy_port supp_mask = {
854 const void *def_mask = &rte_flow_item_phy_port_mask;
855 const struct rte_flow_item_phy_port *spec = NULL;
856 const struct rte_flow_item_phy_port *mask = NULL;
857 efx_mport_sel_t mport_v;
860 if (ctx_mae->match_mport_set) {
861 return rte_flow_error_set(error, ENOTSUP,
862 RTE_FLOW_ERROR_TYPE_ITEM, item,
863 "Can't handle multiple traffic source items");
866 rc = sfc_flow_parse_init(item,
867 (const void **)&spec, (const void **)&mask,
868 (const void *)&supp_mask, def_mask,
869 sizeof(struct rte_flow_item_phy_port), error);
873 if (mask->index != supp_mask.index) {
874 return rte_flow_error_set(error, EINVAL,
875 RTE_FLOW_ERROR_TYPE_ITEM, item,
876 "Bad mask in the PHY_PORT pattern item");
879 /* If "spec" is not set, could be any physical port */
883 rc = efx_mae_mport_by_phy_port(spec->index, &mport_v);
885 return rte_flow_error_set(error, rc,
886 RTE_FLOW_ERROR_TYPE_ITEM, item,
887 "Failed to convert the PHY_PORT index");
890 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
892 return rte_flow_error_set(error, rc,
893 RTE_FLOW_ERROR_TYPE_ITEM, item,
894 "Failed to set MPORT for the PHY_PORT");
897 ctx_mae->match_mport_set = B_TRUE;
903 sfc_mae_rule_parse_item_pf(const struct rte_flow_item *item,
904 struct sfc_flow_parse_ctx *ctx,
905 struct rte_flow_error *error)
907 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
908 const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
909 efx_mport_sel_t mport_v;
912 if (ctx_mae->match_mport_set) {
913 return rte_flow_error_set(error, ENOTSUP,
914 RTE_FLOW_ERROR_TYPE_ITEM, item,
915 "Can't handle multiple traffic source items");
918 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
921 return rte_flow_error_set(error, rc,
922 RTE_FLOW_ERROR_TYPE_ITEM, item,
923 "Failed to convert the PF ID");
926 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
928 return rte_flow_error_set(error, rc,
929 RTE_FLOW_ERROR_TYPE_ITEM, item,
930 "Failed to set MPORT for the PF");
933 ctx_mae->match_mport_set = B_TRUE;
939 sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item,
940 struct sfc_flow_parse_ctx *ctx,
941 struct rte_flow_error *error)
943 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
944 const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
945 const struct rte_flow_item_vf supp_mask = {
948 const void *def_mask = &rte_flow_item_vf_mask;
949 const struct rte_flow_item_vf *spec = NULL;
950 const struct rte_flow_item_vf *mask = NULL;
951 efx_mport_sel_t mport_v;
954 if (ctx_mae->match_mport_set) {
955 return rte_flow_error_set(error, ENOTSUP,
956 RTE_FLOW_ERROR_TYPE_ITEM, item,
957 "Can't handle multiple traffic source items");
960 rc = sfc_flow_parse_init(item,
961 (const void **)&spec, (const void **)&mask,
962 (const void *)&supp_mask, def_mask,
963 sizeof(struct rte_flow_item_vf), error);
967 if (mask->id != supp_mask.id) {
968 return rte_flow_error_set(error, EINVAL,
969 RTE_FLOW_ERROR_TYPE_ITEM, item,
970 "Bad mask in the VF pattern item");
974 * If "spec" is not set, the item requests any VF related to the
975 * PF of the current DPDK port (but not the PF itself).
976 * Reject this match criterion as unsupported.
979 return rte_flow_error_set(error, EINVAL,
980 RTE_FLOW_ERROR_TYPE_ITEM, item,
981 "Bad spec in the VF pattern item");
984 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, spec->id, &mport_v);
986 return rte_flow_error_set(error, rc,
987 RTE_FLOW_ERROR_TYPE_ITEM, item,
988 "Failed to convert the PF + VF IDs");
991 rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec, &mport_v, NULL);
993 return rte_flow_error_set(error, rc,
994 RTE_FLOW_ERROR_TYPE_ITEM, item,
995 "Failed to set MPORT for the PF + VF");
998 ctx_mae->match_mport_set = B_TRUE;
1004 * Having this field ID in a field locator means that this
1005 * locator cannot be used to actually set the field at the
1006 * time when the corresponding item gets encountered. Such
1007 * fields get stashed in the parsing context instead. This
1008 * is required to resolve dependencies between the stashed
1009 * fields. See sfc_mae_rule_process_pattern_data().
1011 #define SFC_MAE_FIELD_HANDLING_DEFERRED EFX_MAE_FIELD_NIDS
1013 struct sfc_mae_field_locator {
1014 efx_mae_field_id_t field_id;
1016 /* Field offset in the corresponding rte_flow_item_ struct */
1021 sfc_mae_item_build_supp_mask(const struct sfc_mae_field_locator *field_locators,
1022 unsigned int nb_field_locators, void *mask_ptr,
1027 memset(mask_ptr, 0, mask_size);
1029 for (i = 0; i < nb_field_locators; ++i) {
1030 const struct sfc_mae_field_locator *fl = &field_locators[i];
1032 SFC_ASSERT(fl->ofst + fl->size <= mask_size);
1033 memset(RTE_PTR_ADD(mask_ptr, fl->ofst), 0xff, fl->size);
1038 sfc_mae_parse_item(const struct sfc_mae_field_locator *field_locators,
1039 unsigned int nb_field_locators, const uint8_t *spec,
1040 const uint8_t *mask, struct sfc_mae_parse_ctx *ctx,
1041 struct rte_flow_error *error)
1043 const efx_mae_field_id_t *fremap = ctx->field_ids_remap;
1047 for (i = 0; i < nb_field_locators; ++i) {
1048 const struct sfc_mae_field_locator *fl = &field_locators[i];
1050 if (fl->field_id == SFC_MAE_FIELD_HANDLING_DEFERRED)
1053 rc = efx_mae_match_spec_field_set(ctx->match_spec,
1054 fremap[fl->field_id],
1055 fl->size, spec + fl->ofst,
1056 fl->size, mask + fl->ofst);
1062 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
1063 NULL, "Failed to process item fields");
1069 static const struct sfc_mae_field_locator flocs_eth[] = {
1072 * This locator is used only for building supported fields mask.
1073 * The field is handled by sfc_mae_rule_process_pattern_data().
1075 SFC_MAE_FIELD_HANDLING_DEFERRED,
1076 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, type),
1077 offsetof(struct rte_flow_item_eth, type),
1080 EFX_MAE_FIELD_ETH_DADDR_BE,
1081 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, dst),
1082 offsetof(struct rte_flow_item_eth, dst),
1085 EFX_MAE_FIELD_ETH_SADDR_BE,
1086 RTE_SIZEOF_FIELD(struct rte_flow_item_eth, src),
1087 offsetof(struct rte_flow_item_eth, src),
1092 sfc_mae_rule_parse_item_eth(const struct rte_flow_item *item,
1093 struct sfc_flow_parse_ctx *ctx,
1094 struct rte_flow_error *error)
1096 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1097 struct rte_flow_item_eth supp_mask;
1098 const uint8_t *spec = NULL;
1099 const uint8_t *mask = NULL;
1102 sfc_mae_item_build_supp_mask(flocs_eth, RTE_DIM(flocs_eth),
1103 &supp_mask, sizeof(supp_mask));
1105 rc = sfc_flow_parse_init(item,
1106 (const void **)&spec, (const void **)&mask,
1107 (const void *)&supp_mask,
1108 &rte_flow_item_eth_mask,
1109 sizeof(struct rte_flow_item_eth), error);
1114 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1115 struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
1116 const struct rte_flow_item_eth *item_spec;
1117 const struct rte_flow_item_eth *item_mask;
1119 item_spec = (const struct rte_flow_item_eth *)spec;
1120 item_mask = (const struct rte_flow_item_eth *)mask;
1122 ethertypes[0].value = item_spec->type;
1123 ethertypes[0].mask = item_mask->type;
1126 * The specification is empty. This is wrong in the case
1127 * when there are more network patterns in line. Other
1128 * than that, any Ethernet can match. All of that is
1129 * checked at the end of parsing.
1134 return sfc_mae_parse_item(flocs_eth, RTE_DIM(flocs_eth), spec, mask,
1138 static const struct sfc_mae_field_locator flocs_vlan[] = {
1141 EFX_MAE_FIELD_VLAN0_TCI_BE,
1142 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci),
1143 offsetof(struct rte_flow_item_vlan, tci),
1147 * This locator is used only for building supported fields mask.
1148 * The field is handled by sfc_mae_rule_process_pattern_data().
1150 SFC_MAE_FIELD_HANDLING_DEFERRED,
1151 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type),
1152 offsetof(struct rte_flow_item_vlan, inner_type),
1157 EFX_MAE_FIELD_VLAN1_TCI_BE,
1158 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, tci),
1159 offsetof(struct rte_flow_item_vlan, tci),
1163 * This locator is used only for building supported fields mask.
1164 * The field is handled by sfc_mae_rule_process_pattern_data().
1166 SFC_MAE_FIELD_HANDLING_DEFERRED,
1167 RTE_SIZEOF_FIELD(struct rte_flow_item_vlan, inner_type),
1168 offsetof(struct rte_flow_item_vlan, inner_type),
1173 sfc_mae_rule_parse_item_vlan(const struct rte_flow_item *item,
1174 struct sfc_flow_parse_ctx *ctx,
1175 struct rte_flow_error *error)
1177 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1178 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1179 const struct sfc_mae_field_locator *flocs;
1180 struct rte_flow_item_vlan supp_mask;
1181 const uint8_t *spec = NULL;
1182 const uint8_t *mask = NULL;
1183 unsigned int nb_flocs;
1186 RTE_BUILD_BUG_ON(SFC_MAE_MATCH_VLAN_MAX_NTAGS != 2);
1188 if (pdata->nb_vlan_tags == SFC_MAE_MATCH_VLAN_MAX_NTAGS) {
1189 return rte_flow_error_set(error, ENOTSUP,
1190 RTE_FLOW_ERROR_TYPE_ITEM, item,
1191 "Can't match that many VLAN tags");
1194 nb_flocs = RTE_DIM(flocs_vlan) / SFC_MAE_MATCH_VLAN_MAX_NTAGS;
1195 flocs = flocs_vlan + pdata->nb_vlan_tags * nb_flocs;
1197 /* If parsing fails, this can remain incremented. */
1198 ++pdata->nb_vlan_tags;
1200 sfc_mae_item_build_supp_mask(flocs, nb_flocs,
1201 &supp_mask, sizeof(supp_mask));
1203 rc = sfc_flow_parse_init(item,
1204 (const void **)&spec, (const void **)&mask,
1205 (const void *)&supp_mask,
1206 &rte_flow_item_vlan_mask,
1207 sizeof(struct rte_flow_item_vlan), error);
1212 struct sfc_mae_ethertype *ethertypes = pdata->ethertypes;
1213 const struct rte_flow_item_vlan *item_spec;
1214 const struct rte_flow_item_vlan *item_mask;
1216 item_spec = (const struct rte_flow_item_vlan *)spec;
1217 item_mask = (const struct rte_flow_item_vlan *)mask;
1219 ethertypes[pdata->nb_vlan_tags].value = item_spec->inner_type;
1220 ethertypes[pdata->nb_vlan_tags].mask = item_mask->inner_type;
1223 * The specification is empty. This is wrong in the case
1224 * when there are more network patterns in line. Other
1225 * than that, any Ethernet can match. All of that is
1226 * checked at the end of parsing.
1231 return sfc_mae_parse_item(flocs, nb_flocs, spec, mask, ctx_mae, error);
1234 static const struct sfc_mae_field_locator flocs_ipv4[] = {
1236 EFX_MAE_FIELD_SRC_IP4_BE,
1237 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.src_addr),
1238 offsetof(struct rte_flow_item_ipv4, hdr.src_addr),
1241 EFX_MAE_FIELD_DST_IP4_BE,
1242 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.dst_addr),
1243 offsetof(struct rte_flow_item_ipv4, hdr.dst_addr),
1247 * This locator is used only for building supported fields mask.
1248 * The field is handled by sfc_mae_rule_process_pattern_data().
1250 SFC_MAE_FIELD_HANDLING_DEFERRED,
1251 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.next_proto_id),
1252 offsetof(struct rte_flow_item_ipv4, hdr.next_proto_id),
1255 EFX_MAE_FIELD_IP_TOS,
1256 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4,
1257 hdr.type_of_service),
1258 offsetof(struct rte_flow_item_ipv4, hdr.type_of_service),
1261 EFX_MAE_FIELD_IP_TTL,
1262 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv4, hdr.time_to_live),
1263 offsetof(struct rte_flow_item_ipv4, hdr.time_to_live),
1268 sfc_mae_rule_parse_item_ipv4(const struct rte_flow_item *item,
1269 struct sfc_flow_parse_ctx *ctx,
1270 struct rte_flow_error *error)
1272 rte_be16_t ethertype_ipv4_be = RTE_BE16(RTE_ETHER_TYPE_IPV4);
1273 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1274 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1275 struct rte_flow_item_ipv4 supp_mask;
1276 const uint8_t *spec = NULL;
1277 const uint8_t *mask = NULL;
1280 sfc_mae_item_build_supp_mask(flocs_ipv4, RTE_DIM(flocs_ipv4),
1281 &supp_mask, sizeof(supp_mask));
1283 rc = sfc_flow_parse_init(item,
1284 (const void **)&spec, (const void **)&mask,
1285 (const void *)&supp_mask,
1286 &rte_flow_item_ipv4_mask,
1287 sizeof(struct rte_flow_item_ipv4), error);
1291 pdata->innermost_ethertype_restriction.value = ethertype_ipv4_be;
1292 pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
1295 const struct rte_flow_item_ipv4 *item_spec;
1296 const struct rte_flow_item_ipv4 *item_mask;
1298 item_spec = (const struct rte_flow_item_ipv4 *)spec;
1299 item_mask = (const struct rte_flow_item_ipv4 *)mask;
1301 pdata->l3_next_proto_value = item_spec->hdr.next_proto_id;
1302 pdata->l3_next_proto_mask = item_mask->hdr.next_proto_id;
1307 return sfc_mae_parse_item(flocs_ipv4, RTE_DIM(flocs_ipv4), spec, mask,
1311 static const struct sfc_mae_field_locator flocs_ipv6[] = {
1313 EFX_MAE_FIELD_SRC_IP6_BE,
1314 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.src_addr),
1315 offsetof(struct rte_flow_item_ipv6, hdr.src_addr),
1318 EFX_MAE_FIELD_DST_IP6_BE,
1319 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.dst_addr),
1320 offsetof(struct rte_flow_item_ipv6, hdr.dst_addr),
1324 * This locator is used only for building supported fields mask.
1325 * The field is handled by sfc_mae_rule_process_pattern_data().
1327 SFC_MAE_FIELD_HANDLING_DEFERRED,
1328 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.proto),
1329 offsetof(struct rte_flow_item_ipv6, hdr.proto),
1332 EFX_MAE_FIELD_IP_TTL,
1333 RTE_SIZEOF_FIELD(struct rte_flow_item_ipv6, hdr.hop_limits),
1334 offsetof(struct rte_flow_item_ipv6, hdr.hop_limits),
1339 sfc_mae_rule_parse_item_ipv6(const struct rte_flow_item *item,
1340 struct sfc_flow_parse_ctx *ctx,
1341 struct rte_flow_error *error)
1343 rte_be16_t ethertype_ipv6_be = RTE_BE16(RTE_ETHER_TYPE_IPV6);
1344 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1345 const efx_mae_field_id_t *fremap = ctx_mae->field_ids_remap;
1346 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1347 struct rte_flow_item_ipv6 supp_mask;
1348 const uint8_t *spec = NULL;
1349 const uint8_t *mask = NULL;
1350 rte_be32_t vtc_flow_be;
1356 sfc_mae_item_build_supp_mask(flocs_ipv6, RTE_DIM(flocs_ipv6),
1357 &supp_mask, sizeof(supp_mask));
1359 vtc_flow_be = RTE_BE32(RTE_IPV6_HDR_TC_MASK);
1360 memcpy(&supp_mask, &vtc_flow_be, sizeof(vtc_flow_be));
1362 rc = sfc_flow_parse_init(item,
1363 (const void **)&spec, (const void **)&mask,
1364 (const void *)&supp_mask,
1365 &rte_flow_item_ipv6_mask,
1366 sizeof(struct rte_flow_item_ipv6), error);
1370 pdata->innermost_ethertype_restriction.value = ethertype_ipv6_be;
1371 pdata->innermost_ethertype_restriction.mask = RTE_BE16(0xffff);
1374 const struct rte_flow_item_ipv6 *item_spec;
1375 const struct rte_flow_item_ipv6 *item_mask;
1377 item_spec = (const struct rte_flow_item_ipv6 *)spec;
1378 item_mask = (const struct rte_flow_item_ipv6 *)mask;
1380 pdata->l3_next_proto_value = item_spec->hdr.proto;
1381 pdata->l3_next_proto_mask = item_mask->hdr.proto;
1386 rc = sfc_mae_parse_item(flocs_ipv6, RTE_DIM(flocs_ipv6), spec, mask,
1391 memcpy(&vtc_flow_be, spec, sizeof(vtc_flow_be));
1392 vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
1393 tc_value = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
1395 memcpy(&vtc_flow_be, mask, sizeof(vtc_flow_be));
1396 vtc_flow = rte_be_to_cpu_32(vtc_flow_be);
1397 tc_mask = (vtc_flow & RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
1399 rc = efx_mae_match_spec_field_set(ctx_mae->match_spec,
1400 fremap[EFX_MAE_FIELD_IP_TOS],
1401 sizeof(tc_value), &tc_value,
1402 sizeof(tc_mask), &tc_mask);
1404 return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
1405 NULL, "Failed to process item fields");
1411 static const struct sfc_mae_field_locator flocs_tcp[] = {
1413 EFX_MAE_FIELD_L4_SPORT_BE,
1414 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.src_port),
1415 offsetof(struct rte_flow_item_tcp, hdr.src_port),
1418 EFX_MAE_FIELD_L4_DPORT_BE,
1419 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.dst_port),
1420 offsetof(struct rte_flow_item_tcp, hdr.dst_port),
1423 EFX_MAE_FIELD_TCP_FLAGS_BE,
1425 * The values have been picked intentionally since the
1426 * target MAE field is oversize (16 bit). This mapping
1427 * relies on the fact that the MAE field is big-endian.
1429 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.data_off) +
1430 RTE_SIZEOF_FIELD(struct rte_flow_item_tcp, hdr.tcp_flags),
1431 offsetof(struct rte_flow_item_tcp, hdr.data_off),
1436 sfc_mae_rule_parse_item_tcp(const struct rte_flow_item *item,
1437 struct sfc_flow_parse_ctx *ctx,
1438 struct rte_flow_error *error)
1440 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1441 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1442 struct rte_flow_item_tcp supp_mask;
1443 const uint8_t *spec = NULL;
1444 const uint8_t *mask = NULL;
1448 * When encountered among outermost items, item TCP is invalid.
1449 * Check which match specification is being constructed now.
1451 if (ctx_mae->match_spec != ctx_mae->match_spec_action) {
1452 return rte_flow_error_set(error, EINVAL,
1453 RTE_FLOW_ERROR_TYPE_ITEM, item,
1454 "TCP in outer frame is invalid");
1457 sfc_mae_item_build_supp_mask(flocs_tcp, RTE_DIM(flocs_tcp),
1458 &supp_mask, sizeof(supp_mask));
1460 rc = sfc_flow_parse_init(item,
1461 (const void **)&spec, (const void **)&mask,
1462 (const void *)&supp_mask,
1463 &rte_flow_item_tcp_mask,
1464 sizeof(struct rte_flow_item_tcp), error);
1468 pdata->l3_next_proto_restriction_value = IPPROTO_TCP;
1469 pdata->l3_next_proto_restriction_mask = 0xff;
1474 return sfc_mae_parse_item(flocs_tcp, RTE_DIM(flocs_tcp), spec, mask,
1478 static const struct sfc_mae_field_locator flocs_udp[] = {
1480 EFX_MAE_FIELD_L4_SPORT_BE,
1481 RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.src_port),
1482 offsetof(struct rte_flow_item_udp, hdr.src_port),
1485 EFX_MAE_FIELD_L4_DPORT_BE,
1486 RTE_SIZEOF_FIELD(struct rte_flow_item_udp, hdr.dst_port),
1487 offsetof(struct rte_flow_item_udp, hdr.dst_port),
1492 sfc_mae_rule_parse_item_udp(const struct rte_flow_item *item,
1493 struct sfc_flow_parse_ctx *ctx,
1494 struct rte_flow_error *error)
1496 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1497 struct sfc_mae_pattern_data *pdata = &ctx_mae->pattern_data;
1498 struct rte_flow_item_udp supp_mask;
1499 const uint8_t *spec = NULL;
1500 const uint8_t *mask = NULL;
1503 sfc_mae_item_build_supp_mask(flocs_udp, RTE_DIM(flocs_udp),
1504 &supp_mask, sizeof(supp_mask));
1506 rc = sfc_flow_parse_init(item,
1507 (const void **)&spec, (const void **)&mask,
1508 (const void *)&supp_mask,
1509 &rte_flow_item_udp_mask,
1510 sizeof(struct rte_flow_item_udp), error);
1514 pdata->l3_next_proto_restriction_value = IPPROTO_UDP;
1515 pdata->l3_next_proto_restriction_mask = 0xff;
1520 return sfc_mae_parse_item(flocs_udp, RTE_DIM(flocs_udp), spec, mask,
1524 static const struct sfc_mae_field_locator flocs_tunnel[] = {
1527 * The size and offset values are relevant
1528 * for Geneve and NVGRE, too.
1530 .size = RTE_SIZEOF_FIELD(struct rte_flow_item_vxlan, vni),
1531 .ofst = offsetof(struct rte_flow_item_vxlan, vni),
1536 * An auxiliary registry which allows using non-encap. field IDs
1537 * directly when building a match specification of type ACTION.
1539 * See sfc_mae_rule_parse_pattern() and sfc_mae_rule_parse_item_tunnel().
1541 static const efx_mae_field_id_t field_ids_no_remap[] = {
1542 #define FIELD_ID_NO_REMAP(_field) \
1543 [EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_##_field
1545 FIELD_ID_NO_REMAP(ETHER_TYPE_BE),
1546 FIELD_ID_NO_REMAP(ETH_SADDR_BE),
1547 FIELD_ID_NO_REMAP(ETH_DADDR_BE),
1548 FIELD_ID_NO_REMAP(VLAN0_TCI_BE),
1549 FIELD_ID_NO_REMAP(VLAN0_PROTO_BE),
1550 FIELD_ID_NO_REMAP(VLAN1_TCI_BE),
1551 FIELD_ID_NO_REMAP(VLAN1_PROTO_BE),
1552 FIELD_ID_NO_REMAP(SRC_IP4_BE),
1553 FIELD_ID_NO_REMAP(DST_IP4_BE),
1554 FIELD_ID_NO_REMAP(IP_PROTO),
1555 FIELD_ID_NO_REMAP(IP_TOS),
1556 FIELD_ID_NO_REMAP(IP_TTL),
1557 FIELD_ID_NO_REMAP(SRC_IP6_BE),
1558 FIELD_ID_NO_REMAP(DST_IP6_BE),
1559 FIELD_ID_NO_REMAP(L4_SPORT_BE),
1560 FIELD_ID_NO_REMAP(L4_DPORT_BE),
1561 FIELD_ID_NO_REMAP(TCP_FLAGS_BE),
1563 #undef FIELD_ID_NO_REMAP
1567 * An auxiliary registry which allows using "ENC" field IDs
1568 * when building a match specification of type OUTER.
1570 * See sfc_mae_rule_encap_parse_init().
1572 static const efx_mae_field_id_t field_ids_remap_to_encap[] = {
1573 #define FIELD_ID_REMAP_TO_ENCAP(_field) \
1574 [EFX_MAE_FIELD_##_field] = EFX_MAE_FIELD_ENC_##_field
1576 FIELD_ID_REMAP_TO_ENCAP(ETHER_TYPE_BE),
1577 FIELD_ID_REMAP_TO_ENCAP(ETH_SADDR_BE),
1578 FIELD_ID_REMAP_TO_ENCAP(ETH_DADDR_BE),
1579 FIELD_ID_REMAP_TO_ENCAP(VLAN0_TCI_BE),
1580 FIELD_ID_REMAP_TO_ENCAP(VLAN0_PROTO_BE),
1581 FIELD_ID_REMAP_TO_ENCAP(VLAN1_TCI_BE),
1582 FIELD_ID_REMAP_TO_ENCAP(VLAN1_PROTO_BE),
1583 FIELD_ID_REMAP_TO_ENCAP(SRC_IP4_BE),
1584 FIELD_ID_REMAP_TO_ENCAP(DST_IP4_BE),
1585 FIELD_ID_REMAP_TO_ENCAP(IP_PROTO),
1586 FIELD_ID_REMAP_TO_ENCAP(IP_TOS),
1587 FIELD_ID_REMAP_TO_ENCAP(IP_TTL),
1588 FIELD_ID_REMAP_TO_ENCAP(SRC_IP6_BE),
1589 FIELD_ID_REMAP_TO_ENCAP(DST_IP6_BE),
1590 FIELD_ID_REMAP_TO_ENCAP(L4_SPORT_BE),
1591 FIELD_ID_REMAP_TO_ENCAP(L4_DPORT_BE),
1593 #undef FIELD_ID_REMAP_TO_ENCAP
1597 sfc_mae_rule_parse_item_tunnel(const struct rte_flow_item *item,
1598 struct sfc_flow_parse_ctx *ctx,
1599 struct rte_flow_error *error)
1601 struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
1602 uint8_t vnet_id_v[sizeof(uint32_t)] = {0};
1603 uint8_t vnet_id_m[sizeof(uint32_t)] = {0};
1604 const struct rte_flow_item_vxlan *vxp;
1605 uint8_t supp_mask[sizeof(uint64_t)];
1606 const uint8_t *spec = NULL;
1607 const uint8_t *mask = NULL;
1611 * We're about to start processing inner frame items.
1612 * Process pattern data that has been deferred so far
1613 * and reset pattern data storage.
1615 rc = sfc_mae_rule_process_pattern_data(ctx_mae, error);
1619 memset(&ctx_mae->pattern_data, 0, sizeof(ctx_mae->pattern_data));
1621 sfc_mae_item_build_supp_mask(flocs_tunnel, RTE_DIM(flocs_tunnel),
1622 &supp_mask, sizeof(supp_mask));
1625 * This tunnel item was preliminarily detected by
1626 * sfc_mae_rule_encap_parse_init(). Default mask
1627 * was also picked by that helper. Use it here.
1629 rc = sfc_flow_parse_init(item,
1630 (const void **)&spec, (const void **)&mask,
1631 (const void *)&supp_mask,
1632 ctx_mae->tunnel_def_mask,
1633 ctx_mae->tunnel_def_mask_size, error);
1638 * This item and later ones comprise a
1639 * match specification of type ACTION.
1641 ctx_mae->match_spec = ctx_mae->match_spec_action;
1643 /* This item and later ones use non-encap. EFX MAE field IDs. */
1644 ctx_mae->field_ids_remap = field_ids_no_remap;
1650 * Field EFX_MAE_FIELD_ENC_VNET_ID_BE is a 32-bit one.
1651 * Copy 24-bit VNI, which is BE, at offset 1 in it.
1652 * The extra byte is 0 both in the mask and in the value.
1654 vxp = (const struct rte_flow_item_vxlan *)spec;
1655 memcpy(vnet_id_v + 1, &vxp->vni, sizeof(vxp->vni));
1657 vxp = (const struct rte_flow_item_vxlan *)mask;
1658 memcpy(vnet_id_m + 1, &vxp->vni, sizeof(vxp->vni));
1660 rc = efx_mae_match_spec_field_set(ctx_mae->match_spec,
1661 EFX_MAE_FIELD_ENC_VNET_ID_BE,
1662 sizeof(vnet_id_v), vnet_id_v,
1663 sizeof(vnet_id_m), vnet_id_m);
1665 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ITEM,
1666 item, "Failed to set VXLAN VNI");
1672 static const struct sfc_flow_item sfc_flow_items[] = {
1674 .type = RTE_FLOW_ITEM_TYPE_PORT_ID,
1676 * In terms of RTE flow, this item is a META one,
1677 * and its position in the pattern is don't care.
1679 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
1680 .layer = SFC_FLOW_ITEM_ANY_LAYER,
1681 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1682 .parse = sfc_mae_rule_parse_item_port_id,
1685 .type = RTE_FLOW_ITEM_TYPE_PHY_PORT,
1687 * In terms of RTE flow, this item is a META one,
1688 * and its position in the pattern is don't care.
1690 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
1691 .layer = SFC_FLOW_ITEM_ANY_LAYER,
1692 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1693 .parse = sfc_mae_rule_parse_item_phy_port,
1696 .type = RTE_FLOW_ITEM_TYPE_PF,
1698 * In terms of RTE flow, this item is a META one,
1699 * and its position in the pattern is don't care.
1701 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
1702 .layer = SFC_FLOW_ITEM_ANY_LAYER,
1703 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1704 .parse = sfc_mae_rule_parse_item_pf,
1707 .type = RTE_FLOW_ITEM_TYPE_VF,
1709 * In terms of RTE flow, this item is a META one,
1710 * and its position in the pattern is don't care.
1712 .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
1713 .layer = SFC_FLOW_ITEM_ANY_LAYER,
1714 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1715 .parse = sfc_mae_rule_parse_item_vf,
1718 .type = RTE_FLOW_ITEM_TYPE_ETH,
1719 .prev_layer = SFC_FLOW_ITEM_START_LAYER,
1720 .layer = SFC_FLOW_ITEM_L2,
1721 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1722 .parse = sfc_mae_rule_parse_item_eth,
1725 .type = RTE_FLOW_ITEM_TYPE_VLAN,
1726 .prev_layer = SFC_FLOW_ITEM_L2,
1727 .layer = SFC_FLOW_ITEM_L2,
1728 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1729 .parse = sfc_mae_rule_parse_item_vlan,
1732 .type = RTE_FLOW_ITEM_TYPE_IPV4,
1733 .prev_layer = SFC_FLOW_ITEM_L2,
1734 .layer = SFC_FLOW_ITEM_L3,
1735 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1736 .parse = sfc_mae_rule_parse_item_ipv4,
1739 .type = RTE_FLOW_ITEM_TYPE_IPV6,
1740 .prev_layer = SFC_FLOW_ITEM_L2,
1741 .layer = SFC_FLOW_ITEM_L3,
1742 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1743 .parse = sfc_mae_rule_parse_item_ipv6,
1746 .type = RTE_FLOW_ITEM_TYPE_TCP,
1747 .prev_layer = SFC_FLOW_ITEM_L3,
1748 .layer = SFC_FLOW_ITEM_L4,
1749 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1750 .parse = sfc_mae_rule_parse_item_tcp,
1753 .type = RTE_FLOW_ITEM_TYPE_UDP,
1754 .prev_layer = SFC_FLOW_ITEM_L3,
1755 .layer = SFC_FLOW_ITEM_L4,
1756 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1757 .parse = sfc_mae_rule_parse_item_udp,
1760 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
1761 .prev_layer = SFC_FLOW_ITEM_L4,
1762 .layer = SFC_FLOW_ITEM_START_LAYER,
1763 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1764 .parse = sfc_mae_rule_parse_item_tunnel,
1767 .type = RTE_FLOW_ITEM_TYPE_GENEVE,
1768 .prev_layer = SFC_FLOW_ITEM_L4,
1769 .layer = SFC_FLOW_ITEM_START_LAYER,
1770 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1771 .parse = sfc_mae_rule_parse_item_tunnel,
1774 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
1775 .prev_layer = SFC_FLOW_ITEM_L3,
1776 .layer = SFC_FLOW_ITEM_START_LAYER,
1777 .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
1778 .parse = sfc_mae_rule_parse_item_tunnel,
1783 sfc_mae_rule_process_outer(struct sfc_adapter *sa,
1784 struct sfc_mae_parse_ctx *ctx,
1785 struct sfc_mae_outer_rule **rulep,
1786 struct rte_flow_error *error)
1788 struct sfc_mae_outer_rule *rule;
1791 if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE) {
1796 SFC_ASSERT(ctx->match_spec_outer != NULL);
1798 if (!efx_mae_match_spec_is_valid(sa->nic, ctx->match_spec_outer)) {
1799 return rte_flow_error_set(error, ENOTSUP,
1800 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1801 "Inconsistent pattern (outer)");
1804 *rulep = sfc_mae_outer_rule_attach(sa, ctx->match_spec_outer,
1806 if (*rulep != NULL) {
1807 efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
1809 rc = sfc_mae_outer_rule_add(sa, ctx->match_spec_outer,
1810 ctx->encap_type, rulep);
1812 return rte_flow_error_set(error, rc,
1813 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1814 "Failed to process the pattern");
1818 /* The spec has now been tracked by the outer rule entry. */
1819 ctx->match_spec_outer = NULL;
1822 * Depending on whether we reuse an existing outer rule or create a
1823 * new one (see above), outer rule ID is either a valid value or
1824 * EFX_MAE_RSRC_ID_INVALID. Set it in the action rule match
1825 * specification (and the full mask, too) in order to have correct
1826 * class comparisons of the new rule with existing ones.
1827 * Also, action rule match specification will be validated shortly,
1828 * and having the full mask set for outer rule ID indicates that we
1829 * will use this field, and support for this field has to be checked.
1832 rc = efx_mae_match_spec_outer_rule_id_set(ctx->match_spec_action,
1833 &rule->fw_rsrc.rule_id);
1835 sfc_mae_outer_rule_del(sa, *rulep);
1838 return rte_flow_error_set(error, rc,
1839 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1840 "Failed to process the pattern");
1847 sfc_mae_rule_encap_parse_init(struct sfc_adapter *sa,
1848 const struct rte_flow_item pattern[],
1849 struct sfc_mae_parse_ctx *ctx,
1850 struct rte_flow_error *error)
1852 struct sfc_mae *mae = &sa->mae;
1855 if (pattern == NULL) {
1856 rte_flow_error_set(error, EINVAL,
1857 RTE_FLOW_ERROR_TYPE_ITEM_NUM, NULL,
1863 switch (pattern->type) {
1864 case RTE_FLOW_ITEM_TYPE_VXLAN:
1865 ctx->encap_type = EFX_TUNNEL_PROTOCOL_VXLAN;
1866 ctx->tunnel_def_mask = &rte_flow_item_vxlan_mask;
1867 ctx->tunnel_def_mask_size =
1868 sizeof(rte_flow_item_vxlan_mask);
1870 case RTE_FLOW_ITEM_TYPE_GENEVE:
1871 ctx->encap_type = EFX_TUNNEL_PROTOCOL_GENEVE;
1872 ctx->tunnel_def_mask = &rte_flow_item_geneve_mask;
1873 ctx->tunnel_def_mask_size =
1874 sizeof(rte_flow_item_geneve_mask);
1876 case RTE_FLOW_ITEM_TYPE_NVGRE:
1877 ctx->encap_type = EFX_TUNNEL_PROTOCOL_NVGRE;
1878 ctx->tunnel_def_mask = &rte_flow_item_nvgre_mask;
1879 ctx->tunnel_def_mask_size =
1880 sizeof(rte_flow_item_nvgre_mask);
1882 case RTE_FLOW_ITEM_TYPE_END:
1892 if (pattern->type == RTE_FLOW_ITEM_TYPE_END)
1895 if ((mae->encap_types_supported & (1U << ctx->encap_type)) == 0) {
1896 return rte_flow_error_set(error, ENOTSUP,
1897 RTE_FLOW_ERROR_TYPE_ITEM,
1898 pattern, "Unsupported tunnel item");
1901 if (ctx->priority >= mae->nb_outer_rule_prios_max) {
1902 return rte_flow_error_set(error, ENOTSUP,
1903 RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY,
1904 NULL, "Unsupported priority level");
1907 rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_OUTER, ctx->priority,
1908 &ctx->match_spec_outer);
1910 return rte_flow_error_set(error, rc,
1911 RTE_FLOW_ERROR_TYPE_ITEM, pattern,
1912 "Failed to initialise outer rule match specification");
1915 /* Outermost items comprise a match specification of type OUTER. */
1916 ctx->match_spec = ctx->match_spec_outer;
1918 /* Outermost items use "ENC" EFX MAE field IDs. */
1919 ctx->field_ids_remap = field_ids_remap_to_encap;
1925 sfc_mae_rule_encap_parse_fini(struct sfc_adapter *sa,
1926 struct sfc_mae_parse_ctx *ctx)
1928 if (ctx->encap_type == EFX_TUNNEL_PROTOCOL_NONE)
1931 if (ctx->match_spec_outer != NULL)
1932 efx_mae_match_spec_fini(sa->nic, ctx->match_spec_outer);
1936 sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
1937 const struct rte_flow_item pattern[],
1938 struct sfc_flow_spec_mae *spec,
1939 struct rte_flow_error *error)
1941 struct sfc_mae_parse_ctx ctx_mae;
1942 struct sfc_flow_parse_ctx ctx;
1945 memset(&ctx_mae, 0, sizeof(ctx_mae));
1946 ctx_mae.priority = spec->priority;
1949 rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
1951 &ctx_mae.match_spec_action);
1953 rc = rte_flow_error_set(error, rc,
1954 RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1955 "Failed to initialise action rule match specification");
1956 goto fail_init_match_spec_action;
1960 * As a preliminary setting, assume that there is no encapsulation
1961 * in the pattern. That is, pattern items are about to comprise a
1962 * match specification of type ACTION and use non-encap. field IDs.
1964 * sfc_mae_rule_encap_parse_init() below may override this.
1966 ctx_mae.encap_type = EFX_TUNNEL_PROTOCOL_NONE;
1967 ctx_mae.match_spec = ctx_mae.match_spec_action;
1968 ctx_mae.field_ids_remap = field_ids_no_remap;
1970 ctx.type = SFC_FLOW_PARSE_CTX_MAE;
1973 rc = sfc_mae_rule_encap_parse_init(sa, pattern, &ctx_mae, error);
1975 goto fail_encap_parse_init;
1977 rc = sfc_flow_parse_pattern(sfc_flow_items, RTE_DIM(sfc_flow_items),
1978 pattern, &ctx, error);
1980 goto fail_parse_pattern;
1982 rc = sfc_mae_rule_process_pattern_data(&ctx_mae, error);
1984 goto fail_process_pattern_data;
1986 rc = sfc_mae_rule_process_outer(sa, &ctx_mae, &spec->outer_rule, error);
1988 goto fail_process_outer;
1990 if (!efx_mae_match_spec_is_valid(sa->nic, ctx_mae.match_spec_action)) {
1991 rc = rte_flow_error_set(error, ENOTSUP,
1992 RTE_FLOW_ERROR_TYPE_ITEM, NULL,
1993 "Inconsistent pattern");
1994 goto fail_validate_match_spec_action;
1997 spec->match_spec = ctx_mae.match_spec_action;
2001 fail_validate_match_spec_action:
2003 fail_process_pattern_data:
2005 sfc_mae_rule_encap_parse_fini(sa, &ctx_mae);
2007 fail_encap_parse_init:
2008 efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
2010 fail_init_match_spec_action:
2015 * An action supported by MAE may correspond to a bundle of RTE flow actions,
2016 * in example, VLAN_PUSH = OF_PUSH_VLAN + OF_VLAN_SET_VID + OF_VLAN_SET_PCP.
2017 * That is, related RTE flow actions need to be tracked as parts of a whole
2018 * so that they can be combined into a single action and submitted to MAE
2019 * representation of a given rule's action set.
2021 * Each RTE flow action provided by an application gets classified as
2022 * one belonging to some bundle type. If an action is not supposed to
2023 * belong to any bundle, or if this action is END, it is described as
2024 * one belonging to a dummy bundle of type EMPTY.
2026 * A currently tracked bundle will be submitted if a repeating
2027 * action or an action of different bundle type follows.
2030 enum sfc_mae_actions_bundle_type {
2031 SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
2032 SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
2035 struct sfc_mae_actions_bundle {
2036 enum sfc_mae_actions_bundle_type type;
2038 /* Indicates actions already tracked by the current bundle */
2039 uint64_t actions_mask;
2041 /* Parameters used by SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH */
2042 rte_be16_t vlan_push_tpid;
2043 rte_be16_t vlan_push_tci;
2047 * Combine configuration of RTE flow actions tracked by the bundle into a
2048 * single action and submit the result to MAE action set specification.
2049 * Do nothing in the case of dummy action bundle.
2052 sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
2053 efx_mae_actions_t *spec)
2057 switch (bundle->type) {
2058 case SFC_MAE_ACTIONS_BUNDLE_EMPTY:
2060 case SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH:
2061 rc = efx_mae_action_set_populate_vlan_push(
2062 spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
2065 SFC_ASSERT(B_FALSE);
2073 * Given the type of the next RTE flow action in the line, decide
2074 * whether a new bundle is about to start, and, if this is the case,
2075 * submit and reset the current bundle.
2078 sfc_mae_actions_bundle_sync(const struct rte_flow_action *action,
2079 struct sfc_mae_actions_bundle *bundle,
2080 efx_mae_actions_t *spec,
2081 struct rte_flow_error *error)
2083 enum sfc_mae_actions_bundle_type bundle_type_new;
2086 switch (action->type) {
2087 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
2088 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
2089 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
2090 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
2094 * Self-sufficient actions, including END, are handled in this
2095 * case. No checks for unsupported actions are needed here
2096 * because parsing doesn't occur at this point.
2098 bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_EMPTY;
2102 if (bundle_type_new != bundle->type ||
2103 (bundle->actions_mask & (1ULL << action->type)) != 0) {
2104 rc = sfc_mae_actions_bundle_submit(bundle, spec);
2108 memset(bundle, 0, sizeof(*bundle));
2111 bundle->type = bundle_type_new;
2116 return rte_flow_error_set(error, rc,
2117 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
2118 "Failed to request the (group of) action(s)");
2122 sfc_mae_rule_parse_action_of_push_vlan(
2123 const struct rte_flow_action_of_push_vlan *conf,
2124 struct sfc_mae_actions_bundle *bundle)
2126 bundle->vlan_push_tpid = conf->ethertype;
2130 sfc_mae_rule_parse_action_of_set_vlan_vid(
2131 const struct rte_flow_action_of_set_vlan_vid *conf,
2132 struct sfc_mae_actions_bundle *bundle)
2134 bundle->vlan_push_tci |= (conf->vlan_vid &
2135 rte_cpu_to_be_16(RTE_LEN2MASK(12, uint16_t)));
2139 sfc_mae_rule_parse_action_of_set_vlan_pcp(
2140 const struct rte_flow_action_of_set_vlan_pcp *conf,
2141 struct sfc_mae_actions_bundle *bundle)
2143 uint16_t vlan_tci_pcp = (uint16_t)(conf->vlan_pcp &
2144 RTE_LEN2MASK(3, uint8_t)) << 13;
2146 bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp);
2149 struct sfc_mae_parsed_item {
2150 const struct rte_flow_item *item;
2151 size_t proto_header_ofst;
2152 size_t proto_header_size;
2156 * For each 16-bit word of the given header, override
2157 * bits enforced by the corresponding 16-bit mask.
2160 sfc_mae_header_force_item_masks(uint8_t *header_buf,
2161 const struct sfc_mae_parsed_item *parsed_items,
2162 unsigned int nb_parsed_items)
2164 unsigned int item_idx;
2166 for (item_idx = 0; item_idx < nb_parsed_items; ++item_idx) {
2167 const struct sfc_mae_parsed_item *parsed_item;
2168 const struct rte_flow_item *item;
2169 size_t proto_header_size;
2172 parsed_item = &parsed_items[item_idx];
2173 proto_header_size = parsed_item->proto_header_size;
2174 item = parsed_item->item;
2176 for (ofst = 0; ofst < proto_header_size;
2177 ofst += sizeof(rte_be16_t)) {
2178 rte_be16_t *wp = RTE_PTR_ADD(header_buf, ofst);
2179 const rte_be16_t *w_maskp;
2180 const rte_be16_t *w_specp;
2182 w_maskp = RTE_PTR_ADD(item->mask, ofst);
2183 w_specp = RTE_PTR_ADD(item->spec, ofst);
2186 *wp |= (*w_specp & *w_maskp);
2189 header_buf += proto_header_size;
2193 #define SFC_IPV4_TTL_DEF 0x40
2194 #define SFC_IPV6_VTC_FLOW_DEF 0x60000000
2195 #define SFC_IPV6_HOP_LIMITS_DEF 0xff
2196 #define SFC_VXLAN_FLAGS_DEF 0x08000000
2199 sfc_mae_rule_parse_action_vxlan_encap(
2200 struct sfc_mae *mae,
2201 const struct rte_flow_action_vxlan_encap *conf,
2202 efx_mae_actions_t *spec,
2203 struct rte_flow_error *error)
2205 struct sfc_mae_bounce_eh *bounce_eh = &mae->bounce_eh;
2206 struct rte_flow_item *pattern = conf->definition;
2207 uint8_t *buf = bounce_eh->buf;
2209 /* This array will keep track of non-VOID pattern items. */
2210 struct sfc_mae_parsed_item parsed_items[1 /* Ethernet */ +
2212 1 /* IPv4 or IPv6 */ +
2215 unsigned int nb_parsed_items = 0;
2217 size_t eth_ethertype_ofst = offsetof(struct rte_ether_hdr, ether_type);
2218 uint8_t dummy_buf[RTE_MAX(sizeof(struct rte_ipv4_hdr),
2219 sizeof(struct rte_ipv6_hdr))];
2220 struct rte_ipv4_hdr *ipv4 = (void *)dummy_buf;
2221 struct rte_ipv6_hdr *ipv6 = (void *)dummy_buf;
2222 struct rte_vxlan_hdr *vxlan = NULL;
2223 struct rte_udp_hdr *udp = NULL;
2224 unsigned int nb_vlan_tags = 0;
2225 size_t next_proto_ofst = 0;
2226 size_t ethertype_ofst = 0;
2229 if (pattern == NULL) {
2230 return rte_flow_error_set(error, EINVAL,
2231 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2232 "The encap. header definition is NULL");
2235 bounce_eh->type = EFX_TUNNEL_PROTOCOL_VXLAN;
2236 bounce_eh->size = 0;
2239 * Process pattern items and remember non-VOID ones.
2240 * Defer applying masks until after the complete header
2241 * has been built from the pattern items.
2243 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_ETH);
2245 for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; ++pattern) {
2246 struct sfc_mae_parsed_item *parsed_item;
2247 const uint64_t exp_items_extra_vlan[] = {
2248 RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN), 0
2250 size_t proto_header_size;
2251 rte_be16_t *ethertypep;
2252 uint8_t *next_protop;
2255 if (pattern->spec == NULL) {
2256 return rte_flow_error_set(error, EINVAL,
2257 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2258 "NULL item spec in the encap. header");
2261 if (pattern->mask == NULL) {
2262 return rte_flow_error_set(error, EINVAL,
2263 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2264 "NULL item mask in the encap. header");
2267 if (pattern->last != NULL) {
2268 /* This is not a match pattern, so disallow range. */
2269 return rte_flow_error_set(error, EINVAL,
2270 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2271 "Range item in the encap. header");
2274 if (pattern->type == RTE_FLOW_ITEM_TYPE_VOID) {
2275 /* Handle VOID separately, for clarity. */
2279 if ((exp_items & RTE_BIT64(pattern->type)) == 0) {
2280 return rte_flow_error_set(error, ENOTSUP,
2281 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2282 "Unexpected item in the encap. header");
2285 parsed_item = &parsed_items[nb_parsed_items];
2286 buf_cur = buf + bounce_eh->size;
2288 switch (pattern->type) {
2289 case RTE_FLOW_ITEM_TYPE_ETH:
2290 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_ETH,
2292 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_eth,
2295 proto_header_size = sizeof(struct rte_ether_hdr);
2297 ethertype_ofst = eth_ethertype_ofst;
2299 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VLAN) |
2300 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
2301 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
2303 case RTE_FLOW_ITEM_TYPE_VLAN:
2304 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VLAN,
2306 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vlan,
2309 proto_header_size = sizeof(struct rte_vlan_hdr);
2311 ethertypep = RTE_PTR_ADD(buf, eth_ethertype_ofst);
2312 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_QINQ);
2314 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
2315 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_VLAN);
2319 offsetof(struct rte_vlan_hdr, eth_proto);
2321 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV4) |
2322 RTE_BIT64(RTE_FLOW_ITEM_TYPE_IPV6);
2323 exp_items |= exp_items_extra_vlan[nb_vlan_tags];
2327 case RTE_FLOW_ITEM_TYPE_IPV4:
2328 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV4,
2330 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv4,
2333 proto_header_size = sizeof(struct rte_ipv4_hdr);
2335 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
2336 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV4);
2340 offsetof(struct rte_ipv4_hdr, next_proto_id);
2342 ipv4 = (struct rte_ipv4_hdr *)buf_cur;
2344 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
2346 case RTE_FLOW_ITEM_TYPE_IPV6:
2347 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_IPV6,
2349 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_ipv6,
2352 proto_header_size = sizeof(struct rte_ipv6_hdr);
2354 ethertypep = RTE_PTR_ADD(buf, ethertype_ofst);
2355 *ethertypep = RTE_BE16(RTE_ETHER_TYPE_IPV6);
2357 next_proto_ofst = bounce_eh->size +
2358 offsetof(struct rte_ipv6_hdr, proto);
2360 ipv6 = (struct rte_ipv6_hdr *)buf_cur;
2362 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_UDP);
2364 case RTE_FLOW_ITEM_TYPE_UDP:
2365 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_UDP,
2367 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_udp,
2370 proto_header_size = sizeof(struct rte_udp_hdr);
2372 next_protop = RTE_PTR_ADD(buf, next_proto_ofst);
2373 *next_protop = IPPROTO_UDP;
2375 udp = (struct rte_udp_hdr *)buf_cur;
2377 exp_items = RTE_BIT64(RTE_FLOW_ITEM_TYPE_VXLAN);
2379 case RTE_FLOW_ITEM_TYPE_VXLAN:
2380 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ITEM_TYPE_VXLAN,
2382 RTE_BUILD_BUG_ON(offsetof(struct rte_flow_item_vxlan,
2385 proto_header_size = sizeof(struct rte_vxlan_hdr);
2387 vxlan = (struct rte_vxlan_hdr *)buf_cur;
2389 udp->dst_port = RTE_BE16(RTE_VXLAN_DEFAULT_PORT);
2390 udp->dgram_len = RTE_BE16(sizeof(*udp) +
2392 udp->dgram_cksum = 0;
2397 return rte_flow_error_set(error, ENOTSUP,
2398 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2399 "Unknown item in the encap. header");
2402 if (bounce_eh->size + proto_header_size > bounce_eh->buf_size) {
2403 return rte_flow_error_set(error, E2BIG,
2404 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2405 "The encap. header is too big");
2408 if ((proto_header_size & 1) != 0) {
2409 return rte_flow_error_set(error, EINVAL,
2410 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2411 "Odd layer size in the encap. header");
2414 rte_memcpy(buf_cur, pattern->spec, proto_header_size);
2415 bounce_eh->size += proto_header_size;
2417 parsed_item->item = pattern;
2418 parsed_item->proto_header_size = proto_header_size;
2422 if (exp_items != 0) {
2423 /* Parsing item VXLAN would have reset exp_items to 0. */
2424 return rte_flow_error_set(error, ENOTSUP,
2425 RTE_FLOW_ERROR_TYPE_ACTION_CONF, NULL,
2426 "No item VXLAN in the encap. header");
2429 /* One of the pointers (ipv4, ipv6) refers to a dummy area. */
2430 ipv4->version_ihl = RTE_IPV4_VHL_DEF;
2431 ipv4->time_to_live = SFC_IPV4_TTL_DEF;
2432 ipv4->total_length = RTE_BE16(sizeof(*ipv4) + sizeof(*udp) +
2434 /* The HW cannot compute this checksum. */
2435 ipv4->hdr_checksum = 0;
2436 ipv4->hdr_checksum = rte_ipv4_cksum(ipv4);
2438 ipv6->vtc_flow = RTE_BE32(SFC_IPV6_VTC_FLOW_DEF);
2439 ipv6->hop_limits = SFC_IPV6_HOP_LIMITS_DEF;
2440 ipv6->payload_len = udp->dgram_len;
2442 vxlan->vx_flags = RTE_BE32(SFC_VXLAN_FLAGS_DEF);
2444 /* Take care of the masks. */
2445 sfc_mae_header_force_item_masks(buf, parsed_items, nb_parsed_items);
2447 return (spec != NULL) ? efx_mae_action_set_populate_encap(spec) : 0;
2451 sfc_mae_rule_parse_action_mark(const struct rte_flow_action_mark *conf,
2452 efx_mae_actions_t *spec)
2454 return efx_mae_action_set_populate_mark(spec, conf->id);
2458 sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
2459 const struct rte_flow_action_phy_port *conf,
2460 efx_mae_actions_t *spec)
2462 efx_mport_sel_t mport;
2466 if (conf->original != 0)
2467 phy_port = efx_nic_cfg_get(sa->nic)->enc_assigned_port;
2469 phy_port = conf->index;
2471 rc = efx_mae_mport_by_phy_port(phy_port, &mport);
2475 return efx_mae_action_set_populate_deliver(spec, &mport);
2479 sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
2480 const struct rte_flow_action_vf *vf_conf,
2481 efx_mae_actions_t *spec)
2483 const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
2484 efx_mport_sel_t mport;
2488 if (vf_conf == NULL)
2489 vf = EFX_PCI_VF_INVALID;
2490 else if (vf_conf->original != 0)
2495 rc = efx_mae_mport_by_pcie_function(encp->enc_pf, vf, &mport);
2499 return efx_mae_action_set_populate_deliver(spec, &mport);
2503 sfc_mae_rule_parse_action_port_id(struct sfc_adapter *sa,
2504 const struct rte_flow_action_port_id *conf,
2505 efx_mae_actions_t *spec)
2507 struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
2508 struct sfc_mae *mae = &sa->mae;
2509 efx_mport_sel_t mport;
2513 port_id = (conf->original != 0) ? sas->port_id : conf->id;
2515 rc = sfc_mae_switch_port_by_ethdev(mae->switch_domain_id,
2520 return efx_mae_action_set_populate_deliver(spec, &mport);
2524 sfc_mae_rule_parse_action(struct sfc_adapter *sa,
2525 const struct rte_flow_action *action,
2526 const struct sfc_mae_outer_rule *outer_rule,
2527 struct sfc_mae_actions_bundle *bundle,
2528 efx_mae_actions_t *spec,
2529 struct rte_flow_error *error)
2531 bool custom_error = B_FALSE;
2534 switch (action->type) {
2535 case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
2536 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_DECAP,
2537 bundle->actions_mask);
2538 if (outer_rule == NULL ||
2539 outer_rule->encap_type != EFX_TUNNEL_PROTOCOL_VXLAN)
2542 rc = efx_mae_action_set_populate_decap(spec);
2544 case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
2545 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_POP_VLAN,
2546 bundle->actions_mask);
2547 rc = efx_mae_action_set_populate_vlan_pop(spec);
2549 case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
2550 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
2551 bundle->actions_mask);
2552 sfc_mae_rule_parse_action_of_push_vlan(action->conf, bundle);
2554 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
2555 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID,
2556 bundle->actions_mask);
2557 sfc_mae_rule_parse_action_of_set_vlan_vid(action->conf, bundle);
2559 case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
2560 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP,
2561 bundle->actions_mask);
2562 sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle);
2564 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
2565 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP,
2566 bundle->actions_mask);
2567 rc = sfc_mae_rule_parse_action_vxlan_encap(&sa->mae,
2570 custom_error = B_TRUE;
2572 case RTE_FLOW_ACTION_TYPE_FLAG:
2573 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
2574 bundle->actions_mask);
2575 rc = efx_mae_action_set_populate_flag(spec);
2577 case RTE_FLOW_ACTION_TYPE_MARK:
2578 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
2579 bundle->actions_mask);
2580 rc = sfc_mae_rule_parse_action_mark(action->conf, spec);
2582 case RTE_FLOW_ACTION_TYPE_PHY_PORT:
2583 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT,
2584 bundle->actions_mask);
2585 rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
2587 case RTE_FLOW_ACTION_TYPE_PF:
2588 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PF,
2589 bundle->actions_mask);
2590 rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec);
2592 case RTE_FLOW_ACTION_TYPE_VF:
2593 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VF,
2594 bundle->actions_mask);
2595 rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec);
2597 case RTE_FLOW_ACTION_TYPE_PORT_ID:
2598 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PORT_ID,
2599 bundle->actions_mask);
2600 rc = sfc_mae_rule_parse_action_port_id(sa, action->conf, spec);
2602 case RTE_FLOW_ACTION_TYPE_DROP:
2603 SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
2604 bundle->actions_mask);
2605 rc = efx_mae_action_set_populate_drop(spec);
2608 return rte_flow_error_set(error, ENOTSUP,
2609 RTE_FLOW_ERROR_TYPE_ACTION, NULL,
2610 "Unsupported action");
2614 bundle->actions_mask |= (1ULL << action->type);
2615 } else if (!custom_error) {
2616 rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION,
2617 NULL, "Failed to request the action");
2624 sfc_mae_bounce_eh_invalidate(struct sfc_mae_bounce_eh *bounce_eh)
2626 bounce_eh->type = EFX_TUNNEL_PROTOCOL_NONE;
2630 sfc_mae_process_encap_header(struct sfc_adapter *sa,
2631 const struct sfc_mae_bounce_eh *bounce_eh,
2632 struct sfc_mae_encap_header **encap_headerp)
2634 if (bounce_eh->type == EFX_TUNNEL_PROTOCOL_NONE) {
2635 encap_headerp = NULL;
2639 *encap_headerp = sfc_mae_encap_header_attach(sa, bounce_eh);
2640 if (*encap_headerp != NULL)
2643 return sfc_mae_encap_header_add(sa, bounce_eh, encap_headerp);
2647 sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
2648 const struct rte_flow_action actions[],
2649 struct sfc_flow_spec_mae *spec_mae,
2650 struct rte_flow_error *error)
2652 struct sfc_mae_encap_header *encap_header = NULL;
2653 struct sfc_mae_actions_bundle bundle = {0};
2654 const struct rte_flow_action *action;
2655 struct sfc_mae *mae = &sa->mae;
2656 efx_mae_actions_t *spec;
2661 if (actions == NULL) {
2662 return rte_flow_error_set(error, EINVAL,
2663 RTE_FLOW_ERROR_TYPE_ACTION_NUM, NULL,
2667 rc = efx_mae_action_set_spec_init(sa->nic, &spec);
2669 goto fail_action_set_spec_init;
2671 /* Cleanup after previous encap. header bounce buffer usage. */
2672 sfc_mae_bounce_eh_invalidate(&mae->bounce_eh);
2674 for (action = actions;
2675 action->type != RTE_FLOW_ACTION_TYPE_END; ++action) {
2676 rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error);
2678 goto fail_rule_parse_action;
2680 rc = sfc_mae_rule_parse_action(sa, action, spec_mae->outer_rule,
2681 &bundle, spec, error);
2683 goto fail_rule_parse_action;
2686 rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error);
2688 goto fail_rule_parse_action;
2690 rc = sfc_mae_process_encap_header(sa, &mae->bounce_eh, &encap_header);
2692 goto fail_process_encap_header;
2694 spec_mae->action_set = sfc_mae_action_set_attach(sa, encap_header,
2696 if (spec_mae->action_set != NULL) {
2697 sfc_mae_encap_header_del(sa, encap_header);
2698 efx_mae_action_set_spec_fini(sa->nic, spec);
2702 rc = sfc_mae_action_set_add(sa, spec, encap_header,
2703 &spec_mae->action_set);
2705 goto fail_action_set_add;
2709 fail_action_set_add:
2710 sfc_mae_encap_header_del(sa, encap_header);
2712 fail_process_encap_header:
2713 fail_rule_parse_action:
2714 efx_mae_action_set_spec_fini(sa->nic, spec);
2716 fail_action_set_spec_init:
2717 if (rc > 0 && rte_errno == 0) {
2718 rc = rte_flow_error_set(error, rc,
2719 RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
2720 NULL, "Failed to process the action");
2726 sfc_mae_rules_class_cmp(struct sfc_adapter *sa,
2727 const efx_mae_match_spec_t *left,
2728 const efx_mae_match_spec_t *right)
2730 bool have_same_class;
2733 rc = efx_mae_match_specs_class_cmp(sa->nic, left, right,
2736 return (rc == 0) ? have_same_class : false;
2740 sfc_mae_outer_rule_class_verify(struct sfc_adapter *sa,
2741 struct sfc_mae_outer_rule *rule)
2743 struct sfc_mae_fw_rsrc *fw_rsrc = &rule->fw_rsrc;
2744 struct sfc_mae_outer_rule *entry;
2745 struct sfc_mae *mae = &sa->mae;
2747 if (fw_rsrc->rule_id.id != EFX_MAE_RSRC_ID_INVALID) {
2748 /* An active rule is reused. It's class is wittingly valid. */
2752 TAILQ_FOREACH_REVERSE(entry, &mae->outer_rules,
2753 sfc_mae_outer_rules, entries) {
2754 const efx_mae_match_spec_t *left = entry->match_spec;
2755 const efx_mae_match_spec_t *right = rule->match_spec;
2760 if (sfc_mae_rules_class_cmp(sa, left, right))
2764 sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
2765 "support for outer frame pattern items is not guaranteed; "
2766 "other than that, the items are valid from SW standpoint");
2771 sfc_mae_action_rule_class_verify(struct sfc_adapter *sa,
2772 struct sfc_flow_spec_mae *spec)
2774 const struct rte_flow *entry;
2776 TAILQ_FOREACH_REVERSE(entry, &sa->flow_list, sfc_flow_list, entries) {
2777 const struct sfc_flow_spec *entry_spec = &entry->spec;
2778 const struct sfc_flow_spec_mae *es_mae = &entry_spec->mae;
2779 const efx_mae_match_spec_t *left = es_mae->match_spec;
2780 const efx_mae_match_spec_t *right = spec->match_spec;
2782 switch (entry_spec->type) {
2783 case SFC_FLOW_SPEC_FILTER:
2784 /* Ignore VNIC-level flows */
2786 case SFC_FLOW_SPEC_MAE:
2787 if (sfc_mae_rules_class_cmp(sa, left, right))
2795 sfc_info(sa, "for now, the HW doesn't support rule validation, and HW "
2796 "support for inner frame pattern items is not guaranteed; "
2797 "other than that, the items are valid from SW standpoint");
2802 * Confirm that a given flow can be accepted by the FW.
2805 * Software adapter context
2807 * Flow to be verified
2809 * Zero on success and non-zero in the case of error.
2810 * A special value of EAGAIN indicates that the adapter is
2811 * not in started state. This state is compulsory because
2812 * it only makes sense to compare the rule class of the flow
2813 * being validated with classes of the active rules.
2814 * Such classes are wittingly supported by the FW.
2817 sfc_mae_flow_verify(struct sfc_adapter *sa,
2818 struct rte_flow *flow)
2820 struct sfc_flow_spec *spec = &flow->spec;
2821 struct sfc_flow_spec_mae *spec_mae = &spec->mae;
2822 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
2825 SFC_ASSERT(sfc_adapter_is_locked(sa));
2827 if (sa->state != SFC_ADAPTER_STARTED)
2830 if (outer_rule != NULL) {
2831 rc = sfc_mae_outer_rule_class_verify(sa, outer_rule);
2836 return sfc_mae_action_rule_class_verify(sa, spec_mae);
2840 sfc_mae_flow_insert(struct sfc_adapter *sa,
2841 struct rte_flow *flow)
2843 struct sfc_flow_spec *spec = &flow->spec;
2844 struct sfc_flow_spec_mae *spec_mae = &spec->mae;
2845 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
2846 struct sfc_mae_action_set *action_set = spec_mae->action_set;
2847 struct sfc_mae_fw_rsrc *fw_rsrc = &action_set->fw_rsrc;
2850 SFC_ASSERT(spec_mae->rule_id.id == EFX_MAE_RSRC_ID_INVALID);
2851 SFC_ASSERT(action_set != NULL);
2853 if (outer_rule != NULL) {
2854 rc = sfc_mae_outer_rule_enable(sa, outer_rule,
2855 spec_mae->match_spec);
2857 goto fail_outer_rule_enable;
2860 rc = sfc_mae_action_set_enable(sa, action_set);
2862 goto fail_action_set_enable;
2864 rc = efx_mae_action_rule_insert(sa->nic, spec_mae->match_spec,
2865 NULL, &fw_rsrc->aset_id,
2866 &spec_mae->rule_id);
2868 goto fail_action_rule_insert;
2872 fail_action_rule_insert:
2873 sfc_mae_action_set_disable(sa, action_set);
2875 fail_action_set_enable:
2876 if (outer_rule != NULL)
2877 sfc_mae_outer_rule_disable(sa, outer_rule);
2879 fail_outer_rule_enable:
2884 sfc_mae_flow_remove(struct sfc_adapter *sa,
2885 struct rte_flow *flow)
2887 struct sfc_flow_spec *spec = &flow->spec;
2888 struct sfc_flow_spec_mae *spec_mae = &spec->mae;
2889 struct sfc_mae_action_set *action_set = spec_mae->action_set;
2890 struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
2893 SFC_ASSERT(spec_mae->rule_id.id != EFX_MAE_RSRC_ID_INVALID);
2894 SFC_ASSERT(action_set != NULL);
2896 rc = efx_mae_action_rule_remove(sa->nic, &spec_mae->rule_id);
2898 sfc_err(sa, "failed to disable flow=%p with AR_ID=0x%08x: %s",
2899 flow, spec_mae->rule_id.id, strerror(rc));
2901 spec_mae->rule_id.id = EFX_MAE_RSRC_ID_INVALID;
2903 sfc_mae_action_set_disable(sa, action_set);
2905 if (outer_rule != NULL)
2906 sfc_mae_outer_rule_disable(sa, outer_rule);