DPDK patches and discussions
 help / color / mirror / Atom feed
From: Aakash Sasidharan <asasidharan@marvell.com>
To: Konstantin Ananyev <konstantin.ananyev@huawei.com>,
	Konstantin Ananyev <konstantin.v.ananyev@yandex.ru>,
	Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Cc: Akhil Goyal <gakhil@marvell.com>,
	Jerin Jacob <jerinj@marvell.com>,
	Anoob Joseph <anoobj@marvell.com>,
	Vidya Sagar Velumuri <vvelumuri@marvell.com>,
	"dev@dpdk.org" <dev@dpdk.org>
Subject: RE: [PATCH v2] ipsec: allow stateless IPsec processing
Date: Fri, 20 Sep 2024 05:53:15 +0000	[thread overview]
Message-ID: <PH0PR18MB4508125C3DFAFD94BF7D8040A16C2@PH0PR18MB4508.namprd18.prod.outlook.com> (raw)
In-Reply-To: <PH0PR18MB4508F5522AB0F8A93477CE03A16C2@PH0PR18MB4508.namprd18.prod.outlook.com>

> > > 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.
> >
> > Few questions/nits below.
> > As a generic one - we need to add a use-case/test-case for it.
> > Without it I think the patch is incomplete.
> 
> Ack. Will add test-case with v3.
> 
> >
> > >
> > > Signed-off-by: Aakash Sasidharan <asasidharan@marvell.com>
> > > ---
> > >  lib/ipsec/esp_outb.c  | 85
> > > +++++++++++++++++++++++++++++++------------
> > >  lib/ipsec/rte_ipsec.h | 68 ++++++++++++++++++++++++++++++++++
> > >  lib/ipsec/sa.c        |  4 +-
> > >  lib/ipsec/sa.h        |  8 ++++
> > >  4 files changed, 140 insertions(+), 25 deletions(-)
> > >
> > > diff --git a/lib/ipsec/esp_outb.c b/lib/ipsec/esp_outb.c index
> > > ec87b1dce2..de28cb166d 100644
> > > --- a/lib/ipsec/esp_outb.c
> > > +++ b/lib/ipsec/esp_outb.c
> > > @@ -288,13 +288,12 @@ 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 num, uint64_t sqn)
> > >  {
> > >  	int32_t rc;
> > > -	uint32_t i, k, n;
> > > -	uint64_t sqn;
> > > +	uint32_t i, k, n = num;
> >
> > You can just do s/num/n/ in function parameter list, then you don't
> > need to keep 'num' at all.
> 
> This function will be called for normal IPsec processing. The function
> esn_outb_update_sqn() updates the local variable n passed as parameter in
> OVERFLOW case. If we remove the local variable n, this error path would be
> lost and it is not our intention I believe.

Apologies. Replied too soon. I understand your suggestion and will update that in v3.

> 
> >
> > >  	rte_be64_t sqc;
> > >  	struct rte_ipsec_sa *sa;
> > >  	struct rte_cryptodev_sym_session *cs; @@ -305,11 +304,6 @@
> > > esp_outb_tun_prepare(const struct rte_ipsec_session *ss, struct
> > > rte_mbuf
> > *mb[],
> > >  	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,16 +547,15 @@ 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 num, 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, n = num;
> >
> > Same here, you can just use 'n' instead of 'num'.
> 
> Same comment as above.
> 
> >
> > >  	uint32_t l2, l3;
> > >  	union sym_op_data icv;
> > >  	struct rte_crypto_va_iova_ptr iv[num]; @@ -551,11 +568,6 @@
> > > cpu_outb_pkt_prepare(const struct rte_ipsec_session *ss,
> > >
> > >  	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..b462068203 100644
> > > --- a/lib/ipsec/rte_ipsec.h
> > > +++ b/lib/ipsec/rte_ipsec.h
> > > @@ -23,11 +23,26 @@ extern "C" {
> > >
> > >  struct rte_ipsec_session;
> > >
> > > +/**
> > > + * IPsec state for stateless processing of a batch of IPsec packets.
> > > + */
> > > +struct rte_ipsec_state {
> > > +	union {
> >
> > Curious what is the purpose of 'union' here?
> > What other mutually exclusive fields you plan to add here?
> >
> > > +		/**
> > > +		 * 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 +57,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 +154,48 @@ 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.
> > > + */
> >
> > We probably need to mark new API as 'rte_experimental'.
> 
> Ack. Will update in v3.
> 
> >
> > > +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); }
> > > +
> > > +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


      reply	other threads:[~2024-09-20  5:53 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-07 10:25 [PATCH] " Aakash Sasidharan
2024-09-08 11:57 ` [PATCH v2] " Aakash Sasidharan
2024-09-17 17:13   ` Konstantin Ananyev
2024-09-20  2:12     ` Aakash Sasidharan
2024-09-20  5:53       ` Aakash Sasidharan [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=PH0PR18MB4508125C3DFAFD94BF7D8040A16C2@PH0PR18MB4508.namprd18.prod.outlook.com \
    --to=asasidharan@marvell.com \
    --cc=anoobj@marvell.com \
    --cc=dev@dpdk.org \
    --cc=gakhil@marvell.com \
    --cc=jerinj@marvell.com \
    --cc=konstantin.ananyev@huawei.com \
    --cc=konstantin.v.ananyev@yandex.ru \
    --cc=vladimir.medvedkin@intel.com \
    --cc=vvelumuri@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).