[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250711121317.340326-13-tanmay@marvell.com>
Date: Fri, 11 Jul 2025 17:43:05 +0530
From: Tanmay Jagdale <tanmay@...vell.com>
To: <davem@...emloft.net>, <leon@...nel.org>, <horms@...nel.org>,
<herbert@...dor.apana.org.au>, <sgoutham@...vell.com>,
<bbhushan2@...vell.com>
CC: <linux-crypto@...r.kernel.org>, <netdev@...r.kernel.org>,
Tanmay Jagdale
<tanmay@...vell.com>
Subject: [PATCH net-next v3 12/14] octeontx2-pf: ipsec: Process CPT metapackets
CPT hardware forwards decrypted IPsec packets to NIX via the X2P bus
as metapackets which are of 256 bytes in length. Each metapacket
contains CPT_PARSE_HDR_S and initial bytes of the decrypted packet
that helps NIX RX in classifying and submitting to CPU. Additionally,
CPT also sets BIT(11) of the channel number to indicate that it's a
2nd pass packet from CPT.
Since the metapackets are not complete packets, they don't have to go
through L3/L4 layer length and checksum verification so these are
disabled via the NIX_LF_INLINE_RQ_CFG mailbox during IPsec initialization.
The CPT_PARSE_HDR_S contains a WQE pointer to the complete decrypted
packet. Add code in the rx NAPI handler to parse the header and extract
WQE pointer. Later, use this WQE pointer to construct the skb, set the
XFRM packet mode flags to indicate successful decryption before submitting
it to the network stack.
Signed-off-by: Tanmay Jagdale <tanmay@...vell.com>
---
Changes in V3:
- Updated cpt_parse_hdr_s structure to use __be64 type
Changes in V2:
- Removed unnecessary casts
- Don't convert complete cpt_parse_hdr from BE to LE and just
convert required fields
- Fixed logic to avoid repeated calculation for start and end in sg
V1 Link: https://lore.kernel.org/netdev/20250502132005.611698-15-tanmay@marvell.com/
V2 Link: https://lore.kernel.org/netdev/20250618113020.130888-13-tanmay@marvell.com/
.../marvell/octeontx2/nic/cn10k_ipsec.c | 46 +++++++++++++++++++
.../marvell/octeontx2/nic/cn10k_ipsec.h | 46 +++++++++++++++++++
.../marvell/octeontx2/nic/otx2_struct.h | 16 +++++++
.../marvell/octeontx2/nic/otx2_txrx.c | 27 ++++++++++-
4 files changed, 134 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
index 1edc38a8bd29..4ee5395a95f8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
@@ -346,6 +346,52 @@ static int cn10k_outb_cpt_init(struct net_device *netdev)
return ret;
}
+struct nix_wqe_rx_s *cn10k_ipsec_process_cpt_metapkt(struct otx2_nic *pfvf,
+ struct sk_buff *skb,
+ dma_addr_t seg_addr)
+{
+ struct nix_wqe_rx_s *wqe = NULL;
+ struct cpt_parse_hdr_s *cptp;
+ struct xfrm_offload *xo;
+ struct xfrm_state *xs;
+ struct sec_path *sp;
+ u64 *sa_ptr;
+
+ /* CPT_PARSE_HDR_S is present in the beginning of the buffer */
+ cptp = phys_to_virt(otx2_iova_to_phys(pfvf->iommu_domain, seg_addr));
+
+ /* Convert the wqe_ptr from CPT_PARSE_HDR_S to a CPU usable pointer */
+ wqe = phys_to_virt(otx2_iova_to_phys(pfvf->iommu_domain,
+ be64_to_cpu(cptp->wqe_ptr)));
+
+ /* Get the XFRM state pointer stored in SA context */
+ sa_ptr = pfvf->ipsec.inb_sa->base + 1024 +
+ (be32_to_cpu(cptp->cookie) * pfvf->ipsec.sa_tbl_entry_sz);
+ xs = (struct xfrm_state *)*sa_ptr;
+
+ /* Set XFRM offload status and flags for successful decryption */
+ sp = secpath_set(skb);
+ if (!sp) {
+ netdev_err(pfvf->netdev, "Failed to secpath_set\n");
+ wqe = NULL;
+ goto err_out;
+ }
+
+ rcu_read_lock();
+ xfrm_state_hold(xs);
+ rcu_read_unlock();
+
+ sp->xvec[sp->len++] = xs;
+ sp->olen++;
+
+ xo = xfrm_offload(skb);
+ xo->flags = CRYPTO_DONE;
+ xo->status = CRYPTO_SUCCESS;
+
+err_out:
+ return wqe;
+}
+
static int cn10k_inb_nix_inline_lf_cfg(struct otx2_nic *pfvf)
{
struct nix_inline_ipsec_lf_cfg *req;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
index 80bc0e4a9da6..ecb0cd8418e0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
@@ -8,6 +8,7 @@
#define CN10K_IPSEC_H
#include <linux/types.h>
+#include "otx2_struct.h"
DECLARE_STATIC_KEY_FALSE(cn10k_ipsec_sa_enabled);
@@ -302,6 +303,41 @@ struct cpt_sg_s {
u64 rsvd_63_50 : 14;
};
+/* CPT Parse Header Structure for Inbound packets */
+struct cpt_parse_hdr_s {
+ /* Word 0 */
+ __be64 pkt_out : 2;
+ __be64 num_frags : 3;
+ __be64 pad_len : 3;
+ __be64 pkt_fmt : 1;
+ __be64 et_owr : 1;
+ __be64 reserved_53 : 1;
+ __be64 reas_sts : 4;
+ __be64 err_sum : 1;
+ __be64 match_id : 16;
+ __be64 cookie : 32;
+
+ /* Word 1 */
+ __be64 wqe_ptr;
+
+ /* Word 2 */
+ __be64 fi_offset : 5;
+ __be64 fi_pad : 3;
+ __be64 il3_off : 8;
+ __be64 pf_func : 16;
+ __be64 res_32_16 : 16;
+ __be64 frag_age : 16;
+
+ /* Word 3 */
+ __be64 spi : 32;
+ __be64 res3_32_16 : 16;
+ __be64 uc_ccode : 8;
+ __be64 hw_ccode : 8;
+
+ /* Word 4 */
+ __be64 misc;
+};
+
/* CPT LF_INPROG Register */
#define CPT_LF_INPROG_INFLIGHT GENMASK_ULL(8, 0)
#define CPT_LF_INPROG_GRB_CNT GENMASK_ULL(39, 32)
@@ -330,6 +366,9 @@ bool cn10k_ipsec_transmit(struct otx2_nic *pf, struct netdev_queue *txq,
struct otx2_snd_queue *sq, struct sk_buff *skb,
int num_segs, int size);
void cn10k_ipsec_free_aura_ptrs(struct otx2_nic *pfvf);
+struct nix_wqe_rx_s *cn10k_ipsec_process_cpt_metapkt(struct otx2_nic *pfvf,
+ struct sk_buff *skb,
+ dma_addr_t seg_addr);
#else
static inline __maybe_unused int cn10k_ipsec_init(struct net_device *netdev)
{
@@ -366,5 +405,12 @@ void cn10k_ipsec_free_aura_ptrs(struct otx2_nic *pfvf)
{
}
+static inline __maybe_unused
+struct nix_wqe_rx_s *cn10k_ipsec_process_cpt_metapkt(struct otx2_nic *pfvf,
+ struct sk_buff *skb,
+ dma_addr_t seg_addr)
+{
+ return NULL;
+}
#endif
#endif // CN10K_IPSEC_H
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h
index 4e5899d8fa2e..506fab414b7e 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_struct.h
@@ -175,6 +175,22 @@ struct nix_cqe_tx_s {
struct nix_send_comp_s comp;
};
+/* NIX WQE header structure */
+struct nix_wqe_hdr_s {
+ u64 flow_tag : 32;
+ u64 tt : 2;
+ u64 reserved_34_43 : 10;
+ u64 node : 2;
+ u64 q : 14;
+ u64 wqe_type : 4;
+};
+
+struct nix_wqe_rx_s {
+ struct nix_wqe_hdr_s hdr;
+ struct nix_rx_parse_s parse;
+ struct nix_rx_sg_s sg;
+};
+
/* NIX SQE header structure */
struct nix_sqe_hdr_s {
u64 total : 18; /* W0 */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 99ace381cc78..a1256ecb29ed 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -205,11 +205,16 @@ static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb,
}
}
+ if (parse->chan & 0x800)
+ off = 0;
+
page = virt_to_page(va);
if (likely(skb_shinfo(skb)->nr_frags < MAX_SKB_FRAGS)) {
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
va - page_address(page) + off,
len - off, pfvf->rbsize);
+ if (parse->chan & 0x800)
+ return false;
return true;
}
@@ -333,6 +338,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
struct nix_cqe_rx_s *cqe, bool *need_xdp_flush)
{
struct nix_rx_parse_s *parse = &cqe->parse;
+ struct nix_wqe_rx_s *orig_pkt_wqe = NULL;
+ u32 desc_sizem1 = parse->desc_sizem1;
struct nix_rx_sg_s *sg = &cqe->sg;
struct sk_buff *skb = NULL;
u64 *word = (u64 *)parse;
@@ -359,8 +366,26 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf,
if (unlikely(!skb))
return;
+ if (parse->chan & 0x800) {
+ orig_pkt_wqe = cn10k_ipsec_process_cpt_metapkt(pfvf, skb, sg->seg_addr);
+ if (!orig_pkt_wqe) {
+ netdev_err(pfvf->netdev, "Invalid WQE in CPT metapacket\n");
+ napi_free_frags(napi);
+ cq->pool_ptrs++;
+ return;
+ }
+ /* Return metapacket buffer back to pool since it's no longer needed */
+ otx2_free_rcv_seg(pfvf, cqe, cq->cq_idx);
+
+ /* Switch *sg to the orig_pkt_wqe's *sg which has the actual
+ * complete decrypted packet by CPT.
+ */
+ sg = &orig_pkt_wqe->sg;
+ desc_sizem1 = orig_pkt_wqe->parse.desc_sizem1;
+ }
+
start = (void *)sg;
- end = start + ((cqe->parse.desc_sizem1 + 1) * 16);
+ end = start + ((desc_sizem1 + 1) * 16);
while (start < end) {
sg = (struct nix_rx_sg_s *)start;
seg_addr = &sg->seg_addr;
--
2.43.0
Powered by blists - more mailing lists