From b61e717a83484569a2c8a6cbd4e54cbb0032638d Mon Sep 17 00:00:00 2001 From: Ivan Malov Date: Tue, 20 Oct 2020 10:13:08 +0100 Subject: [PATCH] net/sfc: add facilities to handle bundles of actions There are MAE actions which do not have uniform counterparts in terms of RTE flow. However, there are bundles of RTE flow actions which can be considered as such counterparts. Implement facilities to handle related RTE flow actions as parts of a whole. These facilities will be used by a later patch to add support for VLAN PUSH actions bundle. Signed-off-by: Ivan Malov Signed-off-by: Andrew Rybchenko Reviewed-by: Andy Moreton --- drivers/net/sfc/sfc_flow.c | 4 -- drivers/net/sfc/sfc_flow.h | 4 ++ drivers/net/sfc/sfc_mae.c | 112 ++++++++++++++++++++++++++++++++++++- 3 files changed, 115 insertions(+), 5 deletions(-) diff --git a/drivers/net/sfc/sfc_flow.c b/drivers/net/sfc/sfc_flow.c index 3af95ac8ee..6ccefef477 100644 --- a/drivers/net/sfc/sfc_flow.c +++ b/drivers/net/sfc/sfc_flow.c @@ -1679,9 +1679,6 @@ sfc_flow_parse_actions(struct sfc_adapter *sa, return -rte_errno; } -#define SFC_BUILD_SET_OVERFLOW(_action, _set) \ - RTE_BUILD_BUG_ON(_action >= sizeof(_set) * CHAR_BIT) - for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { switch (actions->type) { case RTE_FLOW_ACTION_TYPE_VOID: @@ -1777,7 +1774,6 @@ sfc_flow_parse_actions(struct sfc_adapter *sa, actions_set |= (1UL << actions->type); } -#undef SFC_BUILD_SET_OVERFLOW /* When fate is unknown, drop traffic. */ if ((actions_set & fate_actions_mask) == 0) { diff --git a/drivers/net/sfc/sfc_flow.h b/drivers/net/sfc/sfc_flow.h index d3bdbd5f75..e991ae132c 100644 --- a/drivers/net/sfc/sfc_flow.h +++ b/drivers/net/sfc/sfc_flow.h @@ -26,6 +26,10 @@ extern "C" { */ #define SF_FLOW_SPEC_NB_FILTERS_MAX 8 +/* Used to guard action masks */ +#define SFC_BUILD_SET_OVERFLOW(_action, _set) \ + RTE_BUILD_BUG_ON((_action) >= sizeof(_set) * CHAR_BIT) + /* RSS configuration storage */ struct sfc_flow_rss { unsigned int rxq_hw_index_min; diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c index a86a22ad8f..5fbf627f0a 100644 --- a/drivers/net/sfc/sfc_mae.c +++ b/drivers/net/sfc/sfc_mae.c @@ -445,6 +445,99 @@ fail_init_match_spec_action: return rc; } +/* + * An action supported by MAE may correspond to a bundle of RTE flow actions, + * in example, VLAN_PUSH = OF_PUSH_VLAN + OF_VLAN_SET_VID + OF_VLAN_SET_PCP. + * That is, related RTE flow actions need to be tracked as parts of a whole + * so that they can be combined into a single action and submitted to MAE + * representation of a given rule's action set. + * + * Each RTE flow action provided by an application gets classified as + * one belonging to some bundle type. If an action is not supposed to + * belong to any bundle, or if this action is END, it is described as + * one belonging to a dummy bundle of type EMPTY. + * + * A currently tracked bundle will be submitted if a repeating + * action or an action of different bundle type follows. + */ + +enum sfc_mae_actions_bundle_type { + SFC_MAE_ACTIONS_BUNDLE_EMPTY = 0, +}; + +struct sfc_mae_actions_bundle { + enum sfc_mae_actions_bundle_type type; + + /* Indicates actions already tracked by the current bundle */ + uint64_t actions_mask; +}; + +/* + * Combine configuration of RTE flow actions tracked by the bundle into a + * single action and submit the result to MAE action set specification. + * Do nothing in the case of dummy action bundle. + */ +static int +sfc_mae_actions_bundle_submit(const struct sfc_mae_actions_bundle *bundle, + __rte_unused efx_mae_actions_t *spec) +{ + int rc = 0; + + switch (bundle->type) { + case SFC_MAE_ACTIONS_BUNDLE_EMPTY: + break; + default: + SFC_ASSERT(B_FALSE); + break; + } + + return rc; +} + +/* + * Given the type of the next RTE flow action in the line, decide + * whether a new bundle is about to start, and, if this is the case, + * submit and reset the current bundle. + */ +static int +sfc_mae_actions_bundle_sync(const struct rte_flow_action *action, + struct sfc_mae_actions_bundle *bundle, + efx_mae_actions_t *spec, + struct rte_flow_error *error) +{ + enum sfc_mae_actions_bundle_type bundle_type_new; + int rc; + + switch (action->type) { + default: + /* + * Self-sufficient actions, including END, are handled in this + * case. No checks for unsupported actions are needed here + * because parsing doesn't occur at this point. + */ + bundle_type_new = SFC_MAE_ACTIONS_BUNDLE_EMPTY; + break; + } + + if (bundle_type_new != bundle->type || + (bundle->actions_mask & (1ULL << action->type)) != 0) { + rc = sfc_mae_actions_bundle_submit(bundle, spec); + if (rc != 0) + goto fail_submit; + + memset(bundle, 0, sizeof(*bundle)); + } + + bundle->type = bundle_type_new; + + return 0; + +fail_submit: + return rte_flow_error_set(error, rc, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "Failed to request the (group of) action(s)"); +} + static int sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa, const struct rte_flow_action_phy_port *conf, @@ -469,6 +562,7 @@ sfc_mae_rule_parse_action_phy_port(struct sfc_adapter *sa, static int sfc_mae_rule_parse_action(struct sfc_adapter *sa, const struct rte_flow_action *action, + struct sfc_mae_actions_bundle *bundle, efx_mae_actions_t *spec, struct rte_flow_error *error) { @@ -476,9 +570,13 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa, switch (action->type) { case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: + SFC_BUILD_SET_OVERFLOW(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_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; default: @@ -490,6 +588,8 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa, if (rc != 0) { rc = rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "Failed to request the action"); + } else { + bundle->actions_mask |= (1ULL << action->type); } return rc; @@ -501,6 +601,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, struct sfc_mae_action_set **action_setp, struct rte_flow_error *error) { + struct sfc_mae_actions_bundle bundle = {0}; const struct rte_flow_action *action; efx_mae_actions_t *spec; int rc; @@ -517,11 +618,20 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) { - rc = sfc_mae_rule_parse_action(sa, action, spec, error); + rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error); + if (rc != 0) + goto fail_rule_parse_action; + + rc = sfc_mae_rule_parse_action(sa, action, &bundle, spec, + error); if (rc != 0) goto fail_rule_parse_action; } + rc = sfc_mae_actions_bundle_sync(action, &bundle, spec, error); + if (rc != 0) + goto fail_rule_parse_action; + *action_setp = sfc_mae_action_set_attach(sa, spec); if (*action_setp != NULL) { efx_mae_action_set_spec_fini(sa->nic, spec); -- 2.20.1