From 9d3faa51bef05d21e908f2c1bd932a5cfac59b63 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Fri, 13 Mar 2020 20:40:20 -0700 Subject: [PATCH 01/14] net/mlx5: Add missing inline to stub esw_add_restore_rule When CONFIG_MLX5_ESWITCH is unset, clang warns: In file included from drivers/net/ethernet/mellanox/mlx5/core/main.c:58: drivers/net/ethernet/mellanox/mlx5/core/eswitch.h:670:1: warning: unused function 'esw_add_restore_rule' [-Wunused-function] esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag) ^ 1 warning generated. This stub function is missing inline; add it to suppress the warning. Fixes: 11b717d61526 ("net/mlx5: E-Switch, Get reg_c0 value on CQE") Signed-off-by: Nathan Chancellor Reviewed-by: Nick Desaulniers Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 91b2aedcf52b..2318c1cfc434 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -677,7 +677,7 @@ static inline const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev) static inline void mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, const int num_vfs) {} -static struct mlx5_flow_handle * +static inline struct mlx5_flow_handle * esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag) { return ERR_PTR(-EOPNOTSUPP); From 0b3a8b6b53406f2d890cda369aa9d61e30bc4162 Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Sun, 1 Mar 2020 16:12:00 +0200 Subject: [PATCH 02/14] net/mlx5: E-Switch: Fix using fwd and modify when firmware doesn't support it Currently, if firmware doesn't support fwd and modify, driver fails initializing eswitch chains while entering switchdev mode. Instead, on such cases, disable the chains and prio feature (as we can't restore the chain on miss) and the usage of fwd and modify. Fixes: 8f1e0b97cc70 ("net/mlx5: E-Switch, Mark miss packets with new chain id mapping") Signed-off-by: Paul Blakey Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- .../mellanox/mlx5/core/eswitch_offloads_chains.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c index 81421d4fb18d..e1d3dc31311a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c @@ -23,6 +23,8 @@ #define tc_end_fdb(esw) (esw_chains_priv(esw)->tc_end_fdb) #define fdb_ignore_flow_level_supported(esw) \ (MLX5_CAP_ESW_FLOWTABLE_FDB((esw)->dev, ignore_flow_level)) +#define fdb_modify_header_fwd_to_table_supported(esw) \ + (MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_modify_header_fwd_to_table)) /* Firmware currently has 4 pool of 4 sizes that it supports (ESW_POOLS), * and a virtual memory region of 16M (ESW_SIZE), this region is duplicated @@ -107,7 +109,8 @@ bool mlx5_esw_chains_prios_supported(struct mlx5_eswitch *esw) bool mlx5_esw_chains_backwards_supported(struct mlx5_eswitch *esw) { - return fdb_ignore_flow_level_supported(esw); + return mlx5_esw_chains_prios_supported(esw) && + fdb_ignore_flow_level_supported(esw); } u32 mlx5_esw_chains_get_chain_range(struct mlx5_eswitch *esw) @@ -419,7 +422,8 @@ mlx5_esw_chains_add_miss_rule(struct fdb_chain *fdb_chain, dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dest.ft = next_fdb; - if (fdb_chain->chain != mlx5_esw_chains_get_ft_chain(esw)) { + if (fdb_chain->chain != mlx5_esw_chains_get_ft_chain(esw) && + fdb_modify_header_fwd_to_table_supported(esw)) { act.modify_hdr = fdb_chain->miss_modify_hdr; act.action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; } @@ -779,6 +783,13 @@ mlx5_esw_chains_init(struct mlx5_eswitch *esw) esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE) { esw->fdb_table.flags &= ~ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED; esw_warn(dev, "Tc chains and priorities offload aren't supported, update firmware if needed\n"); + } else if (!fdb_modify_header_fwd_to_table_supported(esw)) { + /* Disabled when ttl workaround is needed, e.g + * when ESWITCH_IPV4_TTL_MODIFY_ENABLE = true in mlxconfig + */ + esw_warn(dev, + "Tc chains and priorities offload aren't supported, check firmware version, or mlxconfig settings\n"); + esw->fdb_table.flags &= ~ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED; } else { esw->fdb_table.flags |= ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED; esw_info(dev, "Supported tc offload range - chains: %u, prios: %u\n", From e0cb8afdbba909085514f02a3df2d17e7eac1ae6 Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Mon, 16 Mar 2020 14:55:11 +0200 Subject: [PATCH 03/14] net/mlx5: E-Switch, Skip restore modify header between prios of same chain Restore modify header writes the chain mapping on the packet. This modify header and action is added on all prios connections, and gets overwritten with the same value consecutively in prios of the same chain. Use the chain's modify header only for the last prio of a given tc chain. Signed-off-by: Paul Blakey Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c index e1d3dc31311a..1e275a8441de 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c @@ -422,7 +422,7 @@ mlx5_esw_chains_add_miss_rule(struct fdb_chain *fdb_chain, dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; dest.ft = next_fdb; - if (fdb_chain->chain != mlx5_esw_chains_get_ft_chain(esw) && + if (next_fdb == tc_end_fdb(esw) && fdb_modify_header_fwd_to_table_supported(esw)) { act.modify_hdr = fdb_chain->miss_modify_hdr; act.action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; From 35e725e1b9d645cc412e06bbc204d63dddb1512b Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 14 Mar 2020 18:44:46 +0800 Subject: [PATCH 04/14] net/mlx5e: CT: remove set but not used variable 'unnew' drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c: In function mlx5_tc_ct_parse_match: drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c:699:36: warning: variable unnew set but not used [-Wunused-but-set-variable] Fixes: 4c3844d9e97e ("net/mlx5e: CT: Introduce connection tracking") Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c index 956d9ddcdeed..9fe150957d65 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -696,7 +696,7 @@ mlx5_tc_ct_parse_match(struct mlx5e_priv *priv, { struct mlx5_tc_ct_priv *ct_priv = mlx5_tc_ct_get_ct_priv(priv); struct flow_dissector_key_ct *mask, *key; - bool trk, est, untrk, unest, new, unnew; + bool trk, est, untrk, unest, new; u32 ctstate = 0, ctstate_mask = 0; u16 ct_state_on, ct_state_off; u16 ct_state, ct_state_mask; @@ -739,7 +739,6 @@ mlx5_tc_ct_parse_match(struct mlx5e_priv *priv, new = ct_state_on & TCA_FLOWER_KEY_CT_FLAGS_NEW; est = ct_state_on & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED; untrk = ct_state_off & TCA_FLOWER_KEY_CT_FLAGS_TRACKED; - unnew = ct_state_off & TCA_FLOWER_KEY_CT_FLAGS_NEW; unest = ct_state_off & TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED; ctstate |= trk ? MLX5_CT_STATE_TRK_BIT : 0; From 3cfc4332edbc0e96af99be9c1cadf10c8b7113fb Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Sun, 15 Mar 2020 15:18:47 +0200 Subject: [PATCH 05/14] net/mlx5e: CT: Fix insert rules when TC_CT config isn't enabled If CONFIG_MLX5_TC_CT isn't enabled, all offloading of eswitch tc rules fails on parsing ct match, even if there is no ct match. Return success if there is no ct match, regardless of config. Fixes: 4c3844d9e97e ("net/mlx5e: CT: Introduce connection tracking") Signed-off-by: Paul Blakey Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h index 6b2c893372da..091d305b633e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h @@ -8,6 +8,8 @@ #include #include +#include "en.h" + struct mlx5_esw_flow_attr; struct mlx5e_tc_mod_hdr_acts; struct mlx5_rep_uplink_priv; @@ -128,6 +130,11 @@ mlx5_tc_ct_parse_match(struct mlx5e_priv *priv, struct flow_cls_offload *f, struct netlink_ext_ack *extack) { + if (!flow_rule_match_key(f->rule, FLOW_DISSECTOR_KEY_CT)) + return 0; + + NL_SET_ERR_MSG_MOD(extack, "mlx5 tc ct offload isn't enabled."); + netdev_warn(priv->netdev, "mlx5 tc ct offload isn't enabled.\n"); return -EOPNOTSUPP; } @@ -137,6 +144,8 @@ mlx5_tc_ct_parse_action(struct mlx5e_priv *priv, const struct flow_action_entry *act, struct netlink_ext_ack *extack) { + NL_SET_ERR_MSG_MOD(extack, "mlx5 tc ct offload isn't enabled."); + netdev_warn(priv->netdev, "mlx5 tc ct offload isn't enabled.\n"); return -EOPNOTSUPP; } From aded104d397c22a18b9040f5641309f426d6df27 Mon Sep 17 00:00:00 2001 From: Saeed Mahameed Date: Mon, 16 Mar 2020 15:47:03 -0700 Subject: [PATCH 06/14] net/mlx5e: CT: Fix stack usage compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following warnings: [-Werror=frame-larger-than=] In function ‘mlx5_tc_ct_entry_add_rule’: drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c:541:1: error: the frame size of 1136 bytes is larger than 1024 bytes In function ‘__mlx5_tc_ct_flow_offload’: drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c:1049:1: error: the frame size of 1168 bytes is larger than 1024 bytes Fixes: 4c3844d9e97e ("net/mlx5e: CT: Introduce connection tracking") Signed-off-by: Saeed Mahameed Reviewed-by: Paul Blakey --- .../ethernet/mellanox/mlx5/core/en/tc_ct.c | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c index 9fe150957d65..a22ad6b90847 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -484,19 +484,23 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_zone_rule *zone_rule = &entry->zone_rules[nat]; struct mlx5_esw_flow_attr *attr = &zone_rule->attr; struct mlx5_eswitch *esw = ct_priv->esw; - struct mlx5_flow_spec spec = {}; + struct mlx5_flow_spec *spec = NULL; u32 tupleid = 1; int err; zone_rule->nat = nat; + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) + return -ENOMEM; + /* Get tuple unique id */ err = idr_alloc_u32(&ct_priv->tuple_ids, zone_rule, &tupleid, TUPLE_ID_MAX, GFP_KERNEL); if (err) { netdev_warn(ct_priv->netdev, "Failed to allocate tuple id, err: %d\n", err); - return err; + goto err_idr_alloc; } zone_rule->tupleid = tupleid; @@ -517,18 +521,19 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv, attr->counter = entry->counter; attr->flags |= MLX5_ESW_ATTR_FLAG_NO_IN_PORT; - mlx5_tc_ct_set_tuple_match(&spec, flow_rule); - mlx5e_tc_match_to_reg_match(&spec, ZONE_TO_REG, + mlx5_tc_ct_set_tuple_match(spec, flow_rule); + mlx5e_tc_match_to_reg_match(spec, ZONE_TO_REG, entry->zone & MLX5_CT_ZONE_MASK, MLX5_CT_ZONE_MASK); - zone_rule->rule = mlx5_eswitch_add_offloaded_rule(esw, &spec, attr); + zone_rule->rule = mlx5_eswitch_add_offloaded_rule(esw, spec, attr); if (IS_ERR(zone_rule->rule)) { err = PTR_ERR(zone_rule->rule); ct_dbg("Failed to add ct entry rule, nat: %d", nat); goto err_rule; } + kfree(spec); ct_dbg("Offloaded ct entry rule in zone %d", entry->zone); return 0; @@ -537,6 +542,8 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv, mlx5_modify_header_dealloc(esw->dev, attr->modify_hdr); err_mod_hdr: idr_remove(&ct_priv->tuple_ids, zone_rule->tupleid); +err_idr_alloc: + kfree(spec); return err; } @@ -884,8 +891,8 @@ __mlx5_tc_ct_flow_offload(struct mlx5e_priv *priv, struct mlx5_tc_ct_priv *ct_priv = mlx5_tc_ct_get_ct_priv(priv); bool nat = attr->ct_attr.ct_action & TCA_CT_ACT_NAT; struct mlx5e_tc_mod_hdr_acts pre_mod_acts = {}; + struct mlx5_flow_spec *post_ct_spec = NULL; struct mlx5_eswitch *esw = ct_priv->esw; - struct mlx5_flow_spec post_ct_spec = {}; struct mlx5_esw_flow_attr *pre_ct_attr; struct mlx5_modify_hdr *mod_hdr; struct mlx5_flow_handle *rule; @@ -894,9 +901,13 @@ __mlx5_tc_ct_flow_offload(struct mlx5e_priv *priv, struct mlx5_ct_ft *ft; u32 fte_id = 1; + post_ct_spec = kzalloc(sizeof(*post_ct_spec), GFP_KERNEL); ct_flow = kzalloc(sizeof(*ct_flow), GFP_KERNEL); - if (!ct_flow) + if (!post_ct_spec || !ct_flow) { + kfree(post_ct_spec); + kfree(ct_flow); return -ENOMEM; + } /* Register for CT established events */ ft = mlx5_tc_ct_add_ft_cb(ct_priv, attr->ct_attr.zone, @@ -991,7 +1002,7 @@ __mlx5_tc_ct_flow_offload(struct mlx5e_priv *priv, /* Post ct rule matches on fte_id and executes original rule's * tc rule action */ - mlx5e_tc_match_to_reg_match(&post_ct_spec, FTEID_TO_REG, + mlx5e_tc_match_to_reg_match(post_ct_spec, FTEID_TO_REG, fte_id, MLX5_FTE_ID_MASK); /* Put post_ct rule on post_ct fdb */ @@ -1002,7 +1013,7 @@ __mlx5_tc_ct_flow_offload(struct mlx5e_priv *priv, ct_flow->post_ct_attr.inner_match_level = MLX5_MATCH_NONE; ct_flow->post_ct_attr.outer_match_level = MLX5_MATCH_NONE; ct_flow->post_ct_attr.action &= ~(MLX5_FLOW_CONTEXT_ACTION_DECAP); - rule = mlx5_eswitch_add_offloaded_rule(esw, &post_ct_spec, + rule = mlx5_eswitch_add_offloaded_rule(esw, post_ct_spec, &ct_flow->post_ct_attr); ct_flow->post_ct_rule = rule; if (IS_ERR(ct_flow->post_ct_rule)) { @@ -1026,6 +1037,7 @@ __mlx5_tc_ct_flow_offload(struct mlx5e_priv *priv, attr->ct_attr.ct_flow = ct_flow; *flow_rule = ct_flow->post_ct_rule; dealloc_mod_hdr_actions(&pre_mod_acts); + kfree(post_ct_spec); return 0; @@ -1042,6 +1054,7 @@ __mlx5_tc_ct_flow_offload(struct mlx5e_priv *priv, err_idr: mlx5_tc_ct_del_ft_cb(ct_priv, ft); err_ft: + kfree(post_ct_spec); kfree(ct_flow); netdev_warn(priv->netdev, "Failed to offload ct flow, err %d\n", err); return err; From 636bb96852398548bfc797dc29a2a6d4f95fc693 Mon Sep 17 00:00:00 2001 From: Paul Blakey Date: Tue, 10 Mar 2020 11:24:22 +0200 Subject: [PATCH 07/14] net/mlx5e: en_tc: Rely just on register loopback for tunnel restoration Register loopback which is needed for tunnel restoration, is now always enabled if supported and not just with metadata enabled, check for that instead. Signed-off-by: Paul Blakey Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 044891a03be3..a2ff7df67b46 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1985,11 +1985,11 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv, *match_inner = !needs_mapping; if ((needs_mapping || sets_mapping) && - !mlx5_eswitch_vport_match_metadata_enabled(esw)) { + !mlx5_eswitch_reg_c1_loopback_enabled(esw)) { NL_SET_ERR_MSG(extack, - "Chains on tunnel devices isn't supported without register metadata support"); + "Chains on tunnel devices isn't supported without register loopback support"); netdev_warn(priv->netdev, - "Chains on tunnel devices isn't supported without register metadata support"); + "Chains on tunnel devices isn't supported without register loopback support"); return -EOPNOTSUPP; } From d0645b3780954b7133d9a908009d166ae686bd2a Mon Sep 17 00:00:00 2001 From: Roi Dayan Date: Tue, 3 Mar 2020 11:18:53 +0200 Subject: [PATCH 08/14] net/mlx5e: Fix rejecting all egress rules not on vlan The original condition rejected all egress rules that are not on tunnel device. Also, the whole point of this egress reject was to disallow bad rules because of egdev which doesn't exists today, so remove this check entirely. Fixes: 0a7fcb78cc21 ("net/mlx5e: Support inner header rewrite with goto action") Signed-off-by: Roi Dayan Reviewed-by: Oz Shlomo Reviewed-by: Vlad Buslov Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index a2ff7df67b46..db1aee1d48e3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3044,8 +3044,7 @@ static bool actions_match_supported(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow, struct netlink_ext_ack *extack) { - struct net_device *filter_dev = parse_attr->filter_dev; - bool drop_action, pop_action, ct_flow; + bool ct_flow; u32 actions; ct_flow = flow_flag_test(flow, CT); @@ -3064,18 +3063,6 @@ static bool actions_match_supported(struct mlx5e_priv *priv, actions = flow->nic_attr->action; } - drop_action = actions & MLX5_FLOW_CONTEXT_ACTION_DROP; - pop_action = actions & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP; - - if (flow_flag_test(flow, EGRESS) && !drop_action) { - /* We only support filters on tunnel device, or on vlan - * devices if they have pop/drop action - */ - if (!mlx5e_get_tc_tun(filter_dev) || - (is_vlan_dev(filter_dev) && !pop_action)) - return false; - } - if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) return modify_header_match_supported(&parse_attr->spec, flow_action, actions, From 31e87b39ba9d47cf31f5a91dd3cc9680f5987d12 Mon Sep 17 00:00:00 2001 From: Vladyslav Tarasiuk Date: Wed, 4 Mar 2020 13:33:50 +0200 Subject: [PATCH 09/14] net/mlx5e: Fix devlink port register sequence If udevd is configured to rename interfaces according to persistent naming rules and if a network interface has phys_port_name in sysfs, its contents will be appended to the interface name. However, register_netdev creates device in sysfs and if devlink_port_register is called after that, there is a timeframe in which udevd may read an empty phys_port_name value. The consequence is that the interface will lose this suffix and its name will not be really persistent. The solution is to register the port before registering a netdev. Fixes: c6acd629eec7 ("net/mlx5e: Add support for devlink-port in non-representors mode") Signed-off-by: Vladyslav Tarasiuk Reviewed-by: Maxim Mikityanskiy Reviewed-by: Jiri Pirko Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en/devlink.c | 26 +++++++------------ .../ethernet/mellanox/mlx5/core/en/devlink.h | 3 ++- .../net/ethernet/mellanox/mlx5/core/en_main.c | 16 +++++++----- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/en/devlink.c index e38495e4aa42..f8b2de4b04be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/devlink.c @@ -3,20 +3,14 @@ #include "en/devlink.h" -int mlx5e_devlink_port_register(struct net_device *netdev) +int mlx5e_devlink_port_register(struct mlx5e_priv *priv) { - struct mlx5_core_dev *dev; - struct mlx5e_priv *priv; - struct devlink *devlink; - int err; + struct devlink *devlink = priv_to_devlink(priv->mdev); - priv = netdev_priv(netdev); - dev = priv->mdev; - - if (mlx5_core_is_pf(dev)) + if (mlx5_core_is_pf(priv->mdev)) devlink_port_attrs_set(&priv->dl_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, - PCI_FUNC(dev->pdev->devfn), + PCI_FUNC(priv->mdev->pdev->devfn), false, 0, NULL, 0); else @@ -24,12 +18,12 @@ int mlx5e_devlink_port_register(struct net_device *netdev) DEVLINK_PORT_FLAVOUR_VIRTUAL, 0, false, 0, NULL, 0); - devlink = priv_to_devlink(dev); - err = devlink_port_register(devlink, &priv->dl_port, 1); - if (err) - return err; - devlink_port_type_eth_set(&priv->dl_port, netdev); - return 0; + return devlink_port_register(devlink, &priv->dl_port, 1); +} + +void mlx5e_devlink_port_type_eth_set(struct mlx5e_priv *priv) +{ + devlink_port_type_eth_set(&priv->dl_port, priv->netdev); } void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/devlink.h b/drivers/net/ethernet/mellanox/mlx5/core/en/devlink.h index 3e5393a0901f..83123a801adc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/devlink.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/devlink.h @@ -7,8 +7,9 @@ #include #include "en.h" -int mlx5e_devlink_port_register(struct net_device *dev); +int mlx5e_devlink_port_register(struct mlx5e_priv *priv); void mlx5e_devlink_port_unregister(struct mlx5e_priv *priv); +void mlx5e_devlink_port_type_eth_set(struct mlx5e_priv *priv); struct devlink_port *mlx5e_get_devlink_port(struct net_device *dev); #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index f9c928afec89..be20d2247594 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -5467,25 +5467,27 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev) goto err_destroy_netdev; } - err = register_netdev(netdev); + err = mlx5e_devlink_port_register(priv); if (err) { - mlx5_core_err(mdev, "register_netdev failed, %d\n", err); + mlx5_core_err(mdev, "mlx5e_devlink_port_register failed, %d\n", err); goto err_detach; } - err = mlx5e_devlink_port_register(netdev); + err = register_netdev(netdev); if (err) { - mlx5_core_err(mdev, "mlx5e_devlink_phy_port_register failed, %d\n", err); - goto err_unregister_netdev; + mlx5_core_err(mdev, "register_netdev failed, %d\n", err); + goto err_devlink_port_unregister; } + mlx5e_devlink_port_type_eth_set(priv); + #ifdef CONFIG_MLX5_CORE_EN_DCB mlx5e_dcbnl_init_app(priv); #endif return priv; -err_unregister_netdev: - unregister_netdev(netdev); +err_devlink_port_unregister: + mlx5e_devlink_port_unregister(priv); err_detach: mlx5e_detach(mdev, priv); err_destroy_netdev: From b5f814cc7381e58877ebc9178283e28725c1b4f0 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Sun, 1 Mar 2020 15:31:49 +0200 Subject: [PATCH 10/14] net/mlx5: Avoid configuring eswitch QoS if not supported Check if QoS is enabled for the eswitch before attempting to configure QoS parameters and emit a netlink error if not supported. Introduce an API to check if QoS is supported for the eswitch. Signed-off-by: Eli Cohen Reviewed-by: Roi Dayan Reviewed-by: Paul Blakey Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 6 ++++++ drivers/net/ethernet/mellanox/mlx5/core/eswitch.h | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index db1aee1d48e3..ddb933aa8d59 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -4521,8 +4521,14 @@ static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv, int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv, struct tc_cls_matchall_offload *ma) { + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct netlink_ext_ack *extack = ma->common.extack; + if (!mlx5_esw_qos_enabled(esw)) { + NL_SET_ERR_MSG_MOD(extack, "QoS is not supported on this device"); + return -EOPNOTSUPP; + } + if (ma->common.prio != 1) { NL_SET_ERR_MSG_MOD(extack, "only priority 1 is supported"); return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 2318c1cfc434..c18de018c675 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -453,6 +453,11 @@ int mlx5_esw_create_vport_egress_acl_vlan(struct mlx5_eswitch *esw, struct mlx5_vport *vport, u16 vlan_id, u32 flow_action); +static inline bool mlx5_esw_qos_enabled(struct mlx5_eswitch *esw) +{ + return esw->qos.enabled; +} + static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev, u8 vlan_depth) { From d8a2034f152a99a476c8d444456fbe652da8cfd5 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 27 Feb 2020 12:22:46 +0200 Subject: [PATCH 11/14] net/mlx5: Don't use termination tables in slow path Don't use termination tables for packets that are steered to the slow path, as a pre-step for supporting packet encap (packet reformat) action on termination tables. Packet encap (reformat action) actions steer the packet to the slow path until outer arp entries are resolved. Signed-off-by: Eli Cohen Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/eswitch.h | 2 ++ .../mellanox/mlx5/core/eswitch_offloads.c | 20 +++++++++++++------ .../mlx5/core/eswitch_offloads_termtbl.c | 4 +++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index c18de018c675..95532b258c2b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -332,6 +332,7 @@ struct mlx5_termtbl_handle; bool mlx5_eswitch_termtbl_required(struct mlx5_eswitch *esw, + struct mlx5_esw_flow_attr *attr, struct mlx5_flow_act *flow_act, struct mlx5_flow_spec *spec); @@ -393,6 +394,7 @@ enum { MLX5_ESW_ATTR_FLAG_VLAN_HANDLED = BIT(0), MLX5_ESW_ATTR_FLAG_SLOW_PATH = BIT(1), MLX5_ESW_ATTR_FLAG_NO_IN_PORT = BIT(2), + MLX5_ESW_ATTR_FLAG_HAIRPIN = BIT(3), }; struct mlx5_esw_flow_attr { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index e2a906085a98..0b4b43ebae9a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -300,6 +300,7 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, bool split = !!(attr->split_count); struct mlx5_flow_handle *rule; struct mlx5_flow_table *fdb; + bool hairpin = false; int j, i = 0; if (esw->mode != MLX5_ESWITCH_OFFLOADS) @@ -397,16 +398,21 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw, goto err_esw_get; } - if (mlx5_eswitch_termtbl_required(esw, &flow_act, spec)) + if (mlx5_eswitch_termtbl_required(esw, attr, &flow_act, spec)) { rule = mlx5_eswitch_add_termtbl_rule(esw, fdb, spec, attr, &flow_act, dest, i); - else + hairpin = true; + } else { rule = mlx5_add_flow_rules(fdb, spec, &flow_act, dest, i); + } if (IS_ERR(rule)) goto err_add_rule; else atomic64_inc(&esw->offloads.num_flows); + if (hairpin) + attr->flags |= MLX5_ESW_ATTR_FLAG_HAIRPIN; + return rule; err_add_rule: @@ -495,10 +501,12 @@ __mlx5_eswitch_del_rule(struct mlx5_eswitch *esw, mlx5_del_flow_rules(rule); - /* unref the term table */ - for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) { - if (attr->dests[i].termtbl) - mlx5_eswitch_termtbl_put(esw, attr->dests[i].termtbl); + if (attr->flags & MLX5_ESW_ATTR_FLAG_HAIRPIN) { + /* unref the term table */ + for (i = 0; i < MLX5_MAX_FLOW_FWD_VPORTS; i++) { + if (attr->dests[i].termtbl) + mlx5_eswitch_termtbl_put(esw, attr->dests[i].termtbl); + } } atomic64_dec(&esw->offloads.num_flows); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c index 269eddc3d38b..4e76ddc4ef87 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c @@ -195,10 +195,12 @@ static bool mlx5_eswitch_offload_is_uplink_port(const struct mlx5_eswitch *esw, bool mlx5_eswitch_termtbl_required(struct mlx5_eswitch *esw, + struct mlx5_esw_flow_attr *attr, struct mlx5_flow_act *flow_act, struct mlx5_flow_spec *spec) { - if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, termination_table)) + if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, termination_table) || + attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) return false; /* push vlan on RX */ From 249ccc3c95bd1bca17406b5b3d0474fd67220931 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 13 Feb 2020 14:05:14 +0200 Subject: [PATCH 12/14] net/mlx5e: Add support for offloading traffic from uplink to uplink Termination tables change the direction of a packet in hw from RX to SX pipeline. Use that to offload hairpin flows received from uplink and sent back to uplink. Currently termination tables are used for pushing VLAN to packets received from uplink and targeting a VF. Extend the implementation to allow forwarding packets to uplink. These packets can either be encapsulated or not. In case encapsulation is needed before forwarding, move the reformat object to the termination table as required. Extend the hash table key to include tunnel information for the sake of reusing reformat objects. Signed-off-by: Eli Cohen Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- .../mlx5/core/eswitch_offloads_termtbl.c | 95 ++++++++++++++----- 1 file changed, 69 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c index 4e76ddc4ef87..17a0d2bc102b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c @@ -3,6 +3,7 @@ #include #include "eswitch.h" +#include "fs_core.h" struct mlx5_termtbl_handle { struct hlist_node termtbl_hlist; @@ -28,6 +29,10 @@ mlx5_eswitch_termtbl_hash(struct mlx5_flow_act *flow_act, sizeof(dest->vport.num), hash); hash = jhash((const void *)&dest->vport.vhca_id, sizeof(dest->vport.num), hash); + if (dest->vport.pkt_reformat) + hash = jhash(dest->vport.pkt_reformat, + sizeof(*dest->vport.pkt_reformat), + hash); return hash; } @@ -37,11 +42,19 @@ mlx5_eswitch_termtbl_cmp(struct mlx5_flow_act *flow_act1, struct mlx5_flow_act *flow_act2, struct mlx5_flow_destination *dest2) { - return flow_act1->action != flow_act2->action || - dest1->vport.num != dest2->vport.num || - dest1->vport.vhca_id != dest2->vport.vhca_id || - memcmp(&flow_act1->vlan, &flow_act2->vlan, - sizeof(flow_act1->vlan)); + int ret; + + ret = flow_act1->action != flow_act2->action || + dest1->vport.num != dest2->vport.num || + dest1->vport.vhca_id != dest2->vport.vhca_id || + memcmp(&flow_act1->vlan, &flow_act2->vlan, + sizeof(flow_act1->vlan)); + if (ret) + return ret; + + return dest1->vport.pkt_reformat && dest2->vport.pkt_reformat ? + memcmp(dest1->vport.pkt_reformat, dest2->vport.pkt_reformat, + sizeof(*dest1->vport.pkt_reformat)) : 0; } static int @@ -62,7 +75,8 @@ mlx5_eswitch_termtbl_create(struct mlx5_core_dev *dev, /* As this is the terminating action then the termination table is the * same prio as the slow path */ - ft_attr.flags = MLX5_FLOW_TABLE_TERMINATION; + ft_attr.flags = MLX5_FLOW_TABLE_TERMINATION | + MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; ft_attr.prio = FDB_SLOW_PATH; ft_attr.max_fte = 1; ft_attr.autogroup.max_num_groups = 1; @@ -74,7 +88,6 @@ mlx5_eswitch_termtbl_create(struct mlx5_core_dev *dev, tt->rule = mlx5_add_flow_rules(tt->termtbl, NULL, flow_act, &tt->dest, 1); - if (IS_ERR(tt->rule)) { esw_warn(dev, "Failed to create termination table rule\n"); goto add_flow_err; @@ -92,7 +105,8 @@ mlx5_eswitch_termtbl_create(struct mlx5_core_dev *dev, static struct mlx5_termtbl_handle * mlx5_eswitch_termtbl_get_create(struct mlx5_eswitch *esw, struct mlx5_flow_act *flow_act, - struct mlx5_flow_destination *dest) + struct mlx5_flow_destination *dest, + struct mlx5_esw_flow_attr *attr) { struct mlx5_termtbl_handle *tt; bool found = false; @@ -100,7 +114,6 @@ mlx5_eswitch_termtbl_get_create(struct mlx5_eswitch *esw, int err; mutex_lock(&esw->offloads.termtbl_mutex); - hash_key = mlx5_eswitch_termtbl_hash(flow_act, dest); hash_for_each_possible(esw->offloads.termtbl_tbl, tt, termtbl_hlist, hash_key) { @@ -122,6 +135,7 @@ mlx5_eswitch_termtbl_get_create(struct mlx5_eswitch *esw, tt->dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; tt->dest.vport.num = dest->vport.num; tt->dest.vport.vhca_id = dest->vport.vhca_id; + tt->dest.vport.flags = dest->vport.flags; memcpy(&tt->flow_act, flow_act, sizeof(*flow_act)); err = mlx5_eswitch_termtbl_create(esw->dev, tt, flow_act); @@ -156,25 +170,44 @@ mlx5_eswitch_termtbl_put(struct mlx5_eswitch *esw, } } +static bool mlx5_eswitch_termtbl_is_encap_reformat(struct mlx5_pkt_reformat *rt) +{ + switch (rt->reformat_type) { + case MLX5_REFORMAT_TYPE_L2_TO_VXLAN: + case MLX5_REFORMAT_TYPE_L2_TO_NVGRE: + case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL: + case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL: + return true; + default: + return false; + } +} + static void mlx5_eswitch_termtbl_actions_move(struct mlx5_flow_act *src, struct mlx5_flow_act *dst) { - if (!(src->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH)) - return; + if (src->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) { + src->action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; + dst->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; + memcpy(&dst->vlan[0], &src->vlan[0], sizeof(src->vlan[0])); + memset(&src->vlan[0], 0, sizeof(src->vlan[0])); - src->action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; - dst->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; - memcpy(&dst->vlan[0], &src->vlan[0], sizeof(src->vlan[0])); - memset(&src->vlan[0], 0, sizeof(src->vlan[0])); + if (src->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2) { + src->action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2; + dst->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2; + memcpy(&dst->vlan[1], &src->vlan[1], sizeof(src->vlan[1])); + memset(&src->vlan[1], 0, sizeof(src->vlan[1])); + } + } - if (!(src->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2)) - return; - - src->action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2; - dst->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2; - memcpy(&dst->vlan[1], &src->vlan[1], sizeof(src->vlan[1])); - memset(&src->vlan[1], 0, sizeof(src->vlan[1])); + if (src->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT && + mlx5_eswitch_termtbl_is_encap_reformat(src->pkt_reformat)) { + src->action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; + dst->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; + dst->pkt_reformat = src->pkt_reformat; + src->pkt_reformat = NULL; + } } static bool mlx5_eswitch_offload_is_uplink_port(const struct mlx5_eswitch *esw, @@ -199,13 +232,23 @@ mlx5_eswitch_termtbl_required(struct mlx5_eswitch *esw, struct mlx5_flow_act *flow_act, struct mlx5_flow_spec *spec) { + int i; + if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, termination_table) || - attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) + attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH || + !mlx5_eswitch_offload_is_uplink_port(esw, spec)) return false; /* push vlan on RX */ - return (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) && - mlx5_eswitch_offload_is_uplink_port(esw, spec); + if (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) + return true; + + /* hairpin */ + for (i = attr->split_count; i < attr->out_count; i++) + if (attr->dests[i].rep->vport == MLX5_VPORT_UPLINK) + return true; + + return false; } struct mlx5_flow_handle * @@ -235,7 +278,7 @@ mlx5_eswitch_add_termtbl_rule(struct mlx5_eswitch *esw, /* get the terminating table for the action list */ tt = mlx5_eswitch_termtbl_get_create(esw, &term_tbl_act, - &dest[i]); + &dest[i], attr); if (IS_ERR(tt)) { esw_warn(esw->dev, "Failed to create termination table\n"); goto revert_changes; From 613f53fe09a27f928a7d05132e1a74b5136e8f04 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Mon, 24 Feb 2020 16:59:54 +0200 Subject: [PATCH 13/14] net/mlx5: Eswitch, enable forwarding back to uplink port Add dependencny on cap termination_table_raw_traffic to allow non encapsulated packets received from uplink to be forwarded back to the received uplink port. Refactor the conditions into a separate function. Signed-off-by: Eli Cohen Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en_tc.c | 59 ++++++++++++++----- include/linux/mlx5/mlx5_ifc.h | 3 +- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index ddb933aa8d59..ebf60ff30295 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -3641,6 +3641,46 @@ static int mlx5_validate_goto_chain(struct mlx5_eswitch *esw, return 0; } +static int verify_uplink_forwarding(struct mlx5e_priv *priv, + struct mlx5e_tc_flow *flow, + struct net_device *out_dev, + struct netlink_ext_ack *extack) +{ + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + struct mlx5_esw_flow_attr *attr = flow->esw_attr; + struct mlx5e_rep_priv *rep_priv; + + /* Forwarding non encapsulated traffic between + * uplink ports is allowed only if + * termination_table_raw_traffic cap is set. + * + * Input vport was stored esw_attr->in_rep. + * In LAG case, *priv* is the private data of + * uplink which may be not the input vport. + */ + rep_priv = mlx5e_rep_to_rep_priv(attr->in_rep); + + if (!(mlx5e_eswitch_uplink_rep(rep_priv->netdev) && + mlx5e_eswitch_uplink_rep(out_dev))) + return 0; + + if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, + termination_table_raw_traffic)) { + NL_SET_ERR_MSG_MOD(extack, + "devices are both uplink, can't offload forwarding"); + pr_err("devices %s %s are both uplink, can't offload forwarding\n", + priv->netdev->name, out_dev->name); + return -EOPNOTSUPP; + } else if (out_dev != rep_priv->netdev) { + NL_SET_ERR_MSG_MOD(extack, + "devices are not the same uplink, can't offload forwarding"); + pr_err("devices %s %s are both uplink but not the same, can't offload forwarding\n", + priv->netdev->name, out_dev->name); + return -EOPNOTSUPP; + } + return 0; +} + static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct flow_action *flow_action, struct mlx5e_tc_flow *flow, @@ -3738,7 +3778,6 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH); struct net_device *uplink_upper; - struct mlx5e_rep_priv *rep_priv; if (is_duplicated_output_device(priv->netdev, out_dev, @@ -3774,21 +3813,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, return err; } - /* Don't allow forwarding between uplink. - * - * Input vport was stored esw_attr->in_rep. - * In LAG case, *priv* is the private data of - * uplink which may be not the input vport. - */ - rep_priv = mlx5e_rep_to_rep_priv(attr->in_rep); - if (mlx5e_eswitch_uplink_rep(rep_priv->netdev) && - mlx5e_eswitch_uplink_rep(out_dev)) { - NL_SET_ERR_MSG_MOD(extack, - "devices are both uplink, can't offload forwarding"); - pr_err("devices %s %s are both uplink, can't offload forwarding\n", - priv->netdev->name, out_dev->name); - return -EOPNOTSUPP; - } + err = verify_uplink_forwarding(priv, flow, out_dev, extack); + if (err) + return err; if (!mlx5e_is_valid_eswitch_fwd_dev(priv, out_dev)) { NL_SET_ERR_MSG_MOD(extack, diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 2bd920965bd3..cc55cee3b53c 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -416,7 +416,8 @@ struct mlx5_ifc_flow_table_prop_layout_bits { u8 termination_table[0x1]; u8 reformat_and_fwd_to_table[0x1]; u8 reserved_at_1a[0x6]; - u8 reserved_at_20[0x2]; + u8 termination_table_raw_traffic[0x1]; + u8 reserved_at_21[0x1]; u8 log_max_ft_size[0x6]; u8 log_max_modify_header_context[0x8]; u8 max_modify_header_actions[0x8]; From 87b51810f4ad99a833883f6f00795ee550f3a622 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 12 Mar 2020 17:20:32 +0200 Subject: [PATCH 14/14] net/mlx5: Avoid forwarding to other eswitch uplink Do not allow forwarding of encapsulated traffic received from one eswtich's uplink to another eswtich's uplink. Signed-off-by: Eli Cohen Reviewed-by: Oz Shlomo Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c index 608d0e07c308..b45c3f46570b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c @@ -66,6 +66,9 @@ static int get_route_and_out_devs(struct mlx5e_priv *priv, mlx5e_is_uplink_rep(netdev_priv(*out_dev)))) return -EOPNOTSUPP; + if (mlx5e_eswitch_uplink_rep(priv->netdev) && *out_dev != priv->netdev) + return -EOPNOTSUPP; + return 0; }