tap: split gso and checksum offload functionality
Type: refactor
Change-Id: I0d4b79ef384c11c841576d264bfd8ccb21783e10
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
diff --git a/src/vnet/devices/tap/cli.c b/src/vnet/devices/tap/cli.c
index a85fcbf..8d5e3b4 100644
--- a/src/vnet/devices/tap/cli.c
+++ b/src/vnet/devices/tap/cli.c
@@ -89,6 +89,8 @@
args.tap_flags &= ~TAP_FLAG_GSO;
else if (unformat (line_input, "gso"))
args.tap_flags |= TAP_FLAG_GSO;
+ else if (unformat (line_input, "csum-offload"))
+ args.tap_flags |= TAP_FLAG_CSUM_OFFLOAD;
else if (unformat (line_input, "hw-addr %U",
unformat_ethernet_address, args.mac_addr.bytes))
args.mac_addr_set = 1;
@@ -128,7 +130,7 @@
"[host-bridge <bridge-name>] [host-ip4-addr <ip4addr/mask>] "
"[host-ip6-addr <ip6-addr>] [host-ip4-gw <ip4-addr>] "
"[host-ip6-gw <ip6-addr>] [host-mac-addr <host-mac-address>] "
- "[host-if-name <name>] [host-mtu-size <size>] [no-gso|gso]",
+ "[host-if-name <name>] [host-mtu-size <size>] [no-gso|gso|csum-offload]",
.function = tap_create_command_fn,
};
/* *INDENT-ON* */
@@ -182,14 +184,15 @@
/* *INDENT-ON* */
static clib_error_t *
-tap_gso_command_fn (vlib_main_t * vm, unformat_input_t * input,
- vlib_cli_command_t * cmd)
+tap_offload_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
{
unformat_input_t _line_input, *line_input = &_line_input;
u32 sw_if_index = ~0;
vnet_main_t *vnm = vnet_get_main ();
- int enable = 1;
- int rv;
+ int gso_enable = 0, gso_disable = 0;
+ int csum_offload_enable = 0, csum_offload_disable = 0;
+ int rv = 0;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
@@ -202,10 +205,14 @@
else if (unformat (line_input, "%U", unformat_vnet_sw_interface,
vnm, &sw_if_index))
;
- else if (unformat (line_input, "enable"))
- enable = 1;
- else if (unformat (line_input, "disable"))
- enable = 0;
+ else if (unformat (line_input, "gso-enable"))
+ gso_enable = 1;
+ else if (unformat (line_input, "gso-disable"))
+ gso_disable = 1;
+ else if (unformat (line_input, "csum-offload-enable"))
+ csum_offload_enable = 1;
+ else if (unformat (line_input, "csum-offload-disable"))
+ csum_offload_disable = 1;
else
return clib_error_return (0, "unknown input `%U'",
format_unformat_error, input);
@@ -216,7 +223,15 @@
return clib_error_return (0,
"please specify interface name or sw_if_index");
- rv = tap_gso_enable_disable (vm, sw_if_index, enable);
+ if (gso_enable)
+ rv = tap_gso_enable_disable (vm, sw_if_index, 1);
+ else if (csum_offload_enable)
+ rv = tap_csum_offload_enable_disable (vm, sw_if_index, 1);
+ else if (gso_disable)
+ rv = tap_gso_enable_disable (vm, sw_if_index, 0);
+ else if (csum_offload_disable)
+ rv = tap_csum_offload_enable_disable (vm, sw_if_index, 0);
+
if (rv == VNET_API_ERROR_INVALID_SW_IF_INDEX)
return clib_error_return (0, "not a tap interface");
else if (rv != 0)
@@ -226,11 +241,12 @@
}
/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (tap_gso__command, static) =
+VLIB_CLI_COMMAND (tap_offload_command, static) =
{
- .path = "set tap gso",
- .short_help = "set tap gso {<interface> | sw_if_index <sw_idx>} <enable|disable>",
- .function = tap_gso_command_fn,
+ .path = "set tap offload",
+ .short_help = "set tap offload {<interface> | sw_if_index <sw_idx>}"
+ " <gso-enable | gso-disable | csum-offload-enable | csum-offload-disable>",
+ .function = tap_offload_command_fn,
};
/* *INDENT-ON* */
diff --git a/src/vnet/devices/tap/tap.c b/src/vnet/devices/tap/tap.c
index 061c6ac..a1cb69d 100644
--- a/src/vnet/devices/tap/tap.c
+++ b/src/vnet/devices/tap/tap.c
@@ -210,6 +210,11 @@
offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6;
vif->gso_enabled = 1;
}
+ else if (args->tap_flags & TAP_FLAG_CSUM_OFFLOAD)
+ {
+ offload = TUN_F_CSUM;
+ vif->csum_offload_enabled = 1;
+ }
_IOCTL (tfd, TUNSETIFF, (void *) &ifr);
tap_log_dbg (vif, "TUNSETIFF fd %d name %s flags 0x%x", tfd,
@@ -594,7 +599,12 @@
hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
if (args->tap_flags & TAP_FLAG_GSO)
{
- hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+ hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO |
+ VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
+ }
+ else if (args->tap_flags & TAP_FLAG_CSUM_OFFLOAD)
+ {
+ hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
}
vnet_hw_interface_set_input_node (vnm, vif->hw_if_index,
virtio_input_node.index);
@@ -666,6 +676,62 @@
}
int
+tap_csum_offload_enable_disable (vlib_main_t * vm, u32 sw_if_index,
+ int enable_disable)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ virtio_main_t *mm = &virtio_main;
+ virtio_if_t *vif;
+ vnet_hw_interface_t *hw;
+ clib_error_t *err = 0;
+
+ hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
+
+ if (hw == NULL || virtio_device_class.index != hw->dev_class_index)
+ return VNET_API_ERROR_INVALID_SW_IF_INDEX;
+
+ vif = pool_elt_at_index (mm->interfaces, hw->dev_instance);
+
+ const unsigned int csum_offload_on = TUN_F_CSUM;
+ const unsigned int csum_offload_off = 0;
+ unsigned int offload = enable_disable ? csum_offload_on : csum_offload_off;
+ _IOCTL (vif->tap_fd, TUNSETOFFLOAD, offload);
+ vif->gso_enabled = 0;
+ vif->csum_offload_enabled = enable_disable ? 1 : 0;
+
+ if ((hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) != 0)
+ {
+ hw->flags &= ~VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+ }
+
+ if (enable_disable)
+ {
+ if ((hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD) ==
+ 0)
+ {
+ hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
+ }
+ }
+ else
+ {
+ if ((hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD) !=
+ 0)
+ {
+ hw->flags &= ~VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
+ }
+ }
+
+error:
+ if (err)
+ {
+ clib_warning ("Error %s checksum offload on sw_if_index %d",
+ enable_disable ? "enabling" : "disabling", sw_if_index);
+ return VNET_API_ERROR_SYSCALL_ERROR_3;
+ }
+ return 0;
+}
+
+int
tap_gso_enable_disable (vlib_main_t * vm, u32 sw_if_index, int enable_disable)
{
vnet_main_t *vnm = vnet_get_main ();
@@ -686,18 +752,21 @@
unsigned int offload = enable_disable ? gso_on : gso_off;
_IOCTL (vif->tap_fd, TUNSETOFFLOAD, offload);
vif->gso_enabled = enable_disable ? 1 : 0;
+ vif->csum_offload_enabled = 0;
if (enable_disable)
{
if ((hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) == 0)
{
- hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+ hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO |
+ VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD;
}
}
else
{
if ((hw->flags & VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO) != 0)
{
- hw->flags &= ~VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
+ hw->flags &= ~(VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO |
+ VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD);
}
}
diff --git a/src/vnet/devices/tap/tap.h b/src/vnet/devices/tap/tap.h
index 6eba7af..fd4006b 100644
--- a/src/vnet/devices/tap/tap.h
+++ b/src/vnet/devices/tap/tap.h
@@ -32,6 +32,7 @@
u16 tx_ring_sz;
u32 tap_flags;
#define TAP_FLAG_GSO (1 << 0)
+#define TAP_FLAG_CSUM_OFFLOAD (1 << 1)
u8 *host_namespace;
u8 *host_if_name;
mac_address_t host_mac_addr;
@@ -88,6 +89,9 @@
int tap_delete_if (vlib_main_t * vm, u32 sw_if_index);
int tap_gso_enable_disable (vlib_main_t * vm, u32 sw_if_index,
int enable_disable);
+int
+tap_csum_offload_enable_disable (vlib_main_t * vm, u32 sw_if_index,
+ int enable_disable);
int tap_dump_ifs (tap_interface_details_t ** out_tapids);
#endif /* _VNET_DEVICES_VIRTIO_TAP_H_ */
diff --git a/src/vnet/devices/tap/tapv2.api b/src/vnet/devices/tap/tapv2.api
index ec8bd45..861fe17 100644
--- a/src/vnet/devices/tap/tapv2.api
+++ b/src/vnet/devices/tap/tapv2.api
@@ -27,6 +27,7 @@
enum tap_flags {
TAP_FLAG_GSO = 1,
+ TAP_FLAG_CSUM_OFFLOAD = 2,
};
/** \brief Initialize a new tap interface with the given parameters
diff --git a/src/vnet/devices/virtio/virtio.c b/src/vnet/devices/virtio/virtio.c
index 6504b2a..c0c163f 100644
--- a/src/vnet/devices/virtio/virtio.c
+++ b/src/vnet/devices/virtio/virtio.c
@@ -288,8 +288,6 @@
{
vlib_cli_output (vm, " PCI Address: %U", format_vlib_pci_addr,
&vif->pci_addr);
- vlib_cli_output (vm, " csum-enabled %d",
- vif->csum_offload_enabled);
}
if (type == VIRTIO_IF_TYPE_TAP)
{
@@ -309,6 +307,7 @@
vlib_cli_output (vm, " tap-fd %d", vif->tap_fd);
}
vlib_cli_output (vm, " gso-enabled %d", vif->gso_enabled);
+ vlib_cli_output (vm, " csum-enabled %d", vif->csum_offload_enabled);
vlib_cli_output (vm, " Mac Address: %U", format_ethernet_address,
vif->mac_addr);
vlib_cli_output (vm, " Device instance: %u", vif->dev_instance);