summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Shaw <jeffrey.b.shaw@intel.com>2024-06-17 16:01:20 -0700
committerFan Zhang <fanzhang.oss@gmail.com>2024-06-25 15:37:28 +0000
commit26574dcd4f8608f6149cb93ff847177801105fcd (patch)
tree25d6b0e5eedc096b5e31c544059602a52971f0fb
parent0eccf453c6550bf7c3435dd08c8b504d82e2e2bd (diff)
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 <cian.ferriter@intel.com> Change-Id: I9f8c434c9fe9dbddd8890d5ae366984bfcf34067 Signed-off-by: Jeff Shaw <jeffrey.b.shaw@intel.com>
-rw-r--r--src/vnet/ipsec/esp_encrypt.c33
1 files changed, 33 insertions, 0 deletions
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;
}