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:
parent
8efb2f537e
commit
8cd7725169
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user