From: Barry Cao <barry....@nxp.com> This patch enables support for NAT-T traversal in IPSEC ESP protocol offload mode.
Signed-off-by: Hemant Agrawal <hemant.agra...@nxp.com> Signed-off-by: Barry Cao <barry....@nxp.com> --- drivers/crypto/dpaa_sec/dpaa_sec.c | 63 ++++++++++++++++++++++++------ drivers/crypto/dpaa_sec/dpaa_sec.h | 14 +++++++ 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/drivers/crypto/dpaa_sec/dpaa_sec.c b/drivers/crypto/dpaa_sec/dpaa_sec.c index 881435fdb6..3fa88ca968 100644 --- a/drivers/crypto/dpaa_sec/dpaa_sec.c +++ b/drivers/crypto/dpaa_sec/dpaa_sec.c @@ -20,6 +20,7 @@ #include <dev_driver.h> #include <rte_io.h> #include <rte_ip.h> +#include <rte_udp.h> #include <rte_kvargs.h> #include <rte_malloc.h> #include <rte_mbuf.h> @@ -46,6 +47,7 @@ #include <dpaax_iova_table.h> #define DRIVER_DUMP_MODE "drv_dump_mode" +#define DPAA_DEFAULT_NAT_T_PORT 4500 /* DPAA_SEC_DP_DUMP levels */ enum dpaa_sec_dump_levels { @@ -2961,15 +2963,22 @@ dpaa_sec_set_ipsec_session(__rte_unused struct rte_cryptodev *dev, RTE_SECURITY_IPSEC_TUNNEL_IPV4) { session->ip4_hdr.ip_v = IPVERSION; session->ip4_hdr.ip_hl = 5; - session->ip4_hdr.ip_len = rte_cpu_to_be_16( - sizeof(session->ip4_hdr)); + if (ipsec_xform->options.udp_encap) + session->ip4_hdr.ip_len = rte_cpu_to_be_16( + sizeof(session->ip4_hdr) + sizeof(struct rte_udp_hdr)); + else + session->ip4_hdr.ip_len = rte_cpu_to_be_16( + sizeof(session->ip4_hdr)); session->ip4_hdr.ip_tos = ipsec_xform->tunnel.ipv4.dscp; session->ip4_hdr.ip_id = 0; session->ip4_hdr.ip_off = 0; session->ip4_hdr.ip_ttl = ipsec_xform->tunnel.ipv4.ttl; - session->ip4_hdr.ip_p = (ipsec_xform->proto == - RTE_SECURITY_IPSEC_SA_PROTO_ESP) ? - IPPROTO_ESP : IPPROTO_AH; + if (ipsec_xform->options.udp_encap) + session->ip4_hdr.ip_p = IPPROTO_UDP; + else + session->ip4_hdr.ip_p = (ipsec_xform->proto == + RTE_SECURITY_IPSEC_SA_PROTO_ESP) ? + IPPROTO_ESP : IPPROTO_AH; session->ip4_hdr.ip_sum = 0; session->ip4_hdr.ip_src = ipsec_xform->tunnel.ipv4.src_ip; @@ -2993,9 +3002,12 @@ dpaa_sec_set_ipsec_session(__rte_unused struct rte_cryptodev *dev, session->ip6_hdr.payload_len = 0; session->ip6_hdr.hop_limits = ipsec_xform->tunnel.ipv6.hlimit; - session->ip6_hdr.proto = (ipsec_xform->proto == - RTE_SECURITY_IPSEC_SA_PROTO_ESP) ? - IPPROTO_ESP : IPPROTO_AH; + if (ipsec_xform->options.udp_encap) + session->ip6_hdr.proto = IPPROTO_UDP; + else + session->ip6_hdr.proto = (ipsec_xform->proto == + RTE_SECURITY_IPSEC_SA_PROTO_ESP) ? + IPPROTO_ESP : IPPROTO_AH; memcpy(&session->ip6_hdr.src_addr, &ipsec_xform->tunnel.ipv6.src_addr, 16); memcpy(&session->ip6_hdr.dst_addr, @@ -3022,18 +3034,47 @@ dpaa_sec_set_ipsec_session(__rte_unused struct rte_cryptodev *dev, session->encap_pdb.seq_num_ext_hi = conf->ipsec.esn.hi; session->encap_pdb.seq_num = conf->ipsec.esn.low; } + if (ipsec_xform->options.udp_encap) { + struct rte_udp_hdr *udp_hdr; + + if (ipsec_xform->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) + udp_hdr = (struct rte_udp_hdr *)(&session->udp4.udp_hdr); + else + udp_hdr = (struct rte_udp_hdr *)(&session->udp6.udp_hdr); + + if (ipsec_xform->udp.sport) + udp_hdr->src_port = rte_cpu_to_be_16(ipsec_xform->udp.sport); + else + udp_hdr->src_port = rte_cpu_to_be_16(DPAA_DEFAULT_NAT_T_PORT); + + if (ipsec_xform->udp.dport) + udp_hdr->dst_port = rte_cpu_to_be_16(ipsec_xform->udp.dport); + else + udp_hdr->dst_port = rte_cpu_to_be_16(DPAA_DEFAULT_NAT_T_PORT); + udp_hdr->dgram_len = 0; + udp_hdr->dgram_cksum = 0; + session->encap_pdb.ip_hdr_len += sizeof(struct rte_udp_hdr); + session->encap_pdb.options |= PDBOPTS_ESP_NAT | PDBOPTS_ESP_NUC; + } if (ipsec_xform->options.ecn) session->encap_pdb.options |= PDBOPTS_ESP_TECN; } else if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) { if (ipsec_xform->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4) { - session->decap_pdb.options = sizeof(struct ip) << 16; + if (ipsec_xform->options.udp_encap) + session->decap_pdb.options = + (sizeof(struct ip) + sizeof(struct rte_udp_hdr)) << 16; + else + session->decap_pdb.options = sizeof(struct ip) << 16; if (ipsec_xform->options.copy_df) session->decap_pdb.options |= PDBHMO_ESP_DFV; } else { - session->decap_pdb.options = - sizeof(struct rte_ipv6_hdr) << 16; + if (ipsec_xform->options.udp_encap) + session->decap_pdb.options = + (sizeof(struct rte_ipv6_hdr) + sizeof(struct rte_udp_hdr)) << 16; + else + session->decap_pdb.options = sizeof(struct rte_ipv6_hdr) << 16; } if (ipsec_xform->options.esn) { session->decap_pdb.options |= PDBOPTS_ESP_ESN; diff --git a/drivers/crypto/dpaa_sec/dpaa_sec.h b/drivers/crypto/dpaa_sec/dpaa_sec.h index 603a7d8f38..64d9e22159 100644 --- a/drivers/crypto/dpaa_sec/dpaa_sec.h +++ b/drivers/crypto/dpaa_sec/dpaa_sec.h @@ -143,6 +143,16 @@ typedef struct dpaa_sec_job* (*dpaa_sec_build_raw_dp_fd_t)(uint8_t *drv_ctx, void *userdata, struct qm_fd *fd); +struct dpaa_ipv4_udp { + struct ip ip4_hdr; + struct rte_udp_hdr udp_hdr; +}; + +struct dpaa_ipv6_udp { + struct rte_ipv6_hdr ip6_hdr; + struct rte_udp_hdr udp_hdr; +}; + typedef struct dpaa_sec_session_entry { struct sec_cdb cdb; /**< cmd block associated with qp */ struct dpaa_sec_qp *qp[MAX_DPAA_CORES]; @@ -191,6 +201,8 @@ typedef struct dpaa_sec_session_entry { union { struct ip ip4_hdr; struct rte_ipv6_hdr ip6_hdr; + struct dpaa_ipv4_udp udp4; + struct dpaa_ipv6_udp udp6; }; uint8_t auth_cipher_text; /**< Authenticate/cipher ordering */ @@ -995,6 +1007,7 @@ static const struct rte_security_capability dpaa_sec_security_cap[] = { .dec_ttl = 1, .ecn = 1, .esn = 1, + .udp_encap = 1, }, .replay_win_sz_max = 128 }, @@ -1013,6 +1026,7 @@ static const struct rte_security_capability dpaa_sec_security_cap[] = { .dec_ttl = 1, .ecn = 1, .esn = 1, + .udp_encap = 1, }, .replay_win_sz_max = 128 }, -- 2.25.1