From 6e20d538fb1dfb9c477a8e991da1fca3064ce0f7 Mon Sep 17 00:00:00 2001 From: Chris Mi Date: Thu, 8 Aug 2024 08:59:17 +0300 Subject: [PATCH 01/11] net/mlx5: E-Switch, Increase max int port number for offload Currently MLX5E_TC_MAX_INT_PORT_NUM is 8. Usually int port has one ingress and one egress rules. But sometimes, a temporary rule can be offloaded as well, eg: recirc_id(0),in_port(br-phy),eth(src=10:70:fd:87:57:c0,dst=33:33:00:00:00:16), eth_type(0x86dd),ipv6(frag=no), packets:2, bytes:180, used:0.060s, actions:enp8s0f0 If one int port device offloads 3 rules, only 2 devices can offload. Other devices will hit the limit and fail to offload. Actually it is insufficient for customers. So increase the number to 32. Signed-off-by: Chris Mi Reviewed-by: Roi Dayan Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-2-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index c24bda56b2b5d2..b982e648ea482d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -139,7 +139,7 @@ struct mlx5_rx_tun_attr { #define MLX5E_TC_TABLE_CHAIN_TAG_BITS 16 #define MLX5E_TC_TABLE_CHAIN_TAG_MASK GENMASK(MLX5E_TC_TABLE_CHAIN_TAG_BITS - 1, 0) -#define MLX5E_TC_MAX_INT_PORT_NUM (8) +#define MLX5E_TC_MAX_INT_PORT_NUM (32) #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) From 88c46f6103e232e819b35ca811e96454d70a7138 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Thu, 8 Aug 2024 08:59:18 +0300 Subject: [PATCH 02/11] net/mlx5e: Enable remove flow for hard packet limit In the commit a2a73ea14b1a ("net/mlx5e: Don't listen to remove flows event"), remove_flow_enable event is removed, and the hard limit usually relies on software mechanism added in commit b2f7b01d36a9 ("net/mlx5e: Simulate missing IPsec TX limits hardware functionality"). But the delayed work is rescheduled every one second, which is slow for fast traffic. As a result, traffic can't be blocked even reaches the hard limit, which usually happens when soft and hard limits are very close. In reality it won't happen because soft limit is much lower than hard limit. But, as an optimization for RX to block traffic when reaching hard limit, need to set remove_flow_enable. When remove flow is enabled, IPSEC HARD_LIFETIME ASO syndrome will be set in the metadata defined in the ASO return register if packets reach hard lifetime threshold. And those packets are dropped immediately by the steering table. Signed-off-by: Jianbo Liu Reviewed-by: Leon Romanovsky Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-3-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c index 797db853de3638..53cfa39188cb0e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c @@ -127,6 +127,7 @@ static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn, MLX5_SET(ipsec_aso, aso_ctx, remove_flow_pkt_cnt, attrs->lft.hard_packet_limit); MLX5_SET(ipsec_aso, aso_ctx, hard_lft_arm, 1); + MLX5_SET(ipsec_aso, aso_ctx, remove_flow_enable, 1); } if (attrs->lft.soft_packet_limit != XFRM_INF) { From 16bb8c613379e20d4adabc639ea6aecdaeba2ff1 Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Thu, 8 Aug 2024 08:59:19 +0300 Subject: [PATCH 03/11] net/mlx5e: TC, Offload rewrite and mirror on tunnel over ovs internal port To offload the encap rule when the tunnel IP is configured on an openvswitch internal port, driver need to overwrite vport metadata in reg_c0 to the value assigned to the internal port, then forward packets to root table to be processed again by the rules matching on the metadata for such internal port. When such rule is combined with header rewrite and mirror, openvswitch generates the rule like the following, because it resets mirror after packets are modified. in_port(enp8s0f0npf0sf1),.., actions:enp8s0f0npf0sf2,set(tunnel(...)),set(ipv4(...)),vxlan_sys_4789,enp8s0f0npf0sf2 The split_count was introduced before to support rewrite and mirror. Driver splits the rule into two different hardware rules in order to offload it. But it's not enough to offload the above complicated rule because of the limitations, in both driver and firmware. To resolve this issue, the destination array is split again after the destination indexed by split_count. An extra rule is added for the leftover destinations (in the above example, it is enp8s0f0npf0sf2), and is inserted to post_act table. And the extra destination is added in the original rule to forward to post_act table, so the extra mirror is done there. Signed-off-by: Jianbo Liu Reviewed-by: Cosmin Ratiu Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-4-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en/tc_priv.h | 1 + .../net/ethernet/mellanox/mlx5/core/en_tc.c | 103 ++++++++++++++++++ .../net/ethernet/mellanox/mlx5/core/en_tc.h | 1 + .../mellanox/mlx5/core/eswitch_offloads.c | 7 ++ 4 files changed, 112 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h index 6cc23af66b5be0..efb34de4cb7adb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h @@ -109,6 +109,7 @@ struct mlx5e_tc_flow { struct completion init_done; struct completion del_hw_done; struct mlx5_flow_attr *attr; + struct mlx5_flow_attr *extra_split_attr; struct list_head attrs; u32 chain_mapping; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 30673292e15fee..a28bf05d98f17c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1739,11 +1739,102 @@ has_encap_dests(struct mlx5_flow_attr *attr) return false; } +static int +extra_split_attr_dests_needed(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr) +{ + struct mlx5_esw_flow_attr *esw_attr; + + if (flow->attr != attr || + !list_is_first(&attr->list, &flow->attrs)) + return 0; + + esw_attr = attr->esw_attr; + if (!esw_attr->split_count || + esw_attr->split_count == esw_attr->out_count - 1) + return 0; + + if (esw_attr->dest_int_port && + (esw_attr->dests[esw_attr->split_count].flags & + MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)) + return esw_attr->split_count + 1; + + return 0; +} + +static int +extra_split_attr_dests(struct mlx5e_tc_flow *flow, + struct mlx5_flow_attr *attr, int split_count) +{ + struct mlx5e_post_act *post_act = get_post_action(flow->priv); + struct mlx5e_tc_flow_parse_attr *parse_attr, *parse_attr2; + struct mlx5_esw_flow_attr *esw_attr, *esw_attr2; + struct mlx5e_post_act_handle *handle; + struct mlx5_flow_attr *attr2; + int i, j, err; + + if (IS_ERR(post_act)) + return PTR_ERR(post_act); + + attr2 = mlx5_alloc_flow_attr(mlx5e_get_flow_namespace(flow)); + parse_attr2 = kvzalloc(sizeof(*parse_attr), GFP_KERNEL); + if (!attr2 || !parse_attr2) { + err = -ENOMEM; + goto err_free; + } + attr2->parse_attr = parse_attr2; + + handle = mlx5e_tc_post_act_add(post_act, attr2); + if (IS_ERR(handle)) { + err = PTR_ERR(handle); + goto err_free; + } + + esw_attr = attr->esw_attr; + esw_attr2 = attr2->esw_attr; + esw_attr2->in_rep = esw_attr->in_rep; + + parse_attr = attr->parse_attr; + parse_attr2->filter_dev = parse_attr->filter_dev; + + for (i = split_count, j = 0; i < esw_attr->out_count; i++, j++) + esw_attr2->dests[j] = esw_attr->dests[i]; + + esw_attr2->out_count = j; + attr2->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + + err = mlx5e_tc_post_act_offload(post_act, handle); + if (err) + goto err_post_act_offload; + + err = mlx5e_tc_post_act_set_handle(flow->priv->mdev, handle, + &parse_attr->mod_hdr_acts); + if (err) + goto err_post_act_set_handle; + + esw_attr->out_count = split_count; + attr->extra_split_ft = mlx5e_tc_post_act_get_ft(post_act); + flow->extra_split_attr = attr2; + + attr2->post_act_handle = handle; + + return 0; + +err_post_act_set_handle: + mlx5e_tc_post_act_unoffload(post_act, handle); +err_post_act_offload: + mlx5e_tc_post_act_del(post_act, handle); +err_free: + kvfree(parse_attr2); + kfree(attr2); + return err; +} + static int post_process_attr(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr, struct netlink_ext_ack *extack) { + int extra_split; bool vf_tun; int err = 0; @@ -1757,6 +1848,13 @@ post_process_attr(struct mlx5e_tc_flow *flow, goto err_out; } + extra_split = extra_split_attr_dests_needed(flow, attr); + if (extra_split > 0) { + err = extra_split_attr_dests(flow, attr, extra_split); + if (err) + goto err_out; + } + if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) { err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr); if (err) @@ -1971,6 +2069,11 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, mlx5e_tc_act_stats_del_flow(get_act_stats_handle(priv), flow); free_flow_post_acts(flow); + if (flow->extra_split_attr) { + mlx5_free_flow_attr_actions(flow, flow->extra_split_attr); + kvfree(flow->extra_split_attr->parse_attr); + kfree(flow->extra_split_attr); + } mlx5_free_flow_attr_actions(flow, attr); kvfree(attr->esw_attr->rx_tun_attr); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index b982e648ea482d..e1b8cb78369f11 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -86,6 +86,7 @@ struct mlx5_flow_attr { u32 dest_chain; struct mlx5_flow_table *ft; struct mlx5_flow_table *dest_ft; + struct mlx5_flow_table *extra_split_ft; u8 inner_match_level; u8 outer_match_level; u8 tun_ip_version; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 768199d2255a1d..f24f91d213f24c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -613,6 +613,13 @@ esw_setup_dests(struct mlx5_flow_destination *dest, } } + if (attr->extra_split_ft) { + flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; + dest[*i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; + dest[*i].ft = attr->extra_split_ft; + (*i)++; + } + out: return err; } From b11bde56246ee85a67364efa0e181b479543dfef Mon Sep 17 00:00:00 2001 From: Jianbo Liu Date: Thu, 8 Aug 2024 08:59:20 +0300 Subject: [PATCH 04/11] net/mlx5e: TC, Offload rewrite and mirror to both internal and external dests Firmware has the limitation that it cannot offload a rule with rewrite and mirror to internal and external destinations simultaneously. This patch adds a workaround to this issue. Here the destination array is split again, just like what's done in previous commit, but after the action indexed by split_count - 1. An extra rule is added for the leftover destinations. Such rule can be offloaded, even there are destinations to both internal and external destinations, because the header rewrite is left in the original FTE. Signed-off-by: Jianbo Liu Reviewed-by: Cosmin Ratiu Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-5-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index a28bf05d98f17c..6b3b1afe831214 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1742,12 +1742,17 @@ has_encap_dests(struct mlx5_flow_attr *attr) static int extra_split_attr_dests_needed(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *attr) { + bool int_dest = false, ext_dest = false; struct mlx5_esw_flow_attr *esw_attr; + int i; if (flow->attr != attr || !list_is_first(&attr->list, &flow->attrs)) return 0; + if (flow_flag_test(flow, SLOW)) + return 0; + esw_attr = attr->esw_attr; if (!esw_attr->split_count || esw_attr->split_count == esw_attr->out_count - 1) @@ -1758,6 +1763,18 @@ extra_split_attr_dests_needed(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE)) return esw_attr->split_count + 1; + for (i = esw_attr->split_count; i < esw_attr->out_count; i++) { + /* external dest with encap is considered as internal by firmware */ + if (esw_attr->dests[i].vport == MLX5_VPORT_UPLINK && + !(esw_attr->dests[i].flags & MLX5_ESW_DEST_ENCAP_VALID)) + ext_dest = true; + else + int_dest = true; + + if (ext_dest && int_dest) + return esw_attr->split_count; + } + return 0; } From 4384bcff035e3699ab97286875d190f3661acc15 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Thu, 8 Aug 2024 08:59:21 +0300 Subject: [PATCH 05/11] net/mlx5e: Be consistent with bitmap handling of link modes Use the bitmap operations when accessing the advertised/supported link modes and remove places that access them as arrays of unsigned longs (underlying implementation of the bitmap), this makes the code much more readable and clear. Signed-off-by: Gal Pressman Reviewed-by: Carolina Jubran Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-6-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 36845872ae94e7..5fd81253d6b9d3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -83,17 +83,15 @@ struct ptys2ethtool_config ptys2ext_ethtool_table[MLX5E_EXT_LINK_MODES_NUMBER]; ({ \ struct ptys2ethtool_config *cfg; \ const unsigned int modes[] = { __VA_ARGS__ }; \ - unsigned int i, bit, idx; \ + unsigned int i; \ cfg = &ptys2##table##_ethtool_table[reg_]; \ bitmap_zero(cfg->supported, \ __ETHTOOL_LINK_MODE_MASK_NBITS); \ bitmap_zero(cfg->advertised, \ __ETHTOOL_LINK_MODE_MASK_NBITS); \ for (i = 0 ; i < ARRAY_SIZE(modes) ; ++i) { \ - bit = modes[i] % 64; \ - idx = modes[i] / 64; \ - __set_bit(bit, &cfg->supported[idx]); \ - __set_bit(bit, &cfg->advertised[idx]); \ + bitmap_set(cfg->supported, modes[i], 1); \ + bitmap_set(cfg->advertised, modes[i], 1); \ } \ }) @@ -1299,7 +1297,8 @@ static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes) u32 i, ptys_modes = 0; for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { - if (*ptys2legacy_ethtool_table[i].advertised == 0) + if (bitmap_empty(ptys2legacy_ethtool_table[i].advertised, + __ETHTOOL_LINK_MODE_MASK_NBITS)) continue; if (bitmap_intersects(ptys2legacy_ethtool_table[i].advertised, link_modes, @@ -1313,18 +1312,18 @@ static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes) static u32 mlx5e_ethtool2ptys_ext_adver_link(const unsigned long *link_modes) { u32 i, ptys_modes = 0; - unsigned long modes[2]; + __ETHTOOL_DECLARE_LINK_MODE_MASK(modes); for (i = 0; i < MLX5E_EXT_LINK_MODES_NUMBER; ++i) { - if (ptys2ext_ethtool_table[i].advertised[0] == 0 && - ptys2ext_ethtool_table[i].advertised[1] == 0) + if (bitmap_empty(ptys2ext_ethtool_table[i].advertised, + __ETHTOOL_LINK_MODE_MASK_NBITS)) continue; - memset(modes, 0, sizeof(modes)); + bitmap_zero(modes, __ETHTOOL_LINK_MODE_MASK_NBITS); bitmap_and(modes, ptys2ext_ethtool_table[i].advertised, link_modes, __ETHTOOL_LINK_MODE_MASK_NBITS); - if (modes[0] == ptys2ext_ethtool_table[i].advertised[0] && - modes[1] == ptys2ext_ethtool_table[i].advertised[1]) + if (bitmap_equal(modes, ptys2ext_ethtool_table[i].advertised, + __ETHTOOL_LINK_MODE_MASK_NBITS)) ptys_modes |= MLX5E_PROT_MASK(i); } return ptys_modes; From ab666b5287e898fcafc0ad1f2d4506cc3a1bfd23 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Thu, 8 Aug 2024 08:59:22 +0300 Subject: [PATCH 06/11] net/mlx5e: Use extack in set ringparams callback In case of errors in set ringparams, reflect it through extack instead of a dmesg print. While at it, make the messages more human friendly and remove two redundant checks that are already validated by the core. Signed-off-by: Gal Pressman Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-7-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 +- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 28 ++++++------------- .../net/ethernet/mellanox/mlx5/core/en_rep.c | 2 +- .../mellanox/mlx5/core/ipoib/ethtool.c | 2 +- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 5fd82c67b6ab7f..01781b70434cf0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -1172,7 +1172,8 @@ void mlx5e_ethtool_get_ringparam(struct mlx5e_priv *priv, struct ethtool_ringparam *param, struct kernel_ethtool_ringparam *kernel_param); int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv, - struct ethtool_ringparam *param); + struct ethtool_ringparam *param, + struct netlink_ext_ack *extack); void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv, struct ethtool_channels *ch); int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 5fd81253d6b9d3..51624053722aa7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -352,35 +352,25 @@ static void mlx5e_get_ringparam(struct net_device *dev, } int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv, - struct ethtool_ringparam *param) + struct ethtool_ringparam *param, + struct netlink_ext_ack *extack) { struct mlx5e_params new_params; u8 log_rq_size; u8 log_sq_size; int err = 0; - if (param->rx_jumbo_pending) { - netdev_info(priv->netdev, "%s: rx_jumbo_pending not supported\n", - __func__); - return -EINVAL; - } - if (param->rx_mini_pending) { - netdev_info(priv->netdev, "%s: rx_mini_pending not supported\n", - __func__); - return -EINVAL; - } - if (param->rx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)) { - netdev_info(priv->netdev, "%s: rx_pending (%d) < min (%d)\n", - __func__, param->rx_pending, - 1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); + NL_SET_ERR_MSG_FMT_MOD(extack, "rx (%d) < min (%d)", + param->rx_pending, + 1 << MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE); return -EINVAL; } if (param->tx_pending < (1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)) { - netdev_info(priv->netdev, "%s: tx_pending (%d) < min (%d)\n", - __func__, param->tx_pending, - 1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); + NL_SET_ERR_MSG_FMT_MOD(extack, "tx (%d) < min (%d)", + param->tx_pending, + 1 << MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE); return -EINVAL; } @@ -416,7 +406,7 @@ static int mlx5e_set_ringparam(struct net_device *dev, { struct mlx5e_priv *priv = netdev_priv(dev); - return mlx5e_ethtool_set_ringparam(priv, param); + return mlx5e_ethtool_set_ringparam(priv, param, extack); } void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 8790d57dc6dbf0..916ba0db29f2fe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -360,7 +360,7 @@ mlx5e_rep_set_ringparam(struct net_device *dev, { struct mlx5e_priv *priv = netdev_priv(dev); - return mlx5e_ethtool_set_ringparam(priv, param); + return mlx5e_ethtool_set_ringparam(priv, param, extack); } static void mlx5e_rep_get_channels(struct net_device *dev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c index 26f8a11b89068e..424ff39db28d0e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c @@ -74,7 +74,7 @@ static int mlx5i_set_ringparam(struct net_device *dev, { struct mlx5e_priv *priv = mlx5i_epriv(dev); - return mlx5e_ethtool_set_ringparam(priv, param); + return mlx5e_ethtool_set_ringparam(priv, param, extack); } static void mlx5i_get_ringparam(struct net_device *dev, From 29a943d71d231e2df81fd3834e75264904a77535 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Thu, 8 Aug 2024 08:59:23 +0300 Subject: [PATCH 07/11] net/mlx5e: Use extack in get coalesce callback In case of errors in get coalesce, reflect it through extack instead of a dmesg print. Signed-off-by: Gal Pressman Reviewed-by: Cosmin Ratiu Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-8-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 ++- drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 9 ++++++--- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 01781b70434cf0..7832f6b6c8a826 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -1180,7 +1180,8 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, struct ethtool_channels *ch); int mlx5e_ethtool_get_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal, - struct kernel_ethtool_coalesce *kernel_coal); + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack); int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal, struct kernel_ethtool_coalesce *kernel_coal, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 51624053722aa7..9760215926db5b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -545,12 +545,15 @@ static int mlx5e_set_channels(struct net_device *dev, int mlx5e_ethtool_get_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal, - struct kernel_ethtool_coalesce *kernel_coal) + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) { struct dim_cq_moder *rx_moder, *tx_moder; - if (!MLX5_CAP_GEN(priv->mdev, cq_moderation)) + if (!MLX5_CAP_GEN(priv->mdev, cq_moderation)) { + NL_SET_ERR_MSG_MOD(extack, "CQ moderation not supported"); return -EOPNOTSUPP; + } rx_moder = &priv->channels.params.rx_cq_moderation; coal->rx_coalesce_usecs = rx_moder->usec; @@ -574,7 +577,7 @@ static int mlx5e_get_coalesce(struct net_device *netdev, { struct mlx5e_priv *priv = netdev_priv(netdev); - return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal); + return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal, extack); } static int mlx5e_ethtool_get_per_queue_coalesce(struct mlx5e_priv *priv, u32 queue, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 916ba0db29f2fe..b885042eef1422 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -386,7 +386,7 @@ static int mlx5e_rep_get_coalesce(struct net_device *netdev, { struct mlx5e_priv *priv = netdev_priv(netdev); - return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal); + return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal, extack); } static int mlx5e_rep_set_coalesce(struct net_device *netdev, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c index 424ff39db28d0e..9772327d512461 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c @@ -132,7 +132,7 @@ static int mlx5i_get_coalesce(struct net_device *netdev, { struct mlx5e_priv *priv = mlx5i_epriv(netdev); - return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal); + return mlx5e_ethtool_get_coalesce(priv, coal, kernel_coal, extack); } static int mlx5i_get_ts_info(struct net_device *netdev, From 9c4298b466b19651203c8c8847fcbfe3e37ef6b7 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Thu, 8 Aug 2024 08:59:24 +0300 Subject: [PATCH 08/11] net/mlx5e: Use extack in set coalesce callback In case of errors in set coalesce, reflect it through extack instead of a dmesg print. While at it, make the messages more human friendly. Signed-off-by: Gal Pressman Reviewed-by: Cosmin Ratiu Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-9-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 9760215926db5b..c14a5542ae9c90 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -699,26 +699,34 @@ int mlx5e_ethtool_set_coalesce(struct mlx5e_priv *priv, int err = 0; if (!MLX5_CAP_GEN(mdev, cq_moderation) || - !MLX5_CAP_GEN(mdev, cq_period_mode_modify)) + !MLX5_CAP_GEN(mdev, cq_period_mode_modify)) { + NL_SET_ERR_MSG_MOD(extack, "CQ moderation not supported"); return -EOPNOTSUPP; + } if (coal->tx_coalesce_usecs > MLX5E_MAX_COAL_TIME || coal->rx_coalesce_usecs > MLX5E_MAX_COAL_TIME) { - netdev_info(priv->netdev, "%s: maximum coalesce time supported is %lu usecs\n", - __func__, MLX5E_MAX_COAL_TIME); + NL_SET_ERR_MSG_FMT_MOD( + extack, + "Max coalesce time %lu usecs, tx-usecs (%u) rx-usecs (%u)", + MLX5E_MAX_COAL_TIME, coal->tx_coalesce_usecs, + coal->rx_coalesce_usecs); return -ERANGE; } if (coal->tx_max_coalesced_frames > MLX5E_MAX_COAL_FRAMES || coal->rx_max_coalesced_frames > MLX5E_MAX_COAL_FRAMES) { - netdev_info(priv->netdev, "%s: maximum coalesced frames supported is %lu\n", - __func__, MLX5E_MAX_COAL_FRAMES); + NL_SET_ERR_MSG_FMT_MOD( + extack, + "Max coalesce frames %lu, tx-frames (%u) rx-frames (%u)", + MLX5E_MAX_COAL_FRAMES, coal->tx_max_coalesced_frames, + coal->rx_max_coalesced_frames); return -ERANGE; } if ((kernel_coal->use_cqe_mode_rx || kernel_coal->use_cqe_mode_tx) && !MLX5_CAP_GEN(priv->mdev, cq_period_start_from_cqe)) { - NL_SET_ERR_MSG_MOD(extack, "cqe_mode_rx/tx is not supported on this device"); + NL_SET_ERR_MSG_MOD(extack, "cqe-mode-rx/tx is not supported on this device"); return -EOPNOTSUPP; } From b5100b72da688282558b28255c03a2d72241a729 Mon Sep 17 00:00:00 2001 From: Gal Pressman Date: Thu, 8 Aug 2024 08:59:25 +0300 Subject: [PATCH 09/11] net/mlx5e: Use extack in get module eeprom by page callback In case of errors in get module eeprom by page, reflect it through extack instead of a dmesg print. While at it, make the messages more human friendly. Signed-off-by: Gal Pressman Reviewed-by: Cosmin Ratiu Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-10-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index c14a5542ae9c90..56bdb4d07b7adf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -2015,8 +2015,10 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, if (size_read == -EINVAL) return -EINVAL; if (size_read < 0) { - netdev_err(priv->netdev, "%s: mlx5_query_module_eeprom_by_page failed:0x%x\n", - __func__, size_read); + NL_SET_ERR_MSG_FMT_MOD( + extack, + "Query module eeprom by page failed, read %u bytes, err %d\n", + i, size_read); return i; } From 486aeb2db55b4509039f2e6017b2d06836893ee2 Mon Sep 17 00:00:00 2001 From: Cosmin Ratiu Date: Thu, 8 Aug 2024 08:59:26 +0300 Subject: [PATCH 10/11] net/mlx5e: CT: 'update' rules instead of 'replace' Offloaded rules can be updated with a new modify header action containing a changed restore cookie. This was done using the verb 'replace', while in some configurations 'update' is a better fit. This commit renames the functions used to reflect that. Signed-off-by: Cosmin Ratiu Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-11-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en/tc_ct.c | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 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 71a168746ebe21..ccee07d6ba1de8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -876,10 +876,10 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv, } static int -mlx5_tc_ct_entry_replace_rule(struct mlx5_tc_ct_priv *ct_priv, - struct flow_rule *flow_rule, - struct mlx5_ct_entry *entry, - bool nat, u8 zone_restore_id) +mlx5_tc_ct_entry_update_rule(struct mlx5_tc_ct_priv *ct_priv, + struct flow_rule *flow_rule, + struct mlx5_ct_entry *entry, + bool nat, u8 zone_restore_id) { struct mlx5_ct_zone_rule *zone_rule = &entry->zone_rules[nat]; struct mlx5_flow_attr *attr = zone_rule->attr, *old_attr; @@ -924,7 +924,7 @@ mlx5_tc_ct_entry_replace_rule(struct mlx5_tc_ct_priv *ct_priv, kfree(old_attr); kvfree(spec); - ct_dbg("Replaced ct entry rule in zone %d", entry->tuple.zone); + ct_dbg("Updated ct entry rule in zone %d", entry->tuple.zone); return 0; @@ -1141,23 +1141,23 @@ mlx5_tc_ct_entry_add_rules(struct mlx5_tc_ct_priv *ct_priv, } static int -mlx5_tc_ct_entry_replace_rules(struct mlx5_tc_ct_priv *ct_priv, - struct flow_rule *flow_rule, - struct mlx5_ct_entry *entry, - u8 zone_restore_id) +mlx5_tc_ct_entry_update_rules(struct mlx5_tc_ct_priv *ct_priv, + struct flow_rule *flow_rule, + struct mlx5_ct_entry *entry, + u8 zone_restore_id) { int err = 0; if (mlx5_tc_ct_entry_in_ct_table(entry)) { - err = mlx5_tc_ct_entry_replace_rule(ct_priv, flow_rule, entry, false, - zone_restore_id); + err = mlx5_tc_ct_entry_update_rule(ct_priv, flow_rule, entry, false, + zone_restore_id); if (err) return err; } if (mlx5_tc_ct_entry_in_ct_nat_table(entry)) { - err = mlx5_tc_ct_entry_replace_rule(ct_priv, flow_rule, entry, true, - zone_restore_id); + err = mlx5_tc_ct_entry_update_rule(ct_priv, flow_rule, entry, true, + zone_restore_id); if (err && mlx5_tc_ct_entry_in_ct_table(entry)) mlx5_tc_ct_entry_del_rule(ct_priv, entry, false); } @@ -1165,13 +1165,13 @@ mlx5_tc_ct_entry_replace_rules(struct mlx5_tc_ct_priv *ct_priv, } static int -mlx5_tc_ct_block_flow_offload_replace(struct mlx5_ct_ft *ft, struct flow_rule *flow_rule, - struct mlx5_ct_entry *entry, unsigned long cookie) +mlx5_tc_ct_block_flow_offload_update(struct mlx5_ct_ft *ft, struct flow_rule *flow_rule, + struct mlx5_ct_entry *entry, unsigned long cookie) { struct mlx5_tc_ct_priv *ct_priv = ft->ct_priv; int err; - err = mlx5_tc_ct_entry_replace_rules(ct_priv, flow_rule, entry, ft->zone_restore_id); + err = mlx5_tc_ct_entry_update_rules(ct_priv, flow_rule, entry, ft->zone_restore_id); if (!err) return 0; @@ -1216,7 +1216,7 @@ mlx5_tc_ct_block_flow_offload_add(struct mlx5_ct_ft *ft, entry->restore_cookie = meta_action->ct_metadata.cookie; spin_unlock_bh(&ct_priv->ht_lock); - err = mlx5_tc_ct_block_flow_offload_replace(ft, flow_rule, entry, cookie); + err = mlx5_tc_ct_block_flow_offload_update(ft, flow_rule, entry, cookie); mlx5_tc_ct_entry_put(entry); return err; } From 6b5662b75960b38cee4930284c93bd645b8e03ab Mon Sep 17 00:00:00 2001 From: Cosmin Ratiu Date: Thu, 8 Aug 2024 08:59:27 +0300 Subject: [PATCH 11/11] net/mlx5e: CT: Update connection tracking steering entries Previously, replacing a connection tracking steering entry was done by adding a new rule (with the same tag but possibly different mod hdr actions/labels) then removing the old rule. This approach doesn't work in hardware steering because two steering entries with the same tag cannot coexist in a hardware steering table. This commit prepares for that by adding a new ct_rule_update operation on the ct_fs_ops struct which is used instead of add+delete. Implementations for both dmfs (firmware steering) and smfs (software steering) are provided, which simply add the new rule and delete the old one. Signed-off-by: Cosmin Ratiu Signed-off-by: Tariq Toukan Link: https://patch.msgid.link/20240808055927.2059700-12-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/en/tc/ct_fs.h | 2 ++ .../mellanox/mlx5/core/en/tc/ct_fs_dmfs.c | 21 +++++++++++++++ .../mellanox/mlx5/core/en/tc/ct_fs_smfs.c | 26 +++++++++++++++++++ .../ethernet/mellanox/mlx5/core/en/tc_ct.c | 12 +++------ 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs.h index bb6b1a979ba132..62b3f7ff556211 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs.h @@ -25,6 +25,8 @@ struct mlx5_ct_fs_ops { struct mlx5_flow_attr *attr, struct flow_rule *flow_rule); void (*ct_rule_del)(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_rule); + int (*ct_rule_update)(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_rule, + struct mlx5_flow_spec *spec, struct mlx5_flow_attr *attr); size_t priv_size; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_dmfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_dmfs.c index ae4f55be48cec3..64a82aafaacafd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_dmfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_dmfs.c @@ -65,9 +65,30 @@ mlx5_ct_fs_dmfs_ct_rule_del(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_ru kfree(dmfs_rule); } +static int mlx5_ct_fs_dmfs_ct_rule_update(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_rule, + struct mlx5_flow_spec *spec, struct mlx5_flow_attr *attr) +{ + struct mlx5_ct_fs_dmfs_rule *dmfs_rule = container_of(fs_rule, + struct mlx5_ct_fs_dmfs_rule, + fs_rule); + struct mlx5e_priv *priv = netdev_priv(fs->netdev); + struct mlx5_flow_handle *rule; + + rule = mlx5_tc_rule_insert(priv, spec, attr); + if (IS_ERR(rule)) + return PTR_ERR(rule); + mlx5_tc_rule_delete(priv, dmfs_rule->rule, dmfs_rule->attr); + + dmfs_rule->rule = rule; + dmfs_rule->attr = attr; + + return 0; +} + static struct mlx5_ct_fs_ops dmfs_ops = { .ct_rule_add = mlx5_ct_fs_dmfs_ct_rule_add, .ct_rule_del = mlx5_ct_fs_dmfs_ct_rule_del, + .ct_rule_update = mlx5_ct_fs_dmfs_ct_rule_update, .init = mlx5_ct_fs_dmfs_init, .destroy = mlx5_ct_fs_dmfs_destroy, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c index 8c531f4ec91292..1c062a2e8996e7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c @@ -368,9 +368,35 @@ mlx5_ct_fs_smfs_ct_rule_del(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_ru kfree(smfs_rule); } +static int mlx5_ct_fs_smfs_ct_rule_update(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_rule, + struct mlx5_flow_spec *spec, struct mlx5_flow_attr *attr) +{ + struct mlx5_ct_fs_smfs_rule *smfs_rule = container_of(fs_rule, + struct mlx5_ct_fs_smfs_rule, + fs_rule); + struct mlx5_ct_fs_smfs *fs_smfs = mlx5_ct_fs_priv(fs); + struct mlx5dr_action *actions[3]; /* We only need to create 3 actions, see below. */ + struct mlx5dr_rule *rule; + + actions[0] = smfs_rule->count_action; + actions[1] = attr->modify_hdr->action.dr_action; + actions[2] = fs_smfs->fwd_action; + + rule = mlx5_smfs_rule_create(smfs_rule->smfs_matcher->dr_matcher, spec, + ARRAY_SIZE(actions), actions, spec->flow_context.flow_source); + if (!rule) + return -EINVAL; + + mlx5_smfs_rule_destroy(smfs_rule->rule); + smfs_rule->rule = rule; + + return 0; +} + static struct mlx5_ct_fs_ops fs_smfs_ops = { .ct_rule_add = mlx5_ct_fs_smfs_ct_rule_add, .ct_rule_del = mlx5_ct_fs_smfs_ct_rule_del, + .ct_rule_update = mlx5_ct_fs_smfs_ct_rule_update, .init = mlx5_ct_fs_smfs_init, .destroy = mlx5_ct_fs_smfs_destroy, 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 ccee07d6ba1de8..dcfccaaa8d917b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -884,7 +884,6 @@ mlx5_tc_ct_entry_update_rule(struct mlx5_tc_ct_priv *ct_priv, struct mlx5_ct_zone_rule *zone_rule = &entry->zone_rules[nat]; struct mlx5_flow_attr *attr = zone_rule->attr, *old_attr; struct mlx5e_mod_hdr_handle *mh; - struct mlx5_ct_fs_rule *rule; struct mlx5_flow_spec *spec; int err; @@ -902,22 +901,19 @@ mlx5_tc_ct_entry_update_rule(struct mlx5_tc_ct_priv *ct_priv, err = mlx5_tc_ct_entry_create_mod_hdr(ct_priv, attr, flow_rule, &mh, zone_restore_id, nat, mlx5_tc_ct_entry_in_ct_nat_table(entry)); if (err) { - ct_dbg("Failed to create ct entry mod hdr"); + ct_dbg("Failed to create ct entry mod hdr, err: %d", err); goto err_mod_hdr; } mlx5_tc_ct_set_tuple_match(ct_priv, spec, flow_rule); mlx5e_tc_match_to_reg_match(spec, ZONE_TO_REG, entry->tuple.zone, MLX5_CT_ZONE_MASK); - rule = ct_priv->fs_ops->ct_rule_add(ct_priv->fs, spec, attr, flow_rule); - if (IS_ERR(rule)) { - err = PTR_ERR(rule); - ct_dbg("Failed to add replacement ct entry rule, nat: %d", nat); + err = ct_priv->fs_ops->ct_rule_update(ct_priv->fs, zone_rule->rule, spec, attr); + if (err) { + ct_dbg("Failed to update ct entry rule, nat: %d, err: %d", nat, err); goto err_rule; } - ct_priv->fs_ops->ct_rule_del(ct_priv->fs, zone_rule->rule); - zone_rule->rule = rule; mlx5_tc_ct_entry_destroy_mod_hdr(ct_priv, old_attr, zone_rule->mh); zone_rule->mh = mh; mlx5_put_label_mapping(ct_priv, old_attr->ct_attr.ct_labels_id);