X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdevices%2Fvirtio%2Fvhost_user_output.c;h=5bd60d4e96ef9560bd8a86f7c75051a29fbf6efc;hb=97c998c2813d7cea4a067a0b8ff246cad4924bf3;hp=c0c54d1b13a5010b90c4b36aa093013edc2cd4a2;hpb=47727c02df4c79c21c6ceffaff65222c32cf6996;p=vpp.git diff --git a/src/vnet/devices/virtio/vhost_user_output.c b/src/vnet/devices/virtio/vhost_user_output.c index c0c54d1b13a..5bd60d4e96e 100644 --- a/src/vnet/devices/virtio/vhost_user_output.c +++ b/src/vnet/devices/virtio/vhost_user_output.c @@ -17,6 +17,7 @@ *------------------------------------------------------------------ */ +#include #include /* for open */ #include #include @@ -39,6 +40,7 @@ #include #include +#include #include #include @@ -49,9 +51,12 @@ * entries. In order to not corrupt memory, we have to do the copy when the * static array reaches the copy threshold. We subtract 40 in case the code * goes into the inner loop for a maximum of 64k frames which may require - * more array entries. + * more array entries. We subtract 200 because our default buffer size is + * 2048 and the default desc len is likely 1536. While it takes less than 40 + * vlib buffers for the jumbo frame, it may take twice as much descriptors + * for the same jumbo frame. Use 200 for the extra head room. */ -#define VHOST_USER_TX_COPY_THRESHOLD (VHOST_USER_COPY_ARRAY_N - 40) +#define VHOST_USER_TX_COPY_THRESHOLD (VHOST_USER_COPY_ARRAY_N - 200) extern vnet_device_class_t vhost_user_device_class; @@ -226,6 +231,51 @@ vhost_user_tx_copy (vhost_user_intf_t * vui, vhost_copy_t * cpy, return 0; } +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; + } + } +} + VNET_DEVICE_CLASS_TX_FN (vhost_user_device_class) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) @@ -335,10 +385,15 @@ retry: virtio_net_hdr_mrg_rxbuf_t *hdr = &cpu->tx_headers[tx_headers_len]; tx_headers_len++; hdr->hdr.flags = 0; - hdr->hdr.gso_type = 0; + hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE; hdr->num_buffers = 1; //This is local, no need to check + /* Guest supports csum offload? */ + if (vui->features & (1ULL << FEAT_VIRTIO_NET_F_GUEST_CSUM)) + vhost_user_handle_tx_offload (vui, b0, &hdr->hdr); + // Prepare a copy order executed later for the header + ASSERT (copy_len < VHOST_USER_COPY_ARRAY_N); vhost_copy_t *cpy = &cpu->copy[copy_len]; copy_len++; cpy->len = vui->virtio_net_hdr_sz; @@ -426,6 +481,7 @@ retry: } { + ASSERT (copy_len < VHOST_USER_COPY_ARRAY_N); vhost_copy_t *cpy = &cpu->copy[copy_len]; copy_len++; cpy->len = bytes_left; @@ -515,7 +571,7 @@ done: * retry. * The idea is that it is better to waste some time on packets * that have been processed already than dropping them and get - * more fresh packets with a good likelyhood that they will be dropped too. + * more fresh packets with a good likelihood that they will be dropped too. * This technique also gives more time to VM driver to pick-up packets. * In case the traffic flows from physical to virtual interfaces, this * technique will end-up leveraging the physical NIC buffer in order to