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>
---
 lib/ipsec/iph.h          | 13 +++++++++++++
 lib/ipsec/rte_ipsec_sa.h |  8 +++++++-
 lib/ipsec/sa.c           | 13 ++++++++++++-
 lib/ipsec/sa.h           |  4 ++++
 4 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/lib/ipsec/iph.h b/lib/ipsec/iph.h
index 2d223199ac..093f86d34a 100644
--- a/lib/ipsec/iph.h
+++ b/lib/ipsec/iph.h
@@ -251,6 +251,7 @@ update_tun_outb_l3hdr(const struct rte_ipsec_sa *sa, void 
*outh,
 {
        struct rte_ipv4_hdr *v4h;
        struct rte_ipv6_hdr *v6h;
+       struct rte_udp_hdr *udph;
        uint8_t is_outh_ipv4;
 
        if (sa->type & RTE_IPSEC_SATP_MODE_TUNLV4) {
@@ -258,11 +259,23 @@ update_tun_outb_l3hdr(const struct rte_ipsec_sa *sa, void 
*outh,
                v4h = outh;
                v4h->packet_id = pid;
                v4h->total_length = rte_cpu_to_be_16(plen - l2len);
+
+               if (sa->type & RTE_IPSEC_SATP_NATT_ENABLE) {
+                       udph = (struct rte_udp_hdr *)(v4h + 1);
+                       udph->dgram_len = rte_cpu_to_be_16(plen - l2len -
+                               (sizeof(*v4h) + sizeof(*udph)));
+               }
        } else {
                is_outh_ipv4 = 0;
                v6h = outh;
                v6h->payload_len = rte_cpu_to_be_16(plen - l2len -
                                sizeof(*v6h));
+
+               if (sa->type & RTE_IPSEC_SATP_NATT_ENABLE) {
+                       udph = (struct rte_udp_hdr *)(v6h + 1);
+                       udph->dgram_len = rte_cpu_to_be_16(plen - l2len -
+                               (sizeof(*v6h) + sizeof(*udph)));
+               }
        }
 
        if (sa->type & TUN_HDR_MSK)
diff --git a/lib/ipsec/rte_ipsec_sa.h b/lib/ipsec/rte_ipsec_sa.h
index cf51ad8338..40d1e70d45 100644
--- a/lib/ipsec/rte_ipsec_sa.h
+++ b/lib/ipsec/rte_ipsec_sa.h
@@ -76,6 +76,7 @@ struct rte_ipsec_sa_prm {
  * - inbound/outbound
  * - mode (TRANSPORT/TUNNEL)
  * - for TUNNEL outer IP version (IPv4/IPv6)
+ * - NAT-T UDP encapsulated (TUNNEL mode only)
  * - are SA SQN operations 'atomic'
  * - ESN enabled/disabled
  * ...
@@ -86,7 +87,8 @@ enum {
        RTE_SATP_LOG2_PROTO,
        RTE_SATP_LOG2_DIR,
        RTE_SATP_LOG2_MODE,
-       RTE_SATP_LOG2_SQN = RTE_SATP_LOG2_MODE + 2,
+       RTE_SATP_LOG2_NATT = RTE_SATP_LOG2_MODE + 2,
+       RTE_SATP_LOG2_SQN,
        RTE_SATP_LOG2_ESN,
        RTE_SATP_LOG2_ECN,
        RTE_SATP_LOG2_DSCP
@@ -109,6 +111,10 @@ enum {
 #define RTE_IPSEC_SATP_MODE_TUNLV4     (1ULL << RTE_SATP_LOG2_MODE)
 #define RTE_IPSEC_SATP_MODE_TUNLV6     (2ULL << RTE_SATP_LOG2_MODE)
 
+#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)
+
 #define RTE_IPSEC_SATP_SQN_MASK                (1ULL << RTE_SATP_LOG2_SQN)
 #define RTE_IPSEC_SATP_SQN_RAW         (0ULL << RTE_SATP_LOG2_SQN)
 #define RTE_IPSEC_SATP_SQN_ATOM                (1ULL << RTE_SATP_LOG2_SQN)
diff --git a/lib/ipsec/sa.c b/lib/ipsec/sa.c
index 2ecbbce0a4..8e369e4618 100644
--- a/lib/ipsec/sa.c
+++ b/lib/ipsec/sa.c
@@ -217,6 +217,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;
@@ -372,7 +376,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 +480,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;
diff --git a/lib/ipsec/sa.h b/lib/ipsec/sa.h
index 5e237f3525..3f38921eb3 100644
--- a/lib/ipsec/sa.h
+++ b/lib/ipsec/sa.h
@@ -101,6 +101,10 @@ struct rte_ipsec_sa {
                uint64_t msk;
                uint64_t val;
        } tx_offload;
+       struct {
+               uint16_t sport;
+               uint16_t dport;
+       } natt;
        uint32_t salt;
        uint8_t algo_type;
        uint8_t proto;    /* next proto */
-- 
2.25.1

Reply via email to