> 
> Add support for the IPsec NAT-Traversal use case for Tunnel mode
> packets.
> 
> Signed-off-by: Declan Doherty <declan.dohe...@intel.com>
> Signed-off-by: Radu Nicolau <radu.nico...@intel.com>
> Signed-off-by: Abhijit Sinha <abhijit.si...@intel.com>
> Signed-off-by: Daniel Martin Buckley <daniel.m.buck...@intel.com>
> Acked-by: Fan Zhang <roy.fan.zh...@intel.com>
> ---
>  doc/guides/prog_guide/ipsec_lib.rst    |  2 ++
>  doc/guides/rel_notes/release_21_11.rst |  1 +
>  lib/ipsec/esp_outb.c                   |  9 +++++++++
>  lib/ipsec/rte_ipsec_sa.h               |  9 ++++++++-
>  lib/ipsec/sa.c                         | 28 +++++++++++++++++++++++---
>  5 files changed, 45 insertions(+), 4 deletions(-)
> 
> diff --git a/doc/guides/prog_guide/ipsec_lib.rst 
> b/doc/guides/prog_guide/ipsec_lib.rst
> index 93e213bf36..af51ff8131 100644
> --- a/doc/guides/prog_guide/ipsec_lib.rst
> +++ b/doc/guides/prog_guide/ipsec_lib.rst
> @@ -313,6 +313,8 @@ Supported features
> 
>  *  ESN and replay window.
> 
> +*  NAT-T / UDP encapsulated ESP.
> +
>  *  algorithms: 3DES-CBC, AES-CBC, AES-CTR, AES-GCM, AES_CCM, 
> CHACHA20_POLY1305,
>     AES_GMAC, HMAC-SHA1, NULL.
> 
> diff --git a/doc/guides/rel_notes/release_21_11.rst 
> b/doc/guides/rel_notes/release_21_11.rst
> index 1a29640eea..73a566eaca 100644
> --- a/doc/guides/rel_notes/release_21_11.rst
> +++ b/doc/guides/rel_notes/release_21_11.rst
> @@ -137,6 +137,7 @@ New Features
>  * **IPsec library new features.**
> 
>    * Added support for AEAD algorithms AES_CCM, CHACHA20_POLY1305 and 
> AES_GMAC.
> +  * Added support for NAT-T / UDP encapsulated ESP
> 
> 
>  Removed Items
> diff --git a/lib/ipsec/esp_outb.c b/lib/ipsec/esp_outb.c
> index a3f77469c3..0e3314b358 100644
> --- a/lib/ipsec/esp_outb.c
> +++ b/lib/ipsec/esp_outb.c
> @@ -5,6 +5,7 @@
>  #include <rte_ipsec.h>
>  #include <rte_esp.h>
>  #include <rte_ip.h>
> +#include <rte_udp.h>
>  #include <rte_errno.h>
>  #include <rte_cryptodev.h>
> 
> @@ -185,6 +186,14 @@ outb_tun_pkt_prepare(struct rte_ipsec_sa *sa, rte_be64_t 
> sqc,
>       /* copy tunnel pkt header */
>       rte_memcpy(ph, sa->hdr, sa->hdr_len);
> 
> +     /* if UDP encap is enabled update the dgram_len */
> +     if (sa->type & RTE_IPSEC_SATP_NATT_ENABLE) {
> +             struct rte_udp_hdr *udph = (struct rte_udp_hdr *)
> +                             (ph - sizeof(struct rte_udp_hdr));
> +             udph->dgram_len = rte_cpu_to_be_16(mb->pkt_len - sqh_len -
> +                             sa->hdr_l3_off - sa->hdr_len);
> +     }
> +
>       /* update original and new ip header fields */
>       update_tun_outb_l3hdr(sa, ph + sa->hdr_l3_off, ph + hlen,
>                       mb->pkt_len - sqh_len, sa->hdr_l3_off, sqn_low16(sqc));
> diff --git a/lib/ipsec/rte_ipsec_sa.h b/lib/ipsec/rte_ipsec_sa.h
> index cf51ad8338..3a22705055 100644
> --- a/lib/ipsec/rte_ipsec_sa.h
> +++ b/lib/ipsec/rte_ipsec_sa.h
> @@ -78,6 +78,7 @@ struct rte_ipsec_sa_prm {
>   * - for TUNNEL outer IP version (IPv4/IPv6)
>   * - are SA SQN operations 'atomic'
>   * - ESN enabled/disabled
> + * - NAT-T UDP encapsulated (TUNNEL mode only)
>   * ...
>   */
> 
> @@ -89,7 +90,8 @@ enum {
>       RTE_SATP_LOG2_SQN = RTE_SATP_LOG2_MODE + 2,
>       RTE_SATP_LOG2_ESN,
>       RTE_SATP_LOG2_ECN,
> -     RTE_SATP_LOG2_DSCP
> +     RTE_SATP_LOG2_DSCP,
> +     RTE_SATP_LOG2_NATT
>  };
> 
>  #define RTE_IPSEC_SATP_IPV_MASK              (1ULL << RTE_SATP_LOG2_IPV)
> @@ -125,6 +127,11 @@ enum {
>  #define RTE_IPSEC_SATP_DSCP_DISABLE  (0ULL << RTE_SATP_LOG2_DSCP)
>  #define RTE_IPSEC_SATP_DSCP_ENABLE   (1ULL << RTE_SATP_LOG2_DSCP)
> 
> +#define RTE_IPSEC_SATP_NATT_MASK     (1ULL << RTE_SATP_LOG2_NATT)
> +#define RTE_IPSEC_SATP_NATT_DISABLE  (0ULL << RTE_SATP_LOG2_NATT)
> +#define RTE_IPSEC_SATP_NATT_ENABLE   (1ULL << RTE_SATP_LOG2_NATT)
> +
> +
>  /**
>   * get type of given SA
>   * @return
> diff --git a/lib/ipsec/sa.c b/lib/ipsec/sa.c
> index 720e0f365b..1dd19467a6 100644
> --- a/lib/ipsec/sa.c
> +++ b/lib/ipsec/sa.c
> @@ -5,6 +5,7 @@
>  #include <rte_ipsec.h>
>  #include <rte_esp.h>
>  #include <rte_ip.h>
> +#include <rte_udp.h>
>  #include <rte_errno.h>
>  #include <rte_cryptodev.h>
> 
> @@ -217,6 +218,10 @@ fill_sa_type(const struct rte_ipsec_sa_prm *prm, 
> uint64_t *type)
>       } else
>               return -EINVAL;
> 
> +     /* check for UDP encapsulation flag */
> +     if (prm->ipsec_xform.options.udp_encap == 1)
> +             tp |= RTE_IPSEC_SATP_NATT_ENABLE;
> +
>       /* check for ESN flag */
>       if (prm->ipsec_xform.options.esn == 0)
>               tp |= RTE_IPSEC_SATP_ESN_DISABLE;
> @@ -355,12 +360,22 @@ esp_outb_tun_init(struct rte_ipsec_sa *sa, const struct 
> rte_ipsec_sa_prm *prm)
>       sa->hdr_len = prm->tun.hdr_len;
>       sa->hdr_l3_off = prm->tun.hdr_l3_off;
> 
> +     memcpy(sa->hdr, prm->tun.hdr, prm->tun.hdr_len);
> +
> +     /* insert UDP header if UDP encapsulation is inabled */
> +     if (sa->type & RTE_IPSEC_SATP_NATT_ENABLE) {
> +             struct rte_udp_hdr *udph = (struct rte_udp_hdr *)
> +                             &sa->hdr[prm->tun.hdr_len];

I think we need a check somewhere here (probably in rte_ipsec_sa_init() or so)
to make sure that new sa->hdr_len wouldn't overrun sizeof(sa->hdr).


> +             sa->hdr_len += sizeof(struct rte_udp_hdr);
> +             udph->src_port = prm->ipsec_xform.udp.sport;
> +             udph->dst_port = prm->ipsec_xform.udp.dport;
> +             udph->dgram_cksum = 0;
> +     }
> +
>       /* update l2_len and l3_len fields for outbound mbuf */
>       sa->tx_offload.val = rte_mbuf_tx_offload(sa->hdr_l3_off,
>               sa->hdr_len - sa->hdr_l3_off, 0, 0, 0, 0, 0);


So for such packets UDP cksum will always be zero, and we don't need to
setup l4_hdr or any TX L4 flags, correct?

> 
> -     memcpy(sa->hdr, prm->tun.hdr, sa->hdr_len);
> -
>       esp_outb_init(sa, sa->hdr_len);
>  }
> 
> @@ -372,7 +387,8 @@ esp_sa_init(struct rte_ipsec_sa *sa, const struct 
> rte_ipsec_sa_prm *prm,
>       const struct crypto_xform *cxf)
>  {
>       static const uint64_t msk = RTE_IPSEC_SATP_DIR_MASK |
> -                             RTE_IPSEC_SATP_MODE_MASK;
> +                             RTE_IPSEC_SATP_MODE_MASK |
> +                             RTE_IPSEC_SATP_NATT_MASK;
> 
>       if (prm->ipsec_xform.options.ecn)
>               sa->tos_mask |= RTE_IPV4_HDR_ECN_MASK;
> @@ -475,10 +491,16 @@ esp_sa_init(struct rte_ipsec_sa *sa, const struct 
> rte_ipsec_sa_prm *prm,
>       case (RTE_IPSEC_SATP_DIR_IB | RTE_IPSEC_SATP_MODE_TRANS):
>               esp_inb_init(sa);
>               break;
> +     case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4 |
> +                     RTE_IPSEC_SATP_NATT_ENABLE):
> +     case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6 |
> +                     RTE_IPSEC_SATP_NATT_ENABLE):
>       case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV4):
>       case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TUNLV6):
>               esp_outb_tun_init(sa, prm);
>               break;
> +     case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS |
> +                     RTE_IPSEC_SATP_NATT_ENABLE):
>       case (RTE_IPSEC_SATP_DIR_OB | RTE_IPSEC_SATP_MODE_TRANS):
>               esp_outb_init(sa, 0);
>               break;
> --
> 2.25.1

Reply via email to