Support the use of indirect counters in so-called SWITCH rules (second stage lookup and steering after supposed decapsulation) in tunnel offload. An indirect counter can either come instead of an inline counter or, when the latter is a conntrack-assisted counter, follow it.
Signed-off-by: Ivan Malov <ivan.ma...@arknetworks.am> Reviewed-by: Andy Moreton <andy.more...@amd.com> --- drivers/net/sfc/sfc_mae.c | 66 ++++++++++++++++++++++++++++++++------- drivers/net/sfc/sfc_mae.h | 1 + 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/drivers/net/sfc/sfc_mae.c b/drivers/net/sfc/sfc_mae.c index 60ff6d2181..ebca402ce4 100644 --- a/drivers/net/sfc/sfc_mae.c +++ b/drivers/net/sfc/sfc_mae.c @@ -972,6 +972,9 @@ sfc_mae_counter_del(struct sfc_adapter *sa, struct sfc_mae_counter *counter) --(counter->refcnt); + if (counter->refcnt == 1) + counter->ft_switch_hit_counter = NULL; + if (counter->refcnt != 0) return; @@ -4517,21 +4520,23 @@ sfc_mae_rule_parse_action_indirect(struct sfc_adapter *sa, bool replayable_only, return EEXIST; } - if (ft_rule_type != SFC_FT_RULE_NONE) { - return rte_flow_error_set(error, EINVAL, + if (ft_rule_type != SFC_FT_RULE_SWITCH && + entry->counter->ft_switch_hit_counter != NULL) { + return rte_flow_error_set(error, EBUSY, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "cannot use indirect count action in tunnel model"); + "cannot use requested indirect counter as it is in use by incompatible offload"); } SFC_ASSERT(ctx->counter == NULL); rc = efx_mae_action_set_populate_count(ctx->spec); - if (rc != 0) { + if (rc != 0 && !ctx->counter_implicit) { return rte_flow_error_set(error, rc, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, "failed to add COUNT to MAE action set"); } + ctx->counter_implicit = false; ctx->counter = entry->counter; ++(ctx->counter->refcnt); break; @@ -5237,7 +5242,7 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, goto fail_action_set_spec_init; if (spec_mae->ft_rule_type == SFC_FT_RULE_SWITCH) { - bool have_user_action_count = false; + bool have_inline_action_count = false; /* TUNNEL rules don't decapsulate packets. SWITCH rules do. */ rc = efx_mae_action_set_populate_decap(ctx->spec); @@ -5247,15 +5252,15 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; ++action) { if (action->type == RTE_FLOW_ACTION_TYPE_COUNT) { - have_user_action_count = true; + have_inline_action_count = true; break; } } - if (!have_user_action_count && + if (!have_inline_action_count && sfc_mae_counter_stream_enabled(sa)) { /* - * The user opted not to use action COUNT in this rule, + * The user might have opted not to have a counter here, * but the counter should be enabled implicitly because * packets hitting this rule contribute to the tunnel's * total number of hits. See sfc_mae_counter_get(). @@ -5264,9 +5269,19 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, if (rc != 0) goto fail_enforce_ft_count; - rc = sfc_mae_counter_add(sa, NULL, &ctx->counter); - if (rc != 0) - goto fail_enforce_ft_count; + /* + * An action of type COUNT may come inlined (see above) + * or via a shareable handle (enclosed by an action of + * type INDIRECT). The latter is expensive to resolve + * here. For now assume an implicit counter is needed. + * + * But if the flow does come with an indirect counter, + * sfc_mae_rule_parse_action_indirect() will test the + * flag to cope with its "populate" failure. It will + * reset the flag so that below code can skip + * creating a software object for the counter. + */ + ctx->counter_implicit = true; } } @@ -5314,8 +5329,33 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, */ efx_mae_action_set_populate_mark_reset(ctx->spec); + if (ctx->counter_implicit) { + /* + * Turns out the rule indeed does not have a user + * counter, so add one. The action bit in the + * action set specification has already been + * populated by the above preparse logic. + */ + rc = sfc_mae_counter_add(sa, NULL, &ctx->counter); + if (rc != 0) + goto fail_add_implicit_counter; + } + if (ctx->counter != NULL) { - (ctx->counter)->ft_switch_hit_counter = + struct sfc_mae_counter *counter = ctx->counter; + + if (counter->indirect && + counter->refcnt > 1 /* indirect handle */ + + 1 /* 1st use */ && + counter->ft_switch_hit_counter != + &spec_mae->ft_ctx->switch_hit_counter) { + rc = rte_flow_error_set(error, EBUSY, + RTE_FLOW_ERROR_TYPE_ACTION, NULL, + "requested indirect counter is in use by another tunnel context"); + goto fail_check_indirect_counter_ft_ctx; + } + + counter->ft_switch_hit_counter = &spec_mae->ft_ctx->switch_hit_counter; } else if (sfc_mae_counter_stream_enabled(sa)) { SFC_ASSERT(ct); @@ -5366,6 +5406,8 @@ sfc_mae_rule_parse_actions(struct sfc_adapter *sa, fail_action_set_add: fail_check_fate_action: +fail_check_indirect_counter_ft_ctx: +fail_add_implicit_counter: fail_workaround_tunnel_delivery: fail_rule_parse_action: sfc_mae_encap_header_del(sa, ctx->encap_header); diff --git a/drivers/net/sfc/sfc_mae.h b/drivers/net/sfc/sfc_mae.h index 2bdf5eeec2..c24dd7cd17 100644 --- a/drivers/net/sfc/sfc_mae.h +++ b/drivers/net/sfc/sfc_mae.h @@ -227,6 +227,7 @@ struct sfc_mae_aset_ctx { struct sfc_mae_mac_addr *dst_mac; struct sfc_mae_mac_addr *src_mac; + bool counter_implicit; bool fate_set; efx_mae_actions_t *spec; -- 2.17.1