vppapigen: crc is a negative value for some messages when using python 2.7
[vpp.git] / src / vnet / devices / tap / tap.c
index 061c6ac..6f16a4c 100644 (file)
@@ -170,10 +170,6 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
   vif->num_rxqs = args->num_rx_queues;
   num_q_pairs = clib_max (vif->num_rxqs, vif->num_txqs);
 
-  if (ethernet_mac_address_is_zero (args->host_mac_addr.bytes))
-    ethernet_mac_address_generate (args->host_mac_addr.bytes);
-  clib_memcpy (vif->host_mac_addr, args->host_mac_addr.bytes, 6);
-
   if ((vif->tap_fd = tfd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0)
     {
       args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
@@ -210,6 +206,11 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
       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,
@@ -240,13 +241,6 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
   tap_log_dbg (vif, "TUNSETOFFLOAD: fd %d offload 0x%lx", tfd, offload);
   _IOCTL (tfd, TUNSETOFFLOAD, offload);
 
-  clib_memset (&ifr, 0, sizeof (ifr));
-  ifr.ifr_addr.sa_family = ARPHRD_ETHER;
-  clib_memcpy (ifr.ifr_hwaddr.sa_data, vif->host_mac_addr, 6);
-  tap_log_dbg (vif, "SIOCSIFHWADDR: fd %d hwaddr %U", tfd,
-              format_hex_bytes, ifr.ifr_hwaddr.sa_data, 6);
-  _IOCTL (tfd, SIOCSIFHWADDR, (void *) &ifr);
-
   /* open vhost-net fd for each queue pair and set ownership */
   for (i = 0; i < num_q_pairs; i++)
     {
@@ -345,15 +339,14 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
        }
     }
 
-  if (!ethernet_mac_address_is_zero (args->host_mac_addr.bytes))
+  if (ethernet_mac_address_is_zero (args->host_mac_addr.bytes))
+    ethernet_mac_address_generate (args->host_mac_addr.bytes);
+  args->error = vnet_netlink_set_link_addr (vif->ifindex,
+                                           args->host_mac_addr.bytes);
+  if (args->error)
     {
-      args->error = vnet_netlink_set_link_addr (vif->ifindex,
-                                               args->host_mac_addr.bytes);
-      if (args->error)
-       {
-         args->rv = VNET_API_ERROR_NETLINK_ERROR;
-         goto error;
-       }
+      args->rv = VNET_API_ERROR_NETLINK_ERROR;
+      goto error;
     }
 
   if (args->host_bridge)
@@ -418,18 +411,6 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
        }
     }
 
-  /* switch back to old net namespace */
-  if (args->host_namespace)
-    {
-      if (setns (old_netns_fd, CLONE_NEWNET) == -1)
-       {
-         args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
-         args->error = clib_error_return_unix (0, "setns '%s'",
-                                               args->host_namespace);
-         goto error;
-       }
-    }
-
   if (args->host_mtu_set)
     {
       args->error =
@@ -453,6 +434,18 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
       args->host_mtu_size = tm->host_mtu_size;
     }
 
+  /* switch back to old net namespace */
+  if (args->host_namespace)
+    {
+      if (setns (old_netns_fd, CLONE_NEWNET) == -1)
+       {
+         args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
+         args->error = clib_error_return_unix (0, "setns '%s'",
+                                               args->host_namespace);
+         goto error;
+       }
+    }
+
   for (i = 0; i < num_q_pairs; i++)
     {
       if (i < vif->num_rxqs && (args->error =
@@ -594,7 +587,12 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
   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);
@@ -623,6 +621,7 @@ error:
       args->rv = VNET_API_ERROR_SYSCALL_ERROR_3;
     }
 
+  tap_log_err (vif, "%U", format_clib_error, args->error);
   tap_free (vm, vif);
 done:
   if (vhost_mem)
@@ -665,6 +664,62 @@ tap_delete_if (vlib_main_t * vm, u32 sw_if_index)
   return 0;
 }
 
+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)
 {
@@ -686,18 +741,21 @@ tap_gso_enable_disable (vlib_main_t * vm, u32 sw_if_index, int enable_disable)
   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);
        }
     }