return 0;
}
+static int
+sfc_mae_rule_parse_item_pf(const struct rte_flow_item *item,
+ struct sfc_flow_parse_ctx *ctx,
+ struct rte_flow_error *error)
+{
+ struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+ const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
+ efx_mport_sel_t mport_v;
+ int rc;
+
+ if (ctx_mae->match_mport_set) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Can't handle multiple traffic source items");
+ }
+
+ rc = efx_mae_mport_by_pcie_function(encp->enc_pf, EFX_PCI_VF_INVALID,
+ &mport_v);
+ if (rc != 0) {
+ return rte_flow_error_set(error, rc,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Failed to convert the PF ID");
+ }
+
+ rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+ &mport_v, NULL);
+ if (rc != 0) {
+ return rte_flow_error_set(error, rc,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Failed to set MPORT for the PF");
+ }
+
+ ctx_mae->match_mport_set = B_TRUE;
+
+ return 0;
+}
+
+static int
+sfc_mae_rule_parse_item_vf(const struct rte_flow_item *item,
+ struct sfc_flow_parse_ctx *ctx,
+ struct rte_flow_error *error)
+{
+ struct sfc_mae_parse_ctx *ctx_mae = ctx->mae;
+ const efx_nic_cfg_t *encp = efx_nic_cfg_get(ctx_mae->sa->nic);
+ const struct rte_flow_item_vf supp_mask = {
+ .id = 0xffffffff,
+ };
+ const void *def_mask = &rte_flow_item_vf_mask;
+ const struct rte_flow_item_vf *spec = NULL;
+ const struct rte_flow_item_vf *mask = NULL;
+ efx_mport_sel_t mport_v;
+ int rc;
+
+ if (ctx_mae->match_mport_set) {
+ return rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Can't handle multiple traffic source items");
+ }
+
+ rc = sfc_flow_parse_init(item,
+ (const void **)&spec, (const void **)&mask,
+ (const void *)&supp_mask, def_mask,
+ sizeof(struct rte_flow_item_vf), error);
+ if (rc != 0)
+ return rc;
+
+ if (mask->id != supp_mask.id) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Bad mask in the VF pattern item");
+ }
+
+ /*
+ * If "spec" is not set, the item requests any VF related to the
+ * PF of the current DPDK port (but not the PF itself).
+ * Reject this match criterion as unsupported.
+ */
+ if (spec == NULL) {
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Bad spec in the VF pattern item");
+ }
+
+ rc = efx_mae_mport_by_pcie_function(encp->enc_pf, spec->id, &mport_v);
+ if (rc != 0) {
+ return rte_flow_error_set(error, rc,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Failed to convert the PF + VF IDs");
+ }
+
+ rc = efx_mae_match_spec_mport_set(ctx_mae->match_spec_action,
+ &mport_v, NULL);
+ if (rc != 0) {
+ return rte_flow_error_set(error, rc,
+ RTE_FLOW_ERROR_TYPE_ITEM, item,
+ "Failed to set MPORT for the PF + VF");
+ }
+
+ ctx_mae->match_mport_set = B_TRUE;
+
+ return 0;
+}
+
struct sfc_mae_field_locator {
efx_mae_field_id_t field_id;
size_t size;
.ctx_type = SFC_FLOW_PARSE_CTX_MAE,
.parse = sfc_mae_rule_parse_item_phy_port,
},
+ {
+ .type = RTE_FLOW_ITEM_TYPE_PF,
+ /*
+ * In terms of RTE flow, this item is a META one,
+ * and its position in the pattern is don't care.
+ */
+ .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+ .layer = SFC_FLOW_ITEM_ANY_LAYER,
+ .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+ .parse = sfc_mae_rule_parse_item_pf,
+ },
+ {
+ .type = RTE_FLOW_ITEM_TYPE_VF,
+ /*
+ * In terms of RTE flow, this item is a META one,
+ * and its position in the pattern is don't care.
+ */
+ .prev_layer = SFC_FLOW_ITEM_ANY_LAYER,
+ .layer = SFC_FLOW_ITEM_ANY_LAYER,
+ .ctx_type = SFC_FLOW_PARSE_CTX_MAE,
+ .parse = sfc_mae_rule_parse_item_vf,
+ },
{
.type = RTE_FLOW_ITEM_TYPE_ETH,
.prev_layer = SFC_FLOW_ITEM_START_LAYER,
int rc;
memset(&ctx_mae, 0, sizeof(ctx_mae));
+ ctx_mae.sa = sa;
rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
spec->priority,
enum sfc_mae_actions_bundle_type {
SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0,
+ SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH,
};
struct sfc_mae_actions_bundle {
/* Indicates actions already tracked by the current bundle */
uint64_t actions_mask;
+
+ /* Parameters used by SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH */
+ rte_be16_t vlan_push_tpid;
+ rte_be16_t vlan_push_tci;
};
/*
*/
static int
sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle,
- __rte_unused efx_mae_actions_t *spec)
+ efx_mae_actions_t *spec)
{
int rc = 0;
switch (bundle->type) {
case SFC_MAE_ACTIONS_BUNDLE_EMPTY:
break;
+ case SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH:
+ rc = efx_mae_action_set_populate_vlan_push(
+ spec, bundle->vlan_push_tpid, bundle->vlan_push_tci);
+ break;
default:
SFC_ASSERT(B_FALSE);
break;
int rc;
switch (action->type) {
+ case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+ case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+ case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
+ bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_VLAN_PUSH;
+ break;
default:
/*
* Self-sufficient actions, including END, are handled in this
"Failed to request the (group of) action(s)");
}
+static void
+sfc_mae_rule_parse_action_of_push_vlan(
+ const struct rte_flow_action_of_push_vlan *conf,
+ struct sfc_mae_actions_bundle *bundle)
+{
+ bundle->vlan_push_tpid = conf->ethertype;
+}
+
+static void
+sfc_mae_rule_parse_action_of_set_vlan_vid(
+ const struct rte_flow_action_of_set_vlan_vid *conf,
+ struct sfc_mae_actions_bundle *bundle)
+{
+ bundle->vlan_push_tci |= (conf->vlan_vid &
+ rte_cpu_to_be_16(RTE_LEN2MASK(12, uint16_t)));
+}
+
+static void
+sfc_mae_rule_parse_action_of_set_vlan_pcp(
+ const struct rte_flow_action_of_set_vlan_pcp *conf,
+ struct sfc_mae_actions_bundle *bundle)
+{
+ uint16_t vlan_tci_pcp = (uint16_t)(conf->vlan_pcp &
+ RTE_LEN2MASK(3, uint8_t)) << 13;
+
+ bundle->vlan_push_tci |= rte_cpu_to_be_16(vlan_tci_pcp);
+}
+
+static int
+sfc_mae_rule_parse_action_mark(const struct rte_flow_action_mark *conf,
+ efx_mae_actions_t *spec)
+{
+ return efx_mae_action_set_populate_mark(spec, conf->id);
+}
+
static int
sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa,
const struct rte_flow_action_phy_port *conf,
return efx_mae_action_set_populate_deliver(spec, &mport);
}
+static int
+sfc_mae_rule_parse_action_pf_vf(struct sfc_adapter *sa,
+ const struct rte_flow_action_vf *vf_conf,
+ efx_mae_actions_t *spec)
+{
+ const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic);
+ efx_mport_sel_t mport;
+ uint32_t vf;
+ int rc;
+
+ if (vf_conf == NULL)
+ vf = EFX_PCI_VF_INVALID;
+ else if (vf_conf->original != 0)
+ vf = encp->enc_vf;
+ else
+ vf = vf_conf->id;
+
+ rc = efx_mae_mport_by_pcie_function(encp->enc_pf, vf, &mport);
+ if (rc != 0)
+ return rc;
+
+ return efx_mae_action_set_populate_deliver(spec, &mport);
+}
+
static int
sfc_mae_rule_parse_action(struct sfc_adapter *sa,
const struct rte_flow_action *action,
efx_mae_actions_t *spec,
struct rte_flow_error *error)
{
- int rc;
+ int rc = 0;
switch (action->type) {
case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
bundle->actions_mask);
rc = efx_mae_action_set_populate_vlan_pop(spec);
break;
+ case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
+ bundle->actions_mask);
+ sfc_mae_rule_parse_action_of_push_vlan(action->conf, bundle);
+ break;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID,
+ bundle->actions_mask);
+ sfc_mae_rule_parse_action_of_set_vlan_vid(action->conf, bundle);
+ break;
+ case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP,
+ bundle->actions_mask);
+ sfc_mae_rule_parse_action_of_set_vlan_pcp(action->conf, bundle);
+ break;
+ case RTE_FLOW_ACTION_TYPE_FLAG:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_FLAG,
+ bundle->actions_mask);
+ rc = efx_mae_action_set_populate_flag(spec);
+ break;
+ case RTE_FLOW_ACTION_TYPE_MARK:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
+ bundle->actions_mask);
+ rc = sfc_mae_rule_parse_action_mark(action->conf, spec);
+ break;
case RTE_FLOW_ACTION_TYPE_PHY_PORT:
SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PHY_PORT,
bundle->actions_mask);
rc = sfc_mae_rule_parse_action_phy_port(sa, action->conf, spec);
break;
+ case RTE_FLOW_ACTION_TYPE_PF:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_PF,
+ bundle->actions_mask);
+ rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec);
+ break;
+ case RTE_FLOW_ACTION_TYPE_VF:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_VF,
+ bundle->actions_mask);
+ rc = sfc_mae_rule_parse_action_pf_vf(sa, action->conf, spec);
+ break;
+ case RTE_FLOW_ACTION_TYPE_DROP:
+ SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_DROP,
+ bundle->actions_mask);
+ rc = efx_mae_action_set_populate_drop(spec);
+ break;
default:
return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,