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:
parent
4383cfcc65
commit
8417998131
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue