From af3b7acdd5464263a16fd7219a5cf6d0d951c49a Mon Sep 17 00:00:00 2001 From: Szymon Sliwa Date: Thu, 7 Dec 2017 19:16:57 +0100 Subject: plugins: odp: Add support for IPv6 IPsec Change-Id: I229128ccd88c1cf608e20507ca26752b9c0495f5 Signed-off-by: Szymon Sliwa --- src/plugins/odp/ipsec/esp_decrypt.c | 95 +++++++++++++++++++------------------ src/plugins/odp/ipsec/esp_encrypt.c | 39 +++++++-------- 2 files changed, 65 insertions(+), 69 deletions(-) diff --git a/src/plugins/odp/ipsec/esp_decrypt.c b/src/plugins/odp/ipsec/esp_decrypt.c index 1ef72fe8..3e076768 100644 --- a/src/plugins/odp/ipsec/esp_decrypt.c +++ b/src/plugins/odp/ipsec/esp_decrypt.c @@ -142,14 +142,15 @@ esp_decrypt_node_fn (vlib_main_t * vm, u32 sa_index0 = ~0; u32 seq; ip4_header_t *ih4 = 0, *oh4 = 0; - ip6_header_t *ih6 = 0, *oh6 = 0; - ip4_header_t old_ip_hdr; + ip6_header_t *oh6 = 0; + ip4_header_t old_ip4_hdr; + ip6_header_t old_ip6_hdr; u8 tunnel_mode = 1; u8 transport_ip6 = 0; sa_data_t *sa_sess_data; odp_crypto_op_param_t crypto_op_params; - odp_crypto_op_result_t result; odp_bool_t posted = 0; + odp_crypto_op_result_t result; bi0 = from[0]; from += 1; @@ -209,10 +210,8 @@ esp_decrypt_node_fn (vlib_main_t * vm, crypto_op_params.aad.length = 0; crypto_op_params.pkt = odp_packet_from_vlib_buffer (b0); crypto_op_params.out_pkt = crypto_op_params.pkt; - crypto_op_params.override_iv_ptr = sa_sess_data->iv_data; - if (PREDICT_TRUE (sa0->integ_alg != IPSEC_INTEG_ALG_NONE)) { b0->current_length -= icv_size; @@ -244,6 +243,17 @@ esp_decrypt_node_fn (vlib_main_t * vm, esp_footer_t *f0; u8 ip_hdr_size = 0; + ih4 = (ip4_header_t *) (b0->data + sizeof (ethernet_header_t)); + if (PREDICT_TRUE + ((ih4->ip_version_and_header_length & 0xF0) != 0x40)) + { + ip_hdr_size = sizeof (ip6_header_t); + } + else + { + ip_hdr_size = sizeof (ip4_header_t); + } + int blocks = (b0->current_length - sizeof (esp_header_t) - IV_SIZE) / BLOCK_SIZE; @@ -252,8 +262,6 @@ esp_decrypt_node_fn (vlib_main_t * vm, if (PREDICT_FALSE (!sa0->is_tunnel && !sa0->is_tunnel_ip6)) { tunnel_mode = 0; - ih4 = - (ip4_header_t *) (b0->data + sizeof (ethernet_header_t)); if (PREDICT_TRUE ((ih4->ip_version_and_header_length & 0xF0) != 0x40)) { @@ -262,11 +270,15 @@ esp_decrypt_node_fn (vlib_main_t * vm, 0x60)) { transport_ip6 = 1; - ip_hdr_size = sizeof (ip6_header_t); - ih6 = - (ip6_header_t *) (b0->data + - sizeof (ethernet_header_t)); - oh6 = vlib_buffer_get_current (b0); + oh6 = (ip6_header_t *) ((uintptr_t) + vlib_buffer_get_current (b0) + + sizeof (esp_header_t) + + IV_SIZE - + sizeof (ip6_header_t)); + old_ip6_hdr = + *((ip6_header_t *) ((uintptr_t) + vlib_buffer_get_current (b0) - + ip_hdr_size)); } else { @@ -284,7 +296,10 @@ esp_decrypt_node_fn (vlib_main_t * vm, vlib_buffer_get_current (b0) + sizeof (esp_header_t) + IV_SIZE - sizeof (ip4_header_t)); - ip_hdr_size = sizeof (ip4_header_t); + old_ip4_hdr = + *((ip4_header_t *) ((uintptr_t) + vlib_buffer_get_current (b0) - + ip_hdr_size)); } } @@ -311,38 +326,20 @@ esp_decrypt_node_fn (vlib_main_t * vm, goto trace; } - old_ip_hdr = - *((ip4_header_t *) ((uintptr_t) vlib_buffer_get_current (b0) - - sizeof (ip4_header_t))); - b0->current_data = sizeof (esp_header_t) + IV_SIZE + sizeof (ethernet_header_t); b0->current_length = (blocks * BLOCK_SIZE) - 2; if (tunnel_mode) - b0->current_data += sizeof (ip4_header_t); + b0->current_data += ip_hdr_size; else - b0->current_length += sizeof (ip4_header_t); + b0->current_length += ip_hdr_size; b0->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID; f0 = - (esp_footer_t *) ((u8 *) vlib_buffer_get_current (b0) + - b0->current_length); + ((esp_footer_t *) ((u8 *) vlib_buffer_get_current (b0) + + b0->current_length)); b0->current_length -= f0->pad_length; - if (tunnel_mode) - { - odp_packet_pull_head (crypto_op_params.pkt, - sizeof (esp_header_t) + IV_SIZE + - ip_hdr_size); - } - else - { - odp_packet_pull_head (crypto_op_params.pkt, - sizeof (esp_header_t) + IV_SIZE); - } - odp_packet_pull_tail (crypto_op_params.pkt, - f0->pad_length + icv_size); - /* tunnel mode */ if (PREDICT_TRUE (tunnel_mode)) { @@ -368,18 +365,20 @@ esp_decrypt_node_fn (vlib_main_t * vm, { if (PREDICT_FALSE (transport_ip6)) { - // TODO not supported - assert (0); next0 = ESP_DECRYPT_NEXT_IP6_INPUT; oh6->ip_version_traffic_class_and_flow_label = - ih6->ip_version_traffic_class_and_flow_label; + old_ip6_hdr.ip_version_traffic_class_and_flow_label; oh6->protocol = f0->next_header; - oh6->hop_limit = ih6->hop_limit; - oh6->src_address.as_u64[0] = ih6->src_address.as_u64[0]; - oh6->src_address.as_u64[1] = ih6->src_address.as_u64[1]; - oh6->dst_address.as_u64[0] = ih6->dst_address.as_u64[0]; - oh6->dst_address.as_u64[1] = ih6->dst_address.as_u64[1]; + oh6->hop_limit = old_ip6_hdr.hop_limit; + oh6->src_address.as_u64[0] = + old_ip6_hdr.src_address.as_u64[0]; + oh6->src_address.as_u64[1] = + old_ip6_hdr.src_address.as_u64[1]; + oh6->dst_address.as_u64[0] = + old_ip6_hdr.dst_address.as_u64[0]; + oh6->dst_address.as_u64[1] = + old_ip6_hdr.dst_address.as_u64[1]; oh6->payload_length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, @@ -389,13 +388,15 @@ esp_decrypt_node_fn (vlib_main_t * vm, { next0 = ESP_DECRYPT_NEXT_IP4_INPUT; oh4->ip_version_and_header_length = 0x45; - oh4->tos = old_ip_hdr.tos; + oh4->tos = old_ip4_hdr.tos; oh4->fragment_id = 0; oh4->flags_and_fragment_offset = 0; - oh4->ttl = old_ip_hdr.ttl; + oh4->ttl = old_ip4_hdr.ttl; oh4->protocol = f0->next_header; - oh4->src_address.as_u32 = old_ip_hdr.src_address.as_u32; - oh4->dst_address.as_u32 = old_ip_hdr.dst_address.as_u32; + oh4->src_address.as_u32 = + old_ip4_hdr.src_address.as_u32; + oh4->dst_address.as_u32 = + old_ip4_hdr.dst_address.as_u32; oh4->length = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); diff --git a/src/plugins/odp/ipsec/esp_encrypt.c b/src/plugins/odp/ipsec/esp_encrypt.c index 3e4517f1..24e40185 100644 --- a/src/plugins/odp/ipsec/esp_encrypt.c +++ b/src/plugins/odp/ipsec/esp_encrypt.c @@ -137,13 +137,14 @@ esp_encrypt_node_fn (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - u32 bi0, next0; + u32 bi0, next0, ip_version_traffic_class_and_flow_label; vlib_buffer_t *b0 = 0; u32 sa_index0; ipsec_sa_t *sa0; ip4_and_esp_header_t *ih0, *oh0 = 0; ip6_and_esp_header_t *ih6_0, *oh6_0 = 0; ip4_header_t old_ip4_hdr; + ip6_header_t old_ip6_hdr; ethernet_header_t old_eth_hdr; esp_footer_t *f0; u8 is_ipv6; @@ -184,7 +185,6 @@ esp_encrypt_node_fn (vlib_main_t * vm, old_eth_hdr = *((ethernet_header_t *) ((u8 *) vlib_buffer_get_current (b0) - sizeof (ethernet_header_t))); - old_ip4_hdr = *((ip4_header_t *) vlib_buffer_get_current (b0)); sa_sess_data = pool_elt_at_index (cwm->sa_sess_d[1], sa_index0); if (PREDICT_FALSE (!(sa_sess_data->sess))) @@ -203,10 +203,19 @@ esp_encrypt_node_fn (vlib_main_t * vm, ((ih0->ip4.ip_version_and_header_length & 0xF0) == 0x60)) { ip_hdr_size = sizeof (ip6_header_t); + is_ipv6 = 1; + old_ip6_hdr = *((ip6_header_t *) vlib_buffer_get_current (b0)); + ih6_0 = vlib_buffer_get_current (b0); + ip_version_traffic_class_and_flow_label = + ih6_0->ip6.ip_version_traffic_class_and_flow_label; + ip_proto = ih6_0->ip6.protocol; } else { ip_hdr_size = sizeof (ip4_header_t); + is_ipv6 = 0; + old_ip4_hdr = *((ip4_header_t *) vlib_buffer_get_current (b0)); + ip_proto = old_ip4_hdr.protocol; } odp_packet_t pkt = odp_packet_from_vlib_buffer (b0); @@ -224,40 +233,30 @@ esp_encrypt_node_fn (vlib_main_t * vm, to_next += 1; /* is ipv6 */ - if (PREDICT_FALSE - ((ih0->ip4.ip_version_and_header_length & 0xF0) == 0x60)) + if (PREDICT_FALSE (is_ipv6)) { - // TODO not supported - assert (0); - - is_ipv6 = 1; - ih6_0 = vlib_buffer_get_current (b0); - ip_hdr_size = sizeof (ip6_header_t); next_hdr_type = IP_PROTOCOL_IPV6; oh6_0 = vlib_buffer_get_current (b0); oh6_0->ip6.ip_version_traffic_class_and_flow_label = - ih6_0->ip6.ip_version_traffic_class_and_flow_label; + ip_version_traffic_class_and_flow_label; oh6_0->ip6.protocol = IP_PROTOCOL_IPSEC_ESP; oh6_0->ip6.hop_limit = 254; oh6_0->ip6.src_address.as_u64[0] = - ih6_0->ip6.src_address.as_u64[0]; + old_ip6_hdr.src_address.as_u64[0]; oh6_0->ip6.src_address.as_u64[1] = - ih6_0->ip6.src_address.as_u64[1]; + old_ip6_hdr.src_address.as_u64[1]; oh6_0->ip6.dst_address.as_u64[0] = - ih6_0->ip6.dst_address.as_u64[0]; + old_ip6_hdr.dst_address.as_u64[0]; oh6_0->ip6.dst_address.as_u64[1] = - ih6_0->ip6.dst_address.as_u64[1]; + old_ip6_hdr.dst_address.as_u64[1]; oh6_0->esp.spi = clib_net_to_host_u32 (sa0->spi); oh6_0->esp.seq = clib_net_to_host_u32 (sa0->seq); - ip_proto = ih6_0->ip6.protocol; next0 = ESP_ENCRYPT_NEXT_IP6_LOOKUP; } else { - is_ipv6 = 0; - ip_hdr_size = sizeof (ip4_header_t); next_hdr_type = IP_PROTOCOL_IP_IN_IP; oh0 = vlib_buffer_get_current (b0); @@ -271,7 +270,6 @@ esp_encrypt_node_fn (vlib_main_t * vm, oh0->ip4.dst_address.as_u32 = old_ip4_hdr.dst_address.as_u32; oh0->esp.spi = clib_net_to_host_u32 (sa0->spi); oh0->esp.seq = clib_net_to_host_u32 (sa0->seq); - ip_proto = old_ip4_hdr.protocol; next0 = ESP_ENCRYPT_NEXT_IP4_LOOKUP; } @@ -286,9 +284,6 @@ esp_encrypt_node_fn (vlib_main_t * vm, } else if (is_ipv6 && sa0->is_tunnel && sa0->is_tunnel_ip6) { - // TODO not supported - assert (0); - oh6_0->ip6.src_address.as_u64[0] = sa0->tunnel_src_addr.ip6.as_u64[0]; oh6_0->ip6.src_address.as_u64[1] = -- cgit 1.2.3-korg