+static_always_inline void
+vhost_user_handle_tx_offload (vhost_user_intf_t * vui, vlib_buffer_t * b,
+ virtio_net_hdr_t * hdr)
+{
+ /* checksum offload */
+ if (b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM)
+ {
+ hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
+ hdr->csum_start = vnet_buffer (b)->l4_hdr_offset;
+ hdr->csum_offset = offsetof (udp_header_t, checksum);
+ }
+ else if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
+ {
+ hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
+ hdr->csum_start = vnet_buffer (b)->l4_hdr_offset;
+ hdr->csum_offset = offsetof (tcp_header_t, checksum);
+ }
+
+ /* GSO offload */
+ if (b->flags & VNET_BUFFER_F_GSO)
+ {
+ if (b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)
+ {
+ if ((b->flags & VNET_BUFFER_F_IS_IP4) &&
+ (vui->features & (1ULL << FEAT_VIRTIO_NET_F_GUEST_TSO4)))
+ {
+ hdr->gso_size = vnet_buffer2 (b)->gso_size;
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ }
+ else if ((b->flags & VNET_BUFFER_F_IS_IP6) &&
+ (vui->features & (1ULL << FEAT_VIRTIO_NET_F_GUEST_TSO6)))
+ {
+ hdr->gso_size = vnet_buffer2 (b)->gso_size;
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+ }
+ }
+ else if ((vui->features & (1ULL << FEAT_VIRTIO_NET_F_GUEST_UFO)) &&
+ (b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM))
+ {
+ hdr->gso_size = vnet_buffer2 (b)->gso_size;
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
+ }
+ }
+}
+