blob: 16c70acfadf14c940fac91dada5390bc42d511cc [file] [log] [blame] [edit]
/*
* Copyright (c) 2019 Mellanox Technologies, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <unistd.h>
#include <inttypes.h>
#include "mlx5dv_dr.h"
#define BUFF_SIZE 1024
enum dr_dump_rec_type {
DR_DUMP_REC_TYPE_DOMAIN = 3000,
DR_DUMP_REC_TYPE_DOMAIN_INFO_FLEX_PARSER = 3001,
DR_DUMP_REC_TYPE_DOMAIN_INFO_DEV_ATTR = 3002,
DR_DUMP_REC_TYPE_DOMAIN_INFO_VPORT = 3003,
DR_DUMP_REC_TYPE_DOMAIN_INFO_CAPS = 3004,
DR_DUMP_REC_TYPE_DOMAIN_SEND_RING = 3005,
DR_DUMP_REC_TYPE_TABLE = 3100,
DR_DUMP_REC_TYPE_TABLE_RX = 3101,
DR_DUMP_REC_TYPE_TABLE_TX = 3102,
DR_DUMP_REC_TYPE_MATCHER = 3200,
DR_DUMP_REC_TYPE_MATCHER_MASK_DEPRECATED = 3201,
DR_DUMP_REC_TYPE_MATCHER_RX = 3202,
DR_DUMP_REC_TYPE_MATCHER_TX = 3203,
DR_DUMP_REC_TYPE_MATCHER_BUILDER = 3204,
DR_DUMP_REC_TYPE_MATCHER_MASK = 3205,
DR_DUMP_REC_TYPE_RULE = 3300,
DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V0 = 3301,
DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V0 = 3302,
DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V1 = 3303,
DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V1 = 3304,
DR_DUMP_REC_TYPE_ACTION_ENCAP_L2 = 3400,
DR_DUMP_REC_TYPE_ACTION_ENCAP_L3 = 3401,
DR_DUMP_REC_TYPE_ACTION_MODIFY_HDR = 3402,
DR_DUMP_REC_TYPE_ACTION_DROP = 3403,
DR_DUMP_REC_TYPE_ACTION_QP = 3404,
DR_DUMP_REC_TYPE_ACTION_FT = 3405,
DR_DUMP_REC_TYPE_ACTION_CTR = 3406,
DR_DUMP_REC_TYPE_ACTION_TAG = 3407,
DR_DUMP_REC_TYPE_ACTION_VPORT = 3408,
DR_DUMP_REC_TYPE_ACTION_DECAP_L2 = 3409,
DR_DUMP_REC_TYPE_ACTION_DECAP_L3 = 3410,
DR_DUMP_REC_TYPE_ACTION_DEVX_TIR = 3411,
DR_DUMP_REC_TYPE_ACTION_PUSH_VLAN = 3412,
DR_DUMP_REC_TYPE_ACTION_POP_VLAN = 3413,
DR_DUMP_REC_TYPE_ACTION_METER = 3414,
DR_DUMP_REC_TYPE_ACTION_SAMPLER = 3415,
DR_DUMP_REC_TYPE_ACTION_DEST_ARRAY = 3416,
DR_DUMP_REC_TYPE_ACTION_ASO_FIRST_HIT = 3417,
DR_DUMP_REC_TYPE_ACTION_ASO_FLOW_METER = 3418,
DR_DUMP_REC_TYPE_ACTION_ASO_CT = 3419,
DR_DUMP_REC_TYPE_ACTION_MISS = 3423,
DR_DUMP_REC_TYPE_ACTION_ROOT_FT = 3424,
};
static uint64_t dr_dump_icm_to_idx(uint64_t icm_addr)
{
return (icm_addr >> 6) & 0xffffffff;
}
static void dump_hex_print(char *dest, char *src, uint32_t size)
{
int i;
for (i = 0; i < size; i++)
sprintf(&dest[2 * i], "%02x", (uint8_t)src[i]);
}
static int dr_dump_rule_action(FILE *f, const uint64_t rule_id,
struct mlx5dv_dr_action *action)
{
const uint64_t action_id = (uint64_t) (uintptr_t) action;
int ret;
switch (action->action_type) {
case DR_ACTION_TYP_DROP:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_ACTION_DROP, action_id, rule_id);
break;
case DR_ACTION_TYP_FT:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x,0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_ACTION_FT, action_id, rule_id,
action->dest_tbl->devx_obj->object_id,
(uint64_t)(uintptr_t)action->dest_tbl);
break;
case DR_ACTION_TYP_QP:
if (action->dest_qp.is_qp)
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_QP, action_id,
rule_id, action->dest_qp.qp->qp_num);
else
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_ACTION_DEVX_TIR, action_id,
rule_id, action->dest_qp.devx_tir->rx_icm_addr);
break;
case DR_ACTION_TYP_CTR:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_CTR, action_id, rule_id,
action->ctr.devx_obj->object_id +
action->ctr.offset);
break;
case DR_ACTION_TYP_TAG:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_TAG, action_id, rule_id,
action->flow_tag);
break;
case DR_ACTION_TYP_MODIFY_HDR:
{
struct dr_ptrn_obj *ptrn = action->rewrite.ptrn_arg.ptrn;
struct dr_rewrite_param *param = &action->rewrite.param;
struct dr_arg_obj *arg = action->rewrite.ptrn_arg.arg;
bool ptrn_in_use = false;
int i;
if (!action->rewrite.single_action_opt && ptrn && arg)
ptrn_in_use = true;
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x,%d,0x%x,0x%" PRIx32 ",0x%" PRIx32,
DR_DUMP_REC_TYPE_ACTION_MODIFY_HDR, action_id,
rule_id, param->index,
action->rewrite.single_action_opt,
ptrn_in_use ? param->num_of_actions : 0,
ptrn_in_use ? ptrn->rewrite_param.index : 0,
ptrn_in_use ? dr_arg_get_object_id(arg) : 0);
if (ret < 0)
return ret;
if (ptrn_in_use) {
for (i = 0; i < param->num_of_actions; i++) {
ret = fprintf(f, ",0x%016" PRIx64,
be64toh(((__be64 *)param->data)[i]));
if (ret < 0)
return ret;
}
}
ret = fprintf(f, "\n");
break;
}
case DR_ACTION_TYP_VPORT:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_VPORT, action_id, rule_id,
action->vport.caps->num);
break;
case DR_ACTION_TYP_TNL_L2_TO_L2:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_ACTION_DECAP_L2, action_id,
rule_id);
break;
case DR_ACTION_TYP_TNL_L3_TO_L2:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_DECAP_L3, action_id,
rule_id, action->rewrite.param.index);
break;
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, 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, 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",
DR_DUMP_REC_TYPE_ACTION_METER,
action_id,
rule_id,
(uint64_t)(uintptr_t)action->meter.next_ft,
action->meter.devx_obj->object_id,
action->meter.rx_icm_addr,
action->meter.tx_icm_addr);
break;
case DR_ACTION_TYP_SAMPLER:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 ",0x%x,0x%x,0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_ACTION_SAMPLER,
action_id,
rule_id,
(uint64_t)(uintptr_t)action->sampler.sampler_default->next_ft,
action->sampler.term_tbl->devx_tbl->ft_dvo->object_id,
action->sampler.sampler_default->devx_obj->object_id,
action->sampler.sampler_default->rx_icm_addr,
(action->sampler.sampler_restore) ?
action->sampler.sampler_restore->tx_icm_addr :
action->sampler.sampler_default->tx_icm_addr);
break;
case DR_ACTION_TYP_DEST_ARRAY:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x,0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_ACTION_DEST_ARRAY, action_id, rule_id,
action->dest_array.devx_tbl->ft_dvo->object_id,
action->dest_array.rx_icm_addr,
action->dest_array.tx_icm_addr);
break;
case DR_ACTION_TYP_POP_VLAN:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_ACTION_POP_VLAN, action_id,
rule_id);
break;
case DR_ACTION_TYP_PUSH_VLAN:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_PUSH_VLAN, action_id,
rule_id, action->push_vlan.vlan_hdr);
break;
case DR_ACTION_TYP_ASO_FIRST_HIT:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_ASO_FIRST_HIT, action_id,
rule_id, action->aso.devx_obj->object_id);
break;
case DR_ACTION_TYP_ASO_FLOW_METER:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_ASO_FLOW_METER, action_id,
rule_id, action->aso.devx_obj->object_id);
break;
case DR_ACTION_TYP_ASO_CT:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_ASO_CT, action_id,
rule_id, action->aso.devx_obj->object_id);
break;
case DR_ACTION_TYP_MISS:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_ACTION_MISS, action_id, rule_id);
break;
case DR_ACTION_TYP_ROOT_FT:
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x\n",
DR_DUMP_REC_TYPE_ACTION_ROOT_FT, action_id,
rule_id,
action->root_tbl.devx_tbl->ft_dvo->object_id);
break;
default:
return 0;
}
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_rule_mem(FILE *f, struct dr_ste *ste,
bool is_rx, const uint64_t rule_id,
enum mlx5_ifc_steering_format_version format_ver)
{
char hw_ste_dump[BUFF_SIZE] = {};
enum dr_dump_rec_type mem_rec_type;
int ret;
if (format_ver == MLX5_HW_CONNECTX_5) {
mem_rec_type = is_rx ? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V0 :
DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V0;
} else {
mem_rec_type = is_rx ? DR_DUMP_REC_TYPE_RULE_RX_ENTRY_V1 :
DR_DUMP_REC_TYPE_RULE_TX_ENTRY_V1;
}
dump_hex_print(hw_ste_dump, (char *)ste->hw_ste, ste->size);
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%s\n",
mem_rec_type,
dr_dump_icm_to_idx(dr_ste_get_icm_addr(ste)),
rule_id,
hw_ste_dump);
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_rule_rx_tx(FILE *f, struct dr_rule_rx_tx *nic_rule,
bool is_rx, const uint64_t rule_id,
enum mlx5_ifc_steering_format_version format_ver)
{
struct dr_ste *ste_arr[DR_RULE_MAX_STES + DR_ACTION_MAX_STES];
struct dr_ste *curr_ste = nic_rule->last_rule_ste;
int ret, i;
dr_rule_get_reverse_rule_members(ste_arr, curr_ste, &i);
while (i--) {
ret = dr_dump_rule_mem(f, ste_arr[i], is_rx, rule_id, format_ver);
if (ret < 0)
return ret;
}
return 0;
}
static int dr_dump_rule(FILE *f, struct mlx5dv_dr_rule *rule)
{
const uint64_t rule_id = (uint64_t) (uintptr_t) rule;
enum mlx5_ifc_steering_format_version format_ver;
struct dr_rule_rx_tx *rx = &rule->rx;
struct dr_rule_rx_tx *tx = &rule->tx;
int ret;
int i;
format_ver = rule->matcher->tbl->dmn->info.caps.sw_format_ver;
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_RULE,
rule_id,
(uint64_t) (uintptr_t) rule->matcher);
if (ret < 0)
return ret;
if (!dr_is_root_table(rule->matcher->tbl)) {
if (rx->nic_matcher) {
ret = dr_dump_rule_rx_tx(f, rx, true, rule_id,
format_ver);
if (ret < 0)
return ret;
}
if (tx->nic_matcher) {
ret = dr_dump_rule_rx_tx(f, tx, false, rule_id,
format_ver);
if (ret < 0)
return ret;
}
}
for (i = 0; i < rule->num_actions; i++) {
ret = dr_dump_rule_action(f, rule_id, rule->actions[i]);
if (ret < 0)
return ret;
}
return 0;
}
static int dr_dump_matcher_mask(FILE *f, struct dr_match_param *mask,
uint8_t criteria, const uint64_t matcher_id)
{
char dump[BUFF_SIZE] = {};
int ret;
ret = fprintf(f, "%d,0x%" PRIx64 ",", DR_DUMP_REC_TYPE_MATCHER_MASK, matcher_id);
if (ret < 0)
return ret;
if (criteria & DR_MATCHER_CRITERIA_OUTER) {
dump_hex_print(dump, (char *)&mask->outer, sizeof(mask->outer));
ret = fprintf(f, "%s,", dump);
} else {
ret = fprintf(f, ",");
}
if (ret < 0)
return ret;
if (criteria & DR_MATCHER_CRITERIA_INNER) {
dump_hex_print(dump, (char *)&mask->inner, sizeof(mask->inner));
ret = fprintf(f, "%s,", dump);
} else {
ret = fprintf(f, ",");
}
if (ret < 0)
return ret;
if (criteria & DR_MATCHER_CRITERIA_MISC) {
dump_hex_print(dump, (char *)&mask->misc, sizeof(mask->misc));
ret = fprintf(f, "%s,", dump);
} else {
ret = fprintf(f, ",");
}
if (ret < 0)
return ret;
if (criteria & DR_MATCHER_CRITERIA_MISC2) {
dump_hex_print(dump, (char *)&mask->misc2, sizeof(mask->misc2));
ret = fprintf(f, "%s,", dump);
} else {
ret = fprintf(f, ",");
}
if (ret < 0)
return ret;
if (criteria & DR_MATCHER_CRITERIA_MISC3) {
dump_hex_print(dump, (char *)&mask->misc3, sizeof(mask->misc3));
ret = fprintf(f, "%s,", dump);
} else {
ret = fprintf(f, ",");
}
if (criteria & DR_MATCHER_CRITERIA_MISC4) {
dump_hex_print(dump, (char *)&mask->misc4, sizeof(mask->misc4));
ret = fprintf(f, "%s,", dump);
} else {
ret = fprintf(f, ",");
}
if (criteria & DR_MATCHER_CRITERIA_MISC5) {
dump_hex_print(dump, (char *)&mask->misc5, sizeof(mask->misc5));
ret = fprintf(f, "%s\n", dump);
} else {
ret = fprintf(f, ",\n");
}
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_matcher_builder(FILE *f, struct dr_ste_build *builder,
uint32_t index, bool is_rx,
const uint64_t matcher_id)
{
bool is_match = builder->htbl_type == DR_STE_HTBL_TYPE_MATCH;
int ret;
ret = fprintf(f, "%d,0x%" PRIx64 ",%d,%d,0x%x,%d\n",
DR_DUMP_REC_TYPE_MATCHER_BUILDER,
matcher_id,
index,
is_rx,
builder->lu_type,
is_match ? builder->format_id : -1);
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_matcher_rx_tx(FILE *f, bool is_rx,
struct dr_matcher_rx_tx *matcher_rx_tx,
const uint64_t matcher_id)
{
enum dr_dump_rec_type rec_type;
int i, ret;
rec_type = is_rx ? DR_DUMP_REC_TYPE_MATCHER_RX :
DR_DUMP_REC_TYPE_MATCHER_TX;
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,0x%" PRIx64 ",0x%" PRIx64 ",%d\n",
rec_type,
(uint64_t) (uintptr_t) matcher_rx_tx,
matcher_id,
matcher_rx_tx->num_of_builders,
dr_dump_icm_to_idx(dr_icm_pool_get_chunk_icm_addr(matcher_rx_tx->s_htbl->chunk)),
dr_dump_icm_to_idx(dr_icm_pool_get_chunk_icm_addr(matcher_rx_tx->e_anchor->chunk)),
matcher_rx_tx->fixed_size ? matcher_rx_tx->s_htbl->chunk_size : -1);
if (ret < 0)
return ret;
for (i = 0; i < matcher_rx_tx->num_of_builders; i++) {
ret = dr_dump_matcher_builder(f, &matcher_rx_tx->ste_builder[i],
i, is_rx, matcher_id);
if (ret < 0)
return ret;
}
return 0;
}
static int dr_dump_matcher(FILE *f, struct mlx5dv_dr_matcher *matcher)
{
struct dr_matcher_rx_tx *rx = &matcher->rx;
struct dr_matcher_rx_tx *tx = &matcher->tx;
uint64_t matcher_id;
int ret;
matcher_id = (uint64_t) (uintptr_t) matcher;
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d\n",
DR_DUMP_REC_TYPE_MATCHER,
matcher_id,
(uint64_t) (uintptr_t) matcher->tbl,
matcher->prio);
if (ret < 0)
return ret;
if (!dr_is_root_table(matcher->tbl)) {
ret = dr_dump_matcher_mask(f, &matcher->mask, matcher->match_criteria, matcher_id);
if (ret < 0)
return ret;
if (rx->nic_tbl) {
ret = dr_dump_matcher_rx_tx(f, true, rx, matcher_id);
if (ret < 0)
return ret;
}
if (tx->nic_tbl) {
ret = dr_dump_matcher_rx_tx(f, false, tx, matcher_id);
if (ret < 0)
return ret;
}
}
return 0;
}
static int dr_dump_matcher_all(FILE *fout, struct mlx5dv_dr_matcher *matcher)
{
struct mlx5dv_dr_rule *rule;
int ret;
ret = dr_dump_matcher(fout, matcher);
if (ret < 0)
return ret;
list_for_each(&matcher->rule_list, rule, rule_list) {
ret = dr_dump_rule(fout, rule);
if (ret < 0)
return ret;
}
return 0;
}
static uint64_t dr_domain_id_calc(enum mlx5dv_dr_domain_type type)
{
return (getpid() << 8) | (type & 0xff);
}
static int dr_dump_table_rx_tx(FILE *f, bool is_rx,
struct dr_table_rx_tx *table_rx_tx,
const uint64_t table_id)
{
struct dr_icm_chunk *chunk = table_rx_tx->s_anchor->chunk;
enum dr_dump_rec_type rec_type;
int ret;
rec_type = is_rx ? DR_DUMP_REC_TYPE_TABLE_RX : DR_DUMP_REC_TYPE_TABLE_TX;
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 "\n",
rec_type,
table_id,
dr_dump_icm_to_idx(dr_icm_pool_get_chunk_icm_addr(chunk)));
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_table(FILE *f, struct mlx5dv_dr_table *table)
{
struct dr_table_rx_tx *rx = &table->rx;
struct dr_table_rx_tx *tx = &table->tx;
int ret;
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",%d,%d\n",
DR_DUMP_REC_TYPE_TABLE,
(uint64_t) (uintptr_t) table,
dr_domain_id_calc(table->dmn->type),
table->table_type,
table->level);
if (ret < 0)
return ret;
if (!dr_is_root_table(table)) {
if (rx->nic_dmn) {
ret = dr_dump_table_rx_tx(f, true, rx, (uint64_t) (uintptr_t) table);
if (ret < 0)
return ret;
}
if (tx->nic_dmn) {
ret = dr_dump_table_rx_tx(f, false, tx, (uint64_t) (uintptr_t) table);
if (ret < 0)
return ret;
}
}
return 0;
}
static int dr_dump_table_all(FILE *fout, struct mlx5dv_dr_table *tbl)
{
struct mlx5dv_dr_matcher *matcher;
int ret;
ret = dr_dump_table(fout, tbl);
if (ret < 0)
return ret;
if (!dr_is_root_table(tbl)) {
list_for_each(&tbl->matcher_list, matcher, matcher_list) {
ret = dr_dump_matcher_all(fout, matcher);
if (ret < 0)
return ret;
}
}
return 0;
}
static int dr_dump_send_ring(FILE *f, struct dr_send_ring *ring,
const uint64_t domain_id)
{
int ret;
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%" PRIx64 ",0x%x,0x%x\n",
DR_DUMP_REC_TYPE_DOMAIN_SEND_RING,
(uint64_t) (uintptr_t) ring,
domain_id,
ring->cq.cqn,
ring->qp->obj->object_id);
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_domain_info_flex_parser(FILE *f, const char *flex_parser_name,
const uint8_t flex_parser_value,
const uint64_t domain_id)
{
int ret;
ret = fprintf(f, "%d,0x%" PRIx64 ",%s,0x%x\n",
DR_DUMP_REC_TYPE_DOMAIN_INFO_FLEX_PARSER,
domain_id,
flex_parser_name,
flex_parser_value);
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_vports_table(FILE *f, struct dr_vports_table *vports_tbl,
const uint64_t domain_id)
{
struct dr_devx_vport_cap *vport_cap;
int i, ret;
if (!vports_tbl)
return 0;
for (i = 0; i < DR_VPORTS_BUCKETS; i++) {
vport_cap = vports_tbl->buckets[i];
while (vport_cap) {
ret = fprintf(f, "%d,0x%" PRIx64 ",%d,0x%x,0x%" PRIx64 ",0x%" PRIx64 "\n",
DR_DUMP_REC_TYPE_DOMAIN_INFO_VPORT,
domain_id,
vport_cap->num,
vport_cap->vport_gvmi,
vport_cap->icm_address_rx,
vport_cap->icm_address_tx);
if (ret < 0)
return ret;
vport_cap = vport_cap->next;
}
}
return 0;
}
static int dr_dump_domain_info_caps(FILE *f, struct dr_devx_caps *caps,
const uint64_t domain_id)
{
int ret;
ret = fprintf(f, "%d,0x%" PRIx64 ",0x%x,0x%" PRIx64 ",0x%" PRIx64 ",0x%x,%d,%d\n",
DR_DUMP_REC_TYPE_DOMAIN_INFO_CAPS,
domain_id,
caps->gvmi,
caps->nic_rx_drop_address,
caps->nic_tx_drop_address,
caps->flex_protocols,
caps->vports.num_ports,
caps->eswitch_manager);
if (ret < 0)
return ret;
ret = dr_dump_vports_table(f, caps->vports.vports, domain_id);
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_domain_info_dev_attr(FILE *f, struct dr_domain_info *info,
const uint64_t domain_id)
{
int ret;
ret = fprintf(f, "%d,0x%" PRIx64 ",%u,%s,%d\n",
DR_DUMP_REC_TYPE_DOMAIN_INFO_DEV_ATTR,
domain_id,
info->caps.vports.num_ports,
info->attr.orig_attr.fw_ver,
info->use_mqs);
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_domain_info(FILE *f, struct dr_domain_info *info,
const uint64_t domain_id)
{
int ret;
ret = dr_dump_domain_info_dev_attr(f, info, domain_id);
if (ret < 0)
return ret;
ret = dr_dump_domain_info_caps(f, &info->caps, domain_id);
if (ret < 0)
return ret;
ret = dr_dump_domain_info_flex_parser(f, "icmp_dw0", info->caps.flex_parser_id_icmp_dw0, domain_id);
if (ret < 0)
return ret;
ret = dr_dump_domain_info_flex_parser(f, "icmp_dw1", info->caps.flex_parser_id_icmp_dw1, domain_id);
if (ret < 0)
return ret;
ret = dr_dump_domain_info_flex_parser(f, "icmpv6_dw0", info->caps.flex_parser_id_icmpv6_dw0, domain_id);
if (ret < 0)
return ret;
ret = dr_dump_domain_info_flex_parser(f, "icmpv6_dw1", info->caps.flex_parser_id_icmpv6_dw1, domain_id);
if (ret < 0)
return ret;
return 0;
}
static int dr_dump_domain(FILE *f, struct mlx5dv_dr_domain *dmn)
{
enum mlx5dv_dr_domain_type dmn_type = dmn->type;
char *dev_name = dmn->ctx->device->dev_name;
uint64_t domain_id;
int ret, i;
domain_id = dr_domain_id_calc(dmn_type);
ret = fprintf(f, "%d,0x%" PRIx64 ",%d,0%x,%d,%s,%s,%u,%u,%u,%u,%u\n",
DR_DUMP_REC_TYPE_DOMAIN,
domain_id,
dmn_type,
dmn->info.caps.gvmi,
dmn->info.supp_sw_steering,
PACKAGE_VERSION,
dev_name,
dmn->flags,
dmn->num_buddies[DR_ICM_TYPE_STE],
dmn->num_buddies[DR_ICM_TYPE_MODIFY_ACTION],
dmn->num_buddies[DR_ICM_TYPE_MODIFY_HDR_PTRN],
dmn->info.caps.sw_format_ver);
if (ret < 0)
return ret;
ret = dr_dump_domain_info(f, &dmn->info, domain_id);
if (ret < 0)
return ret;
if (dmn->info.supp_sw_steering) {
for (i = 0; i < DR_MAX_SEND_RINGS; i++) {
ret = dr_dump_send_ring(f, dmn->send_ring[i], domain_id);
if (ret < 0)
return ret;
}
}
return 0;
}
static int dr_dump_domain_all(FILE *fout, struct mlx5dv_dr_domain *dmn)
{
struct mlx5dv_dr_table *tbl;
int ret;
ret = dr_dump_domain(fout, dmn);
if (ret < 0)
return ret;
list_for_each(&dmn->tbl_list, tbl, tbl_list) {
ret = dr_dump_table_all(fout, tbl);
if (ret < 0)
return ret;
}
return 0;
}
int mlx5dv_dump_dr_domain(FILE *fout, struct mlx5dv_dr_domain *dmn)
{
int ret;
if (!fout || !dmn)
return -EINVAL;
pthread_spin_lock(&dmn->debug_lock);
dr_domain_lock(dmn);
ret = dr_dump_domain_all(fout, dmn);
dr_domain_unlock(dmn);
pthread_spin_unlock(&dmn->debug_lock);
return ret;
}
int mlx5dv_dump_dr_table(FILE *fout, struct mlx5dv_dr_table *tbl)
{
int ret;
if (!fout || !tbl)
return -EINVAL;
pthread_spin_lock(&tbl->dmn->debug_lock);
dr_domain_lock(tbl->dmn);
ret = dr_dump_domain(fout, tbl->dmn);
if (ret < 0)
goto out;
ret = dr_dump_table_all(fout, tbl);
out:
dr_domain_unlock(tbl->dmn);
pthread_spin_unlock(&tbl->dmn->debug_lock);
return ret;
}
int mlx5dv_dump_dr_matcher(FILE *fout, struct mlx5dv_dr_matcher *matcher)
{
int ret;
if (!fout || !matcher)
return -EINVAL;
pthread_spin_lock(&matcher->tbl->dmn->debug_lock);
dr_domain_lock(matcher->tbl->dmn);
ret = dr_dump_domain(fout, matcher->tbl->dmn);
if (ret < 0)
goto out;
ret = dr_dump_table(fout, matcher->tbl);
if (ret < 0)
goto out;
ret = dr_dump_matcher_all(fout, matcher);
out:
dr_domain_unlock(matcher->tbl->dmn);
pthread_spin_unlock(&matcher->tbl->dmn->debug_lock);
return ret;
}
int mlx5dv_dump_dr_rule(FILE *fout, struct mlx5dv_dr_rule *rule)
{
int ret;
if (!fout || !rule)
return -EINVAL;
pthread_spin_lock(&rule->matcher->tbl->dmn->debug_lock);
dr_domain_lock(rule->matcher->tbl->dmn);
ret = dr_dump_domain(fout, rule->matcher->tbl->dmn);
if (ret < 0)
goto out;
ret = dr_dump_table(fout, rule->matcher->tbl);
if (ret < 0)
goto out;
ret = dr_dump_matcher(fout, rule->matcher);
if (ret < 0)
goto out;
ret = dr_dump_rule(fout, rule);
out:
dr_domain_unlock(rule->matcher->tbl->dmn);
pthread_spin_unlock(&rule->matcher->tbl->dmn->debug_lock);
return ret;
}