net/mlx5: fix modify field action order for IPv6
authorAlexander Kozyrev <akozyrev@nvidia.com>
Wed, 7 Apr 2021 01:14:33 +0000 (01:14 +0000)
committerRaslan Darawsheh <rasland@nvidia.com>
Tue, 13 Apr 2021 11:22:55 +0000 (13:22 +0200)
Mellanox hardware can only modify any packet field in 32-bit chunks,
which means 4 such chunks are needed to modify an IPv6 address.
The modification order of these chunks starts from the most significant
bits for the IPv6 address. That leads to confusing results when trying
to modify either source or destination address via the MODIFY_FIELD
action. Fix the order of 32-bit chunks for IPv6 addresses modification
by starting from the least significant bits.

Fixes: 641dbe4fb053 ("net/mlx5: support modify field flow action")
Cc: stable@dpdk.org
Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>
Acked-by: Viacheslav Ovsiienko <viacheslavo@nvidia.com>
drivers/net/mlx5/mlx5_flow_dv.c

index 73e59ce..f1b06d0 100644 (file)
@@ -1462,8 +1462,9 @@ mlx5_flow_field_id_to_modify_info
        case RTE_FLOW_FIELD_IPV6_SRC:
                if (mask) {
                        if (data->offset < 32) {
-                               info[idx] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_SIPV6_127_96};
+                               info[idx] = (struct field_modify_info){4,
+                                               4 * idx,
+                                               MLX5_MODI_OUT_SIPV6_31_0};
                                if (width < 32) {
                                        mask[idx] =
                                                rte_cpu_to_be_32(0xffffffff >>
@@ -1480,7 +1481,7 @@ mlx5_flow_field_id_to_modify_info
                        if (data->offset < 64) {
                                info[idx] = (struct field_modify_info){4,
                                                4 * idx,
-                                               MLX5_MODI_OUT_SIPV6_95_64};
+                                               MLX5_MODI_OUT_SIPV6_63_32};
                                if (width < 32) {
                                        mask[idx] =
                                                rte_cpu_to_be_32(0xffffffff >>
@@ -1496,8 +1497,8 @@ mlx5_flow_field_id_to_modify_info
                        }
                        if (data->offset < 96) {
                                info[idx] = (struct field_modify_info){4,
-                                               8 * idx,
-                                               MLX5_MODI_OUT_SIPV6_63_32};
+                                               4 * idx,
+                                               MLX5_MODI_OUT_SIPV6_95_64};
                                if (width < 32) {
                                        mask[idx] =
                                                rte_cpu_to_be_32(0xffffffff >>
@@ -1511,30 +1512,31 @@ mlx5_flow_field_id_to_modify_info
                                        break;
                                ++idx;
                        }
-                       info[idx] = (struct field_modify_info){4, 12 * idx,
-                                               MLX5_MODI_OUT_SIPV6_31_0};
+                       info[idx] = (struct field_modify_info){4, 4 * idx,
+                                               MLX5_MODI_OUT_SIPV6_127_96};
                        mask[idx] = rte_cpu_to_be_32(0xffffffff >>
                                                     (32 - width));
                } else {
                        if (data->offset < 32)
                                info[idx++] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_SIPV6_127_96};
+                                               MLX5_MODI_OUT_SIPV6_31_0};
                        if (data->offset < 64)
                                info[idx++] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_SIPV6_95_64};
+                                               MLX5_MODI_OUT_SIPV6_63_32};
                        if (data->offset < 96)
                                info[idx++] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_SIPV6_63_32};
+                                               MLX5_MODI_OUT_SIPV6_95_64};
                        if (data->offset < 128)
                                info[idx++] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_SIPV6_31_0};
+                                               MLX5_MODI_OUT_SIPV6_127_96};
                }
                break;
        case RTE_FLOW_FIELD_IPV6_DST:
                if (mask) {
                        if (data->offset < 32) {
-                               info[idx] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_DIPV6_127_96};
+                               info[idx] = (struct field_modify_info){4,
+                                               4 * idx,
+                                               MLX5_MODI_OUT_DIPV6_31_0};
                                if (width < 32) {
                                        mask[idx] =
                                                rte_cpu_to_be_32(0xffffffff >>
@@ -1551,7 +1553,7 @@ mlx5_flow_field_id_to_modify_info
                        if (data->offset < 64) {
                                info[idx] = (struct field_modify_info){4,
                                                4 * idx,
-                                               MLX5_MODI_OUT_DIPV6_95_64};
+                                               MLX5_MODI_OUT_DIPV6_63_32};
                                if (width < 32) {
                                        mask[idx] =
                                                rte_cpu_to_be_32(0xffffffff >>
@@ -1567,8 +1569,8 @@ mlx5_flow_field_id_to_modify_info
                        }
                        if (data->offset < 96) {
                                info[idx] = (struct field_modify_info){4,
-                                               8 * idx,
-                                               MLX5_MODI_OUT_DIPV6_63_32};
+                                               4 * idx,
+                                               MLX5_MODI_OUT_DIPV6_95_64};
                                if (width < 32) {
                                        mask[idx] =
                                                rte_cpu_to_be_32(0xffffffff >>
@@ -1582,23 +1584,23 @@ mlx5_flow_field_id_to_modify_info
                                        break;
                                ++idx;
                        }
-                       info[idx] = (struct field_modify_info){4, 12 * idx,
-                                               MLX5_MODI_OUT_DIPV6_31_0};
+                       info[idx] = (struct field_modify_info){4, 4 * idx,
+                                               MLX5_MODI_OUT_DIPV6_127_96};
                        mask[idx] = rte_cpu_to_be_32(0xffffffff >>
                                                     (32 - width));
                } else {
                        if (data->offset < 32)
                                info[idx++] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_DIPV6_127_96};
+                                               MLX5_MODI_OUT_DIPV6_31_0};
                        if (data->offset < 64)
                                info[idx++] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_DIPV6_95_64};
+                                               MLX5_MODI_OUT_DIPV6_63_32};
                        if (data->offset < 96)
                                info[idx++] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_DIPV6_63_32};
+                                               MLX5_MODI_OUT_DIPV6_95_64};
                        if (data->offset < 128)
                                info[idx++] = (struct field_modify_info){4, 0,
-                                               MLX5_MODI_OUT_DIPV6_31_0};
+                                               MLX5_MODI_OUT_DIPV6_127_96};
                }
                break;
        case RTE_FLOW_FIELD_TCP_PORT_SRC: