]> git.itanic.dy.fi Git - linux-stable/commitdiff
net/mlx5: DR, Ignore modify TTL on RX if device doesn't support it
authorYevgeny Kliteynik <kliteyn@nvidia.com>
Sun, 3 Apr 2022 20:18:10 +0000 (23:18 +0300)
committerSaeed Mahameed <saeedm@nvidia.com>
Wed, 18 May 2022 06:03:53 +0000 (23:03 -0700)
When modifying TTL, packet's csum has to be recalculated.
Due to HW issue in ConnectX-5, csum recalculation for modify
TTL on RX is supported through a work-around that is specifically
enabled by configuration.
If the work-around isn't enabled, rather than adding an unsupported
action the modify TTL action on RX should be ignored.
Ignoring modify TTL action might result in zero actions, so in such
cases we will not convert the match STE to modify STE, as it is done
by FW in DMFS.

This patch fixes an issue where modify TTL action was ignored both
on RX and TX instead of only on RX.

Fixes: 4ff725e1d4ad ("net/mlx5: DR, Ignore modify TTL if device doesn't support it")
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Reviewed-by: Alex Vesker <valex@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c

index b52b539c8d2cee7aad60f12e039861a138915f86..1383550f44c1297e25159b0cdb7fc6f81a947d51 100644 (file)
@@ -530,6 +530,37 @@ static int dr_action_handle_cs_recalc(struct mlx5dr_domain *dmn,
        return 0;
 }
 
+static void dr_action_modify_ttl_adjust(struct mlx5dr_domain *dmn,
+                                       struct mlx5dr_ste_actions_attr *attr,
+                                       bool rx_rule,
+                                       bool *recalc_cs_required)
+{
+       *recalc_cs_required = false;
+
+       /* if device supports csum recalculation - no adjustment needed */
+       if (mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps))
+               return;
+
+       /* no adjustment needed on TX rules */
+       if (!rx_rule)
+               return;
+
+       if (!MLX5_CAP_ESW_FLOWTABLE(dmn->mdev, fdb_ipv4_ttl_modify)) {
+               /* Ignore the modify TTL action.
+                * It is always kept as last HW action.
+                */
+               attr->modify_actions--;
+               return;
+       }
+
+       if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB)
+               /* Due to a HW bug on some devices, modifying TTL on RX flows
+                * will cause an incorrect checksum calculation. In such cases
+                * we will use a FW table to recalculate the checksum.
+                */
+               *recalc_cs_required = true;
+}
+
 static void dr_action_print_sequence(struct mlx5dr_domain *dmn,
                                     struct mlx5dr_action *actions[],
                                     int last_idx)
@@ -650,8 +681,9 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
                case DR_ACTION_TYP_MODIFY_HDR:
                        attr.modify_index = action->rewrite->index;
                        attr.modify_actions = action->rewrite->num_of_actions;
-                       recalc_cs_required = action->rewrite->modify_ttl &&
-                                            !mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps);
+                       if (action->rewrite->modify_ttl)
+                               dr_action_modify_ttl_adjust(dmn, &attr, rx_rule,
+                                                           &recalc_cs_required);
                        break;
                case DR_ACTION_TYP_L2_TO_TNL_L2:
                case DR_ACTION_TYP_L2_TO_TNL_L3:
@@ -732,12 +764,7 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
        *new_hw_ste_arr_sz = nic_matcher->num_of_builders;
        last_ste = ste_arr + DR_STE_SIZE * (nic_matcher->num_of_builders - 1);
 
-       /* Due to a HW bug in some devices, modifying TTL on RX flows will
-        * cause an incorrect checksum calculation. In this case we will
-        * use a FW table to recalculate.
-        */
-       if (dmn->type == MLX5DR_DOMAIN_TYPE_FDB &&
-           rx_rule && recalc_cs_required && dest_action) {
+       if (recalc_cs_required && dest_action) {
                ret = dr_action_handle_cs_recalc(dmn, dest_action, &attr.final_icm_addr);
                if (ret) {
                        mlx5dr_err(dmn,
@@ -1558,12 +1585,6 @@ dr_action_modify_check_is_ttl_modify(const void *sw_action)
        return sw_field == MLX5_ACTION_IN_FIELD_OUT_IP_TTL;
 }
 
-static bool dr_action_modify_ttl_ignore(struct mlx5dr_domain *dmn)
-{
-       return !mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps) &&
-              !MLX5_CAP_ESW_FLOWTABLE(dmn->mdev, fdb_ipv4_ttl_modify);
-}
-
 static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
                                            u32 max_hw_actions,
                                            u32 num_sw_actions,
@@ -1575,6 +1596,7 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
        const struct mlx5dr_ste_action_modify_field *hw_dst_action_info;
        const struct mlx5dr_ste_action_modify_field *hw_src_action_info;
        struct mlx5dr_domain *dmn = action->rewrite->dmn;
+       __be64 *modify_ttl_sw_action = NULL;
        int ret, i, hw_idx = 0;
        __be64 *sw_action;
        __be64 hw_action;
@@ -1587,8 +1609,14 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
        action->rewrite->allow_rx = 1;
        action->rewrite->allow_tx = 1;
 
-       for (i = 0; i < num_sw_actions; i++) {
-               sw_action = &sw_actions[i];
+       for (i = 0; i < num_sw_actions || modify_ttl_sw_action; i++) {
+               /* modify TTL is handled separately, as a last action */
+               if (i == num_sw_actions) {
+                       sw_action = modify_ttl_sw_action;
+                       modify_ttl_sw_action = NULL;
+               } else {
+                       sw_action = &sw_actions[i];
+               }
 
                ret = dr_action_modify_check_field_limitation(action,
                                                              sw_action);
@@ -1597,10 +1625,9 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
 
                if (!(*modify_ttl) &&
                    dr_action_modify_check_is_ttl_modify(sw_action)) {
-                       if (dr_action_modify_ttl_ignore(dmn))
-                               continue;
-
+                       modify_ttl_sw_action = sw_action;
                        *modify_ttl = true;
+                       continue;
                }
 
                /* Convert SW action to HW action */
index 5a322335f2043d570302fd810ca7f5a06737d80e..2010d4ac651909e1ff2d5d8a7ca2a485ae13e50c 100644 (file)
@@ -420,7 +420,7 @@ dr_ste_v0_set_actions_tx(struct mlx5dr_domain *dmn,
         * encapsulation. The reason for that is that we support
         * modify headers for outer headers only
         */
-       if (action_type_set[DR_ACTION_TYP_MODIFY_HDR]) {
+       if (action_type_set[DR_ACTION_TYP_MODIFY_HDR] && attr->modify_actions) {
                dr_ste_v0_set_entry_type(last_ste, DR_STE_TYPE_MODIFY_PKT);
                dr_ste_v0_set_rewrite_actions(last_ste,
                                              attr->modify_actions,
@@ -513,7 +513,7 @@ dr_ste_v0_set_actions_rx(struct mlx5dr_domain *dmn,
                }
        }
 
-       if (action_type_set[DR_ACTION_TYP_MODIFY_HDR]) {
+       if (action_type_set[DR_ACTION_TYP_MODIFY_HDR] && attr->modify_actions) {
                if (dr_ste_v0_get_entry_type(last_ste) == DR_STE_TYPE_MODIFY_PKT)
                        dr_ste_v0_arr_init_next(&last_ste,
                                                added_stes,