netdev-linux: Give tap FD to first opener.
authorJesse Gross <jesse@nicira.com>
Tue, 1 Jun 2010 22:27:26 +0000 (15:27 -0700)
committerJesse Gross <jesse@nicira.com>
Wed, 2 Jun 2010 00:27:45 +0000 (17:27 -0700)
Tap devices can have two FDs that allow transmit and receive from
different perspectives.  We previously would always share one of
the FDs among all openers.  However, this is confusing to some
users (primarily the DHCP client) which expect tap devices to behave
like any other device.  Now we give the tap FD to the first opener,
which knows that it has opened a tap device, and a normal system FD
to everyone else for consistency.

lib/netdev-linux.c

index c8d463aeedc1a7a49318537e88f17a04156a046b..2fa05b66e3e2162f346a0369d1e2c641a3a15c76 100644 (file)
@@ -88,6 +88,7 @@ enum {
 
 struct tap_state {
     int fd;
+    bool opened;
 };
 
 struct netdev_dev_linux {
@@ -371,8 +372,15 @@ netdev_linux_open(struct netdev_dev *netdev_dev_, int ethertype,
         goto error;
     }
 
-    if (!strcmp(netdev_dev_get_type(netdev_dev_), "tap")) {
+    if (!strcmp(netdev_dev_get_type(netdev_dev_), "tap") &&
+        !netdev_dev->state.tap.opened) {
+
+        /* We assume that the first user of the tap device is the primary user
+         * and give them the tap FD.  Subsequent users probably just expect
+         * this to be a system device so open it normally to avoid send/receive
+         * directions appearing to be reversed. */
         netdev->fd = netdev_dev->state.tap.fd;
+        netdev_dev->state.tap.opened = true;
     } else if (ethertype != NETDEV_ETH_TYPE_NONE) {
         struct sockaddr_ll sll;
         int protocol;