From: Oleksandr Kolomeiets <okl-...@napatech.com> Add posibilyty to dump flow in human readable format
Signed-off-by: Oleksandr Kolomeiets <okl-...@napatech.com> --- drivers/net/ntnic/include/flow_api_engine.h | 2 + drivers/net/ntnic/nthw/flow_api/flow_api.c | 17 ++ .../profile_inline/flow_api_hw_db_inline.c | 264 ++++++++++++++++++ .../profile_inline/flow_api_hw_db_inline.h | 3 + .../profile_inline/flow_api_profile_inline.c | 81 ++++++ .../profile_inline/flow_api_profile_inline.h | 6 + drivers/net/ntnic/ntnic_filter/ntnic_filter.c | 29 ++ drivers/net/ntnic/ntnic_mod_reg.h | 11 + 8 files changed, 413 insertions(+) diff --git a/drivers/net/ntnic/include/flow_api_engine.h b/drivers/net/ntnic/include/flow_api_engine.h index e52363f04e..155a9e1fd6 100644 --- a/drivers/net/ntnic/include/flow_api_engine.h +++ b/drivers/net/ntnic/include/flow_api_engine.h @@ -281,6 +281,8 @@ struct flow_handle { struct flow_handle *next; struct flow_handle *prev; + /* Flow specific pointer to application data stored during action creation. */ + void *context; void *user_data; union { diff --git a/drivers/net/ntnic/nthw/flow_api/flow_api.c b/drivers/net/ntnic/nthw/flow_api/flow_api.c index 043e4244fc..7f1e311988 100644 --- a/drivers/net/ntnic/nthw/flow_api/flow_api.c +++ b/drivers/net/ntnic/nthw/flow_api/flow_api.c @@ -1006,6 +1006,22 @@ int flow_nic_set_hasher(struct flow_nic_dev *ndev, int hsh_idx, enum flow_nic_ha return 0; } +static int flow_dev_dump(struct flow_eth_dev *dev, + struct flow_handle *flow, + uint16_t caller_id, + FILE *file, + struct rte_flow_error *error) +{ + const struct profile_inline_ops *profile_inline_ops = get_profile_inline_ops(); + + if (profile_inline_ops == NULL) { + NT_LOG(ERR, FILTER, "%s: profile_inline module uninitialized", __func__); + return -1; + } + + return profile_inline_ops->flow_dev_dump_profile_inline(dev, flow, caller_id, file, error); +} + int flow_nic_set_hasher_fields(struct flow_nic_dev *ndev, int hsh_idx, struct nt_eth_rss_conf rss_conf) { @@ -1031,6 +1047,7 @@ static const struct flow_filter_ops ops = { */ .flow_create = flow_create, .flow_destroy = flow_destroy, + .flow_dev_dump = flow_dev_dump, }; void init_flow_filter(void) diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c index 52f85b65af..b5fee67e67 100644 --- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c +++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.c @@ -372,6 +372,270 @@ void hw_db_inline_deref_idxs(struct flow_nic_dev *ndev, void *db_handle, struct } } +void hw_db_inline_dump(struct flow_nic_dev *ndev, void *db_handle, const struct hw_db_idx *idxs, + uint32_t size, FILE *file) +{ + (void)ndev; + struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle; + char str_buffer[4096]; + uint16_t rss_buffer_len = sizeof(str_buffer); + + for (uint32_t i = 0; i < size; ++i) { + switch (idxs[i].type) { + case HW_DB_IDX_TYPE_NONE: + break; + + case HW_DB_IDX_TYPE_MATCH_SET: { + const struct hw_db_inline_match_set_data *data = + &db->match_set[idxs[i].ids].data; + fprintf(file, " MATCH_SET %d, priority %d\n", idxs[i].ids, + (int)data->priority); + fprintf(file, " CAT id %d, KM id %d, KM_FT id %d, ACTION_SET id %d\n", + data->cat.ids, data->km.id1, data->km_ft.id1, + data->action_set.ids); + + if (data->jump) + fprintf(file, " Jumps to %d\n", data->jump); + + break; + } + + case HW_DB_IDX_TYPE_ACTION_SET: { + const struct hw_db_inline_action_set_data *data = + &db->action_set[idxs[i].ids].data; + fprintf(file, " ACTION_SET %d\n", idxs[i].ids); + + if (data->contains_jump) + fprintf(file, " Jumps to %d\n", data->jump); + + else + fprintf(file, + " COT id %d, QSL id %d, SLC_LR id %d, TPE id %d, HSH id %d\n", + data->cot.ids, data->qsl.ids, data->slc_lr.ids, + data->tpe.ids, data->hsh.ids); + + break; + } + + case HW_DB_IDX_TYPE_CAT: { + const struct hw_db_inline_cat_data *data = &db->cat[idxs[i].ids].data; + fprintf(file, " CAT %d\n", idxs[i].ids); + fprintf(file, " Port msk 0x%02x, VLAN msk 0x%02x\n", + (int)data->mac_port_mask, (int)data->vlan_mask); + fprintf(file, + " Proto msks: Frag 0x%02x, l2 0x%02x, l3 0x%02x, l4 0x%02x, l3t 0x%02x, l4t 0x%02x\n", + (int)data->ptc_mask_frag, (int)data->ptc_mask_l2, + (int)data->ptc_mask_l3, (int)data->ptc_mask_l4, + (int)data->ptc_mask_l3_tunnel, (int)data->ptc_mask_l4_tunnel); + fprintf(file, " IP protocol: pn %u pnt %u\n", data->ip_prot, + data->ip_prot_tunnel); + break; + } + + case HW_DB_IDX_TYPE_QSL: { + const struct hw_db_inline_qsl_data *data = &db->qsl[idxs[i].ids].data; + fprintf(file, " QSL %d\n", idxs[i].ids); + + if (data->discard) { + fprintf(file, " Discard\n"); + break; + } + + if (data->drop) { + fprintf(file, " Drop\n"); + break; + } + + fprintf(file, " Table size %d\n", data->table_size); + + for (uint32_t i = 0; + i < data->table_size && i < HW_DB_INLINE_MAX_QST_PER_QSL; ++i) { + fprintf(file, " %u: Queue %d, TX port %d\n", i, + (data->table[i].queue_en ? (int)data->table[i].queue : -1), + (data->table[i].tx_port_en ? (int)data->table[i].tx_port + : -1)); + } + + break; + } + + case HW_DB_IDX_TYPE_COT: { + const struct hw_db_inline_cot_data *data = &db->cot[idxs[i].ids].data; + fprintf(file, " COT %d\n", idxs[i].ids); + fprintf(file, " Color contrib %d, frag rcp %d\n", + (int)data->matcher_color_contrib, (int)data->frag_rcp); + break; + } + + case HW_DB_IDX_TYPE_SLC_LR: { + const struct hw_db_inline_slc_lr_data *data = + &db->slc_lr[idxs[i].ids].data; + fprintf(file, " SLC_LR %d\n", idxs[i].ids); + fprintf(file, " Enable %u, dyn %u, ofs %u\n", data->head_slice_en, + data->head_slice_dyn, data->head_slice_ofs); + break; + } + + case HW_DB_IDX_TYPE_TPE: { + const struct hw_db_inline_tpe_data *data = &db->tpe[idxs[i].ids].data; + fprintf(file, " TPE %d\n", idxs[i].ids); + fprintf(file, " Insert len %u, new outer %u, calc eth %u\n", + data->insert_len, data->new_outer, + data->calc_eth_type_from_inner_ip); + fprintf(file, " TTL enable %u, dyn %u, ofs %u\n", data->ttl_en, + data->ttl_dyn, data->ttl_ofs); + fprintf(file, + " Len A enable %u, pos dyn %u, pos ofs %u, add dyn %u, add ofs %u, sub dyn %u\n", + data->len_a_en, data->len_a_pos_dyn, data->len_a_pos_ofs, + data->len_a_add_dyn, data->len_a_add_ofs, data->len_a_sub_dyn); + fprintf(file, + " Len B enable %u, pos dyn %u, pos ofs %u, add dyn %u, add ofs %u, sub dyn %u\n", + data->len_b_en, data->len_b_pos_dyn, data->len_b_pos_ofs, + data->len_b_add_dyn, data->len_b_add_ofs, data->len_b_sub_dyn); + fprintf(file, + " Len C enable %u, pos dyn %u, pos ofs %u, add dyn %u, add ofs %u, sub dyn %u\n", + data->len_c_en, data->len_c_pos_dyn, data->len_c_pos_ofs, + data->len_c_add_dyn, data->len_c_add_ofs, data->len_c_sub_dyn); + + for (uint32_t i = 0; i < 6; ++i) + if (data->writer[i].en) + fprintf(file, + " Writer %i: Reader %u, dyn %u, ofs %u, len %u\n", + i, data->writer[i].reader_select, + data->writer[i].dyn, data->writer[i].ofs, + data->writer[i].len); + + break; + } + + case HW_DB_IDX_TYPE_TPE_EXT: { + const struct hw_db_inline_tpe_ext_data *data = + &db->tpe_ext[idxs[i].ids].data; + const int rpl_rpl_length = ((int)data->size + 15) / 16; + fprintf(file, " TPE_EXT %d\n", idxs[i].ids); + fprintf(file, " Encap data, size %u\n", data->size); + + for (int i = 0; i < rpl_rpl_length; ++i) { + fprintf(file, " "); + + for (int n = 15; n >= 0; --n) + fprintf(file, " %02x%s", data->hdr8[i * 16 + n], + n == 8 ? " " : ""); + + fprintf(file, "\n"); + } + + break; + } + + case HW_DB_IDX_TYPE_FLM_RCP: { + const struct hw_db_inline_flm_rcp_data *data = &db->flm[idxs[i].id1].data; + fprintf(file, " FLM_RCP %d\n", idxs[i].id1); + fprintf(file, " QW0 dyn %u, ofs %u, QW4 dyn %u, ofs %u\n", + data->qw0_dyn, data->qw0_ofs, data->qw4_dyn, data->qw4_ofs); + fprintf(file, " SW8 dyn %u, ofs %u, SW9 dyn %u, ofs %u\n", + data->sw8_dyn, data->sw8_ofs, data->sw9_dyn, data->sw9_ofs); + fprintf(file, " Outer prot %u, inner prot %u\n", data->outer_prot, + data->inner_prot); + fprintf(file, " Mask:\n"); + fprintf(file, " %08x %08x %08x %08x %08x\n", data->mask[0], + data->mask[1], data->mask[2], data->mask[3], data->mask[4]); + fprintf(file, " %08x %08x %08x %08x %08x\n", data->mask[5], + data->mask[6], data->mask[7], data->mask[8], data->mask[9]); + break; + } + + case HW_DB_IDX_TYPE_FLM_FT: { + const struct hw_db_inline_flm_ft_data *data = + &db->flm[idxs[i].id2].ft[idxs[i].id1].data; + fprintf(file, " FLM_FT %d\n", idxs[i].id1); + + if (data->is_group_zero) + fprintf(file, " Jump to %d\n", data->jump); + + else + fprintf(file, " Group %d\n", data->group); + + fprintf(file, " ACTION_SET id %d\n", data->action_set.ids); + break; + } + + case HW_DB_IDX_TYPE_KM_RCP: { + const struct hw_db_inline_km_rcp_data *data = &db->km[idxs[i].id1].data; + fprintf(file, " KM_RCP %d\n", idxs[i].id1); + fprintf(file, " HW id %u\n", data->rcp); + break; + } + + case HW_DB_IDX_TYPE_KM_FT: { + const struct hw_db_inline_km_ft_data *data = + &db->km[idxs[i].id2].ft[idxs[i].id1].data; + fprintf(file, " KM_FT %d\n", idxs[i].id1); + fprintf(file, " ACTION_SET id %d\n", data->action_set.ids); + fprintf(file, " KM_RCP id %d\n", data->km.ids); + fprintf(file, " CAT id %d\n", data->cat.ids); + break; + } + + case HW_DB_IDX_TYPE_HSH: { + const struct hw_db_inline_hsh_data *data = &db->hsh[idxs[i].ids].data; + fprintf(file, " HSH %d\n", idxs[i].ids); + + switch (data->func) { + case RTE_ETH_HASH_FUNCTION_DEFAULT: + fprintf(file, " Func: NTH10\n"); + break; + + case RTE_ETH_HASH_FUNCTION_TOEPLITZ: + fprintf(file, " Func: Toeplitz\n"); + fprintf(file, " Key:"); + + for (uint8_t i = 0; i < MAX_RSS_KEY_LEN; i++) { + if (i % 10 == 0) + fprintf(file, "\n "); + + fprintf(file, " %02x", data->key[i]); + } + + fprintf(file, "\n"); + break; + + default: + fprintf(file, " Func: %u\n", data->func); + } + + fprintf(file, " Hash mask hex:\n"); + fprintf(file, " %016lx\n", data->hash_mask); + + /* convert hash mask to human readable RTE_ETH_RSS_* form if possible */ + if (sprint_nt_rss_mask(str_buffer, rss_buffer_len, "\n ", + data->hash_mask) == 0) { + fprintf(file, " Hash mask flags:%s\n", str_buffer); + } + + break; + } + + default: { + fprintf(file, " Unknown item. Type %u\n", idxs[i].type); + break; + } + } + } +} + +void hw_db_inline_dump_cfn(struct flow_nic_dev *ndev, void *db_handle, FILE *file) +{ + (void)ndev; + struct hw_db_inline_resource_db *db = (struct hw_db_inline_resource_db *)db_handle; + + fprintf(file, "CFN status:\n"); + + for (uint32_t id = 0; id < db->nb_cat; ++id) + if (db->cfn[id].cfn_hw) + fprintf(file, " ID %d, HW id %d, priority 0x%" PRIx64 "\n", (int)id, + db->cfn[id].cfn_hw, db->cfn[id].priority); +} const void *hw_db_inline_find_data(struct flow_nic_dev *ndev, void *db_handle, enum hw_db_idx_type type, struct hw_db_idx *idxs, uint32_t size) diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.h b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.h index 33de674b72..a9d31c86ea 100644 --- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.h +++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_hw_db_inline.h @@ -276,6 +276,9 @@ void hw_db_inline_deref_idxs(struct flow_nic_dev *ndev, void *db_handle, struct uint32_t size); const void *hw_db_inline_find_data(struct flow_nic_dev *ndev, void *db_handle, enum hw_db_idx_type type, struct hw_db_idx *idxs, uint32_t size); +void hw_db_inline_dump(struct flow_nic_dev *ndev, void *db_handle, const struct hw_db_idx *idxs, + uint32_t size, FILE *file); +void hw_db_inline_dump_cfn(struct flow_nic_dev *ndev, void *db_handle, FILE *file); /**/ diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c index ac29c59f26..e47ef37c6b 100644 --- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c +++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.c @@ -4301,6 +4301,86 @@ int flow_nic_set_hasher_fields_inline(struct flow_nic_dev *ndev, int hsh_idx, return res; } +static void dump_flm_data(const uint32_t *data, FILE *file) +{ + for (unsigned int i = 0; i < 10; ++i) { + fprintf(file, "%s%02X %02X %02X %02X%s", i % 2 ? "" : " ", + (data[i] >> 24) & 0xff, (data[i] >> 16) & 0xff, (data[i] >> 8) & 0xff, + data[i] & 0xff, i % 2 ? "\n" : " "); + } +} + +int flow_dev_dump_profile_inline(struct flow_eth_dev *dev, + struct flow_handle *flow, + uint16_t caller_id, + FILE *file, + struct rte_flow_error *error) +{ + flow_nic_set_error(ERR_SUCCESS, error); + + pthread_mutex_lock(&dev->ndev->mtx); + + if (flow != NULL) { + if (flow->type == FLOW_HANDLE_TYPE_FLM) { + fprintf(file, "Port %d, caller %d, flow type FLM\n", (int)dev->port_id, + (int)flow->caller_id); + fprintf(file, " FLM_DATA:\n"); + dump_flm_data(flow->flm_data, file); + hw_db_inline_dump(dev->ndev, dev->ndev->hw_db_handle, + (struct hw_db_idx *)flow->flm_db_idxs, + flow->flm_db_idx_counter, file); + fprintf(file, " Context: %p\n", flow->context); + + } else { + fprintf(file, "Port %d, caller %d, flow type FLOW\n", (int)dev->port_id, + (int)flow->caller_id); + hw_db_inline_dump(dev->ndev, dev->ndev->hw_db_handle, + (struct hw_db_idx *)flow->db_idxs, flow->db_idx_counter, + file); + } + + } else { + int max_flm_count = 1000; + + hw_db_inline_dump_cfn(dev->ndev, dev->ndev->hw_db_handle, file); + + flow = dev->ndev->flow_base; + + while (flow) { + if (flow->caller_id == caller_id) { + fprintf(file, "Port %d, caller %d, flow type FLOW\n", + (int)dev->port_id, (int)flow->caller_id); + hw_db_inline_dump(dev->ndev, dev->ndev->hw_db_handle, + (struct hw_db_idx *)flow->db_idxs, + flow->db_idx_counter, file); + } + + flow = flow->next; + } + + flow = dev->ndev->flow_base_flm; + + while (flow && max_flm_count >= 0) { + if (flow->caller_id == caller_id) { + fprintf(file, "Port %d, caller %d, flow type FLM\n", + (int)dev->port_id, (int)flow->caller_id); + fprintf(file, " FLM_DATA:\n"); + dump_flm_data(flow->flm_data, file); + hw_db_inline_dump(dev->ndev, dev->ndev->hw_db_handle, + (struct hw_db_idx *)flow->flm_db_idxs, + flow->flm_db_idx_counter, file); + fprintf(file, " Context: %p\n", flow->context); + max_flm_count -= 1; + } + + flow = flow->next; + } + } + + pthread_mutex_unlock(&dev->ndev->mtx); + + return 0; +} static const struct profile_inline_ops ops = { /* @@ -4309,6 +4389,7 @@ static const struct profile_inline_ops ops = { .done_flow_management_of_ndev_profile_inline = done_flow_management_of_ndev_profile_inline, .initialize_flow_management_of_ndev_profile_inline = initialize_flow_management_of_ndev_profile_inline, + .flow_dev_dump_profile_inline = flow_dev_dump_profile_inline, /* * Flow functionality */ diff --git a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.h b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.h index e623bb2352..2c76a2c023 100644 --- a/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.h +++ b/drivers/net/ntnic/nthw/flow_api/profile_inline/flow_api_profile_inline.h @@ -38,6 +38,12 @@ int flow_destroy_profile_inline(struct flow_eth_dev *dev, struct flow_handle *flow, struct rte_flow_error *error); +int flow_dev_dump_profile_inline(struct flow_eth_dev *dev, + struct flow_handle *flow, + uint16_t caller_id, + FILE *file, + struct rte_flow_error *error); + int flow_nic_set_hasher_fields_inline(struct flow_nic_dev *ndev, int hsh_idx, struct nt_eth_rss_conf rss_conf); diff --git a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c index df391b6399..5505198148 100644 --- a/drivers/net/ntnic/ntnic_filter/ntnic_filter.c +++ b/drivers/net/ntnic/ntnic_filter/ntnic_filter.c @@ -569,9 +569,38 @@ static struct rte_flow *eth_flow_create(struct rte_eth_dev *eth_dev, return flow; } +static int eth_flow_dev_dump(struct rte_eth_dev *eth_dev, + struct rte_flow *flow, + FILE *file, + struct rte_flow_error *error) +{ + const struct flow_filter_ops *flow_filter_ops = get_flow_filter_ops(); + + if (flow_filter_ops == NULL) { + NT_LOG(ERR, NTNIC, "%s: flow_filter module uninitialized", __func__); + return -1; + } + + struct pmd_internals *internals = (struct pmd_internals *)eth_dev->data->dev_private; + + static struct rte_flow_error flow_error = { + .type = RTE_FLOW_ERROR_TYPE_NONE, .message = "none" }; + + uint16_t caller_id = get_caller_id(eth_dev->data->port_id); + + int res = flow_filter_ops->flow_dev_dump(internals->flw_dev, + is_flow_handle_typecast(flow) ? (void *)flow + : flow->flw_hdl, + caller_id, file, &flow_error); + + convert_error(error, &flow_error); + return res; +} + static const struct rte_flow_ops dev_flow_ops = { .create = eth_flow_create, .destroy = eth_flow_destroy, + .dev_dump = eth_flow_dev_dump, }; void dev_flow_init(void) diff --git a/drivers/net/ntnic/ntnic_mod_reg.h b/drivers/net/ntnic/ntnic_mod_reg.h index 27d6cbef01..cef655c5e0 100644 --- a/drivers/net/ntnic/ntnic_mod_reg.h +++ b/drivers/net/ntnic/ntnic_mod_reg.h @@ -253,6 +253,12 @@ struct profile_inline_ops { struct flow_handle *flow, struct rte_flow_error *error); + int (*flow_dev_dump_profile_inline)(struct flow_eth_dev *dev, + struct flow_handle *flow, + uint16_t caller_id, + FILE *file, + struct rte_flow_error *error); + int (*flow_nic_set_hasher_fields_inline)(struct flow_nic_dev *ndev, int hsh_idx, struct nt_eth_rss_conf rss_conf); @@ -284,6 +290,11 @@ struct flow_filter_ops { int *rss_target_id, enum flow_eth_dev_profile flow_profile, uint32_t exception_path); + int (*flow_dev_dump)(struct flow_eth_dev *dev, + struct flow_handle *flow, + uint16_t caller_id, + FILE *file, + struct rte_flow_error *error); /* * NT Flow API */ -- 2.45.0