From: Ben Pfaff Date: Wed, 14 Jan 2009 23:35:12 +0000 (-0800) Subject: netdev: New function netdev_nodev_get_flags(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=56f762ee2546e7e705aa7ca3c51a009c75f6d389;p=openvswitch netdev: New function netdev_nodev_get_flags(). 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. --- diff --git a/lib/netdev.c b/lib/netdev.c index a2287864..efa86e80 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -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; +} 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; diff --git a/lib/netdev.h b/lib/netdev.h index 843a143a..0e06e639 100644 --- a/lib/netdev.h +++ b/lib/netdev.h @@ -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 */