* [PATCH v1 0/2] add support for flow aging in CNXK driver @ 2023-07-27 11:59 Ankur Dwivedi 2023-07-27 11:59 ` [PATCH v1 1/2] common/cnxk: add support to get aged flows Ankur Dwivedi ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Ankur Dwivedi @ 2023-07-27 11:59 UTC (permalink / raw) To: dev; +Cc: jerinj, ndabilpuram, kirankumark, skori, skoteshwar, Ankur Dwivedi Adds support for flow aging in CNXK driver. This patch series is for DPDK 23.11. Ankur Dwivedi (2): common/cnxk: add support to get aged flows net/cnxk: add get flow aged ops doc/guides/nics/cnxk.rst | 12 + doc/guides/nics/features/cnxk.ini | 1 + doc/guides/nics/features/cnxk_vf.ini | 1 + drivers/common/cnxk/meson.build | 1 + drivers/common/cnxk/roc_mbox.h | 27 +++ drivers/common/cnxk/roc_npc.c | 22 ++ drivers/common/cnxk/roc_npc.h | 28 +++ drivers/common/cnxk/roc_npc_aging.c | 315 +++++++++++++++++++++++++ drivers/common/cnxk/roc_npc_priv.h | 17 ++ drivers/common/cnxk/roc_platform.h | 8 + drivers/common/cnxk/version.map | 1 + drivers/net/cnxk/cnxk_ethdev_devargs.c | 21 +- drivers/net/cnxk/cnxk_flow.c | 45 ++++ 13 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 drivers/common/cnxk/roc_npc_aging.c -- 2.25.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 1/2] common/cnxk: add support to get aged flows 2023-07-27 11:59 [PATCH v1 0/2] add support for flow aging in CNXK driver Ankur Dwivedi @ 2023-07-27 11:59 ` Ankur Dwivedi 2023-07-27 11:59 ` [PATCH v1 2/2] net/cnxk: add get flow aged ops Ankur Dwivedi 2023-08-08 8:49 ` [PATCH v2 0/2] add support for flow aging in CNXK driver Ankur Dwivedi 2 siblings, 0 replies; 9+ messages in thread From: Ankur Dwivedi @ 2023-07-27 11:59 UTC (permalink / raw) To: dev; +Cc: jerinj, ndabilpuram, kirankumark, skori, skoteshwar, Ankur Dwivedi Adds support to get aged flows in CNXK driver. The control thread polls the status of flows having age action, every 10 seconds and updates a bitmap array with the aged flows. The poll frequency of control thread can be set by devargs. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- drivers/common/cnxk/meson.build | 1 + drivers/common/cnxk/roc_mbox.h | 27 +++ drivers/common/cnxk/roc_npc.c | 22 ++ drivers/common/cnxk/roc_npc.h | 28 +++ drivers/common/cnxk/roc_npc_aging.c | 315 ++++++++++++++++++++++++++++ drivers/common/cnxk/roc_npc_priv.h | 17 ++ drivers/common/cnxk/roc_platform.h | 8 + drivers/common/cnxk/version.map | 1 + 8 files changed, 419 insertions(+) create mode 100644 drivers/common/cnxk/roc_npc_aging.c diff --git a/drivers/common/cnxk/meson.build b/drivers/common/cnxk/meson.build index 79e10bac74..d5dfd93e31 100644 --- a/drivers/common/cnxk/meson.build +++ b/drivers/common/cnxk/meson.build @@ -57,6 +57,7 @@ sources = files( 'roc_npa_irq.c', 'roc_npa_type.c', 'roc_npc.c', + 'roc_npc_aging.c', 'roc_npc_mcam.c', 'roc_npc_mcam_dump.c', 'roc_npc_parse.c', diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h index 2f85b2f755..6db46a86f4 100644 --- a/drivers/common/cnxk/roc_mbox.h +++ b/drivers/common/cnxk/roc_mbox.h @@ -227,6 +227,8 @@ struct mbox_msghdr { npc_mcam_get_stats_req, npc_mcam_get_stats_rsp) \ M(NPC_GET_FIELD_HASH_INFO, 0x6013, npc_get_field_hash_info, \ npc_get_field_hash_info_req, npc_get_field_hash_info_rsp) \ + M(NPC_MCAM_GET_HIT_STATUS, 0x6015, npc_mcam_get_hit_status, \ + npc_mcam_get_hit_status_req, npc_mcam_get_hit_status_rsp) \ /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, nix_lf_alloc_req, \ nix_lf_alloc_rsp) \ @@ -2466,6 +2468,31 @@ struct npc_mcam_get_stats_rsp { uint8_t __io stat_ena; /* enabled */ }; +#define MCAM_ARR_SIZE 256 +#define MCAM_ARR_ELEM_SZ 64 + +struct npc_mcam_get_hit_status_req { + struct mbox_msghdr hdr; + /* If clear == true, then if the hit status bit for mcam id is set, + * then needs to cleared by writing 1 back. + * If clear == false, then leave the hit status bit as is. + */ + bool __io clear; + uint8_t __io reserved[3]; + /* Start range of mcam id */ + uint32_t __io range_valid_mcam_ids_start; + /* End range of mcam id */ + uint32_t __io range_valid_mcam_ids_end; + /* Bitmap of mcam ids for which the hit status needs to checked */ + uint64_t __io mcam_ids[MCAM_ARR_SIZE]; +}; + +struct npc_mcam_get_hit_status_rsp { + struct mbox_msghdr hdr; + /* Bitmap of mcam hit status, prior to clearing */ + uint64_t __io mcam_hit_status[MCAM_ARR_SIZE]; +}; + /* TIM mailbox error codes * Range 801 - 900. */ diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c index 848086c8de..f0bb0aa931 100644 --- a/drivers/common/cnxk/roc_npc.c +++ b/drivers/common/cnxk/roc_npc.c @@ -302,6 +302,7 @@ roc_npc_init(struct roc_npc *roc_npc) npc_mem = mem; TAILQ_INIT(&npc->ipsec_list); + TAILQ_INIT(&npc->age_flow_list); for (idx = 0; idx < npc->flow_max_priority; idx++) { TAILQ_INIT(&npc->flow_list[idx]); TAILQ_INIT(&npc->prio_flow_list[idx]); @@ -330,6 +331,9 @@ roc_npc_init(struct roc_npc *roc_npc) */ plt_bitmap_set(npc->rss_grp_entries, 0); + rc = npc_aged_flows_bitmap_alloc(roc_npc); + if (rc != 0) + goto done; return rc; done: @@ -610,6 +614,17 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, flow->mtr_id = act_mtr->mtr_id; req_act |= ROC_NPC_ACTION_TYPE_METER; break; + case ROC_NPC_ACTION_TYPE_AGE: + if (flow->is_validate == true) + break; + plt_seqcount_init(&roc_npc->flow_age.seq_cnt); + errcode = npc_aging_ctrl_thread_create(roc_npc, + actions->conf, + flow); + if (errcode != 0) + goto err_exit; + req_act |= ROC_NPC_ACTION_TYPE_AGE; + break; default: errcode = NPC_ERR_ACTION_NOTSUP; goto err_exit; @@ -1485,6 +1500,9 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, } } TAILQ_INSERT_TAIL(list, flow, next); + + npc_age_flow_list_entry_add(roc_npc, flow); + return flow; set_rss_failed: @@ -1582,6 +1600,10 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) npc_delete_prio_list_entry(npc, flow); + npc_age_flow_list_entry_delete(roc_npc, flow); + if (roc_npc->flow_age.age_flow_refcnt == 0 && roc_npc->flow_age.aged_flows_poll_thread) + npc_aging_ctrl_thread_destroy(roc_npc); + done: plt_free(flow); return 0; diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index 07e6634aa7..8b8a2eb343 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -180,6 +180,7 @@ enum roc_npc_action_type { ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT = (1 << 15), ROC_NPC_ACTION_TYPE_PORT_ID = (1 << 16), ROC_NPC_ACTION_TYPE_METER = (1 << 17), + ROC_NPC_ACTION_TYPE_AGE = (1 << 18), }; struct roc_npc_action { @@ -203,6 +204,13 @@ struct roc_npc_action_port_id { uint32_t id; /**< port ID. */ }; +struct roc_npc_action_age { + uint32_t timeout : 24; /**< Time in seconds. */ + uint32_t reserved : 8; /**< Reserved, must be zero. */ + /** The user flow context, NULL means the rte_flow pointer. */ + void *context; +}; + /** * ESP Header */ @@ -295,6 +303,9 @@ struct roc_npc_flow { uint16_t match_id; uint8_t is_inline_dev; bool use_pre_alloc; + uint64_t timeout_cycles; + void *age_context; + uint32_t timeout; TAILQ_ENTRY(roc_npc_flow) next; }; @@ -327,6 +338,19 @@ enum flow_vtag_cfg_dir { VTAG_TX, VTAG_RX }; #define ROC_ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ #define ROC_ETHER_TYPE_QINQ 0x88A8 /**< IEEE 802.1ad QinQ tagging. */ +struct roc_npc_flow_age { + plt_seqcount_t seq_cnt; + uint32_t aging_poll_freq; + uint32_t age_flow_refcnt; + uint32_t aged_flows_cnt; + uint32_t start_id; + uint32_t end_id; + pthread_t aged_flows_poll_thread; + struct plt_bitmap *aged_flows; + void *age_mem; + bool aged_flows_get_thread_exit; +}; + struct roc_npc { struct roc_nix *roc_nix; uint8_t switch_header_type; @@ -349,11 +373,14 @@ struct roc_npc { bool is_sdp_mask_set; uint16_t sdp_channel; uint16_t sdp_channel_mask; + struct roc_npc_flow_age flow_age; #define ROC_NPC_MEM_SZ (6 * 1024) uint8_t reserved[ROC_NPC_MEM_SZ]; } __plt_cache_aligned; +#define ROC_NPC_AGE_POLL_FREQ_MIN 10 + int __roc_api roc_npc_init(struct roc_npc *roc_npc); int __roc_api roc_npc_fini(struct roc_npc *roc_npc); const char *__roc_api roc_npc_profile_name_get(struct roc_npc *roc_npc); @@ -397,4 +424,5 @@ int __roc_api roc_npc_validate_portid_action(struct roc_npc *roc_npc_src, struct roc_npc *roc_npc_dst); int __roc_api roc_npc_mcam_init(struct roc_npc *roc_npc, struct roc_npc_flow *flow, int mcam_id); int __roc_api roc_npc_mcam_move(struct roc_npc *roc_npc, uint16_t old_ent, uint16_t new_ent); +void *__roc_api roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id); #endif /* _ROC_NPC_H_ */ diff --git a/drivers/common/cnxk/roc_npc_aging.c b/drivers/common/cnxk/roc_npc_aging.c new file mode 100644 index 0000000000..94126fe9fd --- /dev/null +++ b/drivers/common/cnxk/roc_npc_aging.c @@ -0,0 +1,315 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include "roc_api.h" +#include "roc_priv.h" + +int +npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc) +{ + struct roc_npc_flow_age *flow_age; + uint8_t *age_mem = NULL; + uint32_t bmap_sz; + int rc = 0; + + bmap_sz = plt_bitmap_get_memory_footprint(MCAM_ARR_ELEM_SZ * + MCAM_ARR_SIZE); + age_mem = plt_zmalloc(bmap_sz, 0); + if (age_mem == NULL) { + plt_err("Bmap alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + flow_age = &roc_npc->flow_age; + flow_age->age_mem = age_mem; + flow_age->aged_flows = plt_bitmap_init(MCAM_ARR_ELEM_SZ * MCAM_ARR_SIZE, + age_mem, bmap_sz); + if (!flow_age->aged_flows) { + plt_err("Bitmap init failed"); + plt_free(age_mem); + rc = NPC_ERR_NO_MEM; + goto done; + } + + flow_age->age_flow_refcnt = 0; +done: + return rc; +} + +void +npc_aged_flows_bitmap_free(struct roc_npc *roc_npc) +{ + struct roc_npc_flow_age *flow_age; + + flow_age = &roc_npc->flow_age; + plt_bitmap_free(flow_age->aged_flows); + if (flow_age->age_mem) + plt_free(roc_npc->flow_age.age_mem); +} + +static void +check_timeout_cycles(struct roc_npc *roc_npc, uint32_t mcam_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *fl_iter; + struct roc_npc_flow_age *flow_age; + bool aging_enabled = false; + + flow_age = &roc_npc->flow_age; + list = &npc->age_flow_list; + TAILQ_FOREACH(fl_iter, list, next) { + if (fl_iter->flow->mcam_id == mcam_id && + fl_iter->flow->timeout_cycles < rte_get_timer_cycles()) { + /* update bitmap */ + plt_bitmap_set(flow_age->aged_flows, mcam_id); + if (!aging_enabled) { + flow_age->start_id = mcam_id; + flow_age->end_id = mcam_id; + aging_enabled = true; + } + if (flow_age->start_id > mcam_id) + flow_age->start_id = mcam_id; + else if (flow_age->end_id < mcam_id) + flow_age->end_id = mcam_id; + flow_age->aged_flows_cnt += 1; + break; + } + } +} + +static void +update_timeout_cycles(struct roc_npc *roc_npc, uint32_t mcam_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *fl_iter; + + list = &npc->age_flow_list; + TAILQ_FOREACH(fl_iter, list, next) { + if (fl_iter->flow->mcam_id == mcam_id) { + fl_iter->flow->timeout_cycles = rte_get_timer_cycles() + + fl_iter->flow->timeout * rte_get_timer_hz(); + break; + } + } +} + +static int +npc_mcam_get_hit_status(struct npc *npc, uint64_t *mcam_ids, uint16_t start_id, + uint16_t end_id, uint64_t *hit_status, bool clear) +{ + struct npc_mcam_get_hit_status_req *req; + struct npc_mcam_get_hit_status_rsp *rsp; + struct mbox *mbox = mbox_get(npc->mbox); + uint8_t idx_start; + uint8_t idx_end; + int rc; + int i; + + req = mbox_alloc_msg_npc_mcam_get_hit_status(mbox); + if (req == NULL) + return -ENOSPC; + + idx_start = start_id / MCAM_ARR_ELEM_SZ; + idx_end = end_id / MCAM_ARR_ELEM_SZ; + + for (i = idx_start; i <= idx_end; i++) + req->mcam_ids[i] = mcam_ids[i]; + + req->range_valid_mcam_ids_start = start_id; + req->range_valid_mcam_ids_end = end_id; + req->clear = clear; + + rc = mbox_process_msg(mbox, (void *)&rsp); + if (rc) + goto exit; + + for (i = idx_start; i <= idx_end; i++) + hit_status[i] = rsp->mcam_hit_status[i]; + + rc = 0; +exit: + mbox_put(mbox); + return rc; +} + +void * +npc_aged_flows_get(void *args) +{ + uint64_t hit_status[MCAM_ARR_SIZE] = {0}; + uint64_t mcam_ids[MCAM_ARR_SIZE] = {0}; + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *fl_iter; + struct roc_npc *roc_npc = args; + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct roc_npc_flow_age *flow_age; + bool aging_enabled; + uint32_t start_id; + uint32_t end_id; + uint32_t mcam_id; + uint32_t idx; + uint32_t i; + int rc; + + flow_age = &roc_npc->flow_age; + list = &npc->age_flow_list; + while (!flow_age->aged_flows_get_thread_exit) { + start_id = 0; + end_id = 0; + aging_enabled = false; + memset(mcam_ids, 0, sizeof(mcam_ids)); + TAILQ_FOREACH(fl_iter, list, next) { + mcam_id = fl_iter->flow->mcam_id; + idx = mcam_id / MCAM_ARR_ELEM_SZ; + mcam_ids[idx] |= BIT_ULL(mcam_id % MCAM_ARR_ELEM_SZ); + + if (!aging_enabled) { + start_id = mcam_id; + end_id = mcam_id; + aging_enabled = true; + } + + if (mcam_id < start_id) + start_id = mcam_id; + else if (mcam_id > end_id) + end_id = mcam_id; + } + + if (!aging_enabled) + goto lbl_sleep; + + rc = npc_mcam_get_hit_status(npc, mcam_ids, start_id, end_id, + hit_status, true); + if (rc) + return NULL; + + plt_seqcount_write_begin(&flow_age->seq_cnt); + flow_age->aged_flows_cnt = 0; + for (i = start_id; i <= end_id; i++) { + idx = i / MCAM_ARR_ELEM_SZ; + if (mcam_ids[idx] & BIT_ULL(i % MCAM_ARR_ELEM_SZ)) { + if (!(hit_status[idx] & BIT_ULL(i % MCAM_ARR_ELEM_SZ))) + check_timeout_cycles(roc_npc, i); + else + update_timeout_cycles(roc_npc, i); + } + } + plt_seqcount_write_end(&flow_age->seq_cnt); + +lbl_sleep: + sleep(flow_age->aging_poll_freq); + } + + return NULL; +} + +void +npc_age_flow_list_entry_add(struct roc_npc *roc_npc, struct roc_npc_flow *flow) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_entry *age_fl_iter; + struct npc_age_flow_entry *new_entry; + + new_entry = plt_zmalloc(sizeof(*new_entry), 0); + new_entry->flow = flow; + roc_npc->flow_age.age_flow_refcnt++; + /* List in ascending order of mcam entries */ + TAILQ_FOREACH(age_fl_iter, &npc->age_flow_list, next) { + if (age_fl_iter->flow->mcam_id > flow->mcam_id) { + TAILQ_INSERT_BEFORE(age_fl_iter, new_entry, next); + return; + } + } + TAILQ_INSERT_TAIL(&npc->age_flow_list, new_entry, next); +} + +void +npc_age_flow_list_entry_delete(struct roc_npc *roc_npc, + struct roc_npc_flow *flow) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *curr; + + list = &npc->age_flow_list; + curr = TAILQ_FIRST(list); + + if (!curr) + return; + + while (curr) { + if (flow->mcam_id == curr->flow->mcam_id) { + TAILQ_REMOVE(list, curr, next); + plt_free(curr); + break; + } + curr = TAILQ_NEXT(curr, next); + } + roc_npc->flow_age.age_flow_refcnt--; +} + +int +npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, + const struct roc_npc_action_age *age, + struct roc_npc_flow *flow) +{ + struct roc_npc_flow_age *flow_age; + int errcode = 0; + + flow_age = &roc_npc->flow_age; + if (age->timeout < flow_age->aging_poll_freq) { + plt_err("Age timeout should be greater or equal to %u seconds", + flow_age->aging_poll_freq); + errcode = NPC_ERR_ACTION_NOTSUP; + goto done; + } + + flow->age_context = age->context == NULL ? flow : age->context; + flow->timeout = age->timeout; + flow->timeout_cycles = rte_get_timer_cycles() + age->timeout * + rte_get_timer_hz(); + + if (flow_age->age_flow_refcnt == 0) { + flow_age->aged_flows_get_thread_exit = false; + if (plt_ctrl_thread_create(&flow_age->aged_flows_poll_thread, + "Aged Flows Get Ctrl Thread", NULL, + npc_aged_flows_get, roc_npc) != 0) { + plt_err("Failed to create thread for age flows"); + errcode = NPC_ERR_ACTION_NOTSUP; + goto done; + } + } +done: + return errcode; +} + +void +npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc) +{ + struct roc_npc_flow_age *flow_age; + + flow_age = &roc_npc->flow_age; + flow_age->aged_flows_get_thread_exit = true; + pthread_join(flow_age->aged_flows_poll_thread, NULL); + npc_aged_flows_bitmap_free(roc_npc); +} + +void * +roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *fl_iter; + + list = &npc->age_flow_list; + + TAILQ_FOREACH(fl_iter, list, next) { + if (fl_iter->flow->mcam_id == mcam_id) + return fl_iter->flow->age_context; + } + + return NULL; +} diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h index 593dca353b..6d6cb64c65 100644 --- a/drivers/common/cnxk/roc_npc_priv.h +++ b/drivers/common/cnxk/roc_npc_priv.h @@ -378,6 +378,13 @@ struct npc_prio_flow_entry { TAILQ_HEAD(npc_prio_flow_list_head, npc_prio_flow_entry); +struct npc_age_flow_entry { + struct roc_npc_flow *flow; + TAILQ_ENTRY(npc_age_flow_entry) next; +}; + +TAILQ_HEAD(npc_age_flow_list_head, npc_age_flow_entry); + struct npc { struct mbox *mbox; /* Mbox */ uint32_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */ @@ -403,6 +410,7 @@ struct npc { npc_ld_flags_t prx_lfcfg; /* KEX LD_Flags CFG */ struct npc_flow_list *flow_list; struct npc_prio_flow_list_head *prio_flow_list; + struct npc_age_flow_list_head age_flow_list; struct plt_bitmap *rss_grp_entries; struct npc_flow_list ipsec_list; uint8_t exact_match_ena; @@ -480,4 +488,13 @@ int npc_rss_action_program(struct roc_npc *roc_npc, const struct roc_npc_action int npc_rss_group_free(struct npc *npc, struct roc_npc_flow *flow); int npc_mcam_init(struct npc *npc, struct roc_npc_flow *flow, int mcam_id); int npc_mcam_move(struct mbox *mbox, uint16_t old_ent, uint16_t new_ent); +void npc_age_flow_list_entry_add(struct roc_npc *npc, struct roc_npc_flow *flow); +void npc_age_flow_list_entry_delete(struct roc_npc *npc, struct roc_npc_flow *flow); +void *npc_aged_flows_get(void *args); +int npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc); +void npc_aged_flows_bitmap_free(struct roc_npc *roc_npc); +int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, + const struct roc_npc_action_age *age, + struct roc_npc_flow *flow); +void npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc); #endif /* _ROC_NPC_PRIV_H_ */ diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h index 9884398a99..e7a6564163 100644 --- a/drivers/common/cnxk/roc_platform.h +++ b/drivers/common/cnxk/roc_platform.h @@ -20,6 +20,7 @@ #include <rte_malloc.h> #include <rte_memzone.h> #include <rte_pci.h> +#include <rte_seqcount.h> #include <rte_spinlock.h> #include <rte_string_fns.h> #include <rte_tailq.h> @@ -130,6 +131,13 @@ #define plt_spinlock_unlock rte_spinlock_unlock #define plt_spinlock_trylock rte_spinlock_trylock +#define plt_seqcount_t rte_seqcount_t +#define plt_seqcount_init rte_seqcount_init +#define plt_seqcount_read_begin rte_seqcount_read_begin +#define plt_seqcount_read_retry rte_seqcount_read_retry +#define plt_seqcount_write_begin rte_seqcount_write_begin +#define plt_seqcount_write_end rte_seqcount_write_end + #define plt_intr_callback_register rte_intr_callback_register #define plt_intr_callback_unregister rte_intr_callback_unregister #define plt_intr_disable rte_intr_disable diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map index 8c71497df8..28f0f55934 100644 --- a/drivers/common/cnxk/version.map +++ b/drivers/common/cnxk/version.map @@ -425,6 +425,7 @@ INTERNAL { roc_npa_pool_op_range_set; roc_npa_pool_range_update_check; roc_npa_zero_aura_handle; + roc_npc_aged_flow_ctx_get; roc_npc_fini; roc_npc_flow_create; roc_npc_flow_destroy; -- 2.25.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 2/2] net/cnxk: add get flow aged ops 2023-07-27 11:59 [PATCH v1 0/2] add support for flow aging in CNXK driver Ankur Dwivedi 2023-07-27 11:59 ` [PATCH v1 1/2] common/cnxk: add support to get aged flows Ankur Dwivedi @ 2023-07-27 11:59 ` Ankur Dwivedi 2023-08-08 8:49 ` [PATCH v2 0/2] add support for flow aging in CNXK driver Ankur Dwivedi 2 siblings, 0 replies; 9+ messages in thread From: Ankur Dwivedi @ 2023-07-27 11:59 UTC (permalink / raw) To: dev; +Cc: jerinj, ndabilpuram, kirankumark, skori, skoteshwar, Ankur Dwivedi Adds get flow aged ops in CNXK driver. Also adds the devargs to get the poll frequency of control thread. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- doc/guides/nics/cnxk.rst | 12 +++++++ doc/guides/nics/features/cnxk.ini | 1 + doc/guides/nics/features/cnxk_vf.ini | 1 + drivers/net/cnxk/cnxk_ethdev_devargs.c | 21 +++++++++++- drivers/net/cnxk/cnxk_flow.c | 45 ++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/cnxk.rst b/doc/guides/nics/cnxk.rst index 9229056f6f..dc71ab7fc3 100644 --- a/doc/guides/nics/cnxk.rst +++ b/doc/guides/nics/cnxk.rst @@ -581,6 +581,18 @@ Runtime Config Options for inline device With the above configuration, driver would poll for soft expiry events every 1000 usec. +- ``NPC MCAM Aging poll frequency in seconds`` (default ``10``) + + Poll frequency for aging control thread can be specified by + ``aging_poll_freq`` ``devargs`` parameter. + + For example:: + + -a 0002:01:00.2,aging_poll_freq=50 + + With the above configuration, driver would poll for aging flows every 50 + seconds. + Debugging Options ----------------- diff --git a/doc/guides/nics/features/cnxk.ini b/doc/guides/nics/features/cnxk.ini index 838e781d6d..ebedbd0588 100644 --- a/doc/guides/nics/features/cnxk.ini +++ b/doc/guides/nics/features/cnxk.ini @@ -80,6 +80,7 @@ vxlan = Y vxlan_gpe = Y [rte_flow actions] +age = Y count = Y drop = Y flag = Y diff --git a/doc/guides/nics/features/cnxk_vf.ini b/doc/guides/nics/features/cnxk_vf.ini index 470c45ce59..0e9ad94382 100644 --- a/doc/guides/nics/features/cnxk_vf.ini +++ b/doc/guides/nics/features/cnxk_vf.ini @@ -71,6 +71,7 @@ vxlan = Y vxlan_gpe = Y [rte_flow actions] +age = Y count = Y drop = Y flag = Y diff --git a/drivers/net/cnxk/cnxk_ethdev_devargs.c b/drivers/net/cnxk/cnxk_ethdev_devargs.c index e1a0845ece..8e862be933 100644 --- a/drivers/net/cnxk/cnxk_ethdev_devargs.c +++ b/drivers/net/cnxk/cnxk_ethdev_devargs.c @@ -245,6 +245,19 @@ parse_sdp_channel_mask(const char *key, const char *value, void *extra_args) return 0; } +static int +parse_val_u16(const char *key, const char *value, void *extra_args) +{ + RTE_SET_USED(key); + uint16_t val; + + val = atoi(value); + + *(uint16_t *)extra_args = val; + + return 0; +} + #define CNXK_RSS_RETA_SIZE "reta_size" #define CNXK_SCL_ENABLE "scalar_enable" #define CNXK_TX_COMPL_ENA "tx_compl_ena" @@ -265,10 +278,12 @@ parse_sdp_channel_mask(const char *key, const char *value, void *extra_args) #define CNXK_CUSTOM_SA_ACT "custom_sa_act" #define CNXK_SQB_SLACK "sqb_slack" #define CNXK_NIX_META_BUF_SZ "meta_buf_sz" +#define CNXK_FLOW_AGING_POLL_FREQ "aging_poll_freq" int cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev) { + uint16_t aging_thread_poll_freq = ROC_NPC_AGE_POLL_FREQ_MIN; uint16_t reta_sz = ROC_NIX_RSS_RETA_SZ_64; uint16_t sqb_count = CNXK_NIX_TX_MAX_SQB; struct flow_pre_l2_size_info pre_l2_info; @@ -338,6 +353,8 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev) rte_kvargs_process(kvlist, CNXK_SQB_SLACK, &parse_sqb_count, &sqb_slack); rte_kvargs_process(kvlist, CNXK_NIX_META_BUF_SZ, &parse_meta_bufsize, &meta_buf_sz); + rte_kvargs_process(kvlist, CNXK_FLOW_AGING_POLL_FREQ, &parse_val_u16, + &aging_thread_poll_freq); rte_kvargs_free(kvlist); null_devargs: @@ -369,6 +386,7 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev) dev->npc.pre_l2_size_offset = pre_l2_info.pre_l2_size_off; dev->npc.pre_l2_size_offset_mask = pre_l2_info.pre_l2_size_off_mask; dev->npc.pre_l2_size_shift_dir = pre_l2_info.pre_l2_size_shift_dir; + dev->npc.flow_age.aging_poll_freq = aging_thread_poll_freq; return 0; exit: return -EINVAL; @@ -390,4 +408,5 @@ RTE_PMD_REGISTER_PARAM_STRING(net_cnxk, CNXK_NO_INL_DEV "=0" CNXK_SDP_CHANNEL_MASK "=<1-4095>/<1-4095>" CNXK_CUSTOM_SA_ACT "=1" - CNXK_SQB_SLACK "=<12-512>"); + CNXK_SQB_SLACK "=<12-512>" + CNXK_FLOW_AGING_POLL_FREQ "=<10-65535>"); diff --git a/drivers/net/cnxk/cnxk_flow.c b/drivers/net/cnxk/cnxk_flow.c index 3b8348ae9c..9d69dd90e3 100644 --- a/drivers/net/cnxk/cnxk_flow.c +++ b/drivers/net/cnxk/cnxk_flow.c @@ -230,6 +230,10 @@ cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr, in_actions[i].type = ROC_NPC_ACTION_TYPE_METER; in_actions[i].conf = actions->conf; break; + case RTE_FLOW_ACTION_TYPE_AGE: + in_actions[i].type = ROC_NPC_ACTION_TYPE_AGE; + in_actions[i].conf = actions->conf; + break; default: plt_npc_dbg("Action is not supported = %d", actions->type); @@ -480,10 +484,51 @@ cnxk_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow, return 0; } +static int +cnxk_flow_get_aged_flows(struct rte_eth_dev *eth_dev, void **context, + uint32_t nb_contexts, struct rte_flow_error *err) +{ + struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); + struct roc_npc *roc_npc = &dev->npc; + struct roc_npc_flow_age *flow_age; + uint32_t start_id; + uint32_t end_id; + int cnt = 0; + uint32_t sn; + uint32_t i; + + RTE_SET_USED(err); + + flow_age = &roc_npc->flow_age; + + do { + sn = plt_seqcount_read_begin(&flow_age->seq_cnt); + + if (nb_contexts == 0) + cnt = flow_age->aged_flows_cnt; + else { + start_id = flow_age->start_id; + end_id = flow_age->end_id; + for (i = start_id; i <= end_id; i++) { + if ((int)nb_contexts == cnt) + break; + if (plt_bitmap_get(flow_age->aged_flows, i)) { + context[cnt] = + roc_npc_aged_flow_ctx_get(roc_npc, i); + cnt++; + } + } + } + } while (plt_seqcount_read_retry(&flow_age->seq_cnt, sn)); + + return cnt; +} + struct rte_flow_ops cnxk_flow_ops = { .validate = cnxk_flow_validate, .flush = cnxk_flow_flush, .query = cnxk_flow_query, .isolate = cnxk_flow_isolate, .dev_dump = cnxk_flow_dev_dump, + .get_aged_flows = cnxk_flow_get_aged_flows, }; -- 2.25.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 0/2] add support for flow aging in CNXK driver 2023-07-27 11:59 [PATCH v1 0/2] add support for flow aging in CNXK driver Ankur Dwivedi 2023-07-27 11:59 ` [PATCH v1 1/2] common/cnxk: add support to get aged flows Ankur Dwivedi 2023-07-27 11:59 ` [PATCH v1 2/2] net/cnxk: add get flow aged ops Ankur Dwivedi @ 2023-08-08 8:49 ` Ankur Dwivedi 2023-08-08 8:49 ` [PATCH v2 1/2] common/cnxk: add support to get aged flows Ankur Dwivedi 2023-08-08 8:49 ` [PATCH v2 2/2] net/cnxk: add get flow aged ops Ankur Dwivedi 2 siblings, 2 replies; 9+ messages in thread From: Ankur Dwivedi @ 2023-08-08 8:49 UTC (permalink / raw) To: dev; +Cc: jerinj, ndabilpuram, kirankumark, skori, skoteshwar, Ankur Dwivedi Adds support for flow aging in CNXK driver. v2: - Resolved checkpatch warning in patch (2/2) net/cnxk: add get flow aged ops. Ankur Dwivedi (2): common/cnxk: add support to get aged flows net/cnxk: add get flow aged ops doc/guides/nics/cnxk.rst | 12 + doc/guides/nics/features/cnxk.ini | 1 + doc/guides/nics/features/cnxk_vf.ini | 1 + drivers/common/cnxk/meson.build | 1 + drivers/common/cnxk/roc_mbox.h | 27 +++ drivers/common/cnxk/roc_npc.c | 22 ++ drivers/common/cnxk/roc_npc.h | 28 +++ drivers/common/cnxk/roc_npc_aging.c | 315 +++++++++++++++++++++++++ drivers/common/cnxk/roc_npc_priv.h | 17 ++ drivers/common/cnxk/roc_platform.h | 8 + drivers/common/cnxk/version.map | 1 + drivers/net/cnxk/cnxk_ethdev_devargs.c | 21 +- drivers/net/cnxk/cnxk_flow.c | 45 ++++ 13 files changed, 498 insertions(+), 1 deletion(-) create mode 100644 drivers/common/cnxk/roc_npc_aging.c -- 2.25.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/2] common/cnxk: add support to get aged flows 2023-08-08 8:49 ` [PATCH v2 0/2] add support for flow aging in CNXK driver Ankur Dwivedi @ 2023-08-08 8:49 ` Ankur Dwivedi 2023-08-14 6:56 ` Jerin Jacob 2023-08-08 8:49 ` [PATCH v2 2/2] net/cnxk: add get flow aged ops Ankur Dwivedi 1 sibling, 1 reply; 9+ messages in thread From: Ankur Dwivedi @ 2023-08-08 8:49 UTC (permalink / raw) To: dev; +Cc: jerinj, ndabilpuram, kirankumark, skori, skoteshwar, Ankur Dwivedi Adds support to get aged flows in CNXK driver. The control thread polls the status of flows having age action, every 10 seconds and updates a bitmap array with the aged flows. The poll frequency of control thread can be set by devargs. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- drivers/common/cnxk/meson.build | 1 + drivers/common/cnxk/roc_mbox.h | 27 +++ drivers/common/cnxk/roc_npc.c | 22 ++ drivers/common/cnxk/roc_npc.h | 28 +++ drivers/common/cnxk/roc_npc_aging.c | 315 ++++++++++++++++++++++++++++ drivers/common/cnxk/roc_npc_priv.h | 17 ++ drivers/common/cnxk/roc_platform.h | 8 + drivers/common/cnxk/version.map | 1 + 8 files changed, 419 insertions(+) create mode 100644 drivers/common/cnxk/roc_npc_aging.c diff --git a/drivers/common/cnxk/meson.build b/drivers/common/cnxk/meson.build index 79e10bac74..d5dfd93e31 100644 --- a/drivers/common/cnxk/meson.build +++ b/drivers/common/cnxk/meson.build @@ -57,6 +57,7 @@ sources = files( 'roc_npa_irq.c', 'roc_npa_type.c', 'roc_npc.c', + 'roc_npc_aging.c', 'roc_npc_mcam.c', 'roc_npc_mcam_dump.c', 'roc_npc_parse.c', diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h index 2f85b2f755..6db46a86f4 100644 --- a/drivers/common/cnxk/roc_mbox.h +++ b/drivers/common/cnxk/roc_mbox.h @@ -227,6 +227,8 @@ struct mbox_msghdr { npc_mcam_get_stats_req, npc_mcam_get_stats_rsp) \ M(NPC_GET_FIELD_HASH_INFO, 0x6013, npc_get_field_hash_info, \ npc_get_field_hash_info_req, npc_get_field_hash_info_rsp) \ + M(NPC_MCAM_GET_HIT_STATUS, 0x6015, npc_mcam_get_hit_status, \ + npc_mcam_get_hit_status_req, npc_mcam_get_hit_status_rsp) \ /* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \ M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, nix_lf_alloc_req, \ nix_lf_alloc_rsp) \ @@ -2466,6 +2468,31 @@ struct npc_mcam_get_stats_rsp { uint8_t __io stat_ena; /* enabled */ }; +#define MCAM_ARR_SIZE 256 +#define MCAM_ARR_ELEM_SZ 64 + +struct npc_mcam_get_hit_status_req { + struct mbox_msghdr hdr; + /* If clear == true, then if the hit status bit for mcam id is set, + * then needs to cleared by writing 1 back. + * If clear == false, then leave the hit status bit as is. + */ + bool __io clear; + uint8_t __io reserved[3]; + /* Start range of mcam id */ + uint32_t __io range_valid_mcam_ids_start; + /* End range of mcam id */ + uint32_t __io range_valid_mcam_ids_end; + /* Bitmap of mcam ids for which the hit status needs to checked */ + uint64_t __io mcam_ids[MCAM_ARR_SIZE]; +}; + +struct npc_mcam_get_hit_status_rsp { + struct mbox_msghdr hdr; + /* Bitmap of mcam hit status, prior to clearing */ + uint64_t __io mcam_hit_status[MCAM_ARR_SIZE]; +}; + /* TIM mailbox error codes * Range 801 - 900. */ diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c index 848086c8de..f0bb0aa931 100644 --- a/drivers/common/cnxk/roc_npc.c +++ b/drivers/common/cnxk/roc_npc.c @@ -302,6 +302,7 @@ roc_npc_init(struct roc_npc *roc_npc) npc_mem = mem; TAILQ_INIT(&npc->ipsec_list); + TAILQ_INIT(&npc->age_flow_list); for (idx = 0; idx < npc->flow_max_priority; idx++) { TAILQ_INIT(&npc->flow_list[idx]); TAILQ_INIT(&npc->prio_flow_list[idx]); @@ -330,6 +331,9 @@ roc_npc_init(struct roc_npc *roc_npc) */ plt_bitmap_set(npc->rss_grp_entries, 0); + rc = npc_aged_flows_bitmap_alloc(roc_npc); + if (rc != 0) + goto done; return rc; done: @@ -610,6 +614,17 @@ npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, flow->mtr_id = act_mtr->mtr_id; req_act |= ROC_NPC_ACTION_TYPE_METER; break; + case ROC_NPC_ACTION_TYPE_AGE: + if (flow->is_validate == true) + break; + plt_seqcount_init(&roc_npc->flow_age.seq_cnt); + errcode = npc_aging_ctrl_thread_create(roc_npc, + actions->conf, + flow); + if (errcode != 0) + goto err_exit; + req_act |= ROC_NPC_ACTION_TYPE_AGE; + break; default: errcode = NPC_ERR_ACTION_NOTSUP; goto err_exit; @@ -1485,6 +1500,9 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, } } TAILQ_INSERT_TAIL(list, flow, next); + + npc_age_flow_list_entry_add(roc_npc, flow); + return flow; set_rss_failed: @@ -1582,6 +1600,10 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) npc_delete_prio_list_entry(npc, flow); + npc_age_flow_list_entry_delete(roc_npc, flow); + if (roc_npc->flow_age.age_flow_refcnt == 0 && roc_npc->flow_age.aged_flows_poll_thread) + npc_aging_ctrl_thread_destroy(roc_npc); + done: plt_free(flow); return 0; diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index 07e6634aa7..8b8a2eb343 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -180,6 +180,7 @@ enum roc_npc_action_type { ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT = (1 << 15), ROC_NPC_ACTION_TYPE_PORT_ID = (1 << 16), ROC_NPC_ACTION_TYPE_METER = (1 << 17), + ROC_NPC_ACTION_TYPE_AGE = (1 << 18), }; struct roc_npc_action { @@ -203,6 +204,13 @@ struct roc_npc_action_port_id { uint32_t id; /**< port ID. */ }; +struct roc_npc_action_age { + uint32_t timeout : 24; /**< Time in seconds. */ + uint32_t reserved : 8; /**< Reserved, must be zero. */ + /** The user flow context, NULL means the rte_flow pointer. */ + void *context; +}; + /** * ESP Header */ @@ -295,6 +303,9 @@ struct roc_npc_flow { uint16_t match_id; uint8_t is_inline_dev; bool use_pre_alloc; + uint64_t timeout_cycles; + void *age_context; + uint32_t timeout; TAILQ_ENTRY(roc_npc_flow) next; }; @@ -327,6 +338,19 @@ enum flow_vtag_cfg_dir { VTAG_TX, VTAG_RX }; #define ROC_ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ #define ROC_ETHER_TYPE_QINQ 0x88A8 /**< IEEE 802.1ad QinQ tagging. */ +struct roc_npc_flow_age { + plt_seqcount_t seq_cnt; + uint32_t aging_poll_freq; + uint32_t age_flow_refcnt; + uint32_t aged_flows_cnt; + uint32_t start_id; + uint32_t end_id; + pthread_t aged_flows_poll_thread; + struct plt_bitmap *aged_flows; + void *age_mem; + bool aged_flows_get_thread_exit; +}; + struct roc_npc { struct roc_nix *roc_nix; uint8_t switch_header_type; @@ -349,11 +373,14 @@ struct roc_npc { bool is_sdp_mask_set; uint16_t sdp_channel; uint16_t sdp_channel_mask; + struct roc_npc_flow_age flow_age; #define ROC_NPC_MEM_SZ (6 * 1024) uint8_t reserved[ROC_NPC_MEM_SZ]; } __plt_cache_aligned; +#define ROC_NPC_AGE_POLL_FREQ_MIN 10 + int __roc_api roc_npc_init(struct roc_npc *roc_npc); int __roc_api roc_npc_fini(struct roc_npc *roc_npc); const char *__roc_api roc_npc_profile_name_get(struct roc_npc *roc_npc); @@ -397,4 +424,5 @@ int __roc_api roc_npc_validate_portid_action(struct roc_npc *roc_npc_src, struct roc_npc *roc_npc_dst); int __roc_api roc_npc_mcam_init(struct roc_npc *roc_npc, struct roc_npc_flow *flow, int mcam_id); int __roc_api roc_npc_mcam_move(struct roc_npc *roc_npc, uint16_t old_ent, uint16_t new_ent); +void *__roc_api roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id); #endif /* _ROC_NPC_H_ */ diff --git a/drivers/common/cnxk/roc_npc_aging.c b/drivers/common/cnxk/roc_npc_aging.c new file mode 100644 index 0000000000..94126fe9fd --- /dev/null +++ b/drivers/common/cnxk/roc_npc_aging.c @@ -0,0 +1,315 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2023 Marvell. + */ + +#include "roc_api.h" +#include "roc_priv.h" + +int +npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc) +{ + struct roc_npc_flow_age *flow_age; + uint8_t *age_mem = NULL; + uint32_t bmap_sz; + int rc = 0; + + bmap_sz = plt_bitmap_get_memory_footprint(MCAM_ARR_ELEM_SZ * + MCAM_ARR_SIZE); + age_mem = plt_zmalloc(bmap_sz, 0); + if (age_mem == NULL) { + plt_err("Bmap alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + flow_age = &roc_npc->flow_age; + flow_age->age_mem = age_mem; + flow_age->aged_flows = plt_bitmap_init(MCAM_ARR_ELEM_SZ * MCAM_ARR_SIZE, + age_mem, bmap_sz); + if (!flow_age->aged_flows) { + plt_err("Bitmap init failed"); + plt_free(age_mem); + rc = NPC_ERR_NO_MEM; + goto done; + } + + flow_age->age_flow_refcnt = 0; +done: + return rc; +} + +void +npc_aged_flows_bitmap_free(struct roc_npc *roc_npc) +{ + struct roc_npc_flow_age *flow_age; + + flow_age = &roc_npc->flow_age; + plt_bitmap_free(flow_age->aged_flows); + if (flow_age->age_mem) + plt_free(roc_npc->flow_age.age_mem); +} + +static void +check_timeout_cycles(struct roc_npc *roc_npc, uint32_t mcam_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *fl_iter; + struct roc_npc_flow_age *flow_age; + bool aging_enabled = false; + + flow_age = &roc_npc->flow_age; + list = &npc->age_flow_list; + TAILQ_FOREACH(fl_iter, list, next) { + if (fl_iter->flow->mcam_id == mcam_id && + fl_iter->flow->timeout_cycles < rte_get_timer_cycles()) { + /* update bitmap */ + plt_bitmap_set(flow_age->aged_flows, mcam_id); + if (!aging_enabled) { + flow_age->start_id = mcam_id; + flow_age->end_id = mcam_id; + aging_enabled = true; + } + if (flow_age->start_id > mcam_id) + flow_age->start_id = mcam_id; + else if (flow_age->end_id < mcam_id) + flow_age->end_id = mcam_id; + flow_age->aged_flows_cnt += 1; + break; + } + } +} + +static void +update_timeout_cycles(struct roc_npc *roc_npc, uint32_t mcam_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *fl_iter; + + list = &npc->age_flow_list; + TAILQ_FOREACH(fl_iter, list, next) { + if (fl_iter->flow->mcam_id == mcam_id) { + fl_iter->flow->timeout_cycles = rte_get_timer_cycles() + + fl_iter->flow->timeout * rte_get_timer_hz(); + break; + } + } +} + +static int +npc_mcam_get_hit_status(struct npc *npc, uint64_t *mcam_ids, uint16_t start_id, + uint16_t end_id, uint64_t *hit_status, bool clear) +{ + struct npc_mcam_get_hit_status_req *req; + struct npc_mcam_get_hit_status_rsp *rsp; + struct mbox *mbox = mbox_get(npc->mbox); + uint8_t idx_start; + uint8_t idx_end; + int rc; + int i; + + req = mbox_alloc_msg_npc_mcam_get_hit_status(mbox); + if (req == NULL) + return -ENOSPC; + + idx_start = start_id / MCAM_ARR_ELEM_SZ; + idx_end = end_id / MCAM_ARR_ELEM_SZ; + + for (i = idx_start; i <= idx_end; i++) + req->mcam_ids[i] = mcam_ids[i]; + + req->range_valid_mcam_ids_start = start_id; + req->range_valid_mcam_ids_end = end_id; + req->clear = clear; + + rc = mbox_process_msg(mbox, (void *)&rsp); + if (rc) + goto exit; + + for (i = idx_start; i <= idx_end; i++) + hit_status[i] = rsp->mcam_hit_status[i]; + + rc = 0; +exit: + mbox_put(mbox); + return rc; +} + +void * +npc_aged_flows_get(void *args) +{ + uint64_t hit_status[MCAM_ARR_SIZE] = {0}; + uint64_t mcam_ids[MCAM_ARR_SIZE] = {0}; + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *fl_iter; + struct roc_npc *roc_npc = args; + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct roc_npc_flow_age *flow_age; + bool aging_enabled; + uint32_t start_id; + uint32_t end_id; + uint32_t mcam_id; + uint32_t idx; + uint32_t i; + int rc; + + flow_age = &roc_npc->flow_age; + list = &npc->age_flow_list; + while (!flow_age->aged_flows_get_thread_exit) { + start_id = 0; + end_id = 0; + aging_enabled = false; + memset(mcam_ids, 0, sizeof(mcam_ids)); + TAILQ_FOREACH(fl_iter, list, next) { + mcam_id = fl_iter->flow->mcam_id; + idx = mcam_id / MCAM_ARR_ELEM_SZ; + mcam_ids[idx] |= BIT_ULL(mcam_id % MCAM_ARR_ELEM_SZ); + + if (!aging_enabled) { + start_id = mcam_id; + end_id = mcam_id; + aging_enabled = true; + } + + if (mcam_id < start_id) + start_id = mcam_id; + else if (mcam_id > end_id) + end_id = mcam_id; + } + + if (!aging_enabled) + goto lbl_sleep; + + rc = npc_mcam_get_hit_status(npc, mcam_ids, start_id, end_id, + hit_status, true); + if (rc) + return NULL; + + plt_seqcount_write_begin(&flow_age->seq_cnt); + flow_age->aged_flows_cnt = 0; + for (i = start_id; i <= end_id; i++) { + idx = i / MCAM_ARR_ELEM_SZ; + if (mcam_ids[idx] & BIT_ULL(i % MCAM_ARR_ELEM_SZ)) { + if (!(hit_status[idx] & BIT_ULL(i % MCAM_ARR_ELEM_SZ))) + check_timeout_cycles(roc_npc, i); + else + update_timeout_cycles(roc_npc, i); + } + } + plt_seqcount_write_end(&flow_age->seq_cnt); + +lbl_sleep: + sleep(flow_age->aging_poll_freq); + } + + return NULL; +} + +void +npc_age_flow_list_entry_add(struct roc_npc *roc_npc, struct roc_npc_flow *flow) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_entry *age_fl_iter; + struct npc_age_flow_entry *new_entry; + + new_entry = plt_zmalloc(sizeof(*new_entry), 0); + new_entry->flow = flow; + roc_npc->flow_age.age_flow_refcnt++; + /* List in ascending order of mcam entries */ + TAILQ_FOREACH(age_fl_iter, &npc->age_flow_list, next) { + if (age_fl_iter->flow->mcam_id > flow->mcam_id) { + TAILQ_INSERT_BEFORE(age_fl_iter, new_entry, next); + return; + } + } + TAILQ_INSERT_TAIL(&npc->age_flow_list, new_entry, next); +} + +void +npc_age_flow_list_entry_delete(struct roc_npc *roc_npc, + struct roc_npc_flow *flow) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *curr; + + list = &npc->age_flow_list; + curr = TAILQ_FIRST(list); + + if (!curr) + return; + + while (curr) { + if (flow->mcam_id == curr->flow->mcam_id) { + TAILQ_REMOVE(list, curr, next); + plt_free(curr); + break; + } + curr = TAILQ_NEXT(curr, next); + } + roc_npc->flow_age.age_flow_refcnt--; +} + +int +npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, + const struct roc_npc_action_age *age, + struct roc_npc_flow *flow) +{ + struct roc_npc_flow_age *flow_age; + int errcode = 0; + + flow_age = &roc_npc->flow_age; + if (age->timeout < flow_age->aging_poll_freq) { + plt_err("Age timeout should be greater or equal to %u seconds", + flow_age->aging_poll_freq); + errcode = NPC_ERR_ACTION_NOTSUP; + goto done; + } + + flow->age_context = age->context == NULL ? flow : age->context; + flow->timeout = age->timeout; + flow->timeout_cycles = rte_get_timer_cycles() + age->timeout * + rte_get_timer_hz(); + + if (flow_age->age_flow_refcnt == 0) { + flow_age->aged_flows_get_thread_exit = false; + if (plt_ctrl_thread_create(&flow_age->aged_flows_poll_thread, + "Aged Flows Get Ctrl Thread", NULL, + npc_aged_flows_get, roc_npc) != 0) { + plt_err("Failed to create thread for age flows"); + errcode = NPC_ERR_ACTION_NOTSUP; + goto done; + } + } +done: + return errcode; +} + +void +npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc) +{ + struct roc_npc_flow_age *flow_age; + + flow_age = &roc_npc->flow_age; + flow_age->aged_flows_get_thread_exit = true; + pthread_join(flow_age->aged_flows_poll_thread, NULL); + npc_aged_flows_bitmap_free(roc_npc); +} + +void * +roc_npc_aged_flow_ctx_get(struct roc_npc *roc_npc, uint32_t mcam_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_age_flow_list_head *list; + struct npc_age_flow_entry *fl_iter; + + list = &npc->age_flow_list; + + TAILQ_FOREACH(fl_iter, list, next) { + if (fl_iter->flow->mcam_id == mcam_id) + return fl_iter->flow->age_context; + } + + return NULL; +} diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h index 593dca353b..6d6cb64c65 100644 --- a/drivers/common/cnxk/roc_npc_priv.h +++ b/drivers/common/cnxk/roc_npc_priv.h @@ -378,6 +378,13 @@ struct npc_prio_flow_entry { TAILQ_HEAD(npc_prio_flow_list_head, npc_prio_flow_entry); +struct npc_age_flow_entry { + struct roc_npc_flow *flow; + TAILQ_ENTRY(npc_age_flow_entry) next; +}; + +TAILQ_HEAD(npc_age_flow_list_head, npc_age_flow_entry); + struct npc { struct mbox *mbox; /* Mbox */ uint32_t keyx_supp_nmask[NPC_MAX_INTF]; /* nibble mask */ @@ -403,6 +410,7 @@ struct npc { npc_ld_flags_t prx_lfcfg; /* KEX LD_Flags CFG */ struct npc_flow_list *flow_list; struct npc_prio_flow_list_head *prio_flow_list; + struct npc_age_flow_list_head age_flow_list; struct plt_bitmap *rss_grp_entries; struct npc_flow_list ipsec_list; uint8_t exact_match_ena; @@ -480,4 +488,13 @@ int npc_rss_action_program(struct roc_npc *roc_npc, const struct roc_npc_action int npc_rss_group_free(struct npc *npc, struct roc_npc_flow *flow); int npc_mcam_init(struct npc *npc, struct roc_npc_flow *flow, int mcam_id); int npc_mcam_move(struct mbox *mbox, uint16_t old_ent, uint16_t new_ent); +void npc_age_flow_list_entry_add(struct roc_npc *npc, struct roc_npc_flow *flow); +void npc_age_flow_list_entry_delete(struct roc_npc *npc, struct roc_npc_flow *flow); +void *npc_aged_flows_get(void *args); +int npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc); +void npc_aged_flows_bitmap_free(struct roc_npc *roc_npc); +int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, + const struct roc_npc_action_age *age, + struct roc_npc_flow *flow); +void npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc); #endif /* _ROC_NPC_PRIV_H_ */ diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h index 9884398a99..e7a6564163 100644 --- a/drivers/common/cnxk/roc_platform.h +++ b/drivers/common/cnxk/roc_platform.h @@ -20,6 +20,7 @@ #include <rte_malloc.h> #include <rte_memzone.h> #include <rte_pci.h> +#include <rte_seqcount.h> #include <rte_spinlock.h> #include <rte_string_fns.h> #include <rte_tailq.h> @@ -130,6 +131,13 @@ #define plt_spinlock_unlock rte_spinlock_unlock #define plt_spinlock_trylock rte_spinlock_trylock +#define plt_seqcount_t rte_seqcount_t +#define plt_seqcount_init rte_seqcount_init +#define plt_seqcount_read_begin rte_seqcount_read_begin +#define plt_seqcount_read_retry rte_seqcount_read_retry +#define plt_seqcount_write_begin rte_seqcount_write_begin +#define plt_seqcount_write_end rte_seqcount_write_end + #define plt_intr_callback_register rte_intr_callback_register #define plt_intr_callback_unregister rte_intr_callback_unregister #define plt_intr_disable rte_intr_disable diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map index 8c71497df8..28f0f55934 100644 --- a/drivers/common/cnxk/version.map +++ b/drivers/common/cnxk/version.map @@ -425,6 +425,7 @@ INTERNAL { roc_npa_pool_op_range_set; roc_npa_pool_range_update_check; roc_npa_zero_aura_handle; + roc_npc_aged_flow_ctx_get; roc_npc_fini; roc_npc_flow_create; roc_npc_flow_destroy; -- 2.25.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] common/cnxk: add support to get aged flows 2023-08-08 8:49 ` [PATCH v2 1/2] common/cnxk: add support to get aged flows Ankur Dwivedi @ 2023-08-14 6:56 ` Jerin Jacob 2023-09-28 8:13 ` Jerin Jacob 0 siblings, 1 reply; 9+ messages in thread From: Jerin Jacob @ 2023-08-14 6:56 UTC (permalink / raw) To: Ankur Dwivedi; +Cc: dev, jerinj, ndabilpuram, kirankumark, skori, skoteshwar On Tue, Aug 8, 2023 at 2:20 PM Ankur Dwivedi <adwivedi@marvell.com> wrote: > > Adds support to get aged flows in CNXK driver. > The control thread polls the status of flows having age action, every 10 > seconds and updates a bitmap array with the aged flows. The poll frequency > of control thread can be set by devargs. > > Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> > --- > drivers/common/cnxk/meson.build | 1 + > drivers/common/cnxk/roc_mbox.h | 27 +++ > drivers/common/cnxk/roc_npc.c | 22 ++ > drivers/common/cnxk/roc_npc.h | 28 +++ > drivers/common/cnxk/roc_npc_aging.c | 315 ++++++++++++++++++++++++++++ > drivers/common/cnxk/roc_npc_priv.h | 17 ++ > drivers/common/cnxk/roc_platform.h | 8 + > drivers/common/cnxk/version.map | 1 + > 8 files changed, 419 insertions(+) > create mode 100644 drivers/common/cnxk/roc_npc_aging.c Updated the release notes as diff --git a/doc/guides/rel_notes/release_23_11.rst b/doc/guides/rel_notes/release_23_11.rst index 5b01a52593..10d4484685 100644 --- a/doc/guides/rel_notes/release_23_11.rst +++ b/doc/guides/rel_notes/release_23_11.rst @@ -58,6 +58,7 @@ New Features * **Updated Marvell cnxk ethdev driver.** * Added support for ``RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT`` flow item. + * Added support for ``RTE_FLOW_ACTION_TYPE_AGE`` flow action. Updated the git commit as follows and applied to dpdk-next-net-mrvl/for-next-net. Thanks commit ebee383fbe9a0ca25e083d26d9b251cb0310a5d2 (HEAD -> for-next-net) Author: Ankur Dwivedi <adwivedi@marvell.com> Date: Tue Aug 8 14:19:52 2023 +0530 net/cnxk: support flow aging Support get flow aged ops in cnxk ethdev driver. Also adds the devargs to get the poll frequency of control thread. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> commit d110c44d29e73b74834fb795ba18069635cdff6f Author: Ankur Dwivedi <adwivedi@marvell.com> Date: Tue Aug 8 14:19:51 2023 +0530 common/cnxk: support flow aging Added support to get aged flows in base code. The control thread polls the status of flows having age action, every 10 seconds and updates a bitmap array with the aged flows. The poll frequency of control thread can be set by devargs. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] common/cnxk: add support to get aged flows 2023-08-14 6:56 ` Jerin Jacob @ 2023-09-28 8:13 ` Jerin Jacob 2023-09-28 13:49 ` [EXT] " Ankur Dwivedi 0 siblings, 1 reply; 9+ messages in thread From: Jerin Jacob @ 2023-09-28 8:13 UTC (permalink / raw) To: Ankur Dwivedi Cc: dev, jerinj, ndabilpuram, kirankumark, skori, skoteshwar, Thomas Monjalon On Mon, Aug 14, 2023 at 12:26 PM Jerin Jacob <jerinjacobk@gmail.com> wrote: > > On Tue, Aug 8, 2023 at 2:20 PM Ankur Dwivedi <adwivedi@marvell.com> wrote: > > > > Adds support to get aged flows in CNXK driver. > > The control thread polls the status of flows having age action, every 10 > > seconds and updates a bitmap array with the aged flows. The poll frequency > > of control thread can be set by devargs. > > > > Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> > > --- > > drivers/common/cnxk/meson.build | 1 + > > drivers/common/cnxk/roc_mbox.h | 27 +++ > > drivers/common/cnxk/roc_npc.c | 22 ++ > > drivers/common/cnxk/roc_npc.h | 28 +++ > > drivers/common/cnxk/roc_npc_aging.c | 315 ++++++++++++++++++++++++++++ > > drivers/common/cnxk/roc_npc_priv.h | 17 ++ > > drivers/common/cnxk/roc_platform.h | 8 + > > drivers/common/cnxk/version.map | 1 + > > 8 files changed, 419 insertions(+) > > create mode 100644 drivers/common/cnxk/roc_npc_aging.c > > Updated the release notes as > diff --git a/doc/guides/rel_notes/release_23_11.rst > b/doc/guides/rel_notes/release_23_11.rst > index 5b01a52593..10d4484685 100644 > --- a/doc/guides/rel_notes/release_23_11.rst > +++ b/doc/guides/rel_notes/release_23_11.rst > @@ -58,6 +58,7 @@ New Features > * **Updated Marvell cnxk ethdev driver.** > > * Added support for ``RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT`` flow item. > + * Added support for ``RTE_FLOW_ACTION_TYPE_AGE`` flow action. > > Updated the git commit as follows and applied to > dpdk-next-net-mrvl/for-next-net. Thanks Ankur, following changes in upstream changed the thread APIs. I have adapted to this change in [1]. Please review ASAP - It is blocking rc1 PR. commit 1c1abf1786a6de044bd396da4cc316961e3fd812 Author: Thomas Monjalon <thomas@monjalon.net> Date: Wed Sep 13 13:28:19 2023 +0200 lib: convert to internal control threads Calls to rte_ctrl_thread_create() are replaced with rte_thread_create_internal_control(). Other pthread-related functions are replaced with the rte_thread API. Only pthread_cancel() has no replacement. Signed-off-by: Thomas Monjalon <thomas@monjalon.net> Acked-by: Morten Brørup <mb@smartsharesystems.com> Acked-by: Tyler Retzlaff <roretzla@linux.microsoft.com> Acked-by: Konstantin Ananyev <konstantin.v.ananyev@yandex.ru [1] diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c index 83c04880f2..94c8e94400 100644 --- a/drivers/common/cnxk/roc_npc.c +++ b/drivers/common/cnxk/roc_npc.c @@ -1623,7 +1623,8 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) npc_delete_prio_list_entry(npc, flow); npc_age_flow_list_entry_delete(roc_npc, flow); - if (roc_npc->flow_age.age_flow_refcnt == 0 && roc_npc->flow_age.aged_flows_poll_thread) + if (roc_npc->flow_age.age_flow_refcnt == 0 && + plt_thread_is_valid(roc_npc->flow_age.aged_flows_poll_thread)) npc_aging_ctrl_thread_destroy(roc_npc); done: diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index ad1c3b08cc..5a7117eae4 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -359,7 +359,7 @@ struct roc_npc_flow_age { uint32_t aged_flows_cnt; uint32_t start_id; uint32_t end_id; - pthread_t aged_flows_poll_thread; + rte_thread_t aged_flows_poll_thread; struct plt_bitmap *aged_flows; void *age_mem; bool aged_flows_get_thread_exit; diff --git a/drivers/common/cnxk/roc_npc_aging.c b/drivers/common/cnxk/roc_npc_aging.c index 4b845954b4..74543f227b 100644 --- a/drivers/common/cnxk/roc_npc_aging.c +++ b/drivers/common/cnxk/roc_npc_aging.c @@ -134,7 +134,7 @@ npc_mcam_get_hit_status(struct npc *npc, uint64_t *mcam_ids, uint16_t start_id, return rc; } -void * +uint32_t npc_aged_flows_get(void *args) { uint64_t hit_status[MCAM_ARR_SIZE] = {0}; @@ -182,7 +182,7 @@ npc_aged_flows_get(void *args) rc = npc_mcam_get_hit_status(npc, mcam_ids, start_id, end_id, hit_status, true); if (rc) - return NULL; + return 0; plt_seqcount_write_begin(&flow_age->seq_cnt); flow_age->aged_flows_cnt = 0; @@ -201,7 +201,7 @@ npc_aged_flows_get(void *args) sleep(flow_age->aging_poll_freq); } - return NULL; + return 0; } void @@ -276,8 +276,8 @@ npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, if (flow_age->age_flow_refcnt == 0) { flow_age->aged_flows_get_thread_exit = false; - if (plt_ctrl_thread_create(&flow_age->aged_flows_poll_thread, - "Aged Flows Get Ctrl Thread", NULL, + if (plt_thread_create_control(&flow_age->aged_flows_poll_thread, + "Aged Flows Get Ctrl Thread", npc_aged_flows_get, roc_npc) != 0) { plt_err("Failed to create thread for age flows"); errcode = NPC_ERR_ACTION_NOTSUP; @@ -295,7 +295,7 @@ npc_aging_ctrl_thread_destroy(struct roc_npc *roc_npc) flow_age = &roc_npc->flow_age; flow_age->aged_flows_get_thread_exit = true; - pthread_join(flow_age->aged_flows_poll_thread, NULL); + plt_thread_join(flow_age->aged_flows_poll_thread, NULL); npc_aged_flows_bitmap_free(roc_npc); } diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h index 6d6cb64c65..424f8e207a 100644 --- a/drivers/common/cnxk/roc_npc_priv.h +++ b/drivers/common/cnxk/roc_npc_priv.h @@ -490,7 +490,7 @@ int npc_mcam_init(struct npc *npc, struct roc_npc_flow *flow, int mcam_id); int npc_mcam_move(struct mbox *mbox, uint16_t old_ent, uint16_t new_ent); void npc_age_flow_list_entry_add(struct roc_npc *npc, struct roc_npc_flow *flow); void npc_age_flow_list_entry_delete(struct roc_npc *npc, struct roc_npc_flow *flow); -void *npc_aged_flows_get(void *args); +uint32_t npc_aged_flows_get(void *args); int npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc); void npc_aged_flows_bitmap_free(struct roc_npc *roc_npc); int npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h index ad0d1624a3..1e535a527d 100644 --- a/drivers/common/cnxk/roc_platform.h +++ b/drivers/common/cnxk/roc_platform.h @@ -145,6 +145,12 @@ #define plt_thread_create_control rte_thread_create_internal_control #define plt_thread_join rte_thread_join +static inline bool +plt_thread_is_valid(rte_thread_t thr) +{ + return thr.opaque_id ? true : false; +} + #define plt_intr_efd_counter_size_get rte_intr_efd_counter_size_get #define plt_intr_efd_counter_size_set rte_intr_efd_counter_size_set #define plt_intr_vec_list_index_get rte_intr_vec_list_index_get ^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [EXT] Re: [PATCH v2 1/2] common/cnxk: add support to get aged flows 2023-09-28 8:13 ` Jerin Jacob @ 2023-09-28 13:49 ` Ankur Dwivedi 0 siblings, 0 replies; 9+ messages in thread From: Ankur Dwivedi @ 2023-09-28 13:49 UTC (permalink / raw) To: Jerin Jacob Cc: dev, Jerin Jacob Kollanukkaran, Nithin Kumar Dabilpuram, Kiran Kumar Kokkilagadda, Sunil Kumar Kori, Satha Koteswara Rao Kottidi, Thomas Monjalon > > >Ankur, following changes in upstream changed the thread APIs. I have >adapted to this change in [1]. Please review ASAP - It is blocking rc1 PR. I have reviewed the changes. The changes are fine. Thanks. > >commit 1c1abf1786a6de044bd396da4cc316961e3fd812 >Author: Thomas Monjalon <thomas@monjalon.net> >Date: Wed Sep 13 13:28:19 2023 +0200 > > lib: convert to internal control threads > > Calls to rte_ctrl_thread_create() are replaced with > rte_thread_create_internal_control(). > Other pthread-related functions are replaced with the rte_thread API. > Only pthread_cancel() has no replacement. > > Signed-off-by: Thomas Monjalon <thomas@monjalon.net> > Acked-by: Morten Brørup <mb@smartsharesystems.com> > Acked-by: Tyler Retzlaff <roretzla@linux.microsoft.com> > Acked-by: Konstantin Ananyev <konstantin.v.ananyev@yandex.ru > > >[1] > >diff --git a/drivers/common/cnxk/roc_npc.c >b/drivers/common/cnxk/roc_npc.c index 83c04880f2..94c8e94400 100644 >--- a/drivers/common/cnxk/roc_npc.c >+++ b/drivers/common/cnxk/roc_npc.c >@@ -1623,7 +1623,8 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, >struct roc_npc_flow *flow) > npc_delete_prio_list_entry(npc, flow); > > npc_age_flow_list_entry_delete(roc_npc, flow); >- if (roc_npc->flow_age.age_flow_refcnt == 0 && >roc_npc->flow_age.aged_flows_poll_thread) >+ if (roc_npc->flow_age.age_flow_refcnt == 0 && >+ plt_thread_is_valid(roc_npc->flow_age.aged_flows_poll_thread)) > npc_aging_ctrl_thread_destroy(roc_npc); > > done: >diff --git a/drivers/common/cnxk/roc_npc.h >b/drivers/common/cnxk/roc_npc.h index ad1c3b08cc..5a7117eae4 100644 >--- a/drivers/common/cnxk/roc_npc.h >+++ b/drivers/common/cnxk/roc_npc.h >@@ -359,7 +359,7 @@ struct roc_npc_flow_age { > uint32_t aged_flows_cnt; > uint32_t start_id; > uint32_t end_id; >- pthread_t aged_flows_poll_thread; >+ rte_thread_t aged_flows_poll_thread; > struct plt_bitmap *aged_flows; > void *age_mem; > bool aged_flows_get_thread_exit; >diff --git a/drivers/common/cnxk/roc_npc_aging.c >b/drivers/common/cnxk/roc_npc_aging.c >index 4b845954b4..74543f227b 100644 >--- a/drivers/common/cnxk/roc_npc_aging.c >+++ b/drivers/common/cnxk/roc_npc_aging.c >@@ -134,7 +134,7 @@ npc_mcam_get_hit_status(struct npc *npc, uint64_t >*mcam_ids, uint16_t start_id, > return rc; > } > >-void * >+uint32_t > npc_aged_flows_get(void *args) > { > uint64_t hit_status[MCAM_ARR_SIZE] = {0}; @@ -182,7 +182,7 @@ >npc_aged_flows_get(void *args) > rc = npc_mcam_get_hit_status(npc, mcam_ids, start_id, end_id, > hit_status, true); > if (rc) >- return NULL; >+ return 0; > > plt_seqcount_write_begin(&flow_age->seq_cnt); > flow_age->aged_flows_cnt = 0; >@@ -201,7 +201,7 @@ npc_aged_flows_get(void *args) > sleep(flow_age->aging_poll_freq); > } > >- return NULL; >+ return 0; > } > > void >@@ -276,8 +276,8 @@ npc_aging_ctrl_thread_create(struct roc_npc >*roc_npc, > > if (flow_age->age_flow_refcnt == 0) { > flow_age->aged_flows_get_thread_exit = false; >- if (plt_ctrl_thread_create(&flow_age->aged_flows_poll_thread, >- "Aged Flows Get Ctrl Thread", NULL, >+ if (plt_thread_create_control(&flow_age->aged_flows_poll_thread, >+ "Aged Flows Get Ctrl Thread", > npc_aged_flows_get, roc_npc) != 0) { > plt_err("Failed to create thread for age flows"); > errcode = NPC_ERR_ACTION_NOTSUP; >@@ -295,7 +295,7 @@ npc_aging_ctrl_thread_destroy(struct roc_npc >*roc_npc) > > flow_age = &roc_npc->flow_age; > flow_age->aged_flows_get_thread_exit = true; >- pthread_join(flow_age->aged_flows_poll_thread, NULL); >+ plt_thread_join(flow_age->aged_flows_poll_thread, NULL); > npc_aged_flows_bitmap_free(roc_npc); > } > >diff --git a/drivers/common/cnxk/roc_npc_priv.h >b/drivers/common/cnxk/roc_npc_priv.h >index 6d6cb64c65..424f8e207a 100644 >--- a/drivers/common/cnxk/roc_npc_priv.h >+++ b/drivers/common/cnxk/roc_npc_priv.h >@@ -490,7 +490,7 @@ int npc_mcam_init(struct npc *npc, struct >roc_npc_flow *flow, int mcam_id); int npc_mcam_move(struct mbox *mbox, >uint16_t old_ent, uint16_t new_ent); void >npc_age_flow_list_entry_add(struct roc_npc *npc, struct roc_npc_flow >*flow); void npc_age_flow_list_entry_delete(struct roc_npc *npc, struct >roc_npc_flow *flow); -void *npc_aged_flows_get(void *args); >+uint32_t npc_aged_flows_get(void *args); > int npc_aged_flows_bitmap_alloc(struct roc_npc *roc_npc); void >npc_aged_flows_bitmap_free(struct roc_npc *roc_npc); int >npc_aging_ctrl_thread_create(struct roc_npc *roc_npc, diff --git >a/drivers/common/cnxk/roc_platform.h >b/drivers/common/cnxk/roc_platform.h >index ad0d1624a3..1e535a527d 100644 >--- a/drivers/common/cnxk/roc_platform.h >+++ b/drivers/common/cnxk/roc_platform.h >@@ -145,6 +145,12 @@ > #define plt_thread_create_control rte_thread_create_internal_control > #define plt_thread_join rte_thread_join > >+static inline bool >+plt_thread_is_valid(rte_thread_t thr) >+{ >+ return thr.opaque_id ? true : false; >+} >+ > #define plt_intr_efd_counter_size_get rte_intr_efd_counter_size_get #define >plt_intr_efd_counter_size_set rte_intr_efd_counter_size_set #define >plt_intr_vec_list_index_get rte_intr_vec_list_index_get ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 2/2] net/cnxk: add get flow aged ops 2023-08-08 8:49 ` [PATCH v2 0/2] add support for flow aging in CNXK driver Ankur Dwivedi 2023-08-08 8:49 ` [PATCH v2 1/2] common/cnxk: add support to get aged flows Ankur Dwivedi @ 2023-08-08 8:49 ` Ankur Dwivedi 1 sibling, 0 replies; 9+ messages in thread From: Ankur Dwivedi @ 2023-08-08 8:49 UTC (permalink / raw) To: dev; +Cc: jerinj, ndabilpuram, kirankumark, skori, skoteshwar, Ankur Dwivedi Adds get flow aged ops in CNXK driver. Also adds the devargs to get the poll frequency of control thread. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- doc/guides/nics/cnxk.rst | 12 +++++++ doc/guides/nics/features/cnxk.ini | 1 + doc/guides/nics/features/cnxk_vf.ini | 1 + drivers/net/cnxk/cnxk_ethdev_devargs.c | 21 +++++++++++- drivers/net/cnxk/cnxk_flow.c | 45 ++++++++++++++++++++++++++ 5 files changed, 79 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/cnxk.rst b/doc/guides/nics/cnxk.rst index 9229056f6f..dc71ab7fc3 100644 --- a/doc/guides/nics/cnxk.rst +++ b/doc/guides/nics/cnxk.rst @@ -581,6 +581,18 @@ Runtime Config Options for inline device With the above configuration, driver would poll for soft expiry events every 1000 usec. +- ``NPC MCAM Aging poll frequency in seconds`` (default ``10``) + + Poll frequency for aging control thread can be specified by + ``aging_poll_freq`` ``devargs`` parameter. + + For example:: + + -a 0002:01:00.2,aging_poll_freq=50 + + With the above configuration, driver would poll for aging flows every 50 + seconds. + Debugging Options ----------------- diff --git a/doc/guides/nics/features/cnxk.ini b/doc/guides/nics/features/cnxk.ini index 838e781d6d..ebedbd0588 100644 --- a/doc/guides/nics/features/cnxk.ini +++ b/doc/guides/nics/features/cnxk.ini @@ -80,6 +80,7 @@ vxlan = Y vxlan_gpe = Y [rte_flow actions] +age = Y count = Y drop = Y flag = Y diff --git a/doc/guides/nics/features/cnxk_vf.ini b/doc/guides/nics/features/cnxk_vf.ini index 470c45ce59..0e9ad94382 100644 --- a/doc/guides/nics/features/cnxk_vf.ini +++ b/doc/guides/nics/features/cnxk_vf.ini @@ -71,6 +71,7 @@ vxlan = Y vxlan_gpe = Y [rte_flow actions] +age = Y count = Y drop = Y flag = Y diff --git a/drivers/net/cnxk/cnxk_ethdev_devargs.c b/drivers/net/cnxk/cnxk_ethdev_devargs.c index e1a0845ece..8e862be933 100644 --- a/drivers/net/cnxk/cnxk_ethdev_devargs.c +++ b/drivers/net/cnxk/cnxk_ethdev_devargs.c @@ -245,6 +245,19 @@ parse_sdp_channel_mask(const char *key, const char *value, void *extra_args) return 0; } +static int +parse_val_u16(const char *key, const char *value, void *extra_args) +{ + RTE_SET_USED(key); + uint16_t val; + + val = atoi(value); + + *(uint16_t *)extra_args = val; + + return 0; +} + #define CNXK_RSS_RETA_SIZE "reta_size" #define CNXK_SCL_ENABLE "scalar_enable" #define CNXK_TX_COMPL_ENA "tx_compl_ena" @@ -265,10 +278,12 @@ parse_sdp_channel_mask(const char *key, const char *value, void *extra_args) #define CNXK_CUSTOM_SA_ACT "custom_sa_act" #define CNXK_SQB_SLACK "sqb_slack" #define CNXK_NIX_META_BUF_SZ "meta_buf_sz" +#define CNXK_FLOW_AGING_POLL_FREQ "aging_poll_freq" int cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev) { + uint16_t aging_thread_poll_freq = ROC_NPC_AGE_POLL_FREQ_MIN; uint16_t reta_sz = ROC_NIX_RSS_RETA_SZ_64; uint16_t sqb_count = CNXK_NIX_TX_MAX_SQB; struct flow_pre_l2_size_info pre_l2_info; @@ -338,6 +353,8 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev) rte_kvargs_process(kvlist, CNXK_SQB_SLACK, &parse_sqb_count, &sqb_slack); rte_kvargs_process(kvlist, CNXK_NIX_META_BUF_SZ, &parse_meta_bufsize, &meta_buf_sz); + rte_kvargs_process(kvlist, CNXK_FLOW_AGING_POLL_FREQ, &parse_val_u16, + &aging_thread_poll_freq); rte_kvargs_free(kvlist); null_devargs: @@ -369,6 +386,7 @@ cnxk_ethdev_parse_devargs(struct rte_devargs *devargs, struct cnxk_eth_dev *dev) dev->npc.pre_l2_size_offset = pre_l2_info.pre_l2_size_off; dev->npc.pre_l2_size_offset_mask = pre_l2_info.pre_l2_size_off_mask; dev->npc.pre_l2_size_shift_dir = pre_l2_info.pre_l2_size_shift_dir; + dev->npc.flow_age.aging_poll_freq = aging_thread_poll_freq; return 0; exit: return -EINVAL; @@ -390,4 +408,5 @@ RTE_PMD_REGISTER_PARAM_STRING(net_cnxk, CNXK_NO_INL_DEV "=0" CNXK_SDP_CHANNEL_MASK "=<1-4095>/<1-4095>" CNXK_CUSTOM_SA_ACT "=1" - CNXK_SQB_SLACK "=<12-512>"); + CNXK_SQB_SLACK "=<12-512>" + CNXK_FLOW_AGING_POLL_FREQ "=<10-65535>"); diff --git a/drivers/net/cnxk/cnxk_flow.c b/drivers/net/cnxk/cnxk_flow.c index 3b8348ae9c..e0aeb5ea5f 100644 --- a/drivers/net/cnxk/cnxk_flow.c +++ b/drivers/net/cnxk/cnxk_flow.c @@ -230,6 +230,10 @@ cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr, in_actions[i].type = ROC_NPC_ACTION_TYPE_METER; in_actions[i].conf = actions->conf; break; + case RTE_FLOW_ACTION_TYPE_AGE: + in_actions[i].type = ROC_NPC_ACTION_TYPE_AGE; + in_actions[i].conf = actions->conf; + break; default: plt_npc_dbg("Action is not supported = %d", actions->type); @@ -480,10 +484,51 @@ cnxk_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow, return 0; } +static int +cnxk_flow_get_aged_flows(struct rte_eth_dev *eth_dev, void **context, + uint32_t nb_contexts, struct rte_flow_error *err) +{ + struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev); + struct roc_npc *roc_npc = &dev->npc; + struct roc_npc_flow_age *flow_age; + uint32_t start_id; + uint32_t end_id; + int cnt = 0; + uint32_t sn; + uint32_t i; + + RTE_SET_USED(err); + + flow_age = &roc_npc->flow_age; + + do { + sn = plt_seqcount_read_begin(&flow_age->seq_cnt); + + if (nb_contexts == 0) { + cnt = flow_age->aged_flows_cnt; + } else { + start_id = flow_age->start_id; + end_id = flow_age->end_id; + for (i = start_id; i <= end_id; i++) { + if ((int)nb_contexts == cnt) + break; + if (plt_bitmap_get(flow_age->aged_flows, i)) { + context[cnt] = + roc_npc_aged_flow_ctx_get(roc_npc, i); + cnt++; + } + } + } + } while (plt_seqcount_read_retry(&flow_age->seq_cnt, sn)); + + return cnt; +} + struct rte_flow_ops cnxk_flow_ops = { .validate = cnxk_flow_validate, .flush = cnxk_flow_flush, .query = cnxk_flow_query, .isolate = cnxk_flow_isolate, .dev_dump = cnxk_flow_dev_dump, + .get_aged_flows = cnxk_flow_get_aged_flows, }; -- 2.25.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-09-28 13:49 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2023-07-27 11:59 [PATCH v1 0/2] add support for flow aging in CNXK driver Ankur Dwivedi 2023-07-27 11:59 ` [PATCH v1 1/2] common/cnxk: add support to get aged flows Ankur Dwivedi 2023-07-27 11:59 ` [PATCH v1 2/2] net/cnxk: add get flow aged ops Ankur Dwivedi 2023-08-08 8:49 ` [PATCH v2 0/2] add support for flow aging in CNXK driver Ankur Dwivedi 2023-08-08 8:49 ` [PATCH v2 1/2] common/cnxk: add support to get aged flows Ankur Dwivedi 2023-08-14 6:56 ` Jerin Jacob 2023-09-28 8:13 ` Jerin Jacob 2023-09-28 13:49 ` [EXT] " Ankur Dwivedi 2023-08-08 8:49 ` [PATCH v2 2/2] net/cnxk: add get flow aged ops Ankur Dwivedi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).