mirror of
https://github.com/openvswitch/ovs
synced 2025-09-02 23:35:27 +00:00
netdev-linux: Cache error code from ether-addr ioctl.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
This commit is contained in:
@@ -377,6 +377,7 @@ struct netdev_dev_linux {
|
|||||||
int vport_stats_error; /* Cached error code from vport_get_stats().
|
int vport_stats_error; /* Cached error code from vport_get_stats().
|
||||||
0 or an errno value. */
|
0 or an errno value. */
|
||||||
int netdev_mtu_error; /* Cached error code from SIOCGIFMTU or SIOCSIFMTU. */
|
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 ethtool_drvinfo drvinfo; /* Cached from ETHTOOL_GDRVINFO. */
|
||||||
struct tc *tc;
|
struct tc *tc;
|
||||||
@@ -417,8 +418,7 @@ static int do_set_addr(struct netdev *netdev,
|
|||||||
int ioctl_nr, const char *ioctl_name,
|
int ioctl_nr, const char *ioctl_name,
|
||||||
struct in_addr addr);
|
struct in_addr addr);
|
||||||
static int get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN]);
|
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 int set_etheraddr(const char *netdev_name, const uint8_t[ETH_ADDR_LEN]);
|
||||||
const uint8_t[ETH_ADDR_LEN]);
|
|
||||||
static int get_stats_via_netlink(int ifindex, struct netdev_stats *stats);
|
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);
|
static int get_stats_via_proc(const char *netdev_name, struct netdev_stats *stats);
|
||||||
static int af_packet_sock(void);
|
static int af_packet_sock(void);
|
||||||
@@ -541,6 +541,12 @@ netdev_dev_linux_update(struct netdev_dev_linux *dev,
|
|||||||
dev->netdev_mtu_error = 0;
|
dev->netdev_mtu_error = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!eth_addr_is_zero(change->addr)) {
|
||||||
|
memcpy(dev->etheraddr, change->addr, ETH_ADDR_LEN);
|
||||||
|
dev->cache_valid |= VALID_ETHERADDR;
|
||||||
|
dev->ether_addr_error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
netdev_dev_linux_changed(dev, change->ifi_flags, 0);
|
netdev_dev_linux_changed(dev, change->ifi_flags, 0);
|
||||||
}
|
}
|
||||||
@@ -1008,37 +1014,49 @@ netdev_linux_set_etheraddr(struct netdev *netdev_,
|
|||||||
netdev_dev_linux_cast(netdev_get_dev(netdev_));
|
netdev_dev_linux_cast(netdev_get_dev(netdev_));
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (!(netdev_dev->cache_valid & VALID_ETHERADDR)
|
if (netdev_dev->cache_valid & VALID_ETHERADDR) {
|
||||||
|| !eth_addr_equals(netdev_dev->etheraddr, mac)) {
|
if (netdev_dev->ether_addr_error) {
|
||||||
error = set_etheraddr(netdev_get_name(netdev_), ARPHRD_ETHER, mac);
|
return netdev_dev->ether_addr_error;
|
||||||
|
}
|
||||||
|
if (eth_addr_equals(netdev_dev->etheraddr, mac)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
netdev_dev->cache_valid &= ~VALID_ETHERADDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = set_etheraddr(netdev_get_name(netdev_), mac);
|
||||||
|
if (!error || error == ENODEV) {
|
||||||
|
netdev_dev->ether_addr_error = error;
|
||||||
|
netdev_dev->cache_valid |= VALID_ETHERADDR;
|
||||||
if (!error) {
|
if (!error) {
|
||||||
netdev_dev->cache_valid |= VALID_ETHERADDR;
|
|
||||||
memcpy(netdev_dev->etheraddr, mac, ETH_ADDR_LEN);
|
memcpy(netdev_dev->etheraddr, mac, ETH_ADDR_LEN);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
error = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a pointer to 'netdev''s MAC address. The caller must not modify or
|
/* Copies 'netdev''s MAC address to 'mac' which is passed as param. */
|
||||||
* free the returned buffer. */
|
|
||||||
static int
|
static int
|
||||||
netdev_linux_get_etheraddr(const struct netdev *netdev_,
|
netdev_linux_get_etheraddr(const struct netdev *netdev_,
|
||||||
uint8_t mac[ETH_ADDR_LEN])
|
uint8_t mac[ETH_ADDR_LEN])
|
||||||
{
|
{
|
||||||
struct netdev_dev_linux *netdev_dev =
|
struct netdev_dev_linux *netdev_dev =
|
||||||
netdev_dev_linux_cast(netdev_get_dev(netdev_));
|
netdev_dev_linux_cast(netdev_get_dev(netdev_));
|
||||||
|
|
||||||
if (!(netdev_dev->cache_valid & VALID_ETHERADDR)) {
|
if (!(netdev_dev->cache_valid & VALID_ETHERADDR)) {
|
||||||
int error = get_etheraddr(netdev_get_name(netdev_),
|
int error = get_etheraddr(netdev_get_name(netdev_),
|
||||||
netdev_dev->etheraddr);
|
netdev_dev->etheraddr);
|
||||||
if (error) {
|
|
||||||
return error;
|
netdev_dev->ether_addr_error = error;
|
||||||
}
|
|
||||||
netdev_dev->cache_valid |= VALID_ETHERADDR;
|
netdev_dev->cache_valid |= VALID_ETHERADDR;
|
||||||
}
|
}
|
||||||
memcpy(mac, netdev_dev->etheraddr, ETH_ADDR_LEN);
|
|
||||||
return 0;
|
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',
|
/* Returns the maximum size of transmitted (and received) packets on 'netdev',
|
||||||
@@ -4385,14 +4403,14 @@ get_etheraddr(const char *netdev_name, uint8_t ea[ETH_ADDR_LEN])
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
set_etheraddr(const char *netdev_name, int hwaddr_family,
|
set_etheraddr(const char *netdev_name,
|
||||||
const uint8_t mac[ETH_ADDR_LEN])
|
const uint8_t mac[ETH_ADDR_LEN])
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
|
||||||
memset(&ifr, 0, sizeof ifr);
|
memset(&ifr, 0, sizeof ifr);
|
||||||
ovs_strzcpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
|
ovs_strzcpy(ifr.ifr_name, netdev_name, sizeof ifr.ifr_name);
|
||||||
ifr.ifr_hwaddr.sa_family = hwaddr_family;
|
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);
|
COVERAGE_INC(netdev_set_hwaddr);
|
||||||
if (ioctl(af_inet_sock, SIOCSIFHWADDR, &ifr) < 0) {
|
if (ioctl(af_inet_sock, SIOCSIFHWADDR, &ifr) < 0) {
|
||||||
|
@@ -46,6 +46,7 @@ rtnetlink_link_parse(struct ofpbuf *buf,
|
|||||||
[IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
|
[IFLA_IFNAME] = { .type = NL_A_STRING, .optional = false },
|
||||||
[IFLA_MASTER] = { .type = NL_A_U32, .optional = true },
|
[IFLA_MASTER] = { .type = NL_A_U32, .optional = true },
|
||||||
[IFLA_MTU] = { .type = NL_A_U32, .optional = true },
|
[IFLA_MTU] = { .type = NL_A_U32, .optional = true },
|
||||||
|
[IFLA_ADDRESS] = { .type = NL_A_UNSPEC, .optional = true },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nlattr *attrs[ARRAY_SIZE(policy)];
|
static struct nlattr *attrs[ARRAY_SIZE(policy)];
|
||||||
@@ -72,6 +73,12 @@ rtnetlink_link_parse(struct ofpbuf *buf,
|
|||||||
? nl_attr_get_u32(attrs[IFLA_MTU])
|
? nl_attr_get_u32(attrs[IFLA_MTU])
|
||||||
: 0);
|
: 0);
|
||||||
|
|
||||||
|
if (attrs[IFLA_ADDRESS] &&
|
||||||
|
nl_attr_get_size(attrs[IFLA_ADDRESS]) == ETH_ALEN) {
|
||||||
|
memcpy(change->addr, nl_attr_get(attrs[IFLA_ADDRESS]), ETH_ALEN);
|
||||||
|
} else {
|
||||||
|
memset(change->addr, 0, ETH_ALEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed;
|
return parsed;
|
||||||
|
@@ -18,6 +18,8 @@
|
|||||||
#define RTNETLINK_LINK_H 1
|
#define RTNETLINK_LINK_H 1
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
|
||||||
struct ofpbuf;
|
struct ofpbuf;
|
||||||
struct nln_notifier;
|
struct nln_notifier;
|
||||||
@@ -38,6 +40,7 @@ struct rtnetlink_link_change {
|
|||||||
const char *ifname; /* Name of network device. */
|
const char *ifname; /* Name of network device. */
|
||||||
int master_ifindex; /* Ifindex of datapath master (0 if none). */
|
int master_ifindex; /* Ifindex of datapath master (0 if none). */
|
||||||
int mtu; /* Current MTU. */
|
int mtu; /* Current MTU. */
|
||||||
|
uint8_t addr[ETH_ALEN];
|
||||||
unsigned int ifi_flags; /* Flags of network device. */
|
unsigned int ifi_flags; /* Flags of network device. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user