aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSzymon Sliwa <szs@semihalf.com>2017-12-07 19:16:57 +0100
committerSzymon Sliwa <szs@semihalf.com>2018-02-06 14:48:32 +0100
commitaf3b7acdd5464263a16fd7219a5cf6d0d951c49a (patch)
tree4cf1ea53f1488c041631037661a186fcd312b285
parentafb5b006e4451a9dcb3270d4a5755413e65f5497 (diff)
plugins: odp: Add support for IPv6 IPsec
Change-Id: I229128ccd88c1cf608e20507ca26752b9c0495f5 Signed-off-by: Szymon Sliwa <szs@semihalf.com>
-rw-r--r--src/plugins/odp/ipsec/esp_decrypt.c95
-rw-r--r--src/plugins/odp/ipsec/esp_encrypt.c39
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 1ef72fe..3e07676 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 3e4517f..24e4018 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] =