From: Sergio Gonzalez Monroy Date: Thu, 9 Jun 2016 08:42:49 +0000 (+0100) Subject: examples/ipsec-secgw: support transport mode X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=f159e70b0922;p=dpdk.git examples/ipsec-secgw: support transport mode IPSec transport mode support. Signed-off-by: Sergio Gonzalez Monroy Acked-by: Pablo de Lara --- diff --git a/examples/ipsec-secgw/esp.c b/examples/ipsec-secgw/esp.c index e1fde36ff4..05caa77a2f 100644 --- a/examples/ipsec-secgw/esp.c +++ b/examples/ipsec-secgw/esp.c @@ -42,7 +42,6 @@ #include #include -#include #include #include #include @@ -70,21 +69,24 @@ int esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa, struct rte_crypto_op *cop) { - int32_t payload_len, ip_hdr_len; + struct ip *ip4; struct rte_crypto_sym_op *sym_cop; + int32_t payload_len, ip_hdr_len; RTE_ASSERT(m != NULL); RTE_ASSERT(sa != NULL); RTE_ASSERT(cop != NULL); - ip_hdr_len = 0; - switch (sa->flags) { - case IP4_TUNNEL: - ip_hdr_len = sizeof(struct ip); - break; - case IP6_TUNNEL: + ip4 = rte_pktmbuf_mtod(m, struct ip *); + if (likely(ip4->ip_v == IPVERSION)) + ip_hdr_len = ip4->ip_hl * 4; + else if (ip4->ip_v == IP6_VERSION) + /* XXX No option headers supported */ ip_hdr_len = sizeof(struct ip6_hdr); - break; + else { + RTE_LOG(ERR, IPSEC_ESP, "invalid IP packet type %d\n", + ip4->ip_v); + return -EINVAL; } payload_len = rte_pktmbuf_pkt_len(m) - ip_hdr_len - @@ -126,6 +128,8 @@ int esp_inbound_post(struct rte_mbuf *m, struct ipsec_sa *sa, struct rte_crypto_op *cop) { + struct ip *ip4, *ip; + struct ip6_hdr *ip6; uint8_t *nexthdr, *pad_len; uint8_t *padding; uint16_t i; @@ -135,7 +139,7 @@ esp_inbound_post(struct rte_mbuf *m, struct ipsec_sa *sa, RTE_ASSERT(cop != NULL); if (cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS) { - RTE_LOG(ERR, IPSEC_ESP, "Failed crypto op\n"); + RTE_LOG(ERR, IPSEC_ESP, "failed crypto op\n"); return -1; } @@ -146,7 +150,7 @@ esp_inbound_post(struct rte_mbuf *m, struct ipsec_sa *sa, padding = pad_len - *pad_len; for (i = 0; i < *pad_len; i++) { if (padding[i] != i + 1) { - RTE_LOG(ERR, IPSEC_ESP, "invalid pad_len field\n"); + RTE_LOG(ERR, IPSEC_ESP, "invalid padding\n"); return -EINVAL; } } @@ -157,7 +161,23 @@ esp_inbound_post(struct rte_mbuf *m, struct ipsec_sa *sa, return -EINVAL; } - ipip_inbound(m, sizeof(struct esp_hdr) + sa->iv_len); + if (unlikely(sa->flags == TRANSPORT)) { + ip = rte_pktmbuf_mtod(m, struct ip *); + ip4 = (struct ip *)rte_pktmbuf_adj(m, + sizeof(struct esp_hdr) + sa->iv_len); + if (likely(ip->ip_v == IPVERSION)) { + memmove(ip4, ip, ip->ip_hl * 4); + ip4->ip_p = *nexthdr; + ip4->ip_len = htons(rte_pktmbuf_data_len(m)); + } else { + ip6 = (struct ip6_hdr *)ip4; + /* XXX No option headers supported */ + memmove(ip6, ip, sizeof(struct ip6_hdr)); + ip6->ip6_nxt = *nexthdr; + ip6->ip6_plen = htons(rte_pktmbuf_data_len(m)); + } + } else + ipip_inbound(m, sizeof(struct esp_hdr) + sa->iv_len); return 0; } @@ -166,31 +186,57 @@ int esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa, struct rte_crypto_op *cop) { - uint16_t pad_payload_len, pad_len, ip_hdr_len; struct ip *ip4; struct ip6_hdr *ip6; - struct esp_hdr *esp; - int32_t i; - char *padding; + struct esp_hdr *esp = NULL; + uint8_t *padding, *new_ip, nlp; struct rte_crypto_sym_op *sym_cop; + int32_t i; + uint16_t pad_payload_len, pad_len, ip_hdr_len; RTE_ASSERT(m != NULL); RTE_ASSERT(sa != NULL); RTE_ASSERT(cop != NULL); - /* Payload length */ - pad_payload_len = RTE_ALIGN_CEIL(rte_pktmbuf_pkt_len(m) + 2, - sa->block_size); - pad_len = pad_payload_len - rte_pktmbuf_pkt_len(m); - ip_hdr_len = 0; - switch (sa->flags) { - case IP4_TUNNEL: + + ip4 = rte_pktmbuf_mtod(m, struct ip *); + if (likely(ip4->ip_v == IPVERSION)) { + if (unlikely(sa->flags == TRANSPORT)) { + ip_hdr_len = ip4->ip_hl * 4; + nlp = ip4->ip_p; + } else + nlp = IPPROTO_IPIP; + } else if (ip4->ip_v == IP6_VERSION) { + if (unlikely(sa->flags == TRANSPORT)) { + /* XXX No option headers supported */ + ip_hdr_len = sizeof(struct ip6_hdr); + ip6 = (struct ip6_hdr *)ip4; + nlp = ip6->ip6_nxt; + } else + nlp = IPPROTO_IPV6; + } else { + RTE_LOG(ERR, IPSEC_ESP, "invalid IP packet type %d\n", + ip4->ip_v); + return -EINVAL; + } + + /* Padded payload length */ + pad_payload_len = RTE_ALIGN_CEIL(rte_pktmbuf_pkt_len(m) - + ip_hdr_len + 2, sa->block_size); + pad_len = pad_payload_len + ip_hdr_len - rte_pktmbuf_pkt_len(m); + + RTE_ASSERT(sa->flags == IP4_TUNNEL || sa->flags == IP6_TUNNEL || + sa->flags == TRANSPORT); + + if (likely(sa->flags == IP4_TUNNEL)) ip_hdr_len = sizeof(struct ip); - break; - case IP6_TUNNEL: + else if (sa->flags == IP6_TUNNEL) ip_hdr_len = sizeof(struct ip6_hdr); - break; + else if (sa->flags != TRANSPORT) { + RTE_LOG(ERR, IPSEC_ESP, "Unsupported SA flags: 0x%x\n", + sa->flags); + return -EINVAL; } /* Check maximum packet size */ @@ -200,7 +246,7 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa, return -EINVAL; } - padding = rte_pktmbuf_append(m, pad_len + sa->digest_len); + padding = (uint8_t *)rte_pktmbuf_append(m, pad_len + sa->digest_len); if (unlikely(padding == NULL)) { RTE_LOG(ERR, IPSEC_ESP, "not enough mbuf trailing space\n"); return -ENOSPC; @@ -218,10 +264,20 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa, &sa->src, &sa->dst); esp = (struct esp_hdr *)(ip6 + 1); break; - default: - RTE_LOG(ERR, IPSEC_ESP, "Unsupported SA flags: 0x%x\n", - sa->flags); - return -EINVAL; + case TRANSPORT: + new_ip = (uint8_t *)rte_pktmbuf_prepend(m, + sizeof(struct esp_hdr) + sa->iv_len); + memmove(new_ip, ip4, ip_hdr_len); + esp = (struct esp_hdr *)(new_ip + ip_hdr_len); + if (likely(ip4->ip_v == IPVERSION)) { + ip4 = (struct ip *)new_ip; + ip4->ip_p = IPPROTO_ESP; + ip4->ip_len = htons(rte_pktmbuf_data_len(m)); + } else { + ip6 = (struct ip6_hdr *)new_ip; + ip6->ip6_nxt = IPPROTO_ESP; + ip6->ip6_plen = htons(rte_pktmbuf_data_len(m)); + } } sa->seq++; @@ -235,11 +291,7 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa, for (i = 0; i < pad_len - 2; i++) padding[i] = i + 1; padding[pad_len - 2] = pad_len - 2; - - if (RTE_ETH_IS_IPV4_HDR(m->packet_type)) - padding[pad_len - 1] = IPPROTO_IPIP; - else - padding[pad_len - 1] = IPPROTO_IPV6; + padding[pad_len - 1] = nlp; sym_cop = (struct rte_crypto_sym_op *)(cop + 1); diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h index 83d7b1c471..0d2ee25481 100644 --- a/examples/ipsec-secgw/ipsec.h +++ b/examples/ipsec-secgw/ipsec.h @@ -103,6 +103,7 @@ struct ipsec_sa { uint16_t flags; #define IP4_TUNNEL (1 << 0) #define IP6_TUNNEL (1 << 1) +#define TRANSPORT (1 << 2) struct ip_addr src; struct ip_addr dst; struct rte_crypto_sym_xform *xforms; diff --git a/examples/ipsec-secgw/rt.c b/examples/ipsec-secgw/rt.c index d46df49b3e..fa5f0420e7 100644 --- a/examples/ipsec-secgw/rt.c +++ b/examples/ipsec-secgw/rt.c @@ -62,6 +62,9 @@ static struct ip4_route rt_ip4_ep0[] = { /* Tunnels */ { IPv4(172, 16, 2, 5), 32, 0 }, { IPv4(172, 16, 2, 6), 32, 1 }, + /* Transport */ + { IPv4(192, 168, 175, 0), 24, 0 }, + { IPv4(192, 168, 176, 0), 24, 1 }, /* Bypass */ { IPv4(192, 168, 240, 0), 24, 0 }, { IPv4(192, 168, 241, 0), 24, 1 }, @@ -72,6 +75,9 @@ static struct ip4_route rt_ip4_ep0[] = { { IPv4(192, 168, 116, 0), 24, 3 }, { IPv4(192, 168, 65, 0), 24, 2 }, { IPv4(192, 168, 66, 0), 24, 3 }, + /* Transport */ + { IPv4(192, 168, 185, 0), 24, 2 }, + { IPv4(192, 168, 186, 0), 24, 3 }, /* NULL */ { IPv4(192, 168, 210, 0), 24, 2 }, { IPv4(192, 168, 211, 0), 24, 3 }, @@ -87,6 +93,11 @@ static struct ip6_route rt_ip6_ep0[] = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x55, 0x55 }, 116, 0 }, { { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x66, 0x66 }, 116, 1 }, + /* Transport */ + { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 0 }, + { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 1 }, /* Inbound */ /* Tunnels */ { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, @@ -97,6 +108,11 @@ static struct ip6_route rt_ip6_ep0[] = { 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00 }, 116, 2 }, { { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, 116, 3 }, + /* Transport */ + { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 2 }, + { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 3 }, }; static struct ip4_route rt_ip4_ep1[] = { @@ -104,6 +120,9 @@ static struct ip4_route rt_ip4_ep1[] = { /* Tunnels */ { IPv4(172, 16, 1, 5), 32, 0 }, { IPv4(172, 16, 1, 6), 32, 1 }, + /* Transport */ + { IPv4(192, 168, 185, 0), 24, 0 }, + { IPv4(192, 168, 186, 0), 24, 1 }, /* Bypass */ { IPv4(192, 168, 245, 0), 24, 0 }, { IPv4(192, 168, 246, 0), 24, 1 }, @@ -114,6 +133,9 @@ static struct ip4_route rt_ip4_ep1[] = { { IPv4(192, 168, 106, 0), 24, 3 }, { IPv4(192, 168, 55, 0), 24, 2 }, { IPv4(192, 168, 56, 0), 24, 3 }, + /* Transport */ + { IPv4(192, 168, 175, 0), 24, 2 }, + { IPv4(192, 168, 176, 0), 24, 3 }, /* NULL */ { IPv4(192, 168, 200, 0), 24, 2 }, { IPv4(192, 168, 201, 0), 24, 3 }, @@ -129,6 +151,11 @@ static struct ip6_route rt_ip6_ep1[] = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x55, 0x55 }, 116, 0 }, { { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x66, 0x66 }, 116, 1 }, + /* Transport */ + { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 0 }, + { { 0xff, 0xff, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 1 }, /* Inbound */ /* Tunnels */ @@ -140,6 +167,11 @@ static struct ip6_route rt_ip6_ep1[] = { 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00 }, 116, 2 }, { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }, 116, 3 }, + /* Transport */ + { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 116, 2 }, + { { 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00 }, 116, 3 }, }; void diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index 8b54beb97e..ab18b81103 100644 --- a/examples/ipsec-secgw/sa.c +++ b/examples/ipsec-secgw/sa.c @@ -74,6 +74,24 @@ const struct ipsec_sa sa_out[] = { .flags = IP4_TUNNEL }, { + .spi = 10, + .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC, + .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC, + .digest_len = 12, + .iv_len = 16, + .block_size = 16, + .flags = TRANSPORT + }, + { + .spi = 11, + .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC, + .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC, + .digest_len = 12, + .iv_len = 16, + .block_size = 16, + .flags = TRANSPORT + }, + { .spi = 15, .src.ip4 = IPv4(172, 16, 1, 5), .dst.ip4 = IPv4(172, 16, 2, 5), @@ -148,6 +166,24 @@ const struct ipsec_sa sa_in[] = { .flags = IP4_TUNNEL }, { + .spi = 110, + .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC, + .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC, + .digest_len = 12, + .iv_len = 16, + .block_size = 16, + .flags = TRANSPORT + }, + { + .spi = 111, + .cipher_algo = RTE_CRYPTO_CIPHER_AES_CBC, + .auth_algo = RTE_CRYPTO_AUTH_SHA1_HMAC, + .digest_len = 12, + .iv_len = 16, + .block_size = 16, + .flags = TRANSPORT + }, + { .spi = 115, .src.ip4 = IPv4(172, 16, 2, 5), .dst.ip4 = IPv4(172, 16, 1, 5), @@ -447,6 +483,9 @@ single_inbound_lookup(struct ipsec_sa *sadb, struct rte_mbuf *pkt, !memcmp(&sa->src.ip6, src6_addr, 16) && !memcmp(&sa->dst.ip6, src6_addr + 16, 16)) *sa_ret = sa; + break; + case TRANSPORT: + *sa_ret = sa; } } diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c index 61720c88ce..9c4b256bdb 100644 --- a/examples/ipsec-secgw/sp4.c +++ b/examples/ipsec-secgw/sp4.c @@ -135,6 +135,26 @@ const struct acl4_rules acl4_rules_out[] = { .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} }, { + .data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1}, + /* destination IPv4 */ + .field[2] = {.value.u32 = IPv4(192, 168, 175, 0), + .mask_range.u32 = 24,}, + /* source port */ + .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, + /* destination port */ + .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + }, + { + .data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1}, + /* destination IPv4 */ + .field[2] = {.value.u32 = IPv4(192, 168, 176, 0), + .mask_range.u32 = 24,}, + /* source port */ + .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, + /* destination port */ + .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + }, + { .data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1}, /* destination IPv4 */ .field[2] = {.value.u32 = IPv4(192, 168, 200, 0), @@ -218,6 +238,26 @@ const struct acl4_rules acl4_rules_in[] = { .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} }, { + .data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1}, + /* destination IPv4 */ + .field[2] = {.value.u32 = IPv4(192, 168, 185, 0), + .mask_range.u32 = 24,}, + /* source port */ + .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, + /* destination port */ + .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + }, + { + .data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1}, + /* destination IPv4 */ + .field[2] = {.value.u32 = IPv4(192, 168, 186, 0), + .mask_range.u32 = 24,}, + /* source port */ + .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, + /* destination port */ + .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + }, + { .data = {.userdata = PROTECT(115), .category_mask = 1, .priority = 1}, /* destination IPv4 */ .field[2] = {.value.u32 = IPv4(192, 168, 210, 0), diff --git a/examples/ipsec-secgw/sp6.c b/examples/ipsec-secgw/sp6.c index c6fb851c77..1dda11a443 100644 --- a/examples/ipsec-secgw/sp6.c +++ b/examples/ipsec-secgw/sp6.c @@ -170,6 +170,30 @@ const struct acl6_rules acl6_rules_out[] = { .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} }, { + .data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1}, + /* destination IPv6 */ + .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, + .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, + .field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,}, + .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, + /* source port */ + .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, + /* destination port */ + .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + }, + { + .data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1}, + /* destination IPv6 */ + .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, + .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, + .field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, + .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, + /* source port */ + .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, + /* destination port */ + .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + }, + { .data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1}, /* destination IPv6 */ .field[5] = {.value.u32 = 0x0, .mask_range.u32 = 32,}, @@ -221,6 +245,30 @@ const struct acl6_rules acl6_rules_in[] = { .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} }, { + .data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1}, + /* destination IPv6 */ + .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,}, + .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, + .field[7] = {.value.u32 = 0x00000000, .mask_range.u32 = 32,}, + .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, + /* source port */ + .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, + /* destination port */ + .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + }, + { + .data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1}, + /* destination IPv6 */ + .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,}, + .field[6] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, + .field[7] = {.value.u32 = 0x11111111, .mask_range.u32 = 32,}, + .field[8] = {.value.u32 = 0x0, .mask_range.u32 = 0,}, + /* source port */ + .field[9] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, + /* destination port */ + .field[10] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + }, + { .data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1}, /* destination IPv6 */ .field[5] = {.value.u32 = 0xffff0000, .mask_range.u32 = 32,},