tap: allow change of carrier state on host
[vpp.git] / src / vnet / devices / tap / tap.c
index c265aa2..94a91e5 100644 (file)
@@ -109,8 +109,11 @@ tap_free (vlib_main_t * vm, virtio_if_t * vif)
     virtio_vring_free_tx (vm, vif, TX_QUEUE (i));
   /* *INDENT-ON* */
 
-  _IOCTL (vif->tap_fds[0], TUNSETPERSIST, (void *) (uintptr_t) 0);
-  tap_log_dbg (vif, "TUNSETPERSIST: unset");
+  if (vif->tap_fds)
+    {
+      _IOCTL (vif->tap_fds[0], TUNSETPERSIST, (void *) (uintptr_t) 0);
+      tap_log_dbg (vif, "TUNSETPERSIST: unset");
+    }
 error:
   vec_foreach_index (i, vif->tap_fds) close (vif->tap_fds[i]);
 
@@ -207,7 +210,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
        {
          host_if_name = (char *) args->host_if_name;
          clib_memcpy (ifr.ifr_name, host_if_name,
-                      clib_min (IFNAMSIZ, strlen (host_if_name)));
+                      clib_min (IFNAMSIZ, vec_len (host_if_name)));
        }
       else
        {
@@ -731,7 +734,6 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
   if ((args->tap_flags & TAP_FLAG_GSO)
       && (args->tap_flags & TAP_FLAG_GRO_COALESCE))
     {
-      vif->packet_coalesce = 1;
       virtio_set_packet_coalesce (vif);
     }
   vnet_hw_interface_set_input_node (vnm, vif->hw_if_index,
@@ -741,7 +743,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
     {
       vnet_hw_interface_assign_rx_thread (vnm, vif->hw_if_index, i, ~0);
       vnet_hw_interface_set_rx_mode (vnm, vif->hw_if_index, i,
-                                    VNET_HW_INTERFACE_RX_MODE_DEFAULT);
+                                    VNET_HW_IF_RX_MODE_DEFAULT);
       virtio_vring_set_numa_node (vm, vif, RX_QUEUE (i));
     }
 
@@ -749,6 +751,12 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
   vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
   vnet_hw_interface_set_flags (vnm, vif->hw_if_index,
                               VNET_HW_INTERFACE_FLAG_LINK_UP);
+  /*
+   * Host tun/tap driver link carrier state is "up" at creation. The
+   * driver never changes this unless the backend (VPP) changes it using
+   * TUNSETCARRIER ioctl(). See tap_set_carrier().
+   */
+  vif->host_carrier_up = 1;
   vif->cxq_vring = NULL;
 
   goto done;
@@ -900,7 +908,6 @@ tap_gso_enable_disable (vlib_main_t * vm, u32 sw_if_index, int enable_disable,
        }
       if (is_packet_coalesce)
        {
-         vif->packet_coalesce = 1;
          virtio_set_packet_coalesce (vif);
        }
     }
@@ -946,8 +953,7 @@ tap_dump_ifs (tap_interface_details_t ** out_tapids)
     tapid->sw_if_index = vif->sw_if_index;
     hi = vnet_get_hw_interface (vnm, vif->hw_if_index);
     clib_memcpy(tapid->dev_name, hi->name,
-                MIN (ARRAY_LEN (tapid->dev_name) - 1,
-                     strlen ((const char *) hi->name)));
+                MIN (ARRAY_LEN (tapid->dev_name) - 1, vec_len (hi->name)));
     vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS(0));
     tapid->rx_ring_sz = vring->size;
     vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS(0));
@@ -958,19 +964,19 @@ tap_dump_ifs (tap_interface_details_t ** out_tapids)
       {
         clib_memcpy(tapid->host_if_name, vif->host_if_name,
                     MIN (ARRAY_LEN (tapid->host_if_name) - 1,
-                    strlen ((const char *) vif->host_if_name)));
+                    vec_len (vif->host_if_name)));
       }
     if (vif->net_ns)
       {
         clib_memcpy(tapid->host_namespace, vif->net_ns,
                     MIN (ARRAY_LEN (tapid->host_namespace) - 1,
-                    strlen ((const char *) vif->net_ns)));
+                    vec_len (vif->net_ns)));
       }
     if (vif->host_bridge)
       {
         clib_memcpy(tapid->host_bridge, vif->host_bridge,
                     MIN (ARRAY_LEN (tapid->host_bridge) - 1,
-                    strlen ((const char *) vif->host_bridge)));
+                    vec_len (vif->host_bridge)));
       }
     if (vif->host_ip4_prefix_len)
       clib_memcpy(tapid->host_ip4_addr.as_u8, &vif->host_ip4_addr, 4);
@@ -987,6 +993,41 @@ tap_dump_ifs (tap_interface_details_t ** out_tapids)
   return 0;
 }
 
+/*
+ * Set host tap/tun interface carrier state so it will appear to host
+ * applications that the interface's link state changed.
+ *
+ * If the kernel we're building against does not have support for the
+ * TUNSETCARRIER ioctl command, do nothing.
+ */
+int
+tap_set_carrier (u32 hw_if_index, u32 carrier_up)
+{
+  int ret = 0;
+#ifdef TUNSETCARRIER
+  vnet_main_t *vnm = vnet_get_main ();
+  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
+  virtio_main_t *mm = &virtio_main;
+  virtio_if_t *vif;
+  int *fd;
+
+  vif = pool_elt_at_index (mm->interfaces, hi->dev_instance);
+  vec_foreach (fd, vif->tap_fds)
+  {
+    ret = ioctl (*fd, TUNSETCARRIER, &carrier_up);
+    if (ret < 0)
+      {
+       clib_warning ("ioctl (TUNSETCARRIER) returned %d", ret);
+       break;
+      }
+  }
+  if (!ret)
+    vif->host_carrier_up = (carrier_up != 0);
+#endif
+
+  return ret;
+}
+
 static clib_error_t *
 tap_mtu_config (vlib_main_t * vm, unformat_input_t * input)
 {