Skip to content

Commit

Permalink
sfc: add fallback action-set-lists for TC offload
Browse files Browse the repository at this point in the history
When offloading a TC encap action, the action information for the
 hardware might not be "ready": if there's currently no neighbour entry
 available for the destination address, we can't construct the Ethernet
 header to prepend to the packet.  In this case, we still offload the
 flow rule, but with its action-set-list ID pointing at a "fallback"
 action which simply delivers the packet to its default destination (as
 though no flow rule had matched), thus allowing software TC to handle
 it.  Later, when we receive a neighbouring update that allows us to
 construct the encap header, the rule will become "ready" and we will
 update its action-set-list ID in hardware to point at the actual
 offloaded actions.
This patch sets up these fallback ASLs, but does not yet use them.

Reviewed-by: Pieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com>
Signed-off-by: Edward Cree <ecree.xilinx@gmail.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Edward Cree authored and Jakub Kicinski committed Jun 10, 2023
1 parent d457a0e commit e16ca7f
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
68 changes: 68 additions & 0 deletions drivers/net/ethernet/sfc/tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,58 @@ void efx_tc_deconfigure_default_rule(struct efx_nic *efx,
rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
}

static int efx_tc_configure_fallback_acts(struct efx_nic *efx, u32 eg_port,
struct efx_tc_action_set_list *acts)
{
struct efx_tc_action_set *act;
int rc;

act = kzalloc(sizeof(*act), GFP_KERNEL);
if (!act)
return -ENOMEM;
act->deliver = 1;
act->dest_mport = eg_port;
rc = efx_mae_alloc_action_set(efx, act);
if (rc)
goto fail1;
EFX_WARN_ON_PARANOID(!list_empty(&acts->list));
list_add_tail(&act->list, &acts->list);
rc = efx_mae_alloc_action_set_list(efx, acts);
if (rc)
goto fail2;
return 0;
fail2:
list_del(&act->list);
efx_mae_free_action_set(efx, act->fw_id);
fail1:
kfree(act);
return rc;
}

static int efx_tc_configure_fallback_acts_pf(struct efx_nic *efx)
{
struct efx_tc_action_set_list *acts = &efx->tc->facts.pf;
u32 eg_port;

efx_mae_mport_uplink(efx, &eg_port);
return efx_tc_configure_fallback_acts(efx, eg_port, acts);
}

static int efx_tc_configure_fallback_acts_reps(struct efx_nic *efx)
{
struct efx_tc_action_set_list *acts = &efx->tc->facts.reps;
u32 eg_port;

efx_mae_mport_mport(efx, efx->tc->reps_mport_id, &eg_port);
return efx_tc_configure_fallback_acts(efx, eg_port, acts);
}

static void efx_tc_deconfigure_fallback_acts(struct efx_nic *efx,
struct efx_tc_action_set_list *acts)
{
efx_tc_free_action_set_list(efx, acts, true);
}

static int efx_tc_configure_rep_mport(struct efx_nic *efx)
{
u32 rep_mport_label;
Expand Down Expand Up @@ -1481,6 +1533,12 @@ int efx_init_tc(struct efx_nic *efx)
if (rc)
return rc;
rc = efx_tc_configure_rep_mport(efx);
if (rc)
return rc;
rc = efx_tc_configure_fallback_acts_pf(efx);
if (rc)
return rc;
rc = efx_tc_configure_fallback_acts_reps(efx);
if (rc)
return rc;
efx->tc->up = true;
Expand All @@ -1500,6 +1558,8 @@ void efx_fini_tc(struct efx_nic *efx)
efx_tc_deconfigure_rep_mport(efx);
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf);
efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire);
efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.pf);
efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.reps);
efx->tc->up = false;
}

Expand Down Expand Up @@ -1564,6 +1624,10 @@ int efx_init_struct_tc(struct efx_nic *efx)
efx->tc->dflt.pf.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
INIT_LIST_HEAD(&efx->tc->dflt.wire.acts.list);
efx->tc->dflt.wire.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL;
INIT_LIST_HEAD(&efx->tc->facts.pf.list);
efx->tc->facts.pf.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL;
INIT_LIST_HEAD(&efx->tc->facts.reps.list);
efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL;
efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type;
return 0;
fail_match_action_ht:
Expand All @@ -1589,6 +1653,10 @@ void efx_fini_struct_tc(struct efx_nic *efx)
MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
EFX_WARN_ON_PARANOID(efx->tc->dflt.wire.fw_id !=
MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL);
EFX_WARN_ON_PARANOID(efx->tc->facts.pf.fw_id !=
MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
EFX_WARN_ON_PARANOID(efx->tc->facts.reps.fw_id !=
MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL);
rhashtable_free_and_destroy(&efx->tc->match_action_ht, efx_tc_flow_free,
efx);
rhashtable_free_and_destroy(&efx->tc->encap_match_ht,
Expand Down
9 changes: 9 additions & 0 deletions drivers/net/ethernet/sfc/tc.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ enum efx_tc_rule_prios {
* %EFX_TC_PRIO_DFLT. Named by *ingress* port
* @dflt.pf: rule for traffic ingressing from PF (egresses to wire)
* @dflt.wire: rule for traffic ingressing from wire (egresses to PF)
* @facts: Fallback action-set-lists for unready rules. Named by *egress* port
* @facts.pf: action-set-list for unready rules on PF netdev, hence applying to
* traffic from wire, and egressing to PF
* @facts.reps: action-set-list for unready rules on representors, hence
* applying to traffic from representees, and egressing to the reps mport
* @up: have TC datastructures been set up?
*/
struct efx_tc_state {
Expand All @@ -180,6 +185,10 @@ struct efx_tc_state {
struct efx_tc_flow_rule pf;
struct efx_tc_flow_rule wire;
} dflt;
struct {
struct efx_tc_action_set_list pf;
struct efx_tc_action_set_list reps;
} facts;
bool up;
};

Expand Down

0 comments on commit e16ca7f

Please sign in to comment.