diff options
author | Radu Nicolau <radu.nicolau@intel.com> | 2018-06-13 16:39:05 +0100 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2018-06-21 07:40:33 +0000 |
commit | 0c58ad4045c03552a6c6100e8e8441558aaea972 (patch) | |
tree | 0324628a7fb2dee181909de4760fddac05764d10 | |
parent | 382daf67f3687b281cea1dbd61fdafa0c71376dc (diff) |
dpdk/ipsec: add support for UDP encap/decap
Change-Id: I024c1d398fcb51e5a20f9049d16a87b3b1ba0c20
Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
-rw-r--r-- | src/plugins/dpdk/ipsec/esp_decrypt.c | 31 | ||||
-rw-r--r-- | src/plugins/dpdk/ipsec/esp_encrypt.c | 51 |
2 files changed, 65 insertions, 17 deletions
diff --git a/src/plugins/dpdk/ipsec/esp_decrypt.c b/src/plugins/dpdk/ipsec/esp_decrypt.c index 06909b3d347..8327e743d47 100644 --- a/src/plugins/dpdk/ipsec/esp_decrypt.c +++ b/src/plugins/dpdk/ipsec/esp_decrypt.c @@ -439,6 +439,7 @@ dpdk_esp_decrypt_post_node_fn (vlib_main_t * vm, crypto_alg_t *cipher_alg, *auth_alg; esp_header_t *esp0; u8 trunc_size, is_aead; + u16 udp_encap_adv = 0; next0 = ESP_DECRYPT_NEXT_DROP; @@ -476,9 +477,15 @@ dpdk_esp_decrypt_post_node_fn (vlib_main_t * vm, esp_replay_advance(sa0, seq); } + /* if UDP encapsulation is used adjust the address of the IP header */ + if (sa0->udp_encap && (b0->flags & VNET_BUFFER_F_IS_IP4)) + { + udp_encap_adv = sizeof (udp_header_t); + } + if (b0->flags & VNET_BUFFER_F_IS_IP4) - ih4 = - (ip4_header_t *) ((u8 *) esp0 - sizeof (ip4_header_t)); + ih4 = (ip4_header_t *) + ((u8 *) esp0 - udp_encap_adv - sizeof (ip4_header_t)); else ih4 = (ip4_header_t *) ((u8 *) esp0 - sizeof (ip6_header_t)); @@ -519,15 +526,17 @@ dpdk_esp_decrypt_post_node_fn (vlib_main_t * vm, { if ((ih4->ip_version_and_header_length & 0xF0) == 0x40) { - u16 ih4_len = ip4_header_bytes (ih4); - vlib_buffer_advance (b0, - ih4_len); - oh4 = vlib_buffer_get_current (b0); - memmove(oh4, ih4, ih4_len); - - next0 = ESP_DECRYPT_NEXT_IP4_INPUT; - oh4->protocol = f0->next_header; - oh4->length = clib_host_to_net_u16 (b0->current_length); - oh4->checksum = ip4_header_checksum(oh4); + u16 ih4_len = ip4_header_bytes (ih4); + vlib_buffer_advance (b0, - ih4_len - udp_encap_adv); + next0 = ESP_DECRYPT_NEXT_IP4_INPUT; + if (!sa0->udp_encap) + { + oh4 = vlib_buffer_get_current (b0); + memmove(oh4, ih4, ih4_len); + oh4->protocol = f0->next_header; + oh4->length = clib_host_to_net_u16 (b0->current_length); + oh4->checksum = ip4_header_checksum(oh4); + } } else if ((ih4->ip_version_and_header_length & 0xF0) == 0x60) { diff --git a/src/plugins/dpdk/ipsec/esp_encrypt.c b/src/plugins/dpdk/ipsec/esp_encrypt.c index 07b2dae387a..7947a8e9d02 100644 --- a/src/plugins/dpdk/ipsec/esp_encrypt.c +++ b/src/plugins/dpdk/ipsec/esp_encrypt.c @@ -21,6 +21,7 @@ #include <vnet/ipsec/ipsec.h> #include <vnet/ipsec/esp.h> +#include <vnet/udp/udp.h> #include <dpdk/ipsec/ipsec.h> #include <dpdk/device/dpdk.h> #include <dpdk/device/dpdk_priv.h> @@ -152,6 +153,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, u32 sa_index0; ip4_and_esp_header_t *ih0, *oh0 = 0; ip6_and_esp_header_t *ih6_0, *oh6_0 = 0; + ip4_and_udp_and_esp_header_t *ouh0 = 0; esp_header_t *esp0; esp_footer_t *f0; u8 is_ipv6, next_hdr_type; @@ -159,6 +161,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, u16 orig_sz; u8 trunc_size; u16 rewrite_len; + u16 udp_encap_adv = 0; struct rte_mbuf *mb0 = 0; struct rte_crypto_op *op; u16 res_idx; @@ -266,6 +269,10 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, iv_size = cipher_alg->iv_len; trunc_size = auth_alg->trunc_size; + /* if UDP encapsulation is used adjust the address of the IP header */ + if (sa0->udp_encap && !is_ipv6) + udp_encap_adv = sizeof (udp_header_t); + if (sa0->is_tunnel) { rewrite_len = 0; @@ -273,10 +280,11 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, { /* in tunnel mode send it back to FIB */ priv->next = DPDK_CRYPTO_INPUT_NEXT_IP4_LOOKUP; - u8 adv = - sizeof (ip4_header_t) + sizeof (esp_header_t) + iv_size; + u8 adv = sizeof (ip4_header_t) + udp_encap_adv + + sizeof (esp_header_t) + iv_size; vlib_buffer_advance (b0, -adv); oh0 = vlib_buffer_get_current (b0); + ouh0 = vlib_buffer_get_current (b0); next_hdr_type = IP_PROTOCOL_IP_IN_IP; /* * oh0->ip4.ip_version_and_header_length = 0x45; @@ -297,9 +305,16 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, sa0->tunnel_src_addr.ip4.as_u32; oh0->ip4.dst_address.as_u32 = sa0->tunnel_dst_addr.ip4.as_u32; - esp0 = &oh0->esp; - oh0->esp.spi = clib_host_to_net_u32 (sa0->spi); - oh0->esp.seq = clib_host_to_net_u32 (sa0->seq); + + if (sa0->udp_encap) + { + oh0->ip4.protocol = IP_PROTOCOL_UDP; + esp0 = &ouh0->esp; + } + else + esp0 = &oh0->esp; + esp0->spi = clib_host_to_net_u32 (sa0->spi); + esp0->seq = clib_host_to_net_u32 (sa0->seq); } else if (is_ipv6 && sa0->is_tunnel_ip6) /* ip6inip6 */ { @@ -347,7 +362,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, { priv->next = DPDK_CRYPTO_INPUT_NEXT_INTERFACE_OUTPUT; rewrite_len = vnet_buffer (b0)->ip.save_rewrite_length; - u16 adv = sizeof (esp_header_t) + iv_size; + u16 adv = sizeof (esp_header_t) + iv_size + udp_encap_adv; vlib_buffer_advance (b0, -adv - rewrite_len); u8 *src = ((u8 *) ih0) - rewrite_len; u8 *dst = vlib_buffer_get_current (b0); @@ -371,11 +386,28 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, memmove (dst, src, rewrite_len + ip_size); oh0->ip4.protocol = IP_PROTOCOL_IPSEC_ESP; esp0 = (esp_header_t *) (((u8 *) oh0) + ip_size); + if (sa0->udp_encap) + { + oh0->ip4.protocol = IP_PROTOCOL_UDP; + esp0 = (esp_header_t *) + (((u8 *) oh0) + ip_size + udp_encap_adv); + } + else + { + oh0->ip4.protocol = IP_PROTOCOL_IPSEC_ESP; + esp0 = (esp_header_t *) (((u8 *) oh0) + ip_size); + } } esp0->spi = clib_host_to_net_u32 (sa0->spi); esp0->seq = clib_host_to_net_u32 (sa0->seq); } + if (sa0->udp_encap && ouh0) + { + ouh0->udp.src_port = clib_host_to_net_u16 (UDP_DST_PORT_ipsec); + ouh0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_ipsec); + ouh0->udp.checksum = 0; + } ASSERT (is_pow2 (cipher_alg->boundary)); u16 mask = cipher_alg->boundary - 1; u16 pad_payload_len = ((orig_sz + 2) + mask) & ~mask; @@ -403,6 +435,13 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, oh0->ip4.length = clib_host_to_net_u16 (b0->current_length - rewrite_len); oh0->ip4.checksum = ip4_header_checksum (&oh0->ip4); + if (sa0->udp_encap && ouh0) + { + ouh0->udp.length = + clib_host_to_net_u16 (clib_net_to_host_u16 + (ouh0->ip4.length) - + ip4_header_bytes (&ouh0->ip4)); + } } vnet_buffer (b0)->sw_if_index[VLIB_RX] = |