From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 099F445AAA; Fri, 4 Oct 2024 08:34:53 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 43C4C402E9; Fri, 4 Oct 2024 08:34:51 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id 74EEC40268 for ; Fri, 4 Oct 2024 08:34:49 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 493Hw8Sk003638; Thu, 3 Oct 2024 23:34:48 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=pfpt0220; bh=q cZYyCuWF5sIXvJ5o1+9tfLPbiW9bJjPDdkZEtMWdGk=; b=ip37xcbLtKXmon6Xp G2qCES8tjlZV8lnT949A9qXlM4jVhK6uH/YsK0YDZxwY6aEvkOOV4frDhb1z47Y5 v52+UjMQznpzOq5Pwf4Bg3ft2OjbjJ7cyRt5EX0IalhKZj4+WKy1X8o3stD+jLtG qb4/YlsZd9azK0DRex5BeiNjKdEiOtuDQvl3JyoKb+baE8bro4C4qjFDarW3FcaL olO4ZnENudr69fYofgliZBXHAB3+575SLSN1IR9nCATfBJQoOr2KIQ0VAYBgW7Pd SSg4TD54Ntd3emFcKrF161AE80xla66Q5W0f4SQwl4PGkdthkwJpvQc4TsO1zCQ4 UooZg== Received: from dc5-exch05.marvell.com ([199.233.59.128]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 42204u15ea-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 03 Oct 2024 23:34:48 -0700 (PDT) Received: from DC5-EXCH05.marvell.com (10.69.176.209) by DC5-EXCH05.marvell.com (10.69.176.209) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.4; Thu, 3 Oct 2024 23:34:46 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH05.marvell.com (10.69.176.209) with Microsoft SMTP Server id 15.2.1544.4 via Frontend Transport; Thu, 3 Oct 2024 23:34:46 -0700 Received: from localhost.localdomain (unknown [10.28.36.177]) by maili.marvell.com (Postfix) with ESMTP id 5F9423F7052; Thu, 3 Oct 2024 23:34:44 -0700 (PDT) From: Aakash Sasidharan To: Konstantin Ananyev , Vladimir Medvedkin CC: , , , , , Subject: [PATCH v4 1/2] ipsec: allow stateless IPsec processing Date: Fri, 4 Oct 2024 12:04:42 +0530 Message-ID: <20241004063443.179264-1-asasidharan@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20241003134539.105789-1-asasidharan@marvell.com> References: <20241003134539.105789-1-asasidharan@marvell.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-GUID: xSz-POIfPJFDeOQWQ8l6_glnZMOl0E6P X-Proofpoint-ORIG-GUID: xSz-POIfPJFDeOQWQ8l6_glnZMOl0E6P X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1039,Hydra:6.0.680,FMLib:17.12.60.29 definitions=2024-09-06_09,2024-09-06_01,2024-09-02_01 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Introduce stateless packet preparation API for IPsec processing. The new API would allow preparation of IPsec packets without altering the internal state of an IPsec session. For outbound IPsec processing, the change enables user to provide sequence number to be used for the IPsec operation. Signed-off-by: Aakash Sasidharan --- doc/guides/prog_guide/ipsec_lib.rst | 6 ++ doc/guides/rel_notes/release_24_11.rst | 6 ++ lib/ipsec/esp_outb.c | 101 +++++++++++++++++-------- lib/ipsec/rte_ipsec.h | 84 ++++++++++++++++++++ lib/ipsec/sa.c | 4 +- lib/ipsec/sa.h | 8 ++ 6 files changed, 176 insertions(+), 33 deletions(-) diff --git a/doc/guides/prog_guide/ipsec_lib.rst b/doc/guides/prog_guide/ipsec_lib.rst index 0bdbdad1e4..395512f4f9 100644 --- a/doc/guides/prog_guide/ipsec_lib.rst +++ b/doc/guides/prog_guide/ipsec_lib.rst @@ -328,6 +328,12 @@ statistics. Per SA telemetry statistics can be enabled using ``rte_ipsec_telemetry_sa_add`` and disabled using ``rte_ipsec_telemetry_sa_del``. Note that these calls are not thread safe. +Stateless IPsec packet processing support +----------------------------------------- +Support for stateless IPsec packet processing allowing use of custom +sequence number to be used for IPsec outbound processing. +rte_ipsec_pkt_stateless_prepare() takes as input the state parameter +from the application and prepares the packet for IPsec processing. Limitations ----------- diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index 0ff70d9057..0964f13a12 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -84,6 +84,12 @@ API Changes Also, make sure to start the actual text at the margin. ======================================================= + * ipsec: Add support for stateless IPsec processing. + + Added new API to support stateless IPsec processing. + The new API are ``rte_ipsec_pkr_crypto_prepare_stateless`` and + ``rte_ipsec_pkt_cpu_prepare_stateless`` . + ABI Changes ----------- diff --git a/lib/ipsec/esp_outb.c b/lib/ipsec/esp_outb.c index ec87b1dce2..617fc52b21 100644 --- a/lib/ipsec/esp_outb.c +++ b/lib/ipsec/esp_outb.c @@ -288,28 +288,22 @@ outb_pkt_xprepare(const struct rte_ipsec_sa *sa, rte_be64_t sqc, /* * setup/update packets and crypto ops for ESP outbound tunnel case. */ -uint16_t -esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], - struct rte_crypto_op *cop[], uint16_t num) +static inline uint16_t +esp_outb_tun_prepare_helper(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + struct rte_crypto_op *cop[], uint16_t n, uint64_t sqn) { int32_t rc; - uint32_t i, k, n; - uint64_t sqn; + uint32_t i, k; rte_be64_t sqc; struct rte_ipsec_sa *sa; struct rte_cryptodev_sym_session *cs; union sym_op_data icv; uint64_t iv[IPSEC_MAX_IV_QWORD]; - uint32_t dr[num]; + uint32_t dr[n]; sa = ss->sa; cs = ss->crypto.ses; - n = num; - sqn = esn_outb_update_sqn(sa, &n); - if (n != num) - rte_errno = EOVERFLOW; - k = 0; for (i = 0; i != n; i++) { @@ -339,6 +333,30 @@ esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], return k; } +uint16_t +esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + struct rte_crypto_op *cop[], uint16_t num) +{ + uint64_t sqn; + uint32_t n; + + n = num; + sqn = esn_outb_update_sqn(ss->sa, &n); + if (n != num) + rte_errno = EOVERFLOW; + + return esp_outb_tun_prepare_helper(ss, mb, cop, n, sqn); +} + +uint16_t +esp_outb_tun_prepare_stateless(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + struct rte_crypto_op *cop[], uint16_t num, struct rte_ipsec_state *state) +{ + uint64_t sqn = state->sqn; + + return esp_outb_tun_prepare_helper(ss, mb, cop, num, sqn); +} + /* * setup/update packet data and metadata for ESP outbound transport case. */ @@ -529,33 +547,27 @@ outb_cpu_crypto_prepare(const struct rte_ipsec_sa *sa, uint32_t *pofs, return clen; } -static uint16_t -cpu_outb_pkt_prepare(const struct rte_ipsec_session *ss, - struct rte_mbuf *mb[], uint16_t num, - esp_outb_prepare_t prepare, uint32_t cofs_mask) +static inline uint16_t +cpu_outb_pkt_prepare_helper(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], uint16_t n, esp_outb_prepare_t prepare, + uint32_t cofs_mask, uint64_t sqn) { int32_t rc; - uint64_t sqn; rte_be64_t sqc; struct rte_ipsec_sa *sa; - uint32_t i, k, n; + uint32_t i, k; uint32_t l2, l3; union sym_op_data icv; - struct rte_crypto_va_iova_ptr iv[num]; - struct rte_crypto_va_iova_ptr aad[num]; - struct rte_crypto_va_iova_ptr dgst[num]; - uint32_t dr[num]; - uint32_t l4ofs[num]; - uint32_t clen[num]; - uint64_t ivbuf[num][IPSEC_MAX_IV_QWORD]; + struct rte_crypto_va_iova_ptr iv[n]; + struct rte_crypto_va_iova_ptr aad[n]; + struct rte_crypto_va_iova_ptr dgst[n]; + uint32_t dr[n]; + uint32_t l4ofs[n]; + uint32_t clen[n]; + uint64_t ivbuf[n][IPSEC_MAX_IV_QWORD]; sa = ss->sa; - n = num; - sqn = esn_outb_update_sqn(sa, &n); - if (n != num) - rte_errno = EOVERFLOW; - for (i = 0, k = 0; i != n; i++) { l2 = mb[i]->l2_len; @@ -604,15 +616,40 @@ uint16_t cpu_outb_tun_pkt_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], uint16_t num) { - return cpu_outb_pkt_prepare(ss, mb, num, outb_tun_pkt_prepare, 0); + uint64_t sqn; + uint32_t n; + + n = num; + sqn = esn_outb_update_sqn(ss->sa, &n); + if (n != num) + rte_errno = EOVERFLOW; + + return cpu_outb_pkt_prepare_helper(ss, mb, n, outb_tun_pkt_prepare, 0, sqn); +} + +uint16_t +cpu_outb_tun_pkt_prepare_stateless(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], uint16_t num, struct rte_ipsec_state *state) +{ + uint64_t sqn = state->sqn; + + return cpu_outb_pkt_prepare_helper(ss, mb, num, outb_tun_pkt_prepare, 0, sqn); } uint16_t cpu_outb_trs_pkt_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], uint16_t num) { - return cpu_outb_pkt_prepare(ss, mb, num, outb_trs_pkt_prepare, - UINT32_MAX); + uint64_t sqn; + uint32_t n; + + n = num; + sqn = esn_outb_update_sqn(ss->sa, &n); + if (n != num) + rte_errno = EOVERFLOW; + + return cpu_outb_pkt_prepare_helper(ss, mb, n, outb_trs_pkt_prepare, + UINT32_MAX, sqn); } /* diff --git a/lib/ipsec/rte_ipsec.h b/lib/ipsec/rte_ipsec.h index f15f6f2966..316ace1f19 100644 --- a/lib/ipsec/rte_ipsec.h +++ b/lib/ipsec/rte_ipsec.h @@ -23,11 +23,24 @@ extern "C" { struct rte_ipsec_session; +/** + * IPsec state for stateless processing of a batch of IPsec packets. + */ +struct rte_ipsec_state { + /** + * 64 bit sequence number to be used for the first packet of the + * batch of packets. + */ + uint64_t sqn; +}; + /** * IPsec session specific functions that will be used to: * - prepare - for input mbufs and given IPsec session prepare crypto ops * that can be enqueued into the cryptodev associated with given session * (see *rte_ipsec_pkt_crypto_prepare* below for more details). + * - prepare_stateless - similar to prepare, but further processing is done + * based on IPsec state provided by the 'state' parameter. * - process - finalize processing of packets after crypto-dev finished * with them or process packets that are subjects to inline IPsec offload * (see rte_ipsec_pkt_process for more details). @@ -42,6 +55,17 @@ struct rte_ipsec_sa_pkt_func { struct rte_mbuf *mb[], uint16_t num); } prepare; + union { + uint16_t (*async)(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], + struct rte_crypto_op *cop[], + uint16_t num, + struct rte_ipsec_state *state); + uint16_t (*sync)(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], + uint16_t num, + struct rte_ipsec_state *state); + } prepare_stateless; uint16_t (*process)(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], uint16_t num); @@ -128,6 +152,66 @@ rte_ipsec_pkt_cpu_prepare(const struct rte_ipsec_session *ss, return ss->pkt_func.prepare.sync(ss, mb, num); } +/** + * Same as *rte_ipsec_pkt_crypto_prepare*, but processing is done based on + * IPsec state provided by the 'state' parameter. Internal IPsec state won't + * be updated when this API is called. + * + * For input mbufs and given IPsec session prepare crypto ops that can be + * enqueued into the cryptodev associated with given session. + * expects that for each input packet: + * - l2_len, l3_len are setup correctly + * Note that erroneous mbufs are not freed by the function, + * but are placed beyond last valid mbuf in the *mb* array. + * It is a user responsibility to handle them further. + * @param ss + * Pointer to the *rte_ipsec_session* object the packets belong to. + * @param mb + * The address of an array of *num* pointers to *rte_mbuf* structures + * which contain the input packets. + * @param cop + * The address of an array of *num* pointers to the output *rte_crypto_op* + * structures. + * @param num + * The maximum number of packets to process. + * @param state + * The IPsec state to be used for processing current batch of packets. + * @return + * Number of successfully processed packets, with error code set in rte_errno. + */ +__rte_experimental +static inline uint16_t +rte_ipsec_pkt_crypto_prepare_stateless(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num, + struct rte_ipsec_state *state) +{ + return ss->pkt_func.prepare_stateless.async(ss, mb, cop, num, state); +} + +/** + * Same as *rte_ipsec_pkt_crypto_prepare_stateless*, but processing is done + * in synchronous mode. + * + * @param ss + * Pointer to the *rte_ipsec_session* object the packets belong to. + * @param mb + * The address of an array of *num* pointers to *rte_mbuf* structures + * which contain the input packets. + * @param num + * The maximum number of packets to process. + * @param state + * The IPsec state to be used for processing current batch of packets. + * @return + * Number of successfully processed packets, with error code set in rte_errno. + */ +__rte_experimental +static inline uint16_t +rte_ipsec_pkt_cpu_prepare_stateless(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], uint16_t num, struct rte_ipsec_state *state) +{ + return ss->pkt_func.prepare_stateless.sync(ss, mb, num, state); +} + /** * Finalise processing of packets after crypto-dev finished with them or * process packets that are subjects to inline IPsec offload. diff --git a/lib/ipsec/sa.c b/lib/ipsec/sa.c index 2297bd6d72..741e079831 100644 --- a/lib/ipsec/sa.c +++ b/lib/ipsec/sa.c @@ -710,6 +710,7 @@ lksd_none_pkt_func_select(const struct rte_ipsec_sa *sa, case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4): case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6): pf->prepare.async = esp_outb_tun_prepare; + pf->prepare_stateless.async = esp_outb_tun_prepare_stateless; pf->process = (sa->sqh_len != 0) ? esp_outb_sqh_process : pkt_flag_process; break; @@ -748,6 +749,7 @@ cpu_crypto_pkt_func_select(const struct rte_ipsec_sa *sa, case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4): case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6): pf->prepare.sync = cpu_outb_tun_pkt_prepare; + pf->prepare_stateless.sync = cpu_outb_tun_pkt_prepare_stateless; pf->process = (sa->sqh_len != 0) ? esp_outb_sqh_process : pkt_flag_process; break; @@ -810,7 +812,7 @@ ipsec_sa_pkt_func_select(const struct rte_ipsec_session *ss, int32_t rc; rc = 0; - pf[0] = (struct rte_ipsec_sa_pkt_func) { {NULL}, NULL }; + pf[0] = (struct rte_ipsec_sa_pkt_func) { {NULL}, {NULL}, NULL }; switch (ss->type) { case RTE_SECURITY_ACTION_TYPE_NONE: diff --git a/lib/ipsec/sa.h b/lib/ipsec/sa.h index 719b5c735c..9b53586b2d 100644 --- a/lib/ipsec/sa.h +++ b/lib/ipsec/sa.h @@ -179,6 +179,10 @@ uint16_t esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num); +uint16_t +esp_outb_tun_prepare_stateless(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], + struct rte_crypto_op *cop[], uint16_t num, struct rte_ipsec_state *state); + uint16_t esp_outb_trs_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], struct rte_crypto_op *cop[], uint16_t num); @@ -207,6 +211,10 @@ uint16_t cpu_outb_tun_pkt_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], uint16_t num); uint16_t +cpu_outb_tun_pkt_prepare_stateless(const struct rte_ipsec_session *ss, + struct rte_mbuf *mb[], uint16_t num, struct rte_ipsec_state *state); + +uint16_t cpu_outb_trs_pkt_prepare(const struct rte_ipsec_session *ss, struct rte_mbuf *mb[], uint16_t num); -- 2.25.1