* [net-next PATCH v3 0/2] octeontx2: Multicast/mirror offload changes @ 2023-11-21 9:43 Suman Ghosh 2023-11-21 9:43 ` [net-next PATCH v3 1/2] octeontx2-af: Add new mbox to support multicast/mirror offload Suman Ghosh 2023-11-21 9:43 ` [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror Suman Ghosh 0 siblings, 2 replies; 9+ messages in thread From: Suman Ghosh @ 2023-11-21 9:43 UTC (permalink / raw) To: sgoutham, gakula, sbhatta, hkelam, davem, edumazet, kuba, pabeni, netdev, linux-kernel, lcherian, jerinj, horms, wojciech.drewek Cc: Suman Ghosh This patchset includes changes to support TC multicast/mirror offload. Patch #1: Adds changes to support new mailbox to offload multicast/mirror offload. Patch #2: Adds TC related changes which uses the newly added mailboxes to offload multicast/mirror rules. Suman Ghosh (2): octeontx2-af: Add new mbox to support multicast/mirror offload octeontx2-pf: TC flower offload support for mirror v3 changes: - Updated patch#1 based on comments from Wojciech and Simon. The comments were mostly based on some missed mutex_unlock and code reorganization. v2 changes: - Updated small nits based on review comments from Wojciech Drewek in file drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c .../net/ethernet/marvell/octeontx2/af/mbox.h | 64 ++ .../net/ethernet/marvell/octeontx2/af/rvu.c | 6 +- .../net/ethernet/marvell/octeontx2/af/rvu.h | 39 +- .../ethernet/marvell/octeontx2/af/rvu_nix.c | 699 +++++++++++++++++- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 14 +- .../marvell/octeontx2/af/rvu_npc_fs.c | 73 +- .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 113 ++- 7 files changed, 967 insertions(+), 41 deletions(-) -- 2.25.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [net-next PATCH v3 1/2] octeontx2-af: Add new mbox to support multicast/mirror offload 2023-11-21 9:43 [net-next PATCH v3 0/2] octeontx2: Multicast/mirror offload changes Suman Ghosh @ 2023-11-21 9:43 ` Suman Ghosh 2023-11-23 10:17 ` Paolo Abeni 2023-11-21 9:43 ` [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror Suman Ghosh 1 sibling, 1 reply; 9+ messages in thread From: Suman Ghosh @ 2023-11-21 9:43 UTC (permalink / raw) To: sgoutham, gakula, sbhatta, hkelam, davem, edumazet, kuba, pabeni, netdev, linux-kernel, lcherian, jerinj, horms, wojciech.drewek Cc: Suman Ghosh A new mailbox is added to support offloading of multicast/mirror functionality. The mailbox also supports dynamic updation of the multicast/mirror list. Signed-off-by: Suman Ghosh <sumang@marvell.com> --- .../net/ethernet/marvell/octeontx2/af/mbox.h | 64 ++ .../net/ethernet/marvell/octeontx2/af/rvu.c | 6 +- .../net/ethernet/marvell/octeontx2/af/rvu.h | 39 +- .../ethernet/marvell/octeontx2/af/rvu_nix.c | 699 +++++++++++++++++- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 14 +- .../marvell/octeontx2/af/rvu_npc_fs.c | 73 +- 6 files changed, 857 insertions(+), 38 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index 6845556581c3..a833507c449f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -304,6 +304,13 @@ M(NIX_BANDPROF_GET_HWINFO, 0x801f, nix_bandprof_get_hwinfo, msg_req, \ nix_bandprof_get_hwinfo_rsp) \ M(NIX_READ_INLINE_IPSEC_CFG, 0x8023, nix_read_inline_ipsec_cfg, \ msg_req, nix_inline_ipsec_cfg) \ +M(NIX_MCAST_GRP_CREATE, 0x802b, nix_mcast_grp_create, nix_mcast_grp_create_req, \ + nix_mcast_grp_create_rsp) \ +M(NIX_MCAST_GRP_DESTROY, 0x802c, nix_mcast_grp_destroy, nix_mcast_grp_destroy_req, \ + msg_rsp) \ +M(NIX_MCAST_GRP_UPDATE, 0x802d, nix_mcast_grp_update, \ + nix_mcast_grp_update_req, \ + nix_mcast_grp_update_rsp) \ /* MCS mbox IDs (range 0xA000 - 0xBFFF) */ \ M(MCS_ALLOC_RESOURCES, 0xa000, mcs_alloc_resources, mcs_alloc_rsrc_req, \ mcs_alloc_rsrc_rsp) \ @@ -830,6 +837,9 @@ enum nix_af_status { NIX_AF_ERR_CQ_CTX_WRITE_ERR = -429, NIX_AF_ERR_AQ_CTX_RETRY_WRITE = -430, NIX_AF_ERR_LINK_CREDITS = -431, + NIX_AF_ERR_INVALID_MCAST_GRP = -436, + NIX_AF_ERR_INVALID_MCAST_DEL_REQ = -437, + NIX_AF_ERR_NON_CONTIG_MCE_LIST = -438, }; /* For NIX RX vtag action */ @@ -1204,6 +1214,60 @@ struct nix_bp_cfg_rsp { u8 chan_cnt; /* Number of channel for which bpids are assigned */ }; +struct nix_mcast_grp_create_req { + struct mbox_msghdr hdr; +#define NIX_MCAST_INGRESS 0 +#define NIX_MCAST_EGRESS 1 + u8 dir; + /* Reserving few bytes for future requirement */ + u8 reserved[11]; +}; + +struct nix_mcast_grp_create_rsp { + struct mbox_msghdr hdr; + /* This mcast_grp_idx should be passed during MCAM + * write entry for multicast. AF will identify the + * corresponding multicast table index associated + * with the group id and program the same to MCAM entry. + * This group id is also needed during group delete + * and update request. + */ + u32 mcast_grp_idx; +}; + +struct nix_mcast_grp_destroy_req { + struct mbox_msghdr hdr; + /* Group id returned by nix_mcast_grp_create_rsp */ + u32 mcast_grp_idx; +}; + +struct nix_mcast_grp_update_req { + struct mbox_msghdr hdr; + /* Group id returned by nix_mcast_grp_create_rsp */ + u32 mcast_grp_idx; + /* Number of multicast/mirror entries requested */ + u32 num_mce_entry; +#define NIX_MCE_ENTRY_MAX 64 +#define NIX_RX_RQ 0 +#define NIX_RX_RSS 1 + /* Receive queue or RSS index within pf_func */ + u32 rq_rss_index[NIX_MCE_ENTRY_MAX]; + /* pcifunc is required for both ingress and egress multicast */ + u16 pcifunc[NIX_MCE_ENTRY_MAX]; + /* channel is required for egress multicast */ + u16 channel[NIX_MCE_ENTRY_MAX]; +#define NIX_MCAST_OP_ADD_ENTRY 0 +#define NIX_MCAST_OP_DEL_ENTRY 1 + /* Destination type. 0:Receive queue, 1:RSS*/ + u8 dest_type[NIX_MCE_ENTRY_MAX]; + u8 op; +}; + +struct nix_mcast_grp_update_rsp { + struct mbox_msghdr hdr; + u32 mce_start_index; +}; + /* Global NIX inline IPSec configuration */ struct nix_inline_ipsec_cfg { struct mbox_msghdr hdr; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index 22c395c7d040..7cd98f013fde 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -156,7 +156,7 @@ int rvu_alloc_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc) return start; } -static void rvu_free_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc, int start) +void rvu_free_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc, int start) { if (!rsrc->bmap) return; @@ -2614,6 +2614,10 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc) * 2. Flush and reset SSO/SSOW * 3. Cleanup pools (NPA) */ + + /* Free multicast/mirror node associated with the 'pcifunc' */ + rvu_nix_mcast_flr_free_entries(rvu, pcifunc); + rvu_blklf_teardown(rvu, pcifunc, BLKADDR_NIX0); rvu_blklf_teardown(rvu, pcifunc, BLKADDR_NIX1); rvu_blklf_teardown(rvu, pcifunc, BLKADDR_CPT0); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index c4d999ef5ab4..a3de437f309e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -116,11 +116,12 @@ struct rvu_block { }; struct nix_mcast { - struct qmem *mce_ctx; - struct qmem *mcast_buf; - int replay_pkind; - int next_free_mce; - struct mutex mce_lock; /* Serialize MCE updates */ + struct qmem *mce_ctx; + struct qmem *mcast_buf; + int replay_pkind; + struct rsrc_bmap mce_counter[2]; + /* Counters for both ingress and egress mcast lists */ + struct mutex mce_lock; /* Serialize MCE updates */ }; struct nix_mce_list { @@ -129,6 +130,23 @@ struct nix_mce_list { int max; }; +struct nix_mcast_grp_elem { + struct nix_mce_list mcast_mce_list; + u32 mcast_grp_idx; + u32 pcifunc; + int mcam_index; + int mce_start_index; + struct list_head list; + u8 dir; +}; + +struct nix_mcast_grp { + struct list_head mcast_grp_head; + int count; + int next_grp_index; + struct mutex mcast_grp_lock; /* Serialize MCE updates */ +}; + /* layer metadata to uniquely identify a packet header field */ struct npc_layer_mdata { u8 lid; @@ -339,6 +357,7 @@ struct nix_hw { struct rvu *rvu; struct nix_txsch txsch[NIX_TXSCH_LVL_CNT]; /* Tx schedulers */ struct nix_mcast mcast; + struct nix_mcast_grp mcast_grp; struct nix_flowkey flowkey; struct nix_mark_format mark_format; struct nix_lso lso; @@ -741,6 +760,7 @@ void rvu_free_rsrc(struct rsrc_bmap *rsrc, int id); bool is_rsrc_free(struct rsrc_bmap *rsrc, int id); int rvu_rsrc_free_count(struct rsrc_bmap *rsrc); int rvu_alloc_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc); +void rvu_free_rsrc_contig(struct rsrc_bmap *rsrc, int nrsrc, int start); bool rvu_rsrc_check_contig(struct rsrc_bmap *rsrc, int nrsrc); u16 rvu_get_rsrc_mapcount(struct rvu_pfvf *pfvf, int blkaddr); int rvu_get_pf(u16 pcifunc); @@ -847,6 +867,11 @@ u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu); u32 convert_bytes_to_dwrr_mtu(u32 bytes); void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc, struct nix_txsch *txsch, bool enable); +void rvu_nix_mcast_flr_free_entries(struct rvu *rvu, u16 pcifunc); +int rvu_nix_mcast_get_mce_index(struct rvu *rvu, u16 pcifunc, + u32 mcast_grp_idx); +int rvu_nix_mcast_update_mcam_entry(struct rvu *rvu, u16 pcifunc, + u32 mcast_grp_idx, u16 mcam_index); /* NPC APIs */ void rvu_npc_freemem(struct rvu *rvu); @@ -895,6 +920,10 @@ void npc_mcam_enable_flows(struct rvu *rvu, u16 target); void npc_mcam_disable_flows(struct rvu *rvu, u16 target); void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, int index, bool enable); +u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, int index); +void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, int index, u64 cfg); void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr, u16 src, struct mcam_entry *entry, u8 *intf, u8 *ena); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index 23c2f2ed2fb8..10687f0181b9 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -71,12 +71,19 @@ enum nix_makr_fmt_indexes { /* For now considering MC resources needed for broadcast * pkt replication only. i.e 256 HWVFs + 12 PFs. */ -#define MC_TBL_SIZE MC_TBL_SZ_512 -#define MC_BUF_CNT MC_BUF_CNT_128 +#define MC_TBL_SIZE MC_TBL_SZ_2K +#define MC_BUF_CNT MC_BUF_CNT_1024 + +#define MC_TX_MAX 2048 struct mce { struct hlist_node node; + u32 rq_rss_index; u16 pcifunc; + u16 channel; + u8 dest_type; + u8 is_active; + u8 reserved[2]; }; int rvu_get_next_nix_blkaddr(struct rvu *rvu, int blkaddr) @@ -164,18 +171,33 @@ static void nix_mce_list_init(struct nix_mce_list *list, int max) list->max = max; } -static u16 nix_alloc_mce_list(struct nix_mcast *mcast, int count) +static int nix_alloc_mce_list(struct nix_mcast *mcast, int count, u8 dir) { + struct rsrc_bmap *mce_counter; int idx; if (!mcast) - return 0; + return -EINVAL; - idx = mcast->next_free_mce; - mcast->next_free_mce += count; + mce_counter = &mcast->mce_counter[dir]; + if (!rvu_rsrc_check_contig(mce_counter, count)) + return -ENOSPC; + + idx = rvu_alloc_rsrc_contig(mce_counter, count); return idx; } +static void nix_free_mce_list(struct nix_mcast *mcast, int count, int start, u8 dir) +{ + struct rsrc_bmap *mce_counter; + + if (!mcast) + return; + + mce_counter = &mcast->mce_counter[dir]; + rvu_free_rsrc_contig(mce_counter, count, start); +} + struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr) { int nix_blkaddr = 0, i = 0; @@ -2955,7 +2977,8 @@ int rvu_mbox_handler_nix_vtag_cfg(struct rvu *rvu, } static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw, - int mce, u8 op, u16 pcifunc, int next, bool eol) + int mce, u8 op, u16 pcifunc, int next, + int index, u8 mce_op, bool eol) { struct nix_aq_enq_req aq_req; int err; @@ -2966,8 +2989,8 @@ static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw, aq_req.qidx = mce; /* Use RSS with RSS index 0 */ - aq_req.mce.op = 1; - aq_req.mce.index = 0; + aq_req.mce.op = mce_op; + aq_req.mce.index = index; aq_req.mce.eol = eol; aq_req.mce.pf_func = pcifunc; aq_req.mce.next = next; @@ -2984,6 +3007,208 @@ static int nix_blk_setup_mce(struct rvu *rvu, struct nix_hw *nix_hw, return 0; } +static void nix_delete_mcast_mce_list(struct nix_mce_list *mce_list) +{ + struct hlist_node *tmp; + struct mce *mce; + + /* Scan through the current list */ + hlist_for_each_entry_safe(mce, tmp, &mce_list->head, node) { + hlist_del(&mce->node); + kfree(mce); + } + + mce_list->count = 0; + mce_list->max = 0; +} + +static int nix_get_last_mce_list_index(struct nix_mcast_grp_elem *elem) +{ + return elem->mce_start_index + elem->mcast_mce_list.count - 1; +} + +static int nix_update_ingress_mce_list_hw(struct rvu *rvu, + struct nix_hw *nix_hw, + struct nix_mcast_grp_elem *elem) +{ + int idx, last_idx, next_idx, err; + struct nix_mce_list *mce_list; + struct mce *mce, *prev_mce; + + mce_list = &elem->mcast_mce_list; + idx = elem->mce_start_index; + last_idx = nix_get_last_mce_list_index(elem); + hlist_for_each_entry(mce, &mce_list->head, node) { + if (idx > last_idx) + break; + + if (!mce->is_active) { + if (idx == elem->mce_start_index) { + idx++; + prev_mce = mce; + elem->mce_start_index = idx; + continue; + } else if (idx == last_idx) { + err = nix_blk_setup_mce(rvu, nix_hw, idx - 1, NIX_AQ_INSTOP_WRITE, + prev_mce->pcifunc, next_idx, + prev_mce->rq_rss_index, + prev_mce->dest_type, + false); + if (err) + return err; + + break; + } + } + + next_idx = idx + 1; + /* EOL should be set in last MCE */ + err = nix_blk_setup_mce(rvu, nix_hw, idx, NIX_AQ_INSTOP_WRITE, + mce->pcifunc, next_idx, + mce->rq_rss_index, mce->dest_type, + (next_idx > last_idx) ? true : false); + if (err) + return err; + + idx++; + prev_mce = mce; + } + + return 0; +} + +static void nix_update_egress_mce_list_hw(struct rvu *rvu, + struct nix_hw *nix_hw, + struct nix_mcast_grp_elem *elem) +{ + struct nix_mce_list *mce_list; + int idx, last_idx, next_idx; + struct mce *mce, *prev_mce; + u64 regval; + u8 eol; + + mce_list = &elem->mcast_mce_list; + idx = elem->mce_start_index; + last_idx = nix_get_last_mce_list_index(elem); + hlist_for_each_entry(mce, &mce_list->head, node) { + if (idx > last_idx) + break; + + if (!mce->is_active) { + if (idx == elem->mce_start_index) { + idx++; + prev_mce = mce; + elem->mce_start_index = idx; + continue; + } else if (idx == last_idx) { + regval = (next_idx << 16) | (1 << 12) | prev_mce->channel; + rvu_write64(rvu, nix_hw->blkaddr, + NIX_AF_TX_MCASTX(idx - 1), + regval); + break; + } + } + + eol = 0; + next_idx = idx + 1; + /* EOL should be set in last MCE */ + if (next_idx > last_idx) + eol = 1; + + regval = (next_idx << 16) | (eol << 12) | mce->channel; + rvu_write64(rvu, nix_hw->blkaddr, + NIX_AF_TX_MCASTX(idx), + regval); + idx++; + prev_mce = mce; + } +} + +static int nix_del_mce_list_entry(struct rvu *rvu, + struct nix_hw *nix_hw, + struct nix_mcast_grp_elem *elem, + struct nix_mcast_grp_update_req *req) +{ + u32 num_entry = req->num_mce_entry; + struct nix_mce_list *mce_list; + struct mce *mce; + bool is_found; + int i; + + mce_list = &elem->mcast_mce_list; + for (i = 0; i < num_entry; i++) { + is_found = false; + hlist_for_each_entry(mce, &mce_list->head, node) { + /* If already exists, then delete */ + if (mce->pcifunc == req->pcifunc[i]) { + hlist_del(&mce->node); + kfree(mce); + mce_list->count--; + is_found = true; + break; + } + } + + if (!is_found) + return NIX_AF_ERR_INVALID_MCAST_DEL_REQ; + } + + mce_list->max = mce_list->count; + /* Dump the updated list to HW */ + if (elem->dir == NIX_MCAST_INGRESS) + return nix_update_ingress_mce_list_hw(rvu, nix_hw, elem); + + nix_update_egress_mce_list_hw(rvu, nix_hw, elem); + return 0; +} + +static int nix_add_mce_list_entry(struct rvu *rvu, + struct nix_hw *nix_hw, + struct nix_mcast_grp_elem *elem, + struct nix_mcast_grp_update_req *req) +{ + struct mce *tmp_mce[NIX_MCE_ENTRY_MAX]; + u32 num_entry = req->num_mce_entry; + struct nix_mce_list *mce_list; + struct mce *mce; + int i; + + mce_list = &elem->mcast_mce_list; + for (i = 0; i < num_entry; i++) { + mce = kzalloc(sizeof(*mce), GFP_KERNEL); + if (!mce) + goto free_mce; + + mce->pcifunc = req->pcifunc[i]; + mce->channel = req->channel[i]; + mce->rq_rss_index = req->rq_rss_index[i]; + mce->dest_type = req->dest_type[i]; + mce->is_active = 1; + hlist_add_head(&mce->node, &mce_list->head); + tmp_mce[i] = mce; + mce_list->count++; + } + + mce_list->max += num_entry; + + /* Dump the updated list to HW */ + if (elem->dir == NIX_MCAST_INGRESS) + return nix_update_ingress_mce_list_hw(rvu, nix_hw, elem); + + nix_update_egress_mce_list_hw(rvu, nix_hw, elem); + return 0; + +free_mce: + while (i) { + hlist_del(&tmp_mce[i-1]->node); + kfree(tmp_mce[i-1]); + mce_list->count--; + i--; + } + + return -ENOMEM; +} + static int nix_update_mce_list_entry(struct nix_mce_list *mce_list, u16 pcifunc, bool add) { @@ -3079,6 +3304,7 @@ int nix_update_mce_list(struct rvu *rvu, u16 pcifunc, /* EOL should be set in last MCE */ err = nix_blk_setup_mce(rvu, nix_hw, idx, NIX_AQ_INSTOP_WRITE, mce->pcifunc, next_idx, + 0, 1, (next_idx > last_idx) ? true : false); if (err) goto end; @@ -3159,6 +3385,16 @@ static int nix_update_mce_rule(struct rvu *rvu, u16 pcifunc, return err; } +static void nix_setup_mcast_grp(struct nix_hw *nix_hw) +{ + struct nix_mcast_grp *mcast_grp = &nix_hw->mcast_grp; + + INIT_LIST_HEAD(&mcast_grp->mcast_grp_head); + mutex_init(&mcast_grp->mcast_grp_lock); + mcast_grp->next_grp_index = 1; + mcast_grp->count = 0; +} + static int nix_setup_mce_tables(struct rvu *rvu, struct nix_hw *nix_hw) { struct nix_mcast *mcast = &nix_hw->mcast; @@ -3183,15 +3419,15 @@ static int nix_setup_mce_tables(struct rvu *rvu, struct nix_hw *nix_hw) continue; /* save start idx of broadcast mce list */ - pfvf->bcast_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1); + pfvf->bcast_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1, NIX_MCAST_INGRESS); nix_mce_list_init(&pfvf->bcast_mce_list, numvfs + 1); /* save start idx of multicast mce list */ - pfvf->mcast_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1); + pfvf->mcast_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1, NIX_MCAST_INGRESS); nix_mce_list_init(&pfvf->mcast_mce_list, numvfs + 1); /* save the start idx of promisc mce list */ - pfvf->promisc_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1); + pfvf->promisc_mce_idx = nix_alloc_mce_list(mcast, numvfs + 1, NIX_MCAST_INGRESS); nix_mce_list_init(&pfvf->promisc_mce_list, numvfs + 1); for (idx = 0; idx < (numvfs + 1); idx++) { @@ -3206,7 +3442,7 @@ static int nix_setup_mce_tables(struct rvu *rvu, struct nix_hw *nix_hw) err = nix_blk_setup_mce(rvu, nix_hw, pfvf->bcast_mce_idx + idx, NIX_AQ_INSTOP_INIT, - pcifunc, 0, true); + pcifunc, 0, 0, 1, true); if (err) return err; @@ -3214,7 +3450,7 @@ static int nix_setup_mce_tables(struct rvu *rvu, struct nix_hw *nix_hw) err = nix_blk_setup_mce(rvu, nix_hw, pfvf->mcast_mce_idx + idx, NIX_AQ_INSTOP_INIT, - pcifunc, 0, true); + pcifunc, 0, 0, 1, true); if (err) return err; @@ -3222,7 +3458,7 @@ static int nix_setup_mce_tables(struct rvu *rvu, struct nix_hw *nix_hw) err = nix_blk_setup_mce(rvu, nix_hw, pfvf->promisc_mce_idx + idx, NIX_AQ_INSTOP_INIT, - pcifunc, 0, true); + pcifunc, 0, 0, 1, true); if (err) return err; } @@ -3237,13 +3473,30 @@ static int nix_setup_mcast(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) int err, size; size = (rvu_read64(rvu, blkaddr, NIX_AF_CONST3) >> 16) & 0x0F; - size = (1ULL << size); + size = BIT_ULL(size); + + /* Allocate bitmap for rx mce entries */ + mcast->mce_counter[NIX_MCAST_INGRESS].max = 256UL << MC_TBL_SIZE; + err = rvu_alloc_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); + if (err) + return -ENOMEM; + + /* Allocate bitmap for tx mce entries */ + mcast->mce_counter[NIX_MCAST_EGRESS].max = MC_TX_MAX; + err = rvu_alloc_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); + if (err) { + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); + return -ENOMEM; + } /* Alloc memory for multicast/mirror replication entries */ err = qmem_alloc(rvu->dev, &mcast->mce_ctx, - (256UL << MC_TBL_SIZE), size); - if (err) + mcast->mce_counter[NIX_MCAST_INGRESS].max, size); + if (err) { + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); return -ENOMEM; + } rvu_write64(rvu, blkaddr, NIX_AF_RX_MCAST_BASE, (u64)mcast->mce_ctx->iova); @@ -3256,8 +3509,12 @@ static int nix_setup_mcast(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) size = rvu_read64(rvu, blkaddr, NIX_AF_MC_MIRROR_CONST) & 0xFFFF; err = qmem_alloc(rvu->dev, &mcast->mcast_buf, (8UL << MC_BUF_CNT), size); - if (err) + if (err) { + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); + qmem_free(rvu->dev, mcast->mce_ctx); return -ENOMEM; + } rvu_write64(rvu, blkaddr, NIX_AF_RX_MCAST_BUF_BASE, (u64)mcast->mcast_buf->iova); @@ -3271,6 +3528,8 @@ static int nix_setup_mcast(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) mutex_init(&mcast->mce_lock); + nix_setup_mcast_grp(nix_hw); + return nix_setup_mce_tables(rvu, nix_hw); } @@ -4794,6 +5053,78 @@ void rvu_nix_freemem(struct rvu *rvu) } } +static void nix_mcast_update_action(struct rvu *rvu, + struct nix_mcast_grp_elem *elem) +{ + struct npc_mcam *mcam = &rvu->hw->mcam; + struct nix_rx_action rx_action = { 0 }; + struct nix_tx_action tx_action = { 0 }; + int npc_blkaddr; + + npc_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (elem->dir == NIX_MCAST_INGRESS) { + *(u64 *)&rx_action = npc_get_mcam_action(rvu, mcam, + npc_blkaddr, + elem->mcam_index); + rx_action.index = elem->mce_start_index; + npc_set_mcam_action(rvu, mcam, npc_blkaddr, elem->mcam_index, + *(u64 *)&rx_action); + } else { + *(u64 *)&tx_action = npc_get_mcam_action(rvu, mcam, + npc_blkaddr, + elem->mcam_index); + tx_action.index = elem->mce_start_index; + npc_set_mcam_action(rvu, mcam, npc_blkaddr, elem->mcam_index, + *(u64 *)&tx_action); + } +} + +static void nix_mcast_update_mce_entry(struct rvu *rvu, u16 pcifunc, u8 is_active) +{ + struct nix_mcast_grp_elem *elem; + struct nix_mcast_grp *mcast_grp; + struct nix_hw *nix_hw; + int blkaddr; + + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); + nix_hw = get_nix_hw(rvu->hw, blkaddr); + if (!nix_hw) + return; + + mcast_grp = &nix_hw->mcast_grp; + + mutex_lock(&mcast_grp->mcast_grp_lock); + list_for_each_entry(elem, &mcast_grp->mcast_grp_head, list) { + struct nix_mce_list *mce_list; + struct mce *mce; + + /* Iterate the group elements and disable the element which + * received the disable request. + */ + mce_list = &elem->mcast_mce_list; + hlist_for_each_entry(mce, &mce_list->head, node) { + if (mce->pcifunc == pcifunc) { + if (is_active) + mce->is_active = 1; + else + mce->is_active = 0; + + break; + } + } + + /* Dump the updated list to HW */ + if (elem->dir == NIX_MCAST_INGRESS) + nix_update_ingress_mce_list_hw(rvu, nix_hw, elem); + else + nix_update_egress_mce_list_hw(rvu, nix_hw, elem); + + /* Update the multicast index in NPC rule */ + nix_mcast_update_action(rvu, elem); + } + mutex_unlock(&mcast_grp->mcast_grp_lock); +} + int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req, struct msg_rsp *rsp) { @@ -4805,6 +5136,9 @@ int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req, if (err) return err; + /* Enable the interface if it is in any multicast list */ + nix_mcast_update_mce_entry(rvu, pcifunc, 1); + rvu_npc_enable_default_entries(rvu, pcifunc, nixlf); npc_mcam_enable_flows(rvu, pcifunc); @@ -4829,6 +5163,9 @@ int rvu_mbox_handler_nix_lf_stop_rx(struct rvu *rvu, struct msg_req *req, return err; rvu_npc_disable_mcam_entries(rvu, pcifunc, nixlf); + /* Disable the interface if it is in any multicast list */ + nix_mcast_update_mce_entry(rvu, pcifunc, 0); + pfvf = rvu_get_pfvf(rvu, pcifunc); clear_bit(NIXLF_INITIALIZED, &pfvf->flags); @@ -5797,3 +6134,327 @@ int rvu_mbox_handler_nix_bandprof_get_hwinfo(struct rvu *rvu, struct msg_req *re return 0; } + +static struct nix_mcast_grp_elem *rvu_nix_mcast_find_grp_elem(struct nix_mcast_grp *mcast_grp, + u32 mcast_grp_idx) +{ + struct nix_mcast_grp_elem *iter, *result_iter = NULL; + + mutex_lock(&mcast_grp->mcast_grp_lock); + list_for_each_entry(iter, &mcast_grp->mcast_grp_head, list) { + if (iter->mcast_grp_idx == mcast_grp_idx) { + result_iter = iter; + break; + } + } + mutex_unlock(&mcast_grp->mcast_grp_lock); + + return result_iter; +} + +int rvu_nix_mcast_get_mce_index(struct rvu *rvu, u16 pcifunc, u32 mcast_grp_idx) +{ + struct nix_mcast_grp_elem *elem; + struct nix_mcast_grp *mcast_grp; + struct nix_hw *nix_hw; + int blkaddr; + + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); + nix_hw = get_nix_hw(rvu->hw, blkaddr); + if (!nix_hw) + return NIX_AF_ERR_INVALID_NIXBLK; + + mcast_grp = &nix_hw->mcast_grp; + elem = rvu_nix_mcast_find_grp_elem(mcast_grp, mcast_grp_idx); + if (!elem) + return NIX_AF_ERR_INVALID_MCAST_GRP; + + return elem->mce_start_index; +} + +void rvu_nix_mcast_flr_free_entries(struct rvu *rvu, u16 pcifunc) +{ + struct nix_mcast_grp_destroy_req dreq = { 0 }; + struct nix_mcast_grp_update_req ureq = { 0 }; + struct nix_mcast_grp_update_rsp ursp = { 0 }; + struct nix_mcast_grp_elem *elem, *tmp; + struct nix_mcast_grp *mcast_grp; + struct nix_hw *nix_hw; + int blkaddr; + + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); + nix_hw = get_nix_hw(rvu->hw, blkaddr); + if (!nix_hw) + return; + + mcast_grp = &nix_hw->mcast_grp; + + mutex_lock(&mcast_grp->mcast_grp_lock); + list_for_each_entry_safe(elem, tmp, &mcast_grp->mcast_grp_head, list) { + struct nix_mce_list *mce_list; + struct hlist_node *tmp; + struct mce *mce; + + /* If the pcifunc which created the multicast/mirror + * group received an FLR, then delete the entire group. + */ + if (elem->pcifunc == pcifunc) { + mutex_unlock(&mcast_grp->mcast_grp_lock); + /* Delete group */ + dreq.hdr.pcifunc = elem->pcifunc; + dreq.mcast_grp_idx = elem->mcast_grp_idx; + rvu_mbox_handler_nix_mcast_grp_destroy(rvu, &dreq, NULL); + mutex_lock(&mcast_grp->mcast_grp_lock); + continue; + } + + /* Iterate the group elements and delete the element which + * received the FLR. + */ + mce_list = &elem->mcast_mce_list; + hlist_for_each_entry_safe(mce, tmp, &mce_list->head, node) { + if (mce->pcifunc == pcifunc) { + mutex_unlock(&mcast_grp->mcast_grp_lock); + ureq.hdr.pcifunc = pcifunc; + ureq.num_mce_entry = 1; + ureq.mcast_grp_idx = elem->mcast_grp_idx; + ureq.op = NIX_MCAST_OP_DEL_ENTRY; + ureq.pcifunc[0] = pcifunc; + rvu_mbox_handler_nix_mcast_grp_update(rvu, &ureq, &ursp); + mutex_lock(&mcast_grp->mcast_grp_lock); + break; + } + } + } + mutex_unlock(&mcast_grp->mcast_grp_lock); +} + +int rvu_nix_mcast_update_mcam_entry(struct rvu *rvu, u16 pcifunc, + u32 mcast_grp_idx, u16 mcam_index) +{ + struct nix_mcast_grp_elem *elem; + struct nix_mcast_grp *mcast_grp; + struct nix_hw *nix_hw; + int blkaddr; + + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); + nix_hw = get_nix_hw(rvu->hw, blkaddr); + if (!nix_hw) + return NIX_AF_ERR_INVALID_NIXBLK; + + mcast_grp = &nix_hw->mcast_grp; + elem = rvu_nix_mcast_find_grp_elem(mcast_grp, mcast_grp_idx); + if (!elem) + return NIX_AF_ERR_INVALID_MCAST_GRP; + + elem->mcam_index = mcam_index; + + return 0; +} + +int rvu_mbox_handler_nix_mcast_grp_create(struct rvu *rvu, + struct nix_mcast_grp_create_req *req, + struct nix_mcast_grp_create_rsp *rsp) +{ + struct nix_mcast_grp_elem *elem; + struct nix_mcast_grp *mcast_grp; + struct nix_hw *nix_hw; + int blkaddr, err; + + err = nix_get_struct_ptrs(rvu, req->hdr.pcifunc, &nix_hw, &blkaddr); + if (err) + return err; + + mcast_grp = &nix_hw->mcast_grp; + elem = kzalloc(sizeof(*elem), GFP_KERNEL); + if (!elem) + return -ENOMEM; + + INIT_HLIST_HEAD(&elem->mcast_mce_list.head); + elem->mcam_index = -1; + elem->mce_start_index = -1; + elem->pcifunc = req->hdr.pcifunc; + elem->dir = req->dir; + elem->mcast_grp_idx = mcast_grp->next_grp_index++; + + mutex_lock(&mcast_grp->mcast_grp_lock); + list_add_tail(&elem->list, &mcast_grp->mcast_grp_head); + mcast_grp->count++; + mutex_unlock(&mcast_grp->mcast_grp_lock); + + rsp->mcast_grp_idx = elem->mcast_grp_idx; + return 0; +} + +int rvu_mbox_handler_nix_mcast_grp_destroy(struct rvu *rvu, + struct nix_mcast_grp_destroy_req *req, + struct msg_rsp *rsp) +{ + struct npc_delete_flow_req uninstall_req = { 0 }; + struct npc_delete_flow_rsp uninstall_rsp = { 0 }; + struct nix_mcast_grp_elem *elem; + struct nix_mcast_grp *mcast_grp; + struct nix_mcast *mcast; + struct nix_hw *nix_hw; + int blkaddr, err; + + err = nix_get_struct_ptrs(rvu, req->hdr.pcifunc, &nix_hw, &blkaddr); + if (err) + return err; + + mcast_grp = &nix_hw->mcast_grp; + elem = rvu_nix_mcast_find_grp_elem(mcast_grp, req->mcast_grp_idx); + if (!elem) + return NIX_AF_ERR_INVALID_MCAST_GRP; + + /* If no mce entries are associated with the group + * then just remove it from the global list. + */ + if (!elem->mcast_mce_list.count) + goto delete_grp; + + /* Delete the associated mcam entry and + * remove all mce entries from the group + */ + mcast = &nix_hw->mcast; + mutex_lock(&mcast->mce_lock); + if (elem->mcam_index != -1) { + uninstall_req.hdr.pcifunc = req->hdr.pcifunc; + uninstall_req.entry = elem->mcam_index; + rvu_mbox_handler_npc_delete_flow(rvu, &uninstall_req, &uninstall_rsp); + } + + nix_free_mce_list(mcast, elem->mcast_mce_list.count, + elem->mce_start_index, elem->dir); + nix_delete_mcast_mce_list(&elem->mcast_mce_list); + mutex_unlock(&mcast->mce_lock); + +delete_grp: + mutex_lock(&mcast_grp->mcast_grp_lock); + list_del(&elem->list); + kfree(elem); + mcast_grp->count--; + mutex_unlock(&mcast_grp->mcast_grp_lock); + return 0; +} + +int rvu_mbox_handler_nix_mcast_grp_update(struct rvu *rvu, + struct nix_mcast_grp_update_req *req, + struct nix_mcast_grp_update_rsp *rsp) +{ + struct nix_mcast_grp_destroy_req dreq = { 0 }; + struct npc_mcam *mcam = &rvu->hw->mcam; + struct nix_mcast_grp_elem *elem; + struct nix_mcast_grp *mcast_grp; + int blkaddr, err, npc_blkaddr; + u16 prev_count, new_count; + struct nix_mcast *mcast; + struct nix_hw *nix_hw; + int i, ret; + + if (!req->num_mce_entry) + return 0; + + err = nix_get_struct_ptrs(rvu, req->hdr.pcifunc, &nix_hw, &blkaddr); + if (err) + return err; + + mcast_grp = &nix_hw->mcast_grp; + elem = rvu_nix_mcast_find_grp_elem(mcast_grp, req->mcast_grp_idx); + if (!elem) + return NIX_AF_ERR_INVALID_MCAST_GRP; + + /* If any pcifunc matches the group's pcifunc, then we can + * delete the entire group. + */ + if (req->op == NIX_MCAST_OP_DEL_ENTRY) { + for (i = 0; i < req->num_mce_entry; i++) { + if (elem->pcifunc == req->pcifunc[i]) { + /* Delete group */ + dreq.hdr.pcifunc = elem->pcifunc; + dreq.mcast_grp_idx = elem->mcast_grp_idx; + rvu_mbox_handler_nix_mcast_grp_destroy(rvu, &dreq, NULL); + return 0; + } + } + } + + mcast = &nix_hw->mcast; + mutex_lock(&mcast->mce_lock); + npc_blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0); + if (elem->mcam_index != -1) + npc_enable_mcam_entry(rvu, mcam, npc_blkaddr, elem->mcam_index, false); + + prev_count = elem->mcast_mce_list.count; + if (req->op == NIX_MCAST_OP_ADD_ENTRY) { + new_count = prev_count + req->num_mce_entry; + if (prev_count) + nix_free_mce_list(mcast, prev_count, elem->mce_start_index, elem->dir); + + elem->mce_start_index = nix_alloc_mce_list(mcast, new_count, elem->dir); + + /* It is possible not to get contiguous memory */ + if (elem->mce_start_index < 0) { + if (elem->mcam_index != -1) { + npc_enable_mcam_entry(rvu, mcam, npc_blkaddr, + elem->mcam_index, true); + ret = NIX_AF_ERR_NON_CONTIG_MCE_LIST; + goto done; + } + } + + ret = nix_add_mce_list_entry(rvu, nix_hw, elem, req); + if (ret) { + nix_free_mce_list(mcast, new_count, elem->mce_start_index, elem->dir); + if (prev_count) + elem->mce_start_index = nix_alloc_mce_list(mcast, + prev_count, + elem->dir); + + if (elem->mcam_index != -1) + npc_enable_mcam_entry(rvu, mcam, npc_blkaddr, + elem->mcam_index, true); + + goto done; + } + } else { + if (!prev_count || prev_count < req->num_mce_entry) { + if (elem->mcam_index != -1) + npc_enable_mcam_entry(rvu, mcam, npc_blkaddr, + elem->mcam_index, true); + ret = NIX_AF_ERR_INVALID_MCAST_DEL_REQ; + goto done; + } + + nix_free_mce_list(mcast, prev_count, elem->mce_start_index, elem->dir); + new_count = prev_count - req->num_mce_entry; + elem->mce_start_index = nix_alloc_mce_list(mcast, new_count, elem->dir); + ret = nix_del_mce_list_entry(rvu, nix_hw, elem, req); + if (ret) { + nix_free_mce_list(mcast, new_count, elem->mce_start_index, elem->dir); + elem->mce_start_index = nix_alloc_mce_list(mcast, prev_count, elem->dir); + if (elem->mcam_index != -1) + npc_enable_mcam_entry(rvu, mcam, + npc_blkaddr, + elem->mcam_index, + true); + + goto done; + } + } + + if (elem->mcam_index == -1) { + rsp->mce_start_index = elem->mce_start_index; + ret = 0; + goto done; + } + + nix_mcast_update_action(rvu, elem); + npc_enable_mcam_entry(rvu, mcam, npc_blkaddr, elem->mcam_index, true); + rsp->mce_start_index = elem->mce_start_index; + ret = 0; + +done: + mutex_unlock(&mcast->mce_lock); + return ret; +} diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c index 16cfc802e348..49babf968c1b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -589,8 +589,8 @@ static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam, NPC_AF_MCAMEX_BANKX_CFG(dest, dbank), cfg); } -static u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam, - int blkaddr, int index) +u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, int index) { int bank = npc_get_bank(mcam, index); @@ -599,6 +599,16 @@ static u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam, NPC_AF_MCAMEX_BANKX_ACTION(index, bank)); } +void npc_set_mcam_action(struct rvu *rvu, struct npc_mcam *mcam, + int blkaddr, int index, u64 cfg) +{ + int bank = npc_get_bank(mcam, index); + + index &= (mcam->banksize - 1); + return rvu_write64(rvu, blkaddr, + NPC_AF_MCAMEX_BANKX_ACTION(index, bank), cfg); +} + void rvu_npc_install_ucast_entry(struct rvu *rvu, u16 pcifunc, int nixlf, u64 chan, u8 *mac_addr) { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c index 114e4ec21802..cec01ec31649 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c @@ -1106,13 +1106,40 @@ static void rvu_mcam_add_counter_to_rule(struct rvu *rvu, u16 pcifunc, } } -static void npc_update_rx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, - struct mcam_entry *entry, - struct npc_install_flow_req *req, - u16 target, bool pf_set_vfs_mac) +static int npc_mcast_update_action_index(struct rvu *rvu, struct npc_install_flow_req *req, + u64 op, void *action) +{ + int mce_index; + + /* If a PF/VF is installing a multicast rule then it is expected + * that the PF/VF should have created a group for the multicast/mirror + * list. Otherwise reject the configuration. + * During this scenario, req->index is set as multicast/mirror + * group index. + */ + if (req->hdr.pcifunc && + (op == NIX_RX_ACTIONOP_MCAST || op == NIX_TX_ACTIONOP_MCAST)) { + mce_index = rvu_nix_mcast_get_mce_index(rvu, req->hdr.pcifunc, req->index); + if (mce_index < 0) + return mce_index; + + if (op == NIX_RX_ACTIONOP_MCAST) + ((struct nix_rx_action *)action)->index = mce_index; + else + ((struct nix_tx_action *)action)->index = mce_index; + } + + return 0; +} + +static int npc_update_rx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, + struct mcam_entry *entry, + struct npc_install_flow_req *req, + u16 target, bool pf_set_vfs_mac) { struct rvu_switch *rswitch = &rvu->rswitch; struct nix_rx_action action; + int ret; if (rswitch->mode == DEVLINK_ESWITCH_MODE_SWITCHDEV && pf_set_vfs_mac) req->chan_mask = 0x0; /* Do not care channel */ @@ -1124,6 +1151,11 @@ static void npc_update_rx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, action.pf_func = target; action.op = req->op; action.index = req->index; + + ret = npc_mcast_update_action_index(rvu, req, action.op, (void *)&action); + if (ret) + return ret; + action.match_id = req->match_id; action.flow_key_alg = req->flow_key_alg; @@ -1155,14 +1187,17 @@ static void npc_update_rx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, FIELD_PREP(RX_VTAG1_TYPE_MASK, req->vtag1_type) | FIELD_PREP(RX_VTAG1_LID_MASK, NPC_LID_LB) | FIELD_PREP(RX_VTAG1_RELPTR_MASK, 4); + + return 0; } -static void npc_update_tx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, - struct mcam_entry *entry, - struct npc_install_flow_req *req, u16 target) +static int npc_update_tx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, + struct mcam_entry *entry, + struct npc_install_flow_req *req, u16 target) { struct nix_tx_action action; u64 mask = ~0ULL; + int ret; /* If AF is installing then do not care about * PF_FUNC in Send Descriptor @@ -1176,6 +1211,11 @@ static void npc_update_tx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, *(u64 *)&action = 0x00; action.op = req->op; action.index = req->index; + + ret = npc_mcast_update_action_index(rvu, req, action.op, (void *)&action); + if (ret) + return ret; + action.match_id = req->match_id; entry->action = *(u64 *)&action; @@ -1191,6 +1231,8 @@ static void npc_update_tx_entry(struct rvu *rvu, struct rvu_pfvf *pfvf, FIELD_PREP(TX_VTAG1_OP_MASK, req->vtag1_op) | FIELD_PREP(TX_VTAG1_LID_MASK, NPC_LID_LA) | FIELD_PREP(TX_VTAG1_RELPTR_MASK, 24); + + return 0; } static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target, @@ -1220,10 +1262,15 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target, npc_update_flow(rvu, entry, features, &req->packet, &req->mask, &dummy, req->intf, blkaddr); - if (is_npc_intf_rx(req->intf)) - npc_update_rx_entry(rvu, pfvf, entry, req, target, pf_set_vfs_mac); - else - npc_update_tx_entry(rvu, pfvf, entry, req, target); + if (is_npc_intf_rx(req->intf)) { + err = npc_update_rx_entry(rvu, pfvf, entry, req, target, pf_set_vfs_mac); + if (err) + return err; + } else { + err = npc_update_tx_entry(rvu, pfvf, entry, req, target); + if (err) + return err; + } /* Default unicast rules do not exist for TX */ if (is_npc_intf_tx(req->intf)) @@ -1340,6 +1387,10 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target, return rvu_nix_setup_ratelimit_aggr(rvu, req->hdr.pcifunc, req->index, req->match_id); + if (owner && req->op == NIX_RX_ACTIONOP_MCAST) + return rvu_nix_mcast_update_mcam_entry(rvu, req->hdr.pcifunc, + req->index, entry_index); + return 0; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [net-next PATCH v3 1/2] octeontx2-af: Add new mbox to support multicast/mirror offload 2023-11-21 9:43 ` [net-next PATCH v3 1/2] octeontx2-af: Add new mbox to support multicast/mirror offload Suman Ghosh @ 2023-11-23 10:17 ` Paolo Abeni 2023-11-26 16:04 ` [EXT] " Suman Ghosh 0 siblings, 1 reply; 9+ messages in thread From: Paolo Abeni @ 2023-11-23 10:17 UTC (permalink / raw) To: Suman Ghosh, sgoutham, gakula, sbhatta, hkelam, davem, edumazet, kuba, netdev, linux-kernel, lcherian, jerinj, horms, wojciech.drewek On Tue, 2023-11-21 at 15:13 +0530, Suman Ghosh wrote: [...] > +static int nix_add_mce_list_entry(struct rvu *rvu, > + struct nix_hw *nix_hw, > + struct nix_mcast_grp_elem *elem, > + struct nix_mcast_grp_update_req *req) > +{ > + struct mce *tmp_mce[NIX_MCE_ENTRY_MAX]; If I read correctly the above struct is is 256 bytes wide. Do you really need to put so much data on the stack this deep? > + u32 num_entry = req->num_mce_entry; > + struct nix_mce_list *mce_list; > + struct mce *mce; > + int i; > + > + mce_list = &elem->mcast_mce_list; > + for (i = 0; i < num_entry; i++) { > + mce = kzalloc(sizeof(*mce), GFP_KERNEL); > + if (!mce) > + goto free_mce; > + > + mce->pcifunc = req->pcifunc[i]; > + mce->channel = req->channel[i]; > + mce->rq_rss_index = req->rq_rss_index[i]; > + mce->dest_type = req->dest_type[i]; > + mce->is_active = 1; > + hlist_add_head(&mce->node, &mce_list->head); > + tmp_mce[i] = mce; > + mce_list->count++; > + } > + > + mce_list->max += num_entry; > + > + /* Dump the updated list to HW */ > + if (elem->dir == NIX_MCAST_INGRESS) > + return nix_update_ingress_mce_list_hw(rvu, nix_hw, elem); > + > + nix_update_egress_mce_list_hw(rvu, nix_hw, elem); > + return 0; > + > +free_mce: > + while (i) { > + hlist_del(&tmp_mce[i-1]->node); > + kfree(tmp_mce[i-1]); Minor nit: checkpatch complains about the above: spaces are needed around '-'. > + mce_list->count--; > + i--; > + } > + > + return -ENOMEM; > +} > + > static int nix_update_mce_list_entry(struct nix_mce_list *mce_list, > u16 pcifunc, bool add) > { [...] > @@ -3237,13 +3473,30 @@ static int nix_setup_mcast(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) > int err, size; > > size = (rvu_read64(rvu, blkaddr, NIX_AF_CONST3) >> 16) & 0x0F; > - size = (1ULL << size); > + size = BIT_ULL(size); > + > + /* Allocate bitmap for rx mce entries */ > + mcast->mce_counter[NIX_MCAST_INGRESS].max = 256UL << MC_TBL_SIZE; > + err = rvu_alloc_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); > + if (err) > + return -ENOMEM; > + > + /* Allocate bitmap for tx mce entries */ > + mcast->mce_counter[NIX_MCAST_EGRESS].max = MC_TX_MAX; > + err = rvu_alloc_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); > + if (err) { > + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); > + return -ENOMEM; > + } > > /* Alloc memory for multicast/mirror replication entries */ > err = qmem_alloc(rvu->dev, &mcast->mce_ctx, > - (256UL << MC_TBL_SIZE), size); > - if (err) > + mcast->mce_counter[NIX_MCAST_INGRESS].max, size); > + if (err) { > + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); > + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); > return -ENOMEM; > + } > > rvu_write64(rvu, blkaddr, NIX_AF_RX_MCAST_BASE, > (u64)mcast->mce_ctx->iova); > @@ -3256,8 +3509,12 @@ static int nix_setup_mcast(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) > size = rvu_read64(rvu, blkaddr, NIX_AF_MC_MIRROR_CONST) & 0xFFFF; > err = qmem_alloc(rvu->dev, &mcast->mcast_buf, > (8UL << MC_BUF_CNT), size); > - if (err) > + if (err) { > + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); > + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); > + qmem_free(rvu->dev, mcast->mce_ctx); AFAICS, the above lines frees struct that was already allocated prior to this patch. It looks like a fix possibly worthy a separate patch. [...] > +static void nix_mcast_update_mce_entry(struct rvu *rvu, u16 pcifunc, u8 is_active) > +{ > + struct nix_mcast_grp_elem *elem; > + struct nix_mcast_grp *mcast_grp; > + struct nix_hw *nix_hw; > + int blkaddr; > + > + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); > + nix_hw = get_nix_hw(rvu->hw, blkaddr); > + if (!nix_hw) > + return; > + > + mcast_grp = &nix_hw->mcast_grp; > + > + mutex_lock(&mcast_grp->mcast_grp_lock); > + list_for_each_entry(elem, &mcast_grp->mcast_grp_head, list) { > + struct nix_mce_list *mce_list; > + struct mce *mce; > + > + /* Iterate the group elements and disable the element which > + * received the disable request. > + */ > + mce_list = &elem->mcast_mce_list; > + hlist_for_each_entry(mce, &mce_list->head, node) { > + if (mce->pcifunc == pcifunc) { > + if (is_active) > + mce->is_active = 1; > + else > + mce->is_active = 0; just: mce->is_active = is_active; > + > + break; > + } > + } > + > + /* Dump the updated list to HW */ > + if (elem->dir == NIX_MCAST_INGRESS) > + nix_update_ingress_mce_list_hw(rvu, nix_hw, elem); > + else > + nix_update_egress_mce_list_hw(rvu, nix_hw, elem); > + > + /* Update the multicast index in NPC rule */ > + nix_mcast_update_action(rvu, elem); > + } > + mutex_unlock(&mcast_grp->mcast_grp_lock); > +} > + > int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req *req, > struct msg_rsp *rsp) > { [...] > @@ -5797,3 +6134,327 @@ int rvu_mbox_handler_nix_bandprof_get_hwinfo(struct rvu *rvu, struct msg_req *re > > return 0; > } > + > +static struct nix_mcast_grp_elem *rvu_nix_mcast_find_grp_elem(struct nix_mcast_grp *mcast_grp, > + u32 mcast_grp_idx) > +{ > + struct nix_mcast_grp_elem *iter, *result_iter = NULL; > + > + mutex_lock(&mcast_grp->mcast_grp_lock); > + list_for_each_entry(iter, &mcast_grp->mcast_grp_head, list) { > + if (iter->mcast_grp_idx == mcast_grp_idx) { > + result_iter = iter; > + break; > + } > + } > + mutex_unlock(&mcast_grp->mcast_grp_lock); > + > + return result_iter; What prevents 'result_iter' from being freed at this point? (and causing a later UaF) > +} > + > +int rvu_nix_mcast_get_mce_index(struct rvu *rvu, u16 pcifunc, u32 mcast_grp_idx) > +{ > + struct nix_mcast_grp_elem *elem; > + struct nix_mcast_grp *mcast_grp; > + struct nix_hw *nix_hw; > + int blkaddr; > + > + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); > + nix_hw = get_nix_hw(rvu->hw, blkaddr); > + if (!nix_hw) > + return NIX_AF_ERR_INVALID_NIXBLK; > + > + mcast_grp = &nix_hw->mcast_grp; > + elem = rvu_nix_mcast_find_grp_elem(mcast_grp, mcast_grp_idx); > + if (!elem) > + return NIX_AF_ERR_INVALID_MCAST_GRP; > + > + return elem->mce_start_index; > +} > + > +void rvu_nix_mcast_flr_free_entries(struct rvu *rvu, u16 pcifunc) > +{ > + struct nix_mcast_grp_destroy_req dreq = { 0 }; > + struct nix_mcast_grp_update_req ureq = { 0 }; > + struct nix_mcast_grp_update_rsp ursp = { 0 }; > + struct nix_mcast_grp_elem *elem, *tmp; > + struct nix_mcast_grp *mcast_grp; > + struct nix_hw *nix_hw; > + int blkaddr; > + > + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); > + nix_hw = get_nix_hw(rvu->hw, blkaddr); > + if (!nix_hw) > + return; > + > + mcast_grp = &nix_hw->mcast_grp; > + > + mutex_lock(&mcast_grp->mcast_grp_lock); > + list_for_each_entry_safe(elem, tmp, &mcast_grp->mcast_grp_head, list) { > + struct nix_mce_list *mce_list; > + struct hlist_node *tmp; > + struct mce *mce; > + > + /* If the pcifunc which created the multicast/mirror > + * group received an FLR, then delete the entire group. > + */ > + if (elem->pcifunc == pcifunc) { > + mutex_unlock(&mcast_grp->mcast_grp_lock); > + /* Delete group */ > + dreq.hdr.pcifunc = elem->pcifunc; > + dreq.mcast_grp_idx = elem->mcast_grp_idx; > + rvu_mbox_handler_nix_mcast_grp_destroy(rvu, &dreq, NULL); > + mutex_lock(&mcast_grp->mcast_grp_lock); What prevents 'tmp' from being removed and freed while the 'mcast_grp_lock' is not held? there are other similar chunks later. I'm under the impression that all the multicast data is touched under the rtnl lock protection so the above lock does not matter much, but I really did not validate such impression/guess. Generally speaking the lock schema here looks complex and hard to follow: a more descriptive changelog will help. Cheers, Paolo ^ permalink raw reply [flat|nested] 9+ messages in thread
* RE: [EXT] Re: [net-next PATCH v3 1/2] octeontx2-af: Add new mbox to support multicast/mirror offload 2023-11-23 10:17 ` Paolo Abeni @ 2023-11-26 16:04 ` Suman Ghosh 0 siblings, 0 replies; 9+ messages in thread From: Suman Ghosh @ 2023-11-26 16:04 UTC (permalink / raw) To: Paolo Abeni, Sunil Kovvuri Goutham, Geethasowjanya Akula, Subbaraya Sundeep Bhatta, Hariprasad Kelam, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Linu Cherian, Jerin Jacob Kollanukkaran, horms@kernel.org, wojciech.drewek@intel.com >[...] >> +static int nix_add_mce_list_entry(struct rvu *rvu, >> + struct nix_hw *nix_hw, >> + struct nix_mcast_grp_elem *elem, >> + struct nix_mcast_grp_update_req *req) { >> + struct mce *tmp_mce[NIX_MCE_ENTRY_MAX]; > >If I read correctly the above struct is is 256 bytes wide. Do you really >need to put so much data on the stack this deep? [Suman] Ack, will update the logic in v4. > > >> + u32 num_entry = req->num_mce_entry; >> + struct nix_mce_list *mce_list; >> + struct mce *mce; >> + int i; >> + >> + mce_list = &elem->mcast_mce_list; >> + for (i = 0; i < num_entry; i++) { >> + mce = kzalloc(sizeof(*mce), GFP_KERNEL); >> + if (!mce) >> + goto free_mce; >> + >> + mce->pcifunc = req->pcifunc[i]; >> + mce->channel = req->channel[i]; >> + mce->rq_rss_index = req->rq_rss_index[i]; >> + mce->dest_type = req->dest_type[i]; >> + mce->is_active = 1; >> + hlist_add_head(&mce->node, &mce_list->head); >> + tmp_mce[i] = mce; >> + mce_list->count++; >> + } >> + >> + mce_list->max += num_entry; >> + >> + /* Dump the updated list to HW */ >> + if (elem->dir == NIX_MCAST_INGRESS) >> + return nix_update_ingress_mce_list_hw(rvu, nix_hw, elem); >> + >> + nix_update_egress_mce_list_hw(rvu, nix_hw, elem); >> + return 0; >> + >> +free_mce: >> + while (i) { >> + hlist_del(&tmp_mce[i-1]->node); >> + kfree(tmp_mce[i-1]); > >Minor nit: checkpatch complains about the above: spaces are needed >around '-'. [Suman] This code should be updated in v4. > >> + mce_list->count--; >> + i--; >> + } >> + >> + return -ENOMEM; >> +} >> + >> static int nix_update_mce_list_entry(struct nix_mce_list *mce_list, >> u16 pcifunc, bool add) >> { > >[...] >> @@ -3237,13 +3473,30 @@ static int nix_setup_mcast(struct rvu *rvu, >struct nix_hw *nix_hw, int blkaddr) >> int err, size; >> >> size = (rvu_read64(rvu, blkaddr, NIX_AF_CONST3) >> 16) & 0x0F; >> - size = (1ULL << size); >> + size = BIT_ULL(size); >> + >> + /* Allocate bitmap for rx mce entries */ >> + mcast->mce_counter[NIX_MCAST_INGRESS].max = 256UL << MC_TBL_SIZE; >> + err = rvu_alloc_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); >> + if (err) >> + return -ENOMEM; >> + >> + /* Allocate bitmap for tx mce entries */ >> + mcast->mce_counter[NIX_MCAST_EGRESS].max = MC_TX_MAX; >> + err = rvu_alloc_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); >> + if (err) { >> + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); >> + return -ENOMEM; >> + } >> >> /* Alloc memory for multicast/mirror replication entries */ >> err = qmem_alloc(rvu->dev, &mcast->mce_ctx, >> - (256UL << MC_TBL_SIZE), size); >> - if (err) >> + mcast->mce_counter[NIX_MCAST_INGRESS].max, size); >> + if (err) { >> + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); >> + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); >> return -ENOMEM; >> + } >> >> rvu_write64(rvu, blkaddr, NIX_AF_RX_MCAST_BASE, >> (u64)mcast->mce_ctx->iova); >> @@ -3256,8 +3509,12 @@ static int nix_setup_mcast(struct rvu *rvu, >struct nix_hw *nix_hw, int blkaddr) >> size = rvu_read64(rvu, blkaddr, NIX_AF_MC_MIRROR_CONST) & 0xFFFF; >> err = qmem_alloc(rvu->dev, &mcast->mcast_buf, >> (8UL << MC_BUF_CNT), size); >> - if (err) >> + if (err) { >> + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_INGRESS]); >> + rvu_free_bitmap(&mcast->mce_counter[NIX_MCAST_EGRESS]); >> + qmem_free(rvu->dev, mcast->mce_ctx); > >AFAICS, the above lines frees struct that was already allocated prior to >this patch. It looks like a fix possibly worthy a separate patch. [Suman] Okay. I will push a separate patch for qmem_free() > >[...] >> +static void nix_mcast_update_mce_entry(struct rvu *rvu, u16 pcifunc, >> +u8 is_active) { >> + struct nix_mcast_grp_elem *elem; >> + struct nix_mcast_grp *mcast_grp; >> + struct nix_hw *nix_hw; >> + int blkaddr; >> + >> + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); >> + nix_hw = get_nix_hw(rvu->hw, blkaddr); >> + if (!nix_hw) >> + return; >> + >> + mcast_grp = &nix_hw->mcast_grp; >> + >> + mutex_lock(&mcast_grp->mcast_grp_lock); >> + list_for_each_entry(elem, &mcast_grp->mcast_grp_head, list) { >> + struct nix_mce_list *mce_list; >> + struct mce *mce; >> + >> + /* Iterate the group elements and disable the element which >> + * received the disable request. >> + */ >> + mce_list = &elem->mcast_mce_list; >> + hlist_for_each_entry(mce, &mce_list->head, node) { >> + if (mce->pcifunc == pcifunc) { >> + if (is_active) >> + mce->is_active = 1; >> + else >> + mce->is_active = 0; > >just: [Suman] ack, will update in v4 > > mce->is_active = is_active; > >> + >> + break; >> + } >> + } >> + >> + /* Dump the updated list to HW */ >> + if (elem->dir == NIX_MCAST_INGRESS) >> + nix_update_ingress_mce_list_hw(rvu, nix_hw, elem); >> + else >> + nix_update_egress_mce_list_hw(rvu, nix_hw, elem); >> + >> + /* Update the multicast index in NPC rule */ >> + nix_mcast_update_action(rvu, elem); >> + } >> + mutex_unlock(&mcast_grp->mcast_grp_lock); >> +} >> + >> int rvu_mbox_handler_nix_lf_start_rx(struct rvu *rvu, struct msg_req >*req, >> struct msg_rsp *rsp) >> { > >[...] >> @@ -5797,3 +6134,327 @@ int >> rvu_mbox_handler_nix_bandprof_get_hwinfo(struct rvu *rvu, struct >> msg_req *re >> >> return 0; >> } >> + >> +static struct nix_mcast_grp_elem *rvu_nix_mcast_find_grp_elem(struct >nix_mcast_grp *mcast_grp, >> + u32 mcast_grp_idx) >> +{ >> + struct nix_mcast_grp_elem *iter, *result_iter = NULL; >> + >> + mutex_lock(&mcast_grp->mcast_grp_lock); >> + list_for_each_entry(iter, &mcast_grp->mcast_grp_head, list) { >> + if (iter->mcast_grp_idx == mcast_grp_idx) { >> + result_iter = iter; >> + break; >> + } >> + } >> + mutex_unlock(&mcast_grp->mcast_grp_lock); >> + >> + return result_iter; > >What prevents 'result_iter' from being freed at this point? (and causing >a later UaF) [Suman] I updated this as part of a review comment, but yes, it is not correct. Will revert to older version in v4. > >> +} >> + >> +int rvu_nix_mcast_get_mce_index(struct rvu *rvu, u16 pcifunc, u32 >> +mcast_grp_idx) { >> + struct nix_mcast_grp_elem *elem; >> + struct nix_mcast_grp *mcast_grp; >> + struct nix_hw *nix_hw; >> + int blkaddr; >> + >> + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); >> + nix_hw = get_nix_hw(rvu->hw, blkaddr); >> + if (!nix_hw) >> + return NIX_AF_ERR_INVALID_NIXBLK; >> + >> + mcast_grp = &nix_hw->mcast_grp; >> + elem = rvu_nix_mcast_find_grp_elem(mcast_grp, mcast_grp_idx); >> + if (!elem) >> + return NIX_AF_ERR_INVALID_MCAST_GRP; >> + >> + return elem->mce_start_index; >> +} >> + >> +void rvu_nix_mcast_flr_free_entries(struct rvu *rvu, u16 pcifunc) { >> + struct nix_mcast_grp_destroy_req dreq = { 0 }; >> + struct nix_mcast_grp_update_req ureq = { 0 }; >> + struct nix_mcast_grp_update_rsp ursp = { 0 }; >> + struct nix_mcast_grp_elem *elem, *tmp; >> + struct nix_mcast_grp *mcast_grp; >> + struct nix_hw *nix_hw; >> + int blkaddr; >> + >> + blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); >> + nix_hw = get_nix_hw(rvu->hw, blkaddr); >> + if (!nix_hw) >> + return; >> + >> + mcast_grp = &nix_hw->mcast_grp; >> + >> + mutex_lock(&mcast_grp->mcast_grp_lock); >> + list_for_each_entry_safe(elem, tmp, &mcast_grp->mcast_grp_head, >list) { >> + struct nix_mce_list *mce_list; >> + struct hlist_node *tmp; >> + struct mce *mce; >> + >> + /* If the pcifunc which created the multicast/mirror >> + * group received an FLR, then delete the entire group. >> + */ >> + if (elem->pcifunc == pcifunc) { >> + mutex_unlock(&mcast_grp->mcast_grp_lock); >> + /* Delete group */ >> + dreq.hdr.pcifunc = elem->pcifunc; >> + dreq.mcast_grp_idx = elem->mcast_grp_idx; >> + rvu_mbox_handler_nix_mcast_grp_destroy(rvu, &dreq, NULL); >> + mutex_lock(&mcast_grp->mcast_grp_lock); > >What prevents 'tmp' from being removed and freed while the >'mcast_grp_lock' is not held? there are other similar chunks later. > >I'm under the impression that all the multicast data is touched under >the rtnl lock protection so the above lock does not matter much, but I >really did not validate such impression/guess. > >Generally speaking the lock schema here looks complex and hard to >follow: a more descriptive changelog will help. [Suman] Got it. I will try to simplify the logic and push a v4. > >Cheers, > >Paolo ^ permalink raw reply [flat|nested] 9+ messages in thread
* [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror 2023-11-21 9:43 [net-next PATCH v3 0/2] octeontx2: Multicast/mirror offload changes Suman Ghosh 2023-11-21 9:43 ` [net-next PATCH v3 1/2] octeontx2-af: Add new mbox to support multicast/mirror offload Suman Ghosh @ 2023-11-21 9:43 ` Suman Ghosh 2023-11-21 10:23 ` Wojciech Drewek 2023-11-21 14:48 ` Wojciech Drewek 1 sibling, 2 replies; 9+ messages in thread From: Suman Ghosh @ 2023-11-21 9:43 UTC (permalink / raw) To: sgoutham, gakula, sbhatta, hkelam, davem, edumazet, kuba, pabeni, netdev, linux-kernel, lcherian, jerinj, horms, wojciech.drewek Cc: Suman Ghosh This patch extends TC flower offload support for mirroring ingress/egress traffic to a different PF/VF. Below is an example command, 'tc filter add dev eth1 ingress protocol ip flower src_ip <ip-addr> skip_sw action mirred ingress mirror dev eth2' Signed-off-by: Suman Ghosh <sumang@marvell.com> --- .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 113 +++++++++++++++++- 1 file changed, 110 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 8a5e3987a482..17a8d9778193 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -29,6 +29,8 @@ #define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4) +#define MCAST_INVALID_GRP (-1U) + struct otx2_tc_flow_stats { u64 bytes; u64 pkts; @@ -47,6 +49,7 @@ struct otx2_tc_flow { bool is_act_police; u32 prio; struct npc_install_flow_req req; + u32 mcast_grp_idx; }; static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, @@ -336,22 +339,96 @@ static int otx2_tc_act_set_police(struct otx2_nic *nic, return rc; } +static int otx2_tc_update_mcast(struct otx2_nic *nic, + struct npc_install_flow_req *req, + struct netlink_ext_ack *extack, + struct otx2_tc_flow *node, + struct nix_mcast_grp_update_req *ureq, + u8 num_intf) +{ + struct nix_mcast_grp_update_req *grp_update_req; + struct nix_mcast_grp_create_req *creq; + struct nix_mcast_grp_create_rsp *crsp; + u32 grp_index; + int rc; + + mutex_lock(&nic->mbox.lock); + creq = otx2_mbox_alloc_msg_nix_mcast_grp_create(&nic->mbox); + if (!creq) { + rc = -ENOMEM; + goto error; + } + + creq->dir = NIX_MCAST_INGRESS; + /* Send message to AF */ + rc = otx2_sync_mbox_msg(&nic->mbox); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to create multicast group"); + goto error; + } + + crsp = (struct nix_mcast_grp_create_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox, + 0, + &creq->hdr); + if (IS_ERR(crsp)) { + rc = PTR_ERR(crsp); + goto error; + } + + grp_index = crsp->mcast_grp_idx; + grp_update_req = otx2_mbox_alloc_msg_nix_mcast_grp_update(&nic->mbox); + if (!grp_update_req) { + NL_SET_ERR_MSG_MOD(extack, "Failed to update multicast group"); + rc = -ENOMEM; + goto error; + } + + ureq->op = NIX_MCAST_OP_ADD_ENTRY; + ureq->mcast_grp_idx = grp_index; + ureq->num_mce_entry = num_intf; + ureq->pcifunc[0] = nic->pcifunc; + ureq->channel[0] = nic->hw.tx_chan_base; + + ureq->dest_type[0] = NIX_RX_RSS; + ureq->rq_rss_index[0] = 0; + memcpy(&ureq->hdr, &grp_update_req->hdr, sizeof(struct mbox_msghdr)); + memcpy(grp_update_req, ureq, sizeof(struct nix_mcast_grp_update_req)); + + /* Send message to AF */ + rc = otx2_sync_mbox_msg(&nic->mbox); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to update multicast group"); + goto error; + } + + mutex_unlock(&nic->mbox.lock); + req->op = NIX_RX_ACTIONOP_MCAST; + req->index = grp_index; + node->mcast_grp_idx = grp_index; + return 0; + +error: + mutex_unlock(&nic->mbox.lock); + return rc; +} + static int otx2_tc_parse_actions(struct otx2_nic *nic, struct flow_action *flow_action, struct npc_install_flow_req *req, struct flow_cls_offload *f, struct otx2_tc_flow *node) { + struct nix_mcast_grp_update_req dummy_grp_update_req = { 0 }; struct netlink_ext_ack *extack = f->common.extack; + bool pps = false, mcast = false; struct flow_action_entry *act; struct net_device *target; struct otx2_nic *priv; u32 burst, mark = 0; u8 nr_police = 0; - bool pps = false; + u8 num_intf = 1; + int err, i; u64 rate; - int err; - int i; if (!flow_action_has_entries(flow_action)) { NL_SET_ERR_MSG_MOD(extack, "no tc actions specified"); @@ -423,11 +500,30 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic, req->index = act->rx_queue; break; + case FLOW_ACTION_MIRRED_INGRESS: + target = act->dev; + priv = netdev_priv(target); + dummy_grp_update_req.pcifunc[num_intf] = priv->pcifunc; + dummy_grp_update_req.channel[num_intf] = priv->hw.tx_chan_base; + dummy_grp_update_req.dest_type[num_intf] = NIX_RX_RSS; + dummy_grp_update_req.rq_rss_index[num_intf] = 0; + mcast = true; + num_intf++; + break; + default: return -EOPNOTSUPP; } } + if (mcast) { + err = otx2_tc_update_mcast(nic, req, extack, node, + &dummy_grp_update_req, + num_intf); + if (err) + return err; + } + if (nr_police > 1) { NL_SET_ERR_MSG_MOD(extack, "rate limit police offload requires a single action"); @@ -1033,6 +1129,7 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, struct flow_cls_offload *tc_flow_cmd) { struct otx2_flow_config *flow_cfg = nic->flow_cfg; + struct nix_mcast_grp_destroy_req *grp_destroy_req; struct otx2_tc_flow *flow_node; int err; @@ -1064,6 +1161,15 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, mutex_unlock(&nic->mbox.lock); } + /* Remove the multicast/mirror related nodes */ + if (flow_node->mcast_grp_idx != MCAST_INVALID_GRP) { + mutex_lock(&nic->mbox.lock); + grp_destroy_req = otx2_mbox_alloc_msg_nix_mcast_grp_destroy(&nic->mbox); + grp_destroy_req->mcast_grp_idx = flow_node->mcast_grp_idx; + otx2_sync_mbox_msg(&nic->mbox); + mutex_unlock(&nic->mbox.lock); + } + otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL); otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false); kfree_rcu(flow_node, rcu); @@ -1096,6 +1202,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, spin_lock_init(&new_node->lock); new_node->cookie = tc_flow_cmd->cookie; new_node->prio = tc_flow_cmd->common.prio; + new_node->mcast_grp_idx = MCAST_INVALID_GRP; memset(&dummy, 0, sizeof(struct npc_install_flow_req)); -- 2.25.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror 2023-11-21 9:43 ` [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror Suman Ghosh @ 2023-11-21 10:23 ` Wojciech Drewek 2023-11-21 14:48 ` Wojciech Drewek 1 sibling, 0 replies; 9+ messages in thread From: Wojciech Drewek @ 2023-11-21 10:23 UTC (permalink / raw) To: Suman Ghosh, sgoutham, gakula, sbhatta, hkelam, davem, edumazet, kuba, pabeni, netdev, linux-kernel, lcherian, jerinj, horms On 21.11.2023 10:43, Suman Ghosh wrote: > This patch extends TC flower offload support for mirroring > ingress/egress traffic to a different PF/VF. Below is an example > command, > > 'tc filter add dev eth1 ingress protocol ip flower src_ip <ip-addr> > skip_sw action mirred ingress mirror dev eth2' > > Signed-off-by: Suman Ghosh <sumang@marvell.com> > --- If someone gave you you his tag, please add it to the next version. > .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 113 +++++++++++++++++- > 1 file changed, 110 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c > index 8a5e3987a482..17a8d9778193 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c > @@ -29,6 +29,8 @@ > > #define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4) > > +#define MCAST_INVALID_GRP (-1U) > + > struct otx2_tc_flow_stats { > u64 bytes; > u64 pkts; > @@ -47,6 +49,7 @@ struct otx2_tc_flow { > bool is_act_police; > u32 prio; > struct npc_install_flow_req req; > + u32 mcast_grp_idx; > }; > > static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, > @@ -336,22 +339,96 @@ static int otx2_tc_act_set_police(struct otx2_nic *nic, > return rc; > } > > +static int otx2_tc_update_mcast(struct otx2_nic *nic, > + struct npc_install_flow_req *req, > + struct netlink_ext_ack *extack, > + struct otx2_tc_flow *node, > + struct nix_mcast_grp_update_req *ureq, > + u8 num_intf) > +{ > + struct nix_mcast_grp_update_req *grp_update_req; > + struct nix_mcast_grp_create_req *creq; > + struct nix_mcast_grp_create_rsp *crsp; > + u32 grp_index; > + int rc; > + > + mutex_lock(&nic->mbox.lock); > + creq = otx2_mbox_alloc_msg_nix_mcast_grp_create(&nic->mbox); > + if (!creq) { > + rc = -ENOMEM; > + goto error; > + } > + > + creq->dir = NIX_MCAST_INGRESS; > + /* Send message to AF */ > + rc = otx2_sync_mbox_msg(&nic->mbox); > + if (rc) { > + NL_SET_ERR_MSG_MOD(extack, "Failed to create multicast group"); > + goto error; > + } > + > + crsp = (struct nix_mcast_grp_create_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox, > + 0, > + &creq->hdr); > + if (IS_ERR(crsp)) { > + rc = PTR_ERR(crsp); > + goto error; > + } > + > + grp_index = crsp->mcast_grp_idx; > + grp_update_req = otx2_mbox_alloc_msg_nix_mcast_grp_update(&nic->mbox); > + if (!grp_update_req) { > + NL_SET_ERR_MSG_MOD(extack, "Failed to update multicast group"); > + rc = -ENOMEM; > + goto error; > + } > + > + ureq->op = NIX_MCAST_OP_ADD_ENTRY; > + ureq->mcast_grp_idx = grp_index; > + ureq->num_mce_entry = num_intf; > + ureq->pcifunc[0] = nic->pcifunc; > + ureq->channel[0] = nic->hw.tx_chan_base; > + > + ureq->dest_type[0] = NIX_RX_RSS; > + ureq->rq_rss_index[0] = 0; > + memcpy(&ureq->hdr, &grp_update_req->hdr, sizeof(struct mbox_msghdr)); > + memcpy(grp_update_req, ureq, sizeof(struct nix_mcast_grp_update_req)); > + > + /* Send message to AF */ > + rc = otx2_sync_mbox_msg(&nic->mbox); > + if (rc) { > + NL_SET_ERR_MSG_MOD(extack, "Failed to update multicast group"); > + goto error; > + } > + > + mutex_unlock(&nic->mbox.lock); > + req->op = NIX_RX_ACTIONOP_MCAST; > + req->index = grp_index; > + node->mcast_grp_idx = grp_index; > + return 0; > + > +error: > + mutex_unlock(&nic->mbox.lock); > + return rc; > +} > + > static int otx2_tc_parse_actions(struct otx2_nic *nic, > struct flow_action *flow_action, > struct npc_install_flow_req *req, > struct flow_cls_offload *f, > struct otx2_tc_flow *node) > { > + struct nix_mcast_grp_update_req dummy_grp_update_req = { 0 }; > struct netlink_ext_ack *extack = f->common.extack; > + bool pps = false, mcast = false; > struct flow_action_entry *act; > struct net_device *target; > struct otx2_nic *priv; > u32 burst, mark = 0; > u8 nr_police = 0; > - bool pps = false; > + u8 num_intf = 1; > + int err, i; > u64 rate; > - int err; > - int i; > > if (!flow_action_has_entries(flow_action)) { > NL_SET_ERR_MSG_MOD(extack, "no tc actions specified"); > @@ -423,11 +500,30 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic, > req->index = act->rx_queue; > break; > > + case FLOW_ACTION_MIRRED_INGRESS: > + target = act->dev; > + priv = netdev_priv(target); > + dummy_grp_update_req.pcifunc[num_intf] = priv->pcifunc; > + dummy_grp_update_req.channel[num_intf] = priv->hw.tx_chan_base; > + dummy_grp_update_req.dest_type[num_intf] = NIX_RX_RSS; > + dummy_grp_update_req.rq_rss_index[num_intf] = 0; > + mcast = true; > + num_intf++; > + break; > + > default: > return -EOPNOTSUPP; > } > } > > + if (mcast) { > + err = otx2_tc_update_mcast(nic, req, extack, node, > + &dummy_grp_update_req, > + num_intf); > + if (err) > + return err; > + } > + > if (nr_police > 1) { > NL_SET_ERR_MSG_MOD(extack, > "rate limit police offload requires a single action"); > @@ -1033,6 +1129,7 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, > struct flow_cls_offload *tc_flow_cmd) > { > struct otx2_flow_config *flow_cfg = nic->flow_cfg; > + struct nix_mcast_grp_destroy_req *grp_destroy_req; > struct otx2_tc_flow *flow_node; > int err; > > @@ -1064,6 +1161,15 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, > mutex_unlock(&nic->mbox.lock); > } > > + /* Remove the multicast/mirror related nodes */ > + if (flow_node->mcast_grp_idx != MCAST_INVALID_GRP) { > + mutex_lock(&nic->mbox.lock); > + grp_destroy_req = otx2_mbox_alloc_msg_nix_mcast_grp_destroy(&nic->mbox); > + grp_destroy_req->mcast_grp_idx = flow_node->mcast_grp_idx; > + otx2_sync_mbox_msg(&nic->mbox); > + mutex_unlock(&nic->mbox.lock); > + } > + > otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL); > otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false); > kfree_rcu(flow_node, rcu); > @@ -1096,6 +1202,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, > spin_lock_init(&new_node->lock); > new_node->cookie = tc_flow_cmd->cookie; > new_node->prio = tc_flow_cmd->common.prio; > + new_node->mcast_grp_idx = MCAST_INVALID_GRP; > > memset(&dummy, 0, sizeof(struct npc_install_flow_req)); > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror 2023-11-21 9:43 ` [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror Suman Ghosh 2023-11-21 10:23 ` Wojciech Drewek @ 2023-11-21 14:48 ` Wojciech Drewek 2023-11-23 10:21 ` Paolo Abeni 1 sibling, 1 reply; 9+ messages in thread From: Wojciech Drewek @ 2023-11-21 14:48 UTC (permalink / raw) To: Suman Ghosh, sgoutham, gakula, sbhatta, hkelam, davem, edumazet, kuba, pabeni, netdev, linux-kernel, lcherian, jerinj, horms On 21.11.2023 10:43, Suman Ghosh wrote: > This patch extends TC flower offload support for mirroring > ingress/egress traffic to a different PF/VF. Below is an example > command, > > 'tc filter add dev eth1 ingress protocol ip flower src_ip <ip-addr> > skip_sw action mirred ingress mirror dev eth2' > > Signed-off-by: Suman Ghosh <sumang@marvell.com> Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com> > --- > .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 113 +++++++++++++++++- > 1 file changed, 110 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c > index 8a5e3987a482..17a8d9778193 100644 > --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c > +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c > @@ -29,6 +29,8 @@ > > #define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4) > > +#define MCAST_INVALID_GRP (-1U) > + > struct otx2_tc_flow_stats { > u64 bytes; > u64 pkts; > @@ -47,6 +49,7 @@ struct otx2_tc_flow { > bool is_act_police; > u32 prio; > struct npc_install_flow_req req; > + u32 mcast_grp_idx; > }; > > static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, > @@ -336,22 +339,96 @@ static int otx2_tc_act_set_police(struct otx2_nic *nic, > return rc; > } > > +static int otx2_tc_update_mcast(struct otx2_nic *nic, > + struct npc_install_flow_req *req, > + struct netlink_ext_ack *extack, > + struct otx2_tc_flow *node, > + struct nix_mcast_grp_update_req *ureq, > + u8 num_intf) > +{ > + struct nix_mcast_grp_update_req *grp_update_req; > + struct nix_mcast_grp_create_req *creq; > + struct nix_mcast_grp_create_rsp *crsp; > + u32 grp_index; > + int rc; > + > + mutex_lock(&nic->mbox.lock); > + creq = otx2_mbox_alloc_msg_nix_mcast_grp_create(&nic->mbox); > + if (!creq) { > + rc = -ENOMEM; > + goto error; > + } > + > + creq->dir = NIX_MCAST_INGRESS; > + /* Send message to AF */ > + rc = otx2_sync_mbox_msg(&nic->mbox); > + if (rc) { > + NL_SET_ERR_MSG_MOD(extack, "Failed to create multicast group"); > + goto error; > + } > + > + crsp = (struct nix_mcast_grp_create_rsp *)otx2_mbox_get_rsp(&nic->mbox.mbox, > + 0, > + &creq->hdr); > + if (IS_ERR(crsp)) { > + rc = PTR_ERR(crsp); > + goto error; > + } > + > + grp_index = crsp->mcast_grp_idx; > + grp_update_req = otx2_mbox_alloc_msg_nix_mcast_grp_update(&nic->mbox); > + if (!grp_update_req) { > + NL_SET_ERR_MSG_MOD(extack, "Failed to update multicast group"); > + rc = -ENOMEM; > + goto error; > + } > + > + ureq->op = NIX_MCAST_OP_ADD_ENTRY; > + ureq->mcast_grp_idx = grp_index; > + ureq->num_mce_entry = num_intf; > + ureq->pcifunc[0] = nic->pcifunc; > + ureq->channel[0] = nic->hw.tx_chan_base; > + > + ureq->dest_type[0] = NIX_RX_RSS; > + ureq->rq_rss_index[0] = 0; > + memcpy(&ureq->hdr, &grp_update_req->hdr, sizeof(struct mbox_msghdr)); > + memcpy(grp_update_req, ureq, sizeof(struct nix_mcast_grp_update_req)); > + > + /* Send message to AF */ > + rc = otx2_sync_mbox_msg(&nic->mbox); > + if (rc) { > + NL_SET_ERR_MSG_MOD(extack, "Failed to update multicast group"); > + goto error; > + } > + > + mutex_unlock(&nic->mbox.lock); > + req->op = NIX_RX_ACTIONOP_MCAST; > + req->index = grp_index; > + node->mcast_grp_idx = grp_index; > + return 0; > + > +error: > + mutex_unlock(&nic->mbox.lock); > + return rc; > +} > + > static int otx2_tc_parse_actions(struct otx2_nic *nic, > struct flow_action *flow_action, > struct npc_install_flow_req *req, > struct flow_cls_offload *f, > struct otx2_tc_flow *node) > { > + struct nix_mcast_grp_update_req dummy_grp_update_req = { 0 }; > struct netlink_ext_ack *extack = f->common.extack; > + bool pps = false, mcast = false; > struct flow_action_entry *act; > struct net_device *target; > struct otx2_nic *priv; > u32 burst, mark = 0; > u8 nr_police = 0; > - bool pps = false; > + u8 num_intf = 1; > + int err, i; > u64 rate; > - int err; > - int i; > > if (!flow_action_has_entries(flow_action)) { > NL_SET_ERR_MSG_MOD(extack, "no tc actions specified"); > @@ -423,11 +500,30 @@ static int otx2_tc_parse_actions(struct otx2_nic *nic, > req->index = act->rx_queue; > break; > > + case FLOW_ACTION_MIRRED_INGRESS: > + target = act->dev; > + priv = netdev_priv(target); > + dummy_grp_update_req.pcifunc[num_intf] = priv->pcifunc; > + dummy_grp_update_req.channel[num_intf] = priv->hw.tx_chan_base; > + dummy_grp_update_req.dest_type[num_intf] = NIX_RX_RSS; > + dummy_grp_update_req.rq_rss_index[num_intf] = 0; > + mcast = true; > + num_intf++; > + break; > + > default: > return -EOPNOTSUPP; > } > } > > + if (mcast) { > + err = otx2_tc_update_mcast(nic, req, extack, node, > + &dummy_grp_update_req, > + num_intf); > + if (err) > + return err; > + } > + > if (nr_police > 1) { > NL_SET_ERR_MSG_MOD(extack, > "rate limit police offload requires a single action"); > @@ -1033,6 +1129,7 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, > struct flow_cls_offload *tc_flow_cmd) > { > struct otx2_flow_config *flow_cfg = nic->flow_cfg; > + struct nix_mcast_grp_destroy_req *grp_destroy_req; > struct otx2_tc_flow *flow_node; > int err; > > @@ -1064,6 +1161,15 @@ static int otx2_tc_del_flow(struct otx2_nic *nic, > mutex_unlock(&nic->mbox.lock); > } > > + /* Remove the multicast/mirror related nodes */ > + if (flow_node->mcast_grp_idx != MCAST_INVALID_GRP) { > + mutex_lock(&nic->mbox.lock); > + grp_destroy_req = otx2_mbox_alloc_msg_nix_mcast_grp_destroy(&nic->mbox); > + grp_destroy_req->mcast_grp_idx = flow_node->mcast_grp_idx; > + otx2_sync_mbox_msg(&nic->mbox); > + mutex_unlock(&nic->mbox.lock); > + } > + > otx2_del_mcam_flow_entry(nic, flow_node->entry, NULL); > otx2_tc_update_mcam_table(nic, flow_cfg, flow_node, false); > kfree_rcu(flow_node, rcu); > @@ -1096,6 +1202,7 @@ static int otx2_tc_add_flow(struct otx2_nic *nic, > spin_lock_init(&new_node->lock); > new_node->cookie = tc_flow_cmd->cookie; > new_node->prio = tc_flow_cmd->common.prio; > + new_node->mcast_grp_idx = MCAST_INVALID_GRP; > > memset(&dummy, 0, sizeof(struct npc_install_flow_req)); > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror 2023-11-21 14:48 ` Wojciech Drewek @ 2023-11-23 10:21 ` Paolo Abeni 2023-11-23 10:35 ` Wojciech Drewek 0 siblings, 1 reply; 9+ messages in thread From: Paolo Abeni @ 2023-11-23 10:21 UTC (permalink / raw) To: Wojciech Drewek, Suman Ghosh, sgoutham, gakula, sbhatta, hkelam, davem, edumazet, kuba, netdev, linux-kernel, lcherian, jerinj, horms On Tue, 2023-11-21 at 15:48 +0100, Wojciech Drewek wrote: > > On 21.11.2023 10:43, Suman Ghosh wrote: > > This patch extends TC flower offload support for mirroring > > ingress/egress traffic to a different PF/VF. Below is an example > > command, > > > > 'tc filter add dev eth1 ingress protocol ip flower src_ip <ip-addr> > > skip_sw action mirred ingress mirror dev eth2' > > > > Signed-off-by: Suman Ghosh <sumang@marvell.com> > > Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com> Thank you for your review! Please, additionally try to trim away the irrelevant part of the patch when replying (in this case almost everything). That helps a lot following the discussion, especially on long patches, thanks! @Suman: please retain Wojciech's tag on next revision of this series. Cheers, Paolo ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror 2023-11-23 10:21 ` Paolo Abeni @ 2023-11-23 10:35 ` Wojciech Drewek 0 siblings, 0 replies; 9+ messages in thread From: Wojciech Drewek @ 2023-11-23 10:35 UTC (permalink / raw) To: Paolo Abeni, Suman Ghosh, sgoutham, gakula, sbhatta, hkelam, davem, edumazet, kuba, netdev, linux-kernel, lcherian, jerinj, horms On 23.11.2023 11:21, Paolo Abeni wrote: > On Tue, 2023-11-21 at 15:48 +0100, Wojciech Drewek wrote: >> >> On 21.11.2023 10:43, Suman Ghosh wrote: >>> This patch extends TC flower offload support for mirroring >>> ingress/egress traffic to a different PF/VF. Below is an example >>> command, >>> >>> 'tc filter add dev eth1 ingress protocol ip flower src_ip <ip-addr> >>> skip_sw action mirred ingress mirror dev eth2' >>> >>> Signed-off-by: Suman Ghosh <sumang@marvell.com> >> >> Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com> > > Thank you for your review! > > Please, additionally try to trim away the irrelevant part of the patch > when replying (in this case almost everything). That helps a lot > following the discussion, especially on long patches, thanks! Sure thing. > > @Suman: please retain Wojciech's tag on next revision of this series. > > Cheers, > > Paolo > ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-11-26 16:04 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-11-21 9:43 [net-next PATCH v3 0/2] octeontx2: Multicast/mirror offload changes Suman Ghosh 2023-11-21 9:43 ` [net-next PATCH v3 1/2] octeontx2-af: Add new mbox to support multicast/mirror offload Suman Ghosh 2023-11-23 10:17 ` Paolo Abeni 2023-11-26 16:04 ` [EXT] " Suman Ghosh 2023-11-21 9:43 ` [net-next PATCH v3 2/2] octeontx2-pf: TC flower offload support for mirror Suman Ghosh 2023-11-21 10:23 ` Wojciech Drewek 2023-11-21 14:48 ` Wojciech Drewek 2023-11-23 10:21 ` Paolo Abeni 2023-11-23 10:35 ` Wojciech Drewek
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).