net/mlx5: TC: Offload flow table rules

Since both tc rules and flow table rules are of the same format,
we can re-use tc parsing for that, and move the flow table rules
to their steering domain - In this case, the next chain after
max tc chain.

Signed-off-by: Paul Blakey <paulb@mellanox.com>
Reviewed-by: Mark Bloch <markb@mellanox.com>
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
Paul Blakey 2019-11-12 00:34:30 +01:00 committed by Saeed Mahameed
parent 4383cfcc65
commit 8417998131
3 changed files with 71 additions and 5 deletions

View File

@ -1244,21 +1244,60 @@ static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
} }
} }
static LIST_HEAD(mlx5e_rep_block_cb_list); static int mlx5e_rep_setup_ft_cb(enum tc_setup_type type, void *type_data,
void *cb_priv)
{
struct flow_cls_offload *f = type_data;
struct flow_cls_offload cls_flower;
struct mlx5e_priv *priv = cb_priv;
struct mlx5_eswitch *esw;
unsigned long flags;
int err;
flags = MLX5_TC_FLAG(INGRESS) |
MLX5_TC_FLAG(ESW_OFFLOAD) |
MLX5_TC_FLAG(FT_OFFLOAD);
esw = priv->mdev->priv.eswitch;
switch (type) {
case TC_SETUP_CLSFLOWER:
if (!mlx5_eswitch_prios_supported(esw) || f->common.chain_index)
return -EOPNOTSUPP;
/* Re-use tc offload path by moving the ft flow to the
* reserved ft chain.
*/
memcpy(&cls_flower, f, sizeof(*f));
cls_flower.common.chain_index = FDB_FT_CHAIN;
err = mlx5e_rep_setup_tc_cls_flower(priv, &cls_flower, flags);
memcpy(&f->stats, &cls_flower.stats, sizeof(f->stats));
return err;
default:
return -EOPNOTSUPP;
}
}
static LIST_HEAD(mlx5e_rep_block_tc_cb_list);
static LIST_HEAD(mlx5e_rep_block_ft_cb_list);
static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type, static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data) void *type_data)
{ {
struct mlx5e_priv *priv = netdev_priv(dev); struct mlx5e_priv *priv = netdev_priv(dev);
struct flow_block_offload *f = type_data; struct flow_block_offload *f = type_data;
f->unlocked_driver_cb = true;
switch (type) { switch (type) {
case TC_SETUP_BLOCK: case TC_SETUP_BLOCK:
f->unlocked_driver_cb = true;
return flow_block_cb_setup_simple(type_data, return flow_block_cb_setup_simple(type_data,
&mlx5e_rep_block_cb_list, &mlx5e_rep_block_tc_cb_list,
mlx5e_rep_setup_tc_cb, mlx5e_rep_setup_tc_cb,
priv, priv, true); priv, priv, true);
case TC_SETUP_FT:
return flow_block_cb_setup_simple(type_data,
&mlx5e_rep_block_ft_cb_list,
mlx5e_rep_setup_ft_cb,
priv, priv, true);
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }

View File

@ -74,6 +74,7 @@ enum {
MLX5E_TC_FLOW_FLAG_INGRESS = MLX5E_TC_FLAG_INGRESS_BIT, MLX5E_TC_FLOW_FLAG_INGRESS = MLX5E_TC_FLAG_INGRESS_BIT,
MLX5E_TC_FLOW_FLAG_EGRESS = MLX5E_TC_FLAG_EGRESS_BIT, MLX5E_TC_FLOW_FLAG_EGRESS = MLX5E_TC_FLAG_EGRESS_BIT,
MLX5E_TC_FLOW_FLAG_ESWITCH = MLX5E_TC_FLAG_ESW_OFFLOAD_BIT, MLX5E_TC_FLOW_FLAG_ESWITCH = MLX5E_TC_FLAG_ESW_OFFLOAD_BIT,
MLX5E_TC_FLOW_FLAG_FT = MLX5E_TC_FLAG_FT_OFFLOAD_BIT,
MLX5E_TC_FLOW_FLAG_NIC = MLX5E_TC_FLAG_NIC_OFFLOAD_BIT, MLX5E_TC_FLOW_FLAG_NIC = MLX5E_TC_FLAG_NIC_OFFLOAD_BIT,
MLX5E_TC_FLOW_FLAG_OFFLOADED = MLX5E_TC_FLOW_BASE, MLX5E_TC_FLOW_FLAG_OFFLOADED = MLX5E_TC_FLOW_BASE,
MLX5E_TC_FLOW_FLAG_HAIRPIN = MLX5E_TC_FLOW_BASE + 1, MLX5E_TC_FLOW_FLAG_HAIRPIN = MLX5E_TC_FLOW_BASE + 1,
@ -276,6 +277,11 @@ static bool mlx5e_is_eswitch_flow(struct mlx5e_tc_flow *flow)
return flow_flag_test(flow, ESWITCH); return flow_flag_test(flow, ESWITCH);
} }
static bool mlx5e_is_ft_flow(struct mlx5e_tc_flow *flow)
{
return flow_flag_test(flow, FT);
}
static bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow) static bool mlx5e_is_offloaded_flow(struct mlx5e_tc_flow *flow)
{ {
return flow_flag_test(flow, OFFLOADED); return flow_flag_test(flow, OFFLOADED);
@ -1168,7 +1174,12 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (attr->chain > max_chain) { /* We check chain range only for tc flows.
* For ft flows, we checked attr->chain was originally 0 and set it to
* FDB_FT_CHAIN which is outside tc range.
* See mlx5e_rep_setup_ft_cb().
*/
if (!mlx5e_is_ft_flow(flow) && attr->chain > max_chain) {
NL_SET_ERR_MSG(extack, "Requested chain is out of supported range"); NL_SET_ERR_MSG(extack, "Requested chain is out of supported range");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
@ -3217,6 +3228,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr; struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5e_rep_priv *rpriv = priv->ppriv;
const struct ip_tunnel_info *info = NULL; const struct ip_tunnel_info *info = NULL;
bool ft_flow = mlx5e_is_ft_flow(flow);
const struct flow_action_entry *act; const struct flow_action_entry *act;
bool encap = false; bool encap = false;
u32 action = 0; u32 action = 0;
@ -3261,6 +3273,14 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
return -EINVAL; return -EINVAL;
} }
if (ft_flow && out_dev == priv->netdev) {
/* Ignore forward to self rules generated
* by adding both mlx5 devs to the flow table
* block on a normal nft offload setup.
*/
return -EOPNOTSUPP;
}
if (attr->out_count >= MLX5_MAX_FLOW_FWD_VPORTS) { if (attr->out_count >= MLX5_MAX_FLOW_FWD_VPORTS) {
NL_SET_ERR_MSG_MOD(extack, NL_SET_ERR_MSG_MOD(extack,
"can't support more output ports, can't offload forwarding"); "can't support more output ports, can't offload forwarding");
@ -3385,6 +3405,10 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
u32 dest_chain = act->chain_index; u32 dest_chain = act->chain_index;
u32 max_chain = mlx5_eswitch_get_chain_range(esw); u32 max_chain = mlx5_eswitch_get_chain_range(esw);
if (ft_flow) {
NL_SET_ERR_MSG_MOD(extack, "Goto action is not supported");
return -EOPNOTSUPP;
}
if (dest_chain <= attr->chain) { if (dest_chain <= attr->chain) {
NL_SET_ERR_MSG(extack, "Goto earlier chain isn't supported"); NL_SET_ERR_MSG(extack, "Goto earlier chain isn't supported");
return -EOPNOTSUPP; return -EOPNOTSUPP;
@ -3475,6 +3499,8 @@ static void get_flags(int flags, unsigned long *flow_flags)
__flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH); __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_ESWITCH);
if (flags & MLX5_TC_FLAG(NIC_OFFLOAD)) if (flags & MLX5_TC_FLAG(NIC_OFFLOAD))
__flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC); __flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_NIC);
if (flags & MLX5_TC_FLAG(FT_OFFLOAD))
__flow_flags |= BIT(MLX5E_TC_FLOW_FLAG_FT);
*flow_flags = __flow_flags; *flow_flags = __flow_flags;
} }

View File

@ -44,7 +44,8 @@ enum {
MLX5E_TC_FLAG_EGRESS_BIT, MLX5E_TC_FLAG_EGRESS_BIT,
MLX5E_TC_FLAG_NIC_OFFLOAD_BIT, MLX5E_TC_FLAG_NIC_OFFLOAD_BIT,
MLX5E_TC_FLAG_ESW_OFFLOAD_BIT, MLX5E_TC_FLAG_ESW_OFFLOAD_BIT,
MLX5E_TC_FLAG_LAST_EXPORTED_BIT = MLX5E_TC_FLAG_ESW_OFFLOAD_BIT, MLX5E_TC_FLAG_FT_OFFLOAD_BIT,
MLX5E_TC_FLAG_LAST_EXPORTED_BIT = MLX5E_TC_FLAG_FT_OFFLOAD_BIT,
}; };
#define MLX5_TC_FLAG(flag) BIT(MLX5E_TC_FLAG_##flag##_BIT) #define MLX5_TC_FLAG(flag) BIT(MLX5E_TC_FLAG_##flag##_BIT)