Signed-off-by: Pravin B Shelar <pshe...@nicira.com> --- lib/netdev-linux.c | 85 ++++++++++++++++++++++++++++++---------------------- 1 files changed, 49 insertions(+), 36 deletions(-)
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 3067953..c7991ac 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -378,6 +378,7 @@ struct netdev_dev_linux { int vport_stats_error; /* Cached error code from vport_get_stats(). 0 or an errno value. */ int netdev_mtu_error; /* Cached error code from SIOCGIFMTU or SIOCSIFMTU. */ + int ether_addr_error; /* Cached error code from set/get etheraddr. */ struct ethtool_drvinfo drvinfo; /* Cached from ETHTOOL_GDRVINFO. */ struct tc *tc; @@ -417,8 +418,8 @@ static int get_ifindex(const struct netdev *, int *ifindexp); static int do_set_addr(struct netdev *netdev, int ioctl_nr, const char *ioctl_name, struct in_addr addr); -static int get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN]); -static int set_etheraddr(const char *netdev_name, int hwaddr_family, +static void get_etheraddr(struct netdev_dev_linux *); +static void set_etheraddr(struct netdev_dev_linux *, int hwaddr_family, const uint8_t[ETH_ADDR_LEN]); static int get_stats_via_netlink(int ifindex, struct netdev_stats *stats); static int get_stats_via_proc(const char *netdev_name, struct netdev_stats *stats); @@ -1022,19 +1023,20 @@ netdev_linux_set_etheraddr(struct netdev *netdev_, { struct netdev_dev_linux *netdev_dev = netdev_dev_linux_cast(netdev_get_dev(netdev_)); - int error; - if (!(netdev_dev->cache_valid & VALID_ETHERADDR) - || !eth_addr_equals(netdev_dev->etheraddr, mac)) { - error = set_etheraddr(netdev_get_name(netdev_), ARPHRD_ETHER, mac); - if (!error) { - netdev_dev->cache_valid |= VALID_ETHERADDR; - memcpy(netdev_dev->etheraddr, mac, ETH_ADDR_LEN); - } - } else { - error = 0; + if (netdev_dev->cache_valid & VALID_ETHERADDR) { + if (netdev_dev->ether_addr_error) { + goto out; + } + if (eth_addr_equals(netdev_dev->etheraddr, mac)) { + goto out; + } } - return error; + + set_etheraddr(netdev_dev, ARPHRD_ETHER, mac); + +out: + return netdev_dev->ether_addr_error; } /* Returns a pointer to 'netdev''s MAC address. The caller must not modify or @@ -1045,16 +1047,19 @@ netdev_linux_get_etheraddr(const struct netdev *netdev_, { struct netdev_dev_linux *netdev_dev = netdev_dev_linux_cast(netdev_get_dev(netdev_)); - if (!(netdev_dev->cache_valid & VALID_ETHERADDR)) { - int error = get_etheraddr(netdev_get_name(netdev_), - netdev_dev->etheraddr); - if (error) { - return error; - } - netdev_dev->cache_valid |= VALID_ETHERADDR; + + if (netdev_dev->cache_valid & VALID_ETHERADDR) { + goto out; } - memcpy(mac, netdev_dev->etheraddr, ETH_ADDR_LEN); - return 0; + + get_etheraddr(netdev_dev); + +out: + if (!netdev_dev->ether_addr_error) { + memcpy(mac, netdev_dev->etheraddr, ETH_ADDR_LEN); + } + + return netdev_dev->ether_addr_error; } /* Returns the maximum size of transmitted (and received) packets on 'netdev', @@ -4368,14 +4373,14 @@ get_ifindex(const struct netdev *netdev_, int *ifindexp) return 0; } -static int -get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN]) +static void +get_etheraddr(struct netdev_dev_linux *netdev_dev) { struct ifreq ifr; int hwaddr_family; memset(&ifr, 0, sizeof ifr); - ovs_strzcpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name); + ovs_strzcpy(ifr.ifr_name, netdev_dev->netdev_dev.name, sizeof ifr.ifr_name); COVERAGE_INC(netdev_get_hwaddr); if (ioctl(af_inet_sock, SIOCGIFHWADDR, &ifr) < 0) { /* ENODEV probably means that a vif disappeared asynchronously and @@ -4383,35 +4388,43 @@ get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN]) * to INFO for that case. */ VLOG(errno == ENODEV ? VLL_INFO : VLL_ERR, "ioctl(SIOCGIFHWADDR) on %s device failed: %s", - netdev_name, strerror(errno)); - return errno; + netdev_dev->netdev_dev.name, strerror(errno)); + netdev_dev->ether_addr_error = errno; + goto out; } hwaddr_family = ifr.ifr_hwaddr.sa_family; if (hwaddr_family != AF_UNSPEC && hwaddr_family != ARPHRD_ETHER) { VLOG_WARN("%s device has unknown hardware address family %d", - netdev_name, hwaddr_family); + netdev_dev->netdev_dev.name, hwaddr_family); } - memcpy(ea, ifr.ifr_hwaddr.sa_data, ETH_ADDR_LEN); - return 0; + memcpy(netdev_dev->etheraddr, ifr.ifr_hwaddr.sa_data, ETH_ADDR_LEN); + netdev_dev->ether_addr_error = 0; + +out: + netdev_dev->cache_valid |= VALID_ETHERADDR; } -static int -set_etheraddr(const char *netdev_name, int hwaddr_family, +static void +set_etheraddr(struct netdev_dev_linux *netdev_dev, int hwaddr_family, const uint8_t mac[ETH_ADDR_LEN]) { struct ifreq ifr; memset(&ifr, 0, sizeof ifr); - ovs_strzcpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name); + ovs_strzcpy(ifr.ifr_name, netdev_dev->netdev_dev.name, sizeof ifr.ifr_name); ifr.ifr_hwaddr.sa_family = hwaddr_family; memcpy(ifr.ifr_hwaddr.sa_data, mac, ETH_ADDR_LEN); COVERAGE_INC(netdev_set_hwaddr); if (ioctl(af_inet_sock, SIOCSIFHWADDR, &ifr) < 0) { VLOG_ERR("ioctl(SIOCSIFHWADDR) on %s device failed: %s", - netdev_name, strerror(errno)); - return errno; + netdev_dev->netdev_dev.name, strerror(errno)); + netdev_dev->ether_addr_error = errno; + goto out; } - return 0; + memcpy(netdev_dev->etheraddr, mac, ETH_ADDR_LEN); + netdev_dev->ether_addr_error = 0; +out: + netdev_dev->cache_valid |= VALID_ETHERADDR; } static int -- 1.7.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev