Skip to content

Commit

Permalink
mlx5: DR, Add support for SW encap action
Browse files Browse the repository at this point in the history
Currently, encap reformat action creation is done by using DevX to get
the reformat_id.

This patch adds the support that, when SW encap is supported, will use
the new method for encap reformat creation by default, by copying encap
data to SW-encap ICM memory directly. Otherwise, will fallback to try
again, using DevX to create FW encap action.

Because Dest Array action only supports encap action created by DevX,
when the SW encap action is used by Dest Array, a DevX object will be
created as well, using the same encap data.

Signed-off-by: Shun Hao <shunh@nvidia.com>
Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
  • Loading branch information
Shun-Hao authored and Yishai Hadas committed Dec 14, 2023
1 parent 66f170e commit f50e8dd
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 25 deletions.
118 changes: 101 additions & 17 deletions providers/mlx5/dr_action.c
Expand Up @@ -831,7 +831,7 @@ int dr_actions_build_ste_arr(struct mlx5dv_dr_matcher *matcher,
}

attr.reformat_size = action->reformat.reformat_size;
attr.reformat_id = action->reformat.dvo->object_id;
attr.reformat_id = dr_actions_reformat_get_id(action);
attr.prio_tag_required = dmn->info.caps.prio_tag_required;
break;
case DR_ACTION_TYP_METER:
Expand Down Expand Up @@ -1527,8 +1527,9 @@ dr_action_verify_reformat_params(enum mlx5dv_flow_action_packet_reformat_type re
size_t data_sz,
void *data)
{
if ((!data && data_sz) || (data && !data_sz) || reformat_type >
MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL) {
if ((!data && data_sz) || (data && !data_sz) ||
(dr_domain_is_support_sw_encap(dmn) && (data_sz > dmn->info.caps.max_encap_size)) ||
reformat_type > MLX5DV_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL) {
dr_dbg(dmn, "Invalid reformat parameter!\n");
goto out_err;
}
Expand Down Expand Up @@ -1557,31 +1558,88 @@ dr_action_verify_reformat_params(enum mlx5dv_flow_action_packet_reformat_type re
return errno;
}

static int dr_action_create_sw_reformat(struct mlx5dv_dr_domain *dmn,
struct mlx5dv_dr_action *action,
size_t data_sz, void *data)
{
uint8_t *reformat_data;
int ret;

reformat_data = calloc(1, data_sz);
if (!reformat_data) {
errno = ENOMEM;
return errno;
}
memcpy(reformat_data, data, data_sz);
action->reformat.data = reformat_data;
action->reformat.reformat_size = data_sz;
ret = dr_ste_alloc_encap(action);
if (ret)
goto free_reformat_data;

return 0;

free_reformat_data:
free(reformat_data);
action->reformat.data = NULL;

return ret;
}

static void dr_action_destroy_sw_reformat(struct mlx5dv_dr_action *action)
{
dr_ste_free_encap(action);
free(action->reformat.data);
}

static int dr_action_create_devx_reformat(struct mlx5dv_dr_domain *dmn,
struct mlx5dv_dr_action *action,
size_t data_sz, void *data)
{
struct mlx5dv_devx_obj *obj;
enum reformat_type rt;

if (action->action_type == DR_ACTION_TYP_L2_TO_TNL_L2)
rt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL;
else
rt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;

obj = dr_devx_create_reformat_ctx(dmn->ctx, rt, data_sz, data);
if (!obj)
return errno;

action->reformat.dvo = obj;
action->reformat.reformat_size = data_sz;

return 0;
}

static void dr_action_destroy_devx_reformat(struct mlx5dv_dr_action *action)
{
mlx5dv_devx_obj_destroy(action->reformat.dvo);
}

static int
dr_action_create_reformat_action(struct mlx5dv_dr_domain *dmn,
size_t data_sz, void *data,
struct mlx5dv_dr_action *action)
{
struct mlx5dv_devx_obj *obj;
uint8_t *hw_actions;

switch (action->action_type) {
case DR_ACTION_TYP_L2_TO_TNL_L2:
case DR_ACTION_TYP_L2_TO_TNL_L3:
{
enum reformat_type rt;

if (action->action_type == DR_ACTION_TYP_L2_TO_TNL_L2)
rt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL;
else
rt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
if (dr_domain_is_support_sw_encap(dmn) &&
!dr_action_create_sw_reformat(dmn, action, data_sz, data))
return 0;

obj = dr_devx_create_reformat_ctx(dmn->ctx, rt, data_sz, data);
if (!obj)
/* When failed creating sw encap, fallback to
* use devx to try again.
*/
if (dr_action_create_devx_reformat(dmn, action, data_sz, data))
return errno;

action->reformat.dvo = obj;
action->reformat.reformat_size = data_sz;
return 0;
}
case DR_ACTION_TYP_TNL_L2_TO_L2:
Expand Down Expand Up @@ -1720,6 +1778,14 @@ struct mlx5dv_dr_action *mlx5dv_dr_action_create_push_vlan(struct mlx5dv_dr_doma
return action;
}

uint32_t dr_actions_reformat_get_id(struct mlx5dv_dr_action *action)
{
if (action->reformat.chunk)
return action->reformat.index;

return action->reformat.dvo->object_id;
}

static int
dr_action_modify_sw_to_hw_add(struct mlx5dv_dr_domain *dmn,
__be64 *sw_action,
Expand Down Expand Up @@ -2442,12 +2508,25 @@ dr_action_convert_to_fte_dest(struct mlx5dv_dr_domain *dmn,
}

if (dest_reformat) {
int ret = 0;

switch (dest_reformat->action_type) {
case DR_ACTION_TYP_L2_TO_TNL_L2:
case DR_ACTION_TYP_L2_TO_TNL_L3:
if (dest_reformat->reformat.is_root_level)
goto err_exit;

dr_domain_lock(dmn);
if (!dest_reformat->reformat.dvo) {
ret = dr_action_create_devx_reformat(dmn,
dest_reformat,
dest_reformat->reformat.reformat_size,
dest_reformat->reformat.data);
}
dr_domain_unlock(dmn);
if (ret)
goto err_exit;

fte_attr->extended_dest = true;
dest_info->has_reformat = true;
dest_info->reformat_id = dest_reformat->reformat.dvo->object_id;
Expand Down Expand Up @@ -3013,10 +3092,15 @@ int mlx5dv_dr_action_destroy(struct mlx5dv_dr_action *action)
break;
case DR_ACTION_TYP_L2_TO_TNL_L2:
case DR_ACTION_TYP_L2_TO_TNL_L3:
if (action->reformat.is_root_level)
if (action->reformat.is_root_level) {
mlx5_destroy_flow_action(action->reformat.flow_action);
else
mlx5dv_devx_obj_destroy(action->reformat.dvo);
} else {
if (action->reformat.chunk)
dr_action_destroy_sw_reformat(action);

if (action->reformat.dvo)
dr_action_destroy_devx_reformat(action);
}
atomic_fetch_sub(&action->reformat.dmn->refcount, 1);
break;
case DR_ACTION_TYP_MODIFY_HDR:
Expand Down
4 changes: 2 additions & 2 deletions providers/mlx5/dr_dbg.c
Expand Up @@ -186,12 +186,12 @@ static int dr_dump_rule_action(FILE *f, const uint64_t rule_id,
case DR_ACTION_TYP_L2_TO_TNL_L2:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_ENCAP_L2, action_id,
rule_id, action->reformat.dvo->object_id);
rule_id, dr_actions_reformat_get_id(action));
break;
case DR_ACTION_TYP_L2_TO_TNL_L3:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_ENCAP_L3, action_id,
rule_id, action->reformat.dvo->object_id);
rule_id, dr_actions_reformat_get_id(action));
break;
case DR_ACTION_TYP_METER:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%x,0x%" PRIx64 ",0x%" PRIx64 "\n",
Expand Down
20 changes: 14 additions & 6 deletions providers/mlx5/dr_send.c
Expand Up @@ -951,12 +951,20 @@ int dr_send_postsend_action(struct mlx5dv_dr_domain *dmn,

num_qps = dmn->info.use_mqs ? DR_MAX_SEND_RINGS : 1;

send_info.write.addr = (uintptr_t)action->rewrite.param.data;
send_info.write.length = action->rewrite.param.num_of_actions *
DR_MODIFY_ACTION_SIZE;
send_info.write.lkey = 0;
send_info.remote_addr = dr_icm_pool_get_chunk_mr_addr(action->rewrite.param.chunk);
send_info.rkey = dr_icm_pool_get_chunk_rkey(action->rewrite.param.chunk);
if (action->action_type == DR_ACTION_TYP_L2_TO_TNL_L2 ||
action->action_type == DR_ACTION_TYP_L2_TO_TNL_L3) {
send_info.write.addr = (uintptr_t)action->reformat.data;
send_info.write.length = action->reformat.reformat_size;
send_info.remote_addr = dr_icm_pool_get_chunk_mr_addr(action->reformat.chunk);
send_info.rkey = dr_icm_pool_get_chunk_rkey(action->reformat.chunk);
} else {
send_info.write.addr = (uintptr_t)action->rewrite.param.data;
send_info.write.length = action->rewrite.param.num_of_actions *
DR_MODIFY_ACTION_SIZE;
send_info.remote_addr = dr_icm_pool_get_chunk_mr_addr(action->rewrite.param.chunk);
send_info.rkey = dr_icm_pool_get_chunk_rkey(action->rewrite.param.chunk);
}
send_info.write.lkey = 0;

/* To avoid race between action creation and its use in other QP
* write it in all QP's.
Expand Down
36 changes: 36 additions & 0 deletions providers/mlx5/dr_ste.c
Expand Up @@ -732,6 +732,42 @@ void dr_ste_free_modify_hdr(struct mlx5dv_dr_action *action)
return dr_dealloc_modify_hdr_chunk(action);
}

int dr_ste_alloc_encap(struct mlx5dv_dr_action *action)
{
struct mlx5dv_dr_domain *dmn = action->reformat.dmn;
uint32_t dynamic_chunck_size;
int ret;

dynamic_chunck_size = ilog32((action->reformat.reformat_size - 1) /
DR_SW_ENCAP_ENTRY_SIZE);
action->reformat.chunk = dr_icm_alloc_chunk(dmn->encap_icm_pool,
dynamic_chunck_size);
if (!action->reformat.chunk)
return errno;

action->reformat.index = (dr_icm_pool_get_chunk_icm_addr(action->reformat.chunk) -
dmn->info.caps.indirect_encap_icm_base) /
DR_SW_ENCAP_ENTRY_SIZE;

ret = dr_send_postsend_action(dmn, action);
if (ret)
goto postsend_err;

return 0;

postsend_err:
dr_icm_free_chunk(action->reformat.chunk);
action->reformat.chunk = NULL;
action->reformat.index = 0;

return ret;
}

void dr_ste_free_encap(struct mlx5dv_dr_action *action)
{
dr_icm_free_chunk(action->reformat.chunk);
}

static int dr_ste_build_pre_check_spec(struct mlx5dv_dr_domain *dmn,
struct dr_match_spec *m_spec,
struct dr_match_spec *v_spec)
Expand Down
7 changes: 7 additions & 0 deletions providers/mlx5/mlx5dv_dr.h
Expand Up @@ -693,6 +693,8 @@ int dr_actions_build_attr(struct mlx5dv_dr_matcher *matcher,
struct mlx5dv_flow_action_attr *attr,
struct mlx5_flow_action_attr_aux *attr_aux);

uint32_t dr_actions_reformat_get_id(struct mlx5dv_dr_action *action);

struct dr_match_spec {
uint32_t smac_47_16; /* Source MAC address of incoming packet */
uint32_t smac_15_0:16; /* Source MAC address of incoming packet */
Expand Down Expand Up @@ -1279,6 +1281,9 @@ struct mlx5dv_dr_action {
struct ibv_flow_action *flow_action; /* root*/
struct {
struct mlx5dv_devx_obj *dvo;
uint8_t *data;
uint32_t index;
struct dr_icm_chunk *chunk;
uint32_t reformat_size;
};
};
Expand Down Expand Up @@ -1781,6 +1786,8 @@ void dr_buddy_free_mem(struct dr_icm_buddy_mem *buddy, uint32_t seg, int order);

void dr_ste_free_modify_hdr(struct mlx5dv_dr_action *action);
int dr_ste_alloc_modify_hdr(struct mlx5dv_dr_action *action);
int dr_ste_alloc_encap(struct mlx5dv_dr_action *action);
void dr_ste_free_encap(struct mlx5dv_dr_action *action);

void dr_vports_table_add_wire(struct dr_devx_vports *vports);
void dr_vports_table_del_wire(struct dr_devx_vports *vports);
Expand Down

0 comments on commit f50e8dd

Please sign in to comment.