From bbd6b746e09cc4ae4239173081d95349e0263759 Mon Sep 17 00:00:00 2001 From: Mohsin Kazmi Date: Thu, 2 May 2019 13:54:59 +0200 Subject: [PATCH] virtio: Add gso support for native virtio driver Change-Id: I7b735f5a540e8c278bac88245acb3f8c041c49c0 Signed-off-by: Mohsin Kazmi --- src/vat/api_format.c | 30 +++--------------- src/vnet/devices/virtio/cli.c | 2 ++ src/vnet/devices/virtio/pci.c | 61 +++++++++++++++++++++++++++++++++--- src/vnet/devices/virtio/pci.h | 13 ++++++++ src/vnet/devices/virtio/virtio.api | 4 +-- src/vnet/devices/virtio/virtio_api.c | 4 +++ src/vpp/api/custom_dump.c | 2 ++ 7 files changed, 83 insertions(+), 33 deletions(-) diff --git a/src/vat/api_format.c b/src/vat/api_format.c index b330a389ef8..c57f045fdd4 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -7681,9 +7681,9 @@ api_virtio_pci_create (vat_main_t * vam) vl_api_virtio_pci_create_t *mp; u8 mac_address[6]; u8 random_mac = 1; + u8 gso_enabled = 0; u32 pci_addr = 0; u64 features = (u64) ~ (0ULL); - u32 rx_ring_sz = 0, tx_ring_sz = 0; int ret; clib_memset (mac_address, 0, sizeof (mac_address)); @@ -7699,10 +7699,8 @@ api_virtio_pci_create (vat_main_t * vam) ; else if (unformat (i, "features 0x%llx", &features)) ; - else if (unformat (i, "rx-ring-size %u", &rx_ring_sz)) - ; - else if (unformat (i, "tx-ring-size %u", &tx_ring_sz)) - ; + else if (unformat (i, "gso-enabled")) + gso_enabled = 1; else break; } @@ -7712,26 +7710,6 @@ api_virtio_pci_create (vat_main_t * vam) errmsg ("pci address must be non zero. "); return -99; } - if (!is_pow2 (rx_ring_sz)) - { - errmsg ("rx ring size must be power of 2. "); - return -99; - } - if (rx_ring_sz > 32768) - { - errmsg ("rx ring size must be 32768 or lower. "); - return -99; - } - if (!is_pow2 (tx_ring_sz)) - { - errmsg ("tx ring size must be power of 2. "); - return -99; - } - if (tx_ring_sz > 32768) - { - errmsg ("tx ring size must be 32768 or lower. "); - return -99; - } /* Construct the API message */ M (VIRTIO_PCI_CREATE, mp); @@ -22293,7 +22271,7 @@ _(tap_delete_v2, \ " | sw_if_index ") \ _(sw_interface_tap_v2_dump, "") \ _(virtio_pci_create, \ - "pci-addr [use_random_mac | hw-addr ] [tx-ring-size [rx-ring-size ] [features ]") \ + "pci-addr [use_random_mac | hw-addr ] [features ] [gso-enabled]") \ _(virtio_pci_delete, \ " | sw_if_index ") \ _(sw_interface_virtio_pci_dump, "") \ diff --git a/src/vnet/devices/virtio/cli.c b/src/vnet/devices/virtio/cli.c index 956284c9716..10b545edb5e 100644 --- a/src/vnet/devices/virtio/cli.c +++ b/src/vnet/devices/virtio/cli.c @@ -42,6 +42,8 @@ virtio_pci_create_command_fn (vlib_main_t * vm, unformat_input_t * input, ; else if (unformat (line_input, "feature-mask 0x%llx", &feature_mask)) args.features = feature_mask; + else if (unformat (line_input, "gso-enabled")) + args.gso_enabled = 1; else return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); diff --git a/src/vnet/devices/virtio/pci.c b/src/vnet/devices/virtio/pci.c index 3736225b25c..f53552a8436 100644 --- a/src/vnet/devices/virtio/pci.c +++ b/src/vnet/devices/virtio/pci.c @@ -556,6 +556,27 @@ virtio_pci_send_ctrl_msg (vlib_main_t * vm, virtio_if_t * vif, return status; } +static int +virtio_pci_enable_gso (vlib_main_t * vm, virtio_if_t * vif) +{ + virtio_main_t *vim = &virtio_main; + struct virtio_ctrl_msg gso_hdr; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + + gso_hdr.ctrl.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS; + gso_hdr.ctrl.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET; + gso_hdr.status = VIRTIO_NET_ERR; + u64 offloads = VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM) + | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO4) + | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6) + | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_UFO); + clib_memcpy (gso_hdr.data, &offloads, sizeof (offloads)); + + status = virtio_pci_send_ctrl_msg (vm, vif, &gso_hdr, sizeof (offloads)); + virtio_log_debug (vim, vif, "enable gso"); + return status; +} + static int virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif, u16 num_queues) @@ -720,8 +741,18 @@ virtio_negotiate_features (vlib_main_t * vm, virtio_if_t * vif, * if features are not requested * default: all supported features */ - u64 supported_features = VIRTIO_FEATURE (VIRTIO_NET_F_MTU) + u64 supported_features = VIRTIO_FEATURE (VIRTIO_NET_F_CSUM) + | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_CSUM) + | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) + | VIRTIO_FEATURE (VIRTIO_NET_F_MTU) | VIRTIO_FEATURE (VIRTIO_NET_F_MAC) + | VIRTIO_FEATURE (VIRTIO_NET_F_GSO) + | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO4) + | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_TSO6) + | VIRTIO_FEATURE (VIRTIO_NET_F_GUEST_UFO) + | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO4) + | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_TSO6) + | VIRTIO_FEATURE (VIRTIO_NET_F_HOST_UFO) | VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF) | VIRTIO_FEATURE (VIRTIO_NET_F_STATUS) | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ) @@ -1175,14 +1206,31 @@ virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args) else vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0); - if ((vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) && - (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ))) + if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) { - if (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs)) - virtio_log_warning (vim, vif, "multiqueue is not set"); + if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_GUEST_OFFLOADS) && + args->gso_enabled) + { + if (virtio_pci_enable_gso (vm, vif)) + { + virtio_log_warning (vim, vif, "gso is not enabled"); + } + else + { + vif->gso_enabled = 1; + hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO; + vnm->interface_main.gso_interface_count++; + } + } + if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ)) + { + if (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs)) + virtio_log_warning (vim, vif, "multiqueue is not set"); + } } return; + error: virtio_pci_delete_if (vm, vif); args->rv = VNET_API_ERROR_INVALID_INTERFACE; @@ -1212,6 +1260,9 @@ virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif) virtio_pci_legacy_reset (vm, vif); + if (vif->gso_enabled) + vnm->interface_main.gso_interface_count--; + if (vif->hw_if_index) { vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0); diff --git a/src/vnet/devices/virtio/pci.h b/src/vnet/devices/virtio/pci.h index dcf9b146463..b1e29162108 100644 --- a/src/vnet/devices/virtio/pci.h +++ b/src/vnet/devices/virtio/pci.h @@ -101,10 +101,22 @@ typedef enum * at the end of the used ring. Guest should ignore the used->flags field. */ \ _ (VHOST_USER_F_PROTOCOL_FEATURES, 30) +#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 #define VIRTIO_NET_F_MTU 3 #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ #define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ +/* + * Control network offloads + * Reconfigures the network offloads that Guest can handle. + * Available with the VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit. + * Command data format matches the feature bit mask exactly. + * See VIRTIO_NET_F_GUEST_* for the list of offloads + * that can be enabled/disabled. + */ +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 + /* Common configuration */ #define VIRTIO_PCI_CAP_COMMON_CFG 1 /* Notifications */ @@ -233,6 +245,7 @@ typedef struct u8 mac_addr_set; u8 mac_addr[6]; u64 features; + u8 gso_enabled; clib_error_t *error; } virtio_pci_create_if_args_t; diff --git a/src/vnet/devices/virtio/virtio.api b/src/vnet/devices/virtio/virtio.api index 3a40fa9a952..9e81b35c175 100644 --- a/src/vnet/devices/virtio/virtio.api +++ b/src/vnet/devices/virtio/virtio.api @@ -22,8 +22,7 @@ option version = "1.0.0"; 0-15 domain, 16-23 bus, 24-28 slot, 29-31 function @param use_random_mac - let the system generate a unique mac address @param mac_address - mac addr to assign to the interface if use_radom not set - @param tx_ring_sz - the number of entries of TX ring - @param rx_ring_sz - the number of entries of RX ring + @param gso_enabled - enable gso feature if available, 1 to enable @param features - the virtio features which driver should negotiate with device */ define virtio_pci_create @@ -33,6 +32,7 @@ define virtio_pci_create u32 pci_addr; u8 use_random_mac; u8 mac_address[6]; + u8 gso_enabled; u64 features; }; diff --git a/src/vnet/devices/virtio/virtio_api.c b/src/vnet/devices/virtio/virtio_api.c index 82ff791a866..d73e6f877d5 100644 --- a/src/vnet/devices/virtio/virtio_api.c +++ b/src/vnet/devices/virtio/virtio_api.c @@ -66,6 +66,10 @@ vl_api_virtio_pci_create_t_handler (vl_api_virtio_pci_create_t * mp) ap->mac_addr_set = 1; } ap->sw_if_index = (u32) ~ 0; + if (mp->gso_enabled) + ap->gso_enabled = 1; + else + ap->gso_enabled = 0; ap->features = clib_net_to_host_u64 (mp->features); virtio_pci_create_if (vm, ap); diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c index 0122496a6f6..e9175d6ddcd 100644 --- a/src/vpp/api/custom_dump.c +++ b/src/vpp/api/custom_dump.c @@ -613,6 +613,8 @@ static void *vl_api_virtio_pci_create_t_print format_ethernet_address, mp->mac_address); if (mp->features) s = format (s, "features 0x%llx ", clib_net_to_host_u64 (mp->features)); + if (mp->gso_enabled) + s = format (s, "gso-enabled"); FINISH; } -- 2.16.6