tap: set device name on creation via TUNSETIFF 96/33696/3
authorDuncan Eastoe <duncan@graphiant.com>
Wed, 8 Sep 2021 18:11:33 +0000 (19:11 +0100)
committerBeno�t Ganne <bganne@cisco.com>
Wed, 15 Sep 2021 12:58:35 +0000 (12:58 +0000)
Type: fix

Currently when a new TAP/TUN device is created from tap_create_if()
via the TUNSETIFF ioctl(), a name is allocated by the kernel (eg.
tap0). If the caller supplied a name this is subsequently set via
netlink, after the device has been created.

Now we request the kernel to create the new device with the caller's
requested name in the first instance, thus avoiding the need to
rename the device, and therefore avoiding a window where the device
exists with a different name.

This can be beneficial, for example, when writing systemd-udevd link
files [1]. Having the TAP/TUN devices created with the requested name
ensures they can be correctly matched by the OriginalName option.

Writing link files might be necessary, for example, to avoid VPP and
systemd-udevd racing to set the MAC address on a newly created TAP
interface. systemd-udevd can be configured to not manipulate the MAC
addresses of matched interfaces.

These changes also resolve an issue where the created device would not
be renamed if the caller requested it be moved to a different network
namespace, since vnet_netlink_set_link_name() was not called in that
case.

[1] https://www.freedesktop.org/software/systemd/man/systemd.link.html

Signed-off-by: Duncan Eastoe <duncan@graphiant.com>
Change-Id: I3d657632856d03979d6b914225c3c841c379e0a1

src/vnet/devices/tap/tap.c

index 33d6e3b..8fca35d 100644 (file)
@@ -195,13 +195,7 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
 
   if (args->tap_flags & TAP_FLAG_ATTACH)
     {
-      if (args->host_if_name != NULL)
-       {
-         host_if_name = (char *) args->host_if_name;
-         clib_memcpy (ifr.ifr_name, host_if_name,
-                      clib_min (IFNAMSIZ, vec_len (host_if_name)));
-       }
-      else
+      if (args->host_if_name == NULL)
        {
          args->rv = VNET_API_ERROR_NO_MATCHING_INTERFACE;
          err = clib_error_return (0, "host_if_name is not provided");
@@ -227,6 +221,13 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
        }
     }
 
+  if (args->host_if_name != NULL)
+    {
+      host_if_name = (char *) args->host_if_name;
+      clib_memcpy (ifr.ifr_name, host_if_name,
+                  clib_min (IFNAMSIZ, vec_len (host_if_name)));
+    }
+
   if ((tfd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0)
     {
       args->rv = VNET_API_ERROR_SYSCALL_ERROR_2;
@@ -435,16 +436,6 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args)
              goto error;
            }
        }
-      else if (host_if_name)
-       {
-         args->error =
-           vnet_netlink_set_link_name (vif->ifindex, host_if_name);
-         if (args->error)
-           {
-             args->rv = VNET_API_ERROR_NETLINK_ERROR;
-             goto error;
-           }
-       }
     }
 
   if (vif->type == VIRTIO_IF_TYPE_TAP)