Enable UDP encapsulation for both transport and tunnel modes for the
inline crypto offload path.

Signed-off-by: Radu Nicolau <radu.nico...@intel.com>
---
 examples/ipsec-secgw/ipsec.c |  34 ++++++++--
 examples/ipsec-secgw/ipsec.h |   7 +-
 examples/ipsec-secgw/sa.c    | 123 ++++++++++++++++++++++++++++-------
 3 files changed, 136 insertions(+), 28 deletions(-)

diff --git a/examples/ipsec-secgw/ipsec.c b/examples/ipsec-secgw/ipsec.c
index 868089ad3e..edc0b21478 100644
--- a/examples/ipsec-secgw/ipsec.c
+++ b/examples/ipsec-secgw/ipsec.c
@@ -222,6 +222,13 @@ create_inline_session(struct socket_ctx *skt_ctx, struct 
ipsec_sa *sa,
                }
        }
 
+       if (sa->udp_encap) {
+               sess_conf.ipsec.options.udp_encap = 1;
+
+               sess_conf.ipsec.udp.sport = htons(sa->udp.sport);
+               sess_conf.ipsec.udp.dport = htons(sa->udp.dport);
+       }
+
        if (sa->esn > 0) {
                sess_conf.ipsec.options.esn = 1;
                sess_conf.ipsec.esn.value = sa->esn;
@@ -295,12 +302,31 @@ create_inline_session(struct socket_ctx *skt_ctx, struct 
ipsec_sa *sa,
                        sa->ipv4_spec.hdr.src_addr = sa->src.ip.ip4;
                }
 
-               sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
-               sa->pattern[2].spec = &sa->esp_spec;
-               sa->pattern[2].mask = &rte_flow_item_esp_mask;
                sa->esp_spec.hdr.spi = rte_cpu_to_be_32(sa->spi);
 
-               sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+               if (sa->udp_encap) {
+
+                       sa->udp_spec.hdr.dst_port =
+                                       rte_cpu_to_be_16(sa->udp.dport);
+                       sa->udp_spec.hdr.src_port =
+                                       rte_cpu_to_be_16(sa->udp.sport);
+
+                       sa->pattern[2].mask = &rte_flow_item_udp_mask;
+                       sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_UDP;
+                       sa->pattern[2].spec = &sa->udp_spec;
+
+                       sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_ESP;
+                       sa->pattern[3].spec = &sa->esp_spec;
+                       sa->pattern[3].mask = &rte_flow_item_esp_mask;
+
+                       sa->pattern[4].type = RTE_FLOW_ITEM_TYPE_END;
+               } else {
+                       sa->pattern[2].type = RTE_FLOW_ITEM_TYPE_ESP;
+                       sa->pattern[2].spec = &sa->esp_spec;
+                       sa->pattern[2].mask = &rte_flow_item_esp_mask;
+
+                       sa->pattern[3].type = RTE_FLOW_ITEM_TYPE_END;
+               }
 
                sa->action[0].type = RTE_FLOW_ACTION_TYPE_SECURITY;
                sa->action[0].conf = ips->security.ses;
diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h
index 3ec3e55170..5fa4e62f37 100644
--- a/examples/ipsec-secgw/ipsec.h
+++ b/examples/ipsec-secgw/ipsec.h
@@ -128,6 +128,10 @@ struct ipsec_sa {
 
        struct ip_addr src;
        struct ip_addr dst;
+       struct {
+               uint16_t sport;
+               uint16_t dport;
+       } udp;
        uint8_t cipher_key[MAX_KEY_SIZE];
        uint16_t cipher_key_len;
        uint8_t auth_key[MAX_KEY_SIZE];
@@ -145,7 +149,7 @@ struct ipsec_sa {
        uint8_t fdir_qid;
        uint8_t fdir_flag;
 
-#define MAX_RTE_FLOW_PATTERN (4)
+#define MAX_RTE_FLOW_PATTERN (5)
 #define MAX_RTE_FLOW_ACTIONS (3)
        struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN];
        struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS];
@@ -154,6 +158,7 @@ struct ipsec_sa {
                struct rte_flow_item_ipv4 ipv4_spec;
                struct rte_flow_item_ipv6 ipv6_spec;
        };
+       struct rte_flow_item_udp udp_spec;
        struct rte_flow_item_esp esp_spec;
        struct rte_flow *flow;
        struct rte_security_session_conf sess_conf;
diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c
index bd58edebc9..847ac37b81 100644
--- a/examples/ipsec-secgw/sa.c
+++ b/examples/ipsec-secgw/sa.c
@@ -17,6 +17,7 @@
 #include <rte_byteorder.h>
 #include <rte_errno.h>
 #include <rte_ip.h>
+#include <rte_udp.h>
 #include <rte_random.h>
 #include <rte_ethdev.h>
 #include <rte_malloc.h>
@@ -882,6 +883,11 @@ parse_sa_tokens(char **tokens, uint32_t n_tokens,
                                app_sa_prm.udp_encap = 1;
                                udp_encap_p = 1;
                                break;
+                       case RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO:
+                               rule->udp_encap = 1;
+                               rule->udp.sport = 0;
+                               rule->udp.dport = 4500;
+                               break;
                        default:
                                APP_CHECK(0, status,
                                        "UDP encapsulation not supported for "
@@ -969,6 +975,8 @@ print_one_sa_rule(const struct ipsec_sa *sa, int inbound)
        }
 
        printf("mode:");
+       if (sa->udp_encap)
+               printf("UDP encapsulated ");
 
        switch (WITHOUT_TRANSPORT_VERSION(sa->flags)) {
        case IP4_TUNNEL:
@@ -1428,9 +1436,21 @@ fill_ipsec_app_sa_prm(struct rte_ipsec_sa_prm *prm,
        prm->ipsec_xform.replay_win_sz = app_prm->window_size;
 }
 
+struct udp_ipv4_tunnel {
+       struct rte_ipv4_hdr v4;
+       struct rte_udp_hdr udp;
+} __rte_packed;
+
+struct udp_ipv6_tunnel {
+       struct rte_ipv6_hdr v6;
+       struct rte_udp_hdr udp;
+} __rte_packed;
+
 static int
 fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const struct ipsec_sa *ss,
-       const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6)
+       const struct rte_ipv4_hdr *v4, struct rte_ipv6_hdr *v6,
+       const struct udp_ipv4_tunnel *udp_ipv4,
+       const struct udp_ipv6_tunnel *udp_ipv6)
 {
        int32_t rc;
 
@@ -1454,6 +1474,7 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const 
struct ipsec_sa *ss,
        prm->ipsec_xform.mode = (IS_TRANSPORT(ss->flags)) ?
                RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT :
                RTE_SECURITY_IPSEC_SA_MODE_TUNNEL;
+       prm->ipsec_xform.options.udp_encap = ss->udp_encap;
        prm->ipsec_xform.options.ecn = 1;
        prm->ipsec_xform.options.copy_dscp = 1;
 
@@ -1471,16 +1492,31 @@ fill_ipsec_sa_prm(struct rte_ipsec_sa_prm *prm, const 
struct ipsec_sa *ss,
                prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV4;
                prm->tun.hdr_l3_len = sizeof(*v4);
                prm->tun.hdr_l3_off = 0;
-               prm->tun.hdr_len = sizeof(*v4);
                prm->tun.next_proto = rc;
-               prm->tun.hdr = v4;
+               if (ss->udp_encap) {
+                       prm->tun.hdr_len = sizeof(*udp_ipv4);
+                       prm->tun.hdr = udp_ipv4;
+
+               } else {
+                       prm->tun.hdr_len = sizeof(*v4);
+                       prm->tun.hdr = v4;
+               }
+
        } else if (IS_IP6_TUNNEL(ss->flags)) {
                prm->ipsec_xform.tunnel.type = RTE_SECURITY_IPSEC_TUNNEL_IPV6;
                prm->tun.hdr_l3_len = sizeof(*v6);
                prm->tun.hdr_l3_off = 0;
-               prm->tun.hdr_len = sizeof(*v6);
                prm->tun.next_proto = rc;
-               prm->tun.hdr = v6;
+               if (ss->udp_encap) {
+
+                       prm->tun.hdr_len = sizeof(*udp_ipv6);
+                       prm->tun.hdr = udp_ipv6;
+
+               } else {
+                       prm->tun.hdr_len = sizeof(*v6);
+                       prm->tun.hdr = v6;
+               }
+
        } else {
                /* transport mode */
                prm->trs.proto = rc;
@@ -1519,25 +1555,66 @@ ipsec_sa_init(struct ipsec_sa *lsa, struct rte_ipsec_sa 
*sa, uint32_t sa_size)
        int rc;
        struct rte_ipsec_sa_prm prm;
        struct rte_ipsec_session *ips;
-       struct rte_ipv4_hdr v4  = {
-               .version_ihl = IPVERSION << 4 |
-                       sizeof(v4) / RTE_IPV4_IHL_MULTIPLIER,
-               .time_to_live = IPDEFTTL,
-               .next_proto_id = IPPROTO_ESP,
-               .src_addr = lsa->src.ip.ip4,
-               .dst_addr = lsa->dst.ip.ip4,
-       };
-       struct rte_ipv6_hdr v6 = {
-               .vtc_flow = htonl(IP6_VERSION << 28),
-               .proto = IPPROTO_ESP,
-       };
-
-       if (IS_IP6_TUNNEL(lsa->flags)) {
-               memcpy(v6.src_addr, lsa->src.ip.ip6.ip6_b, sizeof(v6.src_addr));
-               memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b, sizeof(v6.dst_addr));
+       struct rte_ipv4_hdr v4;
+       struct rte_ipv6_hdr v6;
+       struct udp_ipv4_tunnel udp_ipv4;
+       struct udp_ipv6_tunnel udp_ipv6;
+
+
+       if (IS_TUNNEL(lsa->flags) && (lsa->udp_encap)) {
+               if (IS_IP4(lsa->flags)) {
+
+                       udp_ipv4.v4.version_ihl = IPVERSION << 4 | sizeof(v4) /
+                                       RTE_IPV4_IHL_MULTIPLIER;
+                       udp_ipv4.v4.time_to_live = IPDEFTTL;
+                       udp_ipv4.v4.next_proto_id = IPPROTO_UDP;
+                       udp_ipv4.v4.src_addr = lsa->src.ip.ip4;
+                       udp_ipv4.v4.dst_addr = lsa->dst.ip.ip4;
+
+                       udp_ipv4.udp.src_port =
+                                       rte_cpu_to_be_16(lsa->udp.sport);
+                       udp_ipv4.udp.dst_port =
+                                       rte_cpu_to_be_16(lsa->udp.dport);
+
+               } else if (IS_IP6(lsa->flags)) {
+
+                       udp_ipv6.v6.vtc_flow = htonl(IP6_VERSION << 28),
+                       udp_ipv6.v6.proto = IPPROTO_UDP,
+                       memcpy(udp_ipv6.v6.src_addr, lsa->src.ip.ip6.ip6_b,
+                                       sizeof(udp_ipv6.v6.src_addr));
+                       memcpy(udp_ipv6.v6.dst_addr, lsa->dst.ip.ip6.ip6_b,
+                                       sizeof(udp_ipv6.v6.dst_addr));
+
+                       udp_ipv6.udp.src_port =
+                                       rte_cpu_to_be_16(lsa->udp.sport);
+                       udp_ipv6.udp.dst_port =
+                                       rte_cpu_to_be_16(lsa->udp.dport);
+               }
+
+       } else if (IS_TUNNEL(lsa->flags)) {
+
+               if (IS_IP4(lsa->flags)) {
+                       v4.version_ihl = IPVERSION << 4 | sizeof(v4) /
+                                       RTE_IPV4_IHL_MULTIPLIER;
+                       v4.time_to_live = IPDEFTTL;
+                       v4.next_proto_id = IPPROTO_ESP;
+                       v4.src_addr = lsa->src.ip.ip4;
+                       v4.dst_addr = lsa->dst.ip.ip4;
+
+               } else if (IS_IP6(lsa->flags)) {
+
+                       v6.vtc_flow = htonl(IP6_VERSION << 28),
+                       v6.proto = IPPROTO_ESP,
+                       memcpy(v6.src_addr, lsa->src.ip.ip6.ip6_b,
+                                       sizeof(v6.src_addr));
+                       memcpy(v6.dst_addr, lsa->dst.ip.ip6.ip6_b,
+                                       sizeof(v6.dst_addr));
+
+               }
+
        }
 
-       rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6);
+       rc = fill_ipsec_sa_prm(&prm, lsa, &v4, &v6, &udp_ipv4, &udp_ipv6);
        if (rc == 0)
                rc = rte_ipsec_sa_init(sa, &prm, sa_size);
        if (rc < 0)
@@ -1575,7 +1652,7 @@ ipsec_satbl_init(struct sa_ctx *ctx, uint32_t nb_ent, 
int32_t socket)
 
        /* determine SA size */
        idx = 0;
-       fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL);
+       fill_ipsec_sa_prm(&prm, ctx->sa + idx, NULL, NULL, NULL, NULL);
        sz = rte_ipsec_sa_size(&prm);
        if (sz < 0) {
                RTE_LOG(ERR, IPSEC, "%s(%p, %u, %d): "
-- 
2.25.1

Reply via email to