From 8762718d721204a89d5de1a499c869a38f2f639b Mon Sep 17 00:00:00 2001 From: Alexander Kozyrev Date: Mon, 5 Jul 2021 12:47:04 +0300 Subject: [PATCH] net/mlx5: fix offset calculation for modify field action Offsets are not taken into account during MAC addresses manipulation for the MODIFY_FIELD action. That leads to a wrong split between 0-15 and 16-47 bits and corrupted data being copied to/from MAC addresses. Use both source and destination offsets to calcucate the proper modify header action specification. Fixes: fdd0c046f4 ("net/mlx5: fix modify field action order for MAC") Cc: stable@dpdk.org Signed-off-by: Alexander Kozyrev Acked-by: Viacheslav Ovsiienko --- drivers/net/mlx5/mlx5_flow_dv.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 4c7eb6cb0e..6ffdaf188c 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -413,6 +413,7 @@ flow_dv_convert_modify_action(struct rte_flow_item *item, { uint32_t i = resource->actions_num; struct mlx5_modification_cmd *actions = resource->actions; + uint32_t carry_b = 0; /* * The item and mask are provided in big-endian format. @@ -422,8 +423,8 @@ flow_dv_convert_modify_action(struct rte_flow_item *item, MLX5_ASSERT(item->mask); MLX5_ASSERT(field->size); do { - unsigned int size_b; - unsigned int off_b; + uint32_t size_b; + uint32_t off_b; uint32_t mask; uint32_t data; bool next_field = true; @@ -441,7 +442,7 @@ flow_dv_convert_modify_action(struct rte_flow_item *item, continue; } /* Deduce actual data width in bits from mask value. */ - off_b = rte_bsf32(mask); + off_b = rte_bsf32(mask) + carry_b; size_b = sizeof(uint32_t) * CHAR_BIT - off_b - __builtin_clz(mask); MLX5_ASSERT(size_b); @@ -463,19 +464,23 @@ flow_dv_convert_modify_action(struct rte_flow_item *item, * Destination field overflow. Copy leftovers of * a source field to the next destination field. */ - if ((size_b > dcopy->size * CHAR_BIT) && dcopy->size) { - actions[i].length = dcopy->size * CHAR_BIT; - field->offset += dcopy->size; + carry_b = 0; + if ((size_b > dcopy->size * CHAR_BIT - dcopy->offset) && + dcopy->size != 0) { + actions[i].length = + dcopy->size * CHAR_BIT - dcopy->offset; + carry_b = actions[i].length; next_field = false; } /* * Not enough bits in a source filed to fill a * destination field. Switch to the next source. */ - if (dcopy->size > field->size && - (size_b == field->size * CHAR_BIT)) { - actions[i].length = field->size * CHAR_BIT; - dcopy->offset += field->size * CHAR_BIT; + if ((size_b < dcopy->size * CHAR_BIT - dcopy->offset) && + (size_b == field->size * CHAR_BIT - off_b)) { + actions[i].length = + field->size * CHAR_BIT - off_b; + dcopy->offset += actions[i].length; next_dcopy = false; } if (next_dcopy) -- 2.20.1