From 26574dcd4f8608f6149cb93ff847177801105fcd Mon Sep 17 00:00:00 2001 From: Jeff Shaw Date: Mon, 17 Jun 2024 16:01:20 -0700 Subject: ipsec: enable ipv6 udp checksum offload RFC6935 section 5 states that, by default, the UDP checksum must be computed when originating an IPv6 UDP packet. The default behavior may be overridden when conditions defined by RFC6936 are satisfied. However this implementation does not satisfy all the conditions so the checksum must be computed. After ESP encryption the packet is an IPv6 UDP packet so set the l3_hdr_offset and l4_hdr_offset values, and set the UDP_CKSUM offload flag in the buffer. Type: improvement Co-authored-by: Cian Ferriter Change-Id: I9f8c434c9fe9dbddd8890d5ae366984bfcf34067 Signed-off-by: Jeff Shaw --- src/vnet/ipsec/esp_encrypt.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/vnet/ipsec/esp_encrypt.c b/src/vnet/ipsec/esp_encrypt.c index 544ff7b6aa8..f6d1ecaed24 100644 --- a/src/vnet/ipsec/esp_encrypt.c +++ b/src/vnet/ipsec/esp_encrypt.c @@ -589,6 +589,22 @@ esp_prepare_async_frame (vlib_main_t *vm, ipsec_per_thread_data_t *ptd, async_next, iv, tag, aad, flag); } +/* Per RFC6935 section 5, the UDP checksum must be computed when originating + * an IPv6 UDP packet. The default behavior may be overridden when conditions + * defined by RFC6936 are satisfied. This implementation does not satisfy all + * the conditions so the checksum must be computed. + */ +static_always_inline void +set_ip6_udp_cksum_offload (vlib_buffer_t *b, i16 l3_hdr_offset, + i16 l4_hdr_offset) +{ + vnet_buffer (b)->l3_hdr_offset = l3_hdr_offset; + vnet_buffer (b)->l4_hdr_offset = l4_hdr_offset; + vnet_buffer_offload_flags_set (b, VNET_BUFFER_OFFLOAD_F_UDP_CKSUM); + b->flags |= (VNET_BUFFER_F_IS_IP6 | VNET_BUFFER_F_L3_HDR_OFFSET_VALID | + VNET_BUFFER_F_L4_HDR_OFFSET_VALID); +} + always_inline uword esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vnet_link_t lt, int is_tun, @@ -869,6 +885,15 @@ esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node, esp_update_ip4_hdr (ip4, len, /* is_transport */ 0, 0); } + if (ipsec_sa_is_set_UDP_ENCAP (sa0) && + ipsec_sa_is_set_IS_TUNNEL_V6 (sa0)) + { + i16 l3_off = b[0]->current_data - hdr_len; + i16 l4_off = l3_off + sizeof (ip6_header_t); + + set_ip6_udp_cksum_offload (b[0], l3_off, l4_off); + } + dpo = &sa0->dpo; if (!is_tun) { @@ -988,6 +1013,14 @@ esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node, esp_fill_udp_hdr (sa0, udp, udp_len); } + if (udp && (VNET_LINK_IP6 == lt)) + { + i16 l3_off = b[0]->current_data - hdr_len + l2_len; + i16 l4_off = l3_off + ip_len; + + set_ip6_udp_cksum_offload (b[0], l3_off, l4_off); + } + sync_next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT; } -- cgit 1.2.3-korg