netdev: New function netdev_nodev_get_flags().
authorBen Pfaff <blp@nicira.com>
Wed, 14 Jan 2009 23:35:12 +0000 (15:35 -0800)
committerBen Pfaff <blp@nicira.com>
Fri, 23 Jan 2009 18:47:02 +0000 (10:47 -0800)
An upcoming change will move detection of netdev flags changes into
secchan.  That change will require polling the flags for many network
devices.  Opening and closing that many network devices, or keeping
around fds for them, is a waste of time (or fds).

But it's easy to get flags for any number of netdevs from a single file
descriptor, so add a function to do this.

lib/netdev.c
lib/netdev.h

index a22878645226c9c6181387b533037d78674dfbed..efa86e80c120c58f145c3ee0438c89546fbe9f9a 100644 (file)
@@ -114,8 +114,8 @@ static void init_netdev(void);
 static int do_open_netdev(const char *name, int ethertype, int tap_fd,
                           struct netdev **netdev_);
 static int restore_flags(struct netdev *netdev);
-static int get_flags(const struct netdev *, int fd, int *flagsp);
-static int set_flags(struct netdev *, int flags);
+static int get_flags(const char *netdev_name, int *flagsp);
+static int set_flags(const char *netdev_name, int flags);
 
 /* Obtains the IPv6 address for 'name' into 'in6'. */
 static void
@@ -456,7 +456,7 @@ do_open_netdev(const char *name, int ethertype, int tap_fd,
     do_ethtool(netdev);
 
     /* Save flags to restore at close or exit. */
-    error = get_flags(netdev, netdev_fd, &netdev->save_flags);
+    error = get_flags(netdev->name, &netdev->save_flags);
     if (error) {
         goto error_already_set;
     }
@@ -831,21 +831,7 @@ netdev_get_in6(const struct netdev *netdev, struct in6_addr *in6)
 int
 netdev_get_flags(const struct netdev *netdev, enum netdev_flags *flagsp)
 {
-    int error, flags;
-
-    error = get_flags(netdev, netdev->netdev_fd, &flags);
-    if (error) {
-        return error;
-    }
-
-    *flagsp = 0;
-    if (flags & IFF_UP) {
-        *flagsp |= NETDEV_UP;
-    }
-    if (flags & IFF_PROMISC) {
-        *flagsp |= NETDEV_PROMISC;
-    }
-    return 0;
+    return netdev_nodev_get_flags(netdev->name, flagsp);
 }
 
 static int
@@ -866,13 +852,13 @@ nd_to_iff_flags(enum netdev_flags nd)
  * will be reverted when 'netdev' is closed or the program exits.  Returns 0 if
  * successful, otherwise a positive errno value. */
 static int
-do_update_flags(struct netdev *netdev, int fd, enum netdev_flags off,
+do_update_flags(struct netdev *netdev, enum netdev_flags off,
                 enum netdev_flags on, bool permanent)
 {
     int old_flags, new_flags;
     int error;
 
-    error = get_flags(netdev, fd, &old_flags);
+    error = get_flags(netdev->name, &old_flags);
     if (error) {
         return error;
     }
@@ -882,7 +868,7 @@ do_update_flags(struct netdev *netdev, int fd, enum netdev_flags off,
         netdev->changed_flags |= new_flags ^ old_flags; 
     }
     if (new_flags != old_flags) {
-        error = set_flags(netdev, new_flags);
+        error = set_flags(netdev->name, new_flags);
     }
     return error;
 }
@@ -895,7 +881,7 @@ int
 netdev_set_flags(struct netdev *netdev, enum netdev_flags flags,
                  bool permanent)
 {
-    return do_update_flags(netdev, netdev->netdev_fd, -1, flags, permanent);
+    return do_update_flags(netdev, -1, flags, permanent);
 }
 
 /* Turns on the specified 'flags' on 'netdev'.
@@ -906,7 +892,7 @@ int
 netdev_turn_flags_on(struct netdev *netdev, enum netdev_flags flags,
                      bool permanent)
 {
-    return do_update_flags(netdev, netdev->netdev_fd, 0, flags, permanent);
+    return do_update_flags(netdev, 0, flags, permanent);
 }
 
 /* Turns off the specified 'flags' on 'netdev'.
@@ -917,7 +903,7 @@ int
 netdev_turn_flags_off(struct netdev *netdev, enum netdev_flags flags,
                       bool permanent)
 {
-    return do_update_flags(netdev, netdev->netdev_fd, flags, 0, permanent);
+    return do_update_flags(netdev, flags, 0, permanent);
 }
 
 /* Looks up the ARP table entry for 'ip' on 'netdev'.  If one exists and can be
@@ -970,6 +956,34 @@ netdev_enumerate(struct svec *svec)
                   strerror(errno));
     }
 }
+
+/* Obtains the current flags for the network device named 'netdev_name' and
+ * stores them into '*flagsp'.  Returns 0 if successful, otherwise a positive
+ * errno value.
+ *
+ * If only device flags are needed, this is more efficient than calling
+ * netdev_open(), netdev_get_flags(), netdev_close(). */
+int
+netdev_nodev_get_flags(const char *netdev_name, enum netdev_flags *flagsp)
+{
+    int error, flags;
+
+    init_netdev();
+
+    error = get_flags(netdev_name, &flags);
+    if (error) {
+        return error;
+    }
+
+    *flagsp = 0;
+    if (flags & IFF_UP) {
+        *flagsp |= NETDEV_UP;
+    }
+    if (flags & IFF_PROMISC) {
+        *flagsp |= NETDEV_PROMISC;
+    }
+    return 0;
+}
 \f
 static void restore_all_flags(void *aux);
 
@@ -1031,13 +1045,13 @@ restore_all_flags(void *aux UNUSED)
 }
 
 static int
-get_flags(const struct netdev *netdev, int fd, int *flags)
+get_flags(const char *netdev_name, int *flags)
 {
     struct ifreq ifr;
-    strncpy(ifr.ifr_name, netdev->name, sizeof ifr.ifr_name);
-    if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+    strncpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
+    if (ioctl(af_inet_sock, SIOCGIFFLAGS, &ifr) < 0) {
         VLOG_ERR("ioctl(SIOCGIFFLAGS) on %s device failed: %s",
-                 netdev->name, strerror(errno));
+                 netdev_name, strerror(errno));
         return errno;
     }
     *flags = ifr.ifr_flags;
@@ -1045,14 +1059,14 @@ get_flags(const struct netdev *netdev, int fd, int *flags)
 }
 
 static int
-set_flags(struct netdev *netdev, int flags)
+set_flags(const char *netdev_name, int flags)
 {
     struct ifreq ifr;
-    strncpy(ifr.ifr_name, netdev->name, sizeof ifr.ifr_name);
+    strncpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
     ifr.ifr_flags = flags;
-    if (ioctl(netdev->netdev_fd, SIOCSIFFLAGS, &ifr) < 0) {
+    if (ioctl(af_inet_sock, SIOCSIFFLAGS, &ifr) < 0) {
         VLOG_ERR("ioctl(SIOCSIFFLAGS) on %s device failed: %s",
-                 netdev->name, strerror(errno));
+                 netdev_name, strerror(errno));
         return errno;
     }
     return 0;
index 843a143a3314402427c3a507f5f398abf3aad9d4..0e06e6393256e349ab6a89b711040afd6889a174 100644 (file)
@@ -94,5 +94,6 @@ int netdev_turn_flags_off(struct netdev *, enum netdev_flags, bool permanent);
 int netdev_arp_lookup(const struct netdev *, uint32_t ip, uint8_t mac[6]);
 
 void netdev_enumerate(struct svec *);
+int netdev_nodev_get_flags(const char *netdev_name, enum netdev_flags *);
 
 #endif /* netdev.h */