net/sfc: use action rules in tunnel offload jump rules

By design, JUMP flows should be represented solely by the outer rules. But
the HW/FW hasn't got support for setting Rx mark from RECIRC_ID on outer
rule lookup yet. Neither does it support outer rule counters. As a
workaround, an action rule of lower priority is used to do the job.

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
This commit is contained in:
Ivan Malov 2021-10-13 16:15:11 +03:00 committed by Ferruh Yigit
parent 8efb2f537e
commit 8cd7725169
2 changed files with 55 additions and 12 deletions

View File

@ -2563,17 +2563,20 @@ sfc_flow_parse_rte_to_mae(struct rte_eth_dev *dev,
if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) { if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
/* /*
* This flow is represented solely by the outer rule. * By design, this flow should be represented solely by the
* It is supposed to mark and count matching packets. * outer rule. But the HW/FW hasn't got support for setting
* Rx mark from RECIRC_ID on outer rule lookup yet. Neither
* does it support outer rule counters. As a workaround, an
* action rule of lower priority is used to do the job.
*
* So don't skip sfc_mae_rule_parse_actions() below.
*/ */
goto skip_action_rule;
} }
rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error); rc = sfc_mae_rule_parse_actions(sa, actions, spec_mae, error);
if (rc != 0) if (rc != 0)
goto fail; goto fail;
skip_action_rule:
if (spec_mae->ft != NULL) { if (spec_mae->ft != NULL) {
if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP)
spec_mae->ft->jump_rule_is_set = B_TRUE; spec_mae->ft->jump_rule_is_set = B_TRUE;

View File

@ -2597,6 +2597,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
struct rte_flow_error *error) struct rte_flow_error *error)
{ {
struct sfc_mae_parse_ctx ctx_mae; struct sfc_mae_parse_ctx ctx_mae;
unsigned int priority_shift = 0;
struct sfc_flow_parse_ctx ctx; struct sfc_flow_parse_ctx ctx;
int rc; int rc;
@ -2608,13 +2609,32 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
switch (ctx_mae.ft_rule_type) { switch (ctx_mae.ft_rule_type) {
case SFC_FT_RULE_JUMP: case SFC_FT_RULE_JUMP:
/* No action rule */ /*
break; * By design, this flow should be represented solely by the
* outer rule. But the HW/FW hasn't got support for setting
* Rx mark from RECIRC_ID on outer rule lookup yet. Neither
* does it support outer rule counters. As a workaround, an
* action rule of lower priority is used to do the job.
*/
priority_shift = 1;
/* FALLTHROUGH */
case SFC_FT_RULE_GROUP: case SFC_FT_RULE_GROUP:
if (ctx_mae.priority != 0) {
/*
* Because of the above workaround, deny the
* use of priorities to JUMP and GROUP rules.
*/
rc = rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
"tunnel offload: priorities are not supported");
goto fail_priority_check;
}
/* FALLTHROUGH */ /* FALLTHROUGH */
case SFC_FT_RULE_NONE: case SFC_FT_RULE_NONE:
rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION, rc = efx_mae_match_spec_init(sa->nic, EFX_MAE_RULE_ACTION,
spec->priority, spec->priority + priority_shift,
&ctx_mae.match_spec_action); &ctx_mae.match_spec_action);
if (rc != 0) { if (rc != 0) {
rc = rte_flow_error_set(error, rc, rc = rte_flow_error_set(error, rc,
@ -2689,6 +2709,7 @@ sfc_mae_rule_parse_pattern(struct sfc_adapter *sa,
efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action); efx_mae_match_spec_fini(sa->nic, ctx_mae.match_spec_action);
fail_init_match_spec_action: fail_init_match_spec_action:
fail_priority_check:
return rc; return rc;
} }
@ -3138,11 +3159,14 @@ sfc_mae_rule_parse_action_vxlan_encap(
static int static int
sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa, sfc_mae_rule_parse_action_mark(struct sfc_adapter *sa,
const struct rte_flow_action_mark *conf, const struct rte_flow_action_mark *conf,
const struct sfc_flow_spec_mae *spec_mae,
efx_mae_actions_t *spec) efx_mae_actions_t *spec)
{ {
int rc; int rc;
if (conf->id > SFC_FT_USER_MARK_MASK) { if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
/* Workaround. See sfc_flow_parse_rte_to_mae() */
} else if (conf->id > SFC_FT_USER_MARK_MASK) {
sfc_err(sa, "the mark value is too large"); sfc_err(sa, "the mark value is too large");
return EINVAL; return EINVAL;
} }
@ -3302,16 +3326,18 @@ static const char * const action_names[] = {
[RTE_FLOW_ACTION_TYPE_VF] = "VF", [RTE_FLOW_ACTION_TYPE_VF] = "VF",
[RTE_FLOW_ACTION_TYPE_PORT_ID] = "PORT_ID", [RTE_FLOW_ACTION_TYPE_PORT_ID] = "PORT_ID",
[RTE_FLOW_ACTION_TYPE_DROP] = "DROP", [RTE_FLOW_ACTION_TYPE_DROP] = "DROP",
[RTE_FLOW_ACTION_TYPE_JUMP] = "JUMP",
}; };
static int static int
sfc_mae_rule_parse_action(struct sfc_adapter *sa, sfc_mae_rule_parse_action(struct sfc_adapter *sa,
const struct rte_flow_action *action, const struct rte_flow_action *action,
const struct sfc_mae_outer_rule *outer_rule, const struct sfc_flow_spec_mae *spec_mae,
struct sfc_mae_actions_bundle *bundle, struct sfc_mae_actions_bundle *bundle,
efx_mae_actions_t *spec, efx_mae_actions_t *spec,
struct rte_flow_error *error) struct rte_flow_error *error)
{ {
const struct sfc_mae_outer_rule *outer_rule = spec_mae->outer_rule;
const uint64_t rx_metadata = sa->negotiated_rx_metadata; const uint64_t rx_metadata = sa->negotiated_rx_metadata;
bool custom_error = B_FALSE; bool custom_error = B_FALSE;
int rc = 0; int rc = 0;
@ -3375,9 +3401,10 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
case RTE_FLOW_ACTION_TYPE_MARK: case RTE_FLOW_ACTION_TYPE_MARK:
SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK, SFC_BUILD_SET_OVERFLOW(RTE_FLOW_ACTION_TYPE_MARK,
bundle->actions_mask); bundle->actions_mask);
if ((rx_metadata & RTE_ETH_RX_METADATA_USER_MARK) != 0) { if ((rx_metadata & RTE_ETH_RX_METADATA_USER_MARK) != 0 ||
spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
rc = sfc_mae_rule_parse_action_mark(sa, action->conf, rc = sfc_mae_rule_parse_action_mark(sa, action->conf,
spec); spec_mae, spec);
} else { } else {
rc = rte_flow_error_set(error, ENOTSUP, rc = rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, RTE_FLOW_ERROR_TYPE_ACTION,
@ -3411,6 +3438,12 @@ sfc_mae_rule_parse_action(struct sfc_adapter *sa,
bundle->actions_mask); bundle->actions_mask);
rc = efx_mae_action_set_populate_drop(spec); rc = efx_mae_action_set_populate_drop(spec);
break; break;
case RTE_FLOW_ACTION_TYPE_JUMP:
if (spec_mae->ft_rule_type == SFC_FT_RULE_JUMP) {
/* Workaround. See sfc_flow_parse_rte_to_mae() */
break;
}
/* FALLTHROUGH */
default: default:
return rte_flow_error_set(error, ENOTSUP, return rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL, RTE_FLOW_ERROR_TYPE_ACTION, NULL,
@ -3500,7 +3533,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
if (rc != 0) if (rc != 0)
goto fail_rule_parse_action; goto fail_rule_parse_action;
rc = sfc_mae_rule_parse_action(sa, action, spec_mae->outer_rule, rc = sfc_mae_rule_parse_action(sa, action, spec_mae,
&bundle, spec, error); &bundle, spec, error);
if (rc != 0) if (rc != 0)
goto fail_rule_parse_action; goto fail_rule_parse_action;
@ -3524,6 +3557,12 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
switch (spec_mae->ft_rule_type) { switch (spec_mae->ft_rule_type) {
case SFC_FT_RULE_NONE: case SFC_FT_RULE_NONE:
break; break;
case SFC_FT_RULE_JUMP:
/* Workaround. See sfc_flow_parse_rte_to_mae() */
rc = sfc_mae_rule_parse_action_pf_vf(sa, NULL, spec);
if (rc != 0)
goto fail_workaround_jump_delivery;
break;
case SFC_FT_RULE_GROUP: case SFC_FT_RULE_GROUP:
/* /*
* Packets that go to the rule's AR have FT mark set (from the * Packets that go to the rule's AR have FT mark set (from the
@ -3553,6 +3592,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa,
return 0; return 0;
fail_action_set_add: fail_action_set_add:
fail_workaround_jump_delivery:
fail_nb_count: fail_nb_count:
sfc_mae_encap_header_del(sa, encap_header); sfc_mae_encap_header_del(sa, encap_header);