This patch enables support for NAT-T traversal in IPSEC ESP
protocol offload mode for IPv6

Signed-off-by: Hemant Agrawal <hemant.agra...@nxp.com>
---
 drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c | 68 +++++++++++++--------
 1 file changed, 43 insertions(+), 25 deletions(-)

diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c 
b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
index b34183d594..3814f954ce 100644
--- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
+++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
@@ -50,6 +50,7 @@
 #define FSL_SUBSYSTEM_SEC       1
 #define FSL_MC_DPSECI_DEVID     3
 
+#define DPAA2_DEFAULT_NAT_T_PORT 4500
 #define NO_PREFETCH 0
 
 #define DRIVER_DUMP_MODE "drv_dump_mode"
@@ -3164,6 +3165,7 @@ dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev,
                uint8_t hdr[48] = {};
                struct rte_ipv4_hdr *ip4_hdr;
                struct rte_ipv6_hdr *ip6_hdr;
+               struct rte_udp_hdr *uh = NULL;
                struct ipsec_encap_pdb encap_pdb;
 
                flc->dhr = SEC_FLC_DHR_OUTBOUND;
@@ -3235,29 +3237,10 @@ dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev,
                        memcpy(&ip4_hdr->dst_addr, 
&ipsec_xform->tunnel.ipv4.dst_ip,
                               sizeof(struct in_addr));
                        if (ipsec_xform->options.udp_encap) {
-                               uint16_t sport, dport;
-                               struct rte_udp_hdr *uh =
-                                       (struct rte_udp_hdr *) (hdr +
-                                               sizeof(struct rte_ipv4_hdr));
-
-                               sport = ipsec_xform->udp.sport ?
-                                       ipsec_xform->udp.sport : 4500;
-                               dport = ipsec_xform->udp.dport ?
-                                       ipsec_xform->udp.dport : 4500;
-                               uh->src_port = rte_cpu_to_be_16(sport);
-                               uh->dst_port = rte_cpu_to_be_16(dport);
-                               uh->dgram_len = 0;
-                               uh->dgram_cksum = 0;
-
                                ip4_hdr->next_proto_id = IPPROTO_UDP;
-                               ip4_hdr->total_length =
-                                       rte_cpu_to_be_16(
+                               ip4_hdr->total_length = rte_cpu_to_be_16(
                                                sizeof(struct rte_ipv4_hdr) +
                                                sizeof(struct rte_udp_hdr));
-                               encap_pdb.ip_hdr_len +=
-                                       sizeof(struct rte_udp_hdr);
-                               encap_pdb.options |=
-                                       PDBOPTS_ESP_NAT | PDBOPTS_ESP_NUC;
                        } else {
                                ip4_hdr->total_length =
                                        rte_cpu_to_be_16(
@@ -3284,14 +3267,39 @@ dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev,
                        ip6_hdr->payload_len = 0;
                        ip6_hdr->hop_limits = ipsec_xform->tunnel.ipv6.hlimit ?
                                        ipsec_xform->tunnel.ipv6.hlimit : 0x40;
-                       ip6_hdr->proto = (ipsec_xform->proto ==
-                                       RTE_SECURITY_IPSEC_SA_PROTO_ESP) ?
-                                       IPPROTO_ESP : IPPROTO_AH;
                        memcpy(&ip6_hdr->src_addr,
                                &ipsec_xform->tunnel.ipv6.src_addr, 16);
                        memcpy(&ip6_hdr->dst_addr,
                                &ipsec_xform->tunnel.ipv6.dst_addr, 16);
                        encap_pdb.ip_hdr_len = sizeof(struct rte_ipv6_hdr);
+                       if (ipsec_xform->options.udp_encap)
+                               ip6_hdr->proto = IPPROTO_UDP;
+                       else
+                               ip6_hdr->proto = (ipsec_xform->proto ==
+                                       RTE_SECURITY_IPSEC_SA_PROTO_ESP) ?
+                                       IPPROTO_ESP : IPPROTO_AH;
+               }
+               if (ipsec_xform->options.udp_encap) {
+                       uint16_t sport, dport;
+
+                       if (ipsec_xform->tunnel.type == 
RTE_SECURITY_IPSEC_TUNNEL_IPV4)
+                               uh = (struct rte_udp_hdr *) (hdr +
+                                               sizeof(struct rte_ipv4_hdr));
+                       else
+                               uh = (struct rte_udp_hdr *) (hdr +
+                                               sizeof(struct rte_ipv6_hdr));
+
+                       sport = ipsec_xform->udp.sport ?
+                               ipsec_xform->udp.sport : 
DPAA2_DEFAULT_NAT_T_PORT;
+                       dport = ipsec_xform->udp.dport ?
+                               ipsec_xform->udp.dport : 
DPAA2_DEFAULT_NAT_T_PORT;
+                       uh->src_port = rte_cpu_to_be_16(sport);
+                       uh->dst_port = rte_cpu_to_be_16(dport);
+                       uh->dgram_len = 0;
+                       uh->dgram_cksum = 0;
+
+                       encap_pdb.ip_hdr_len += sizeof(struct rte_udp_hdr);
+                       encap_pdb.options |= PDBOPTS_ESP_NAT | PDBOPTS_ESP_NUC;
                }
 
                bufsize = cnstr_shdsc_ipsec_new_encap(priv->flc_desc[0].desc,
@@ -3320,13 +3328,23 @@ dpaa2_sec_set_ipsec_session(struct rte_cryptodev *dev,
 
                if (ipsec_xform->tunnel.type ==
                                RTE_SECURITY_IPSEC_TUNNEL_IPV4) {
-                       decap_pdb.options = sizeof(struct ip) << 16;
+                       if (ipsec_xform->options.udp_encap)
+                               decap_pdb.options =
+                                       (sizeof(struct ip) + sizeof(struct 
rte_udp_hdr)) << 16;
+                       else
+                               decap_pdb.options = sizeof(struct ip) << 16;
                        if (ipsec_xform->options.copy_df)
                                decap_pdb.options |= PDBHMO_ESP_DFV;
                        if (ipsec_xform->options.dec_ttl)
                                decap_pdb.options |= PDBHMO_ESP_DECAP_DTTL;
                } else {
-                       decap_pdb.options = sizeof(struct rte_ipv6_hdr) << 16;
+                       if (ipsec_xform->options.udp_encap) {
+                               decap_pdb.options =
+                                       (sizeof(struct rte_ipv6_hdr) +
+                                        sizeof(struct rte_udp_hdr)) << 16;
+                       } else {
+                               decap_pdb.options = sizeof(struct rte_ipv6_hdr) 
<< 16;
+                       }
                }
                if (ipsec_xform->options.esn) {
                        decap_pdb.options |= PDBOPTS_ESP_ESN;
-- 
2.25.1

Reply via email to