From f5462369f3ad22c9d19f54832faa2b6e61449f66 Mon Sep 17 00:00:00 2001 From: Mohsin Kazmi Date: Tue, 23 Feb 2021 15:55:04 +0100 Subject: devices: add support for pseudo header checksum Type: improvement Linux uses pseudo header checksum when checksum of l4 is offloaded. This patch adds similar support in virtual interfaces. Change-Id: I6a94d1104e59356f95057e7c122e3be9cd8659a3 Signed-off-by: Aloys Augustin Signed-off-by: Mohsin Kazmi --- src/vnet/devices/virtio/device.c | 42 +++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) (limited to 'src/vnet/devices/virtio/device.c') diff --git a/src/vnet/devices/virtio/device.c b/src/vnet/devices/virtio/device.c index 6c2fe34abf0..ac9be6b02ae 100644 --- a/src/vnet/devices/virtio/device.c +++ b/src/vnet/devices/virtio/device.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -296,37 +297,60 @@ set_checksum_offsets (vlib_buffer_t *b, virtio_net_hdr_v1_t *hdr, 0 /* ip6 */ ); hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; hdr->csum_start = gho.l4_hdr_offset; // 0x22; + + /* + * virtio devices do not support IP4 checksum offload. So driver takes + * care of it while doing tx. + */ + ip4 = (ip4_header_t *) (vlib_buffer_get_current (b) + gho.l3_hdr_offset); + if (oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM) + ip4->checksum = ip4_header_checksum (ip4); + + /* + * virtio devices assume the l4 header is set to the checksum of the + * l3 pseudo-header, so we compute it before tx-ing + */ if (oflags & VNET_BUFFER_OFFLOAD_F_TCP_CKSUM) { + tcp_header_t *tcp = + (tcp_header_t *) (vlib_buffer_get_current (b) + gho.l4_hdr_offset); + tcp->checksum = ip4_pseudo_header_cksum (ip4); hdr->csum_offset = STRUCT_OFFSET_OF (tcp_header_t, checksum); } else if (oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM) { + udp_header_t *udp = + (udp_header_t *) (vlib_buffer_get_current (b) + gho.l4_hdr_offset); + udp->checksum = ip4_pseudo_header_cksum (ip4); hdr->csum_offset = STRUCT_OFFSET_OF (udp_header_t, checksum); } - - /* - * virtio devices do not support IP4 checksum offload. So driver takes care - * of it while doing tx. - */ - ip4 = - (ip4_header_t *) (vlib_buffer_get_current (b) + gho.l3_hdr_offset); - if (oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM) - ip4->checksum = ip4_header_checksum (ip4); } else if (b->flags & VNET_BUFFER_F_IS_IP6) { + ip6_header_t *ip6; generic_header_offset_t gho = { 0 }; vnet_generic_header_offset_parser (b, &gho, is_l2, 0 /* ip4 */ , 1 /* ip6 */ ); hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; hdr->csum_start = gho.l4_hdr_offset; // 0x36; + ip6 = (ip6_header_t *) (vlib_buffer_get_current (b) + gho.l3_hdr_offset); + + /* + * virtio devices assume the l4 header is set to the checksum of the + * l3 pseudo-header, so we compute it before tx-ing + */ if (oflags & VNET_BUFFER_OFFLOAD_F_TCP_CKSUM) { + tcp_header_t *tcp = + (tcp_header_t *) (vlib_buffer_get_current (b) + gho.l4_hdr_offset); + tcp->checksum = ip6_pseudo_header_cksum (ip6); hdr->csum_offset = STRUCT_OFFSET_OF (tcp_header_t, checksum); } else if (oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM) { + udp_header_t *udp = + (udp_header_t *) (vlib_buffer_get_current (b) + gho.l4_hdr_offset); + udp->checksum = ip6_pseudo_header_cksum (ip6); hdr->csum_offset = STRUCT_OFFSET_OF (udp_header_t, checksum); } } -- cgit 1.2.3-korg