/* The following are figured out "on demand" only. They are only valid
* when the corresponding VALID_* bit in 'cache_valid' is set. */
int ifindex;
- uint8_t etheraddr[ETH_ADDR_LEN];
+ struct eth_addr etheraddr;
struct in_addr address, netmask;
struct in6_addr in6;
int mtu;
int netdev_policing_error; /* Cached error code from set policing. */
int get_features_error; /* Cached error code from ETHTOOL_GSET. */
int get_ifindex_error; /* Cached error code from SIOCGIFINDEX. */
+ int in4_error; /* Cached error code from reading in4 addr. */
+ int in6_error; /* Cached error code from reading in6 addr. */
enum netdev_features current; /* Cached from ETHTOOL_GSET. */
enum netdev_features advertised; /* Cached from ETHTOOL_GSET. */
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, const uint8_t[ETH_ADDR_LEN]);
+static int get_etheraddr(const char *netdev_name, struct eth_addr *ea);
+static int set_etheraddr(const char *netdev_name, const struct eth_addr);
static int get_stats_via_netlink(const struct netdev *, struct netdev_stats *);
static int af_packet_sock(void);
static bool netdev_linux_miimon_enabled(void);
dev->netdev_mtu_error = 0;
}
- if (!eth_addr_is_zero(change->addr)) {
- memcpy(dev->etheraddr, change->addr, ETH_ADDR_LEN);
+ if (!eth_addr_is_zero(change->mac)) {
+ dev->etheraddr = change->mac;
dev->cache_valid |= VALID_ETHERADDR;
dev->ether_addr_error = 0;
}
dp_packet_delete(buffer);
} else {
dp_packet_pad(buffer);
- dp_packet_set_rss_hash(buffer, 0);
+ dp_packet_rss_invalidate(buffer);
packets[0] = buffer;
*c = 1;
}
/* Attempts to set 'netdev''s MAC address to 'mac'. Returns 0 if successful,
* otherwise a positive errno value. */
static int
-netdev_linux_set_etheraddr(struct netdev *netdev_,
- const uint8_t mac[ETH_ADDR_LEN])
+netdev_linux_set_etheraddr(struct netdev *netdev_, const struct eth_addr mac)
{
struct netdev_linux *netdev = netdev_linux_cast(netdev_);
enum netdev_flags old_flags = 0;
netdev->ether_addr_error = error;
netdev->cache_valid |= VALID_ETHERADDR;
if (!error) {
- memcpy(netdev->etheraddr, mac, ETH_ADDR_LEN);
+ netdev->etheraddr = mac;
}
}
/* Copies 'netdev''s MAC address to 'mac' which is passed as param. */
static int
-netdev_linux_get_etheraddr(const struct netdev *netdev_,
- uint8_t mac[ETH_ADDR_LEN])
+netdev_linux_get_etheraddr(const struct netdev *netdev_, struct eth_addr *mac)
{
struct netdev_linux *netdev = netdev_linux_cast(netdev_);
int error;
ovs_mutex_lock(&netdev->mutex);
if (!(netdev->cache_valid & VALID_ETHERADDR)) {
netdev->ether_addr_error = get_etheraddr(netdev_get_name(netdev_),
- netdev->etheraddr);
+ &netdev->etheraddr);
netdev->cache_valid |= VALID_ETHERADDR;
}
error = netdev->ether_addr_error;
if (!error) {
- memcpy(mac, netdev->etheraddr, ETH_ADDR_LEN);
+ *mac = netdev->etheraddr;
}
ovs_mutex_unlock(&netdev->mutex);
if (!error) {
error = netdev_linux_get_ipv4(netdev_, &netdev->netmask,
SIOCGIFNETMASK, "SIOCGIFNETMASK");
- if (!error) {
- netdev->cache_valid |= VALID_IN4;
- }
}
+ netdev->in4_error = error;
+ netdev->cache_valid |= VALID_IN4;
} else {
- error = 0;
+ error = netdev->in4_error;
}
if (!error) {
ovs_mutex_lock(&netdev->mutex);
error = do_set_addr(netdev_, SIOCSIFADDR, "SIOCSIFADDR", address);
if (!error) {
- netdev->cache_valid |= VALID_IN4;
netdev->address = address;
netdev->netmask = netmask;
if (address.s_addr != INADDR_ANY) {
"SIOCSIFNETMASK", netmask);
}
}
+
+ if (!error) {
+ netdev->cache_valid |= VALID_IN4;
+ netdev->in4_error = 0;
+ } else {
+ netdev->cache_valid &= ~VALID_IN4;
+ }
ovs_mutex_unlock(&netdev->mutex);
return error;
ifname);
}
-/* If 'netdev' has an assigned IPv6 address, sets '*in6' to that address (if
- * 'in6' is non-null) and returns true. Otherwise, returns false. */
+/* If 'netdev' has an assigned IPv6 address, sets '*in6' to that address.
+ * Otherwise, sets '*in6' to 'in6addr_any' and returns the corresponding
+ * error. */
static int
netdev_linux_get_in6(const struct netdev *netdev_, struct in6_addr *in6)
{
struct netdev_linux *netdev = netdev_linux_cast(netdev_);
+ int error;
ovs_mutex_lock(&netdev->mutex);
if (!(netdev->cache_valid & VALID_IN6)) {
char line[128];
netdev->in6 = in6addr_any;
+ netdev->in6_error = EADDRNOTAVAIL;
file = fopen("/proc/net/if_inet6", "r");
if (file != NULL) {
&& !strcmp(name, ifname))
{
netdev->in6 = in6_tmp;
+ netdev->in6_error = 0;
break;
}
}
fclose(file);
+ } else {
+ netdev->in6_error = EOPNOTSUPP;
}
netdev->cache_valid |= VALID_IN6;
}
*in6 = netdev->in6;
+ error = netdev->in6_error;
ovs_mutex_unlock(&netdev->mutex);
- return 0;
+ return error;
}
static void
* ENXIO indicates that there is not ARP table entry for 'ip' on 'netdev'. */
static int
netdev_linux_arp_lookup(const struct netdev *netdev,
- ovs_be32 ip, uint8_t mac[ETH_ADDR_LEN])
+ ovs_be32 ip, struct eth_addr *mac)
{
struct arpreq r;
struct sockaddr_in sin;
}
COVERAGE_INC(netdev_set_ethtool);
- evalue.data = new_flags = (evalue.data & ~flag) | (enable ? flag : 0);
+ new_flags = (evalue.data & ~flag) | (enable ? flag : 0);
+ if (new_flags == evalue.data) {
+ return 0;
+ }
+ evalue.data = new_flags;
error = netdev_linux_do_ethtool(netdev_name,
(struct ethtool_cmd *)&evalue,
ETHTOOL_SFLAGS, "ETHTOOL_SFLAGS");
}
static int
-get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN])
+get_etheraddr(const char *netdev_name, struct eth_addr *ea)
{
struct ifreq ifr;
int hwaddr_family;
}
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",
+ VLOG_INFO("%s device has unknown hardware address family %d",
netdev_name, hwaddr_family);
+ return EINVAL;
}
memcpy(ea, ifr.ifr_hwaddr.sa_data, ETH_ADDR_LEN);
return 0;
}
static int
-set_etheraddr(const char *netdev_name,
- const uint8_t mac[ETH_ADDR_LEN])
+set_etheraddr(const char *netdev_name, const struct eth_addr mac)
{
struct ifreq ifr;
int error;
memset(&ifr, 0, sizeof ifr);
ovs_strzcpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
- memcpy(ifr.ifr_hwaddr.sa_data, mac, ETH_ADDR_LEN);
+ memcpy(ifr.ifr_hwaddr.sa_data, &mac, ETH_ADDR_LEN);
COVERAGE_INC(netdev_set_hwaddr);
error = af_inet_ioctl(SIOCSIFHWADDR, &ifr);
if (error) {