diff options
Diffstat (limited to 'src/vnet/devices/virtio/device.c')
-rw-r--r-- | src/vnet/devices/virtio/device.c | 42 |
1 files changed, 33 insertions, 9 deletions
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 <vnet/gso/hdr_offset_parser.h> #include <vnet/ip/ip4_packet.h> #include <vnet/ip/ip6_packet.h> +#include <vnet/ip/ip_psh_cksum.h> #include <vnet/tcp/tcp_packet.h> #include <vnet/udp/udp_packet.h> #include <vnet/devices/virtio/virtio.h> @@ -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); } } |