/*
- * Copyright (c) 2009, 2010, 2011 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
VALID_IN6 = 1 << 3,
VALID_MTU = 1 << 4,
VALID_POLICING = 1 << 5,
- VALID_HAVE_VPORT_STATS = 1 << 6
+ VALID_VPORT_STAT_ERROR = 1 << 6
};
struct tap_state {
struct in_addr address, netmask;
struct in6_addr in6;
int mtu;
- int ifi_flags;
+ unsigned int ifi_flags;
long long int carrier_resets;
uint32_t kbits_rate; /* Policing data. */
uint32_t kbits_burst;
- bool have_vport_stats;
+ int vport_stats_error; /* Cached error code from vport_get_stats().
+ 0 or an errno value. */
struct tc *tc;
union {
const char *cmd_name);
static int netdev_linux_get_ipv4(const struct netdev *, struct in_addr *,
int cmd, const char *cmd_name);
-static int get_flags(const struct netdev_dev *, int *flagsp);
-static int set_flags(struct netdev *, int flags);
+static int get_flags(const struct netdev_dev *, unsigned int *flags);
+static int set_flags(struct netdev *, unsigned int flags);
static int do_get_ifindex(const char *netdev_name);
static int get_ifindex(const struct netdev *, int *ifindexp);
static int do_set_addr(struct netdev *netdev,
}
static void
-netdev_dev_linux_changed(struct netdev_dev_linux *dev)
+netdev_dev_linux_changed(struct netdev_dev_linux *dev, unsigned int ifi_flags)
{
dev->change_seq++;
if (!dev->change_seq) {
dev->change_seq++;
}
+
+ if ((dev->ifi_flags ^ ifi_flags) & IFF_RUNNING) {
+ dev->carrier_resets++;
+ }
+ dev->ifi_flags = ifi_flags;
+
dev->cache_valid = 0;
}
if (is_netdev_linux_class(netdev_class)) {
dev = netdev_dev_linux_cast(base_dev);
-
- if ((dev->ifi_flags ^ change->ifi_flags) & IFF_RUNNING) {
- dev->carrier_resets++;
- }
- dev->ifi_flags = change->ifi_flags;
-
- netdev_dev_linux_changed(dev);
+ netdev_dev_linux_changed(dev, change->ifi_flags);
}
}
} else {
shash_init(&device_shash);
netdev_dev_get_devices(&netdev_linux_class, &device_shash);
SHASH_FOR_EACH (node, &device_shash) {
- int flags;
+ unsigned int flags;
dev = node->data;
get_flags(&dev->netdev_dev, &flags);
- if ((dev->ifi_flags ^ flags) & IFF_RUNNING) {
- dev->carrier_resets++;
- }
- dev->ifi_flags = flags;
-
- netdev_dev_linux_changed(dev);
+ netdev_dev_linux_changed(dev, flags);
}
shash_destroy(&device_shash);
}
netdev_linux_get_miimon(dev->netdev_dev.name, &miimon);
if (miimon != dev->miimon) {
dev->miimon = miimon;
- netdev_dev_linux_changed(dev);
+ netdev_dev_linux_changed(dev, dev->ifi_flags);
}
timer_set_duration(&dev->miimon_timer, dev->miimon_interval);
struct netdev_dev_linux *netdev_dev =
netdev_dev_linux_cast(netdev_get_dev(netdev_));
- if (netdev_dev->have_vport_stats ||
- !(netdev_dev->cache_valid & VALID_HAVE_VPORT_STATS)) {
+ if (!netdev_dev->vport_stats_error ||
+ !(netdev_dev->cache_valid & VALID_VPORT_STAT_ERROR)) {
int error;
error = netdev_vport_get_stats(netdev_, stats);
VLOG_WARN_RL(&rl, "%s: obtaining netdev stats via vport failed "
"(%s)", netdev_get_name(netdev_), strerror(error));
}
- netdev_dev->have_vport_stats = !error;
- netdev_dev->cache_valid |= VALID_HAVE_VPORT_STATS;
+ netdev_dev->vport_stats_error = error;
+ netdev_dev->cache_valid |= VALID_VPORT_STAT_ERROR;
}
}
error = netdev_linux_sys_get_stats(netdev_, &dev_stats);
if (error) {
- if (!netdev_dev->have_vport_stats) {
+ if (netdev_dev->vport_stats_error) {
return error;
} else {
return 0;
}
}
- if (!netdev_dev->have_vport_stats) {
+ if (netdev_dev->vport_stats_error) {
/* stats not available from OVS then use ioctl stats. */
*stats = dev_stats;
} else {
/* Retrieves current device stats for 'netdev-tap' netdev or
* netdev-internal. */
static int
-netdev_pseudo_get_stats(const struct netdev *netdev_,
+netdev_tap_get_stats(const struct netdev *netdev_,
struct netdev_stats *stats)
{
struct netdev_dev_linux *netdev_dev =
error = netdev_linux_sys_get_stats(netdev_, &dev_stats);
if (error) {
- if (!netdev_dev->have_vport_stats) {
+ if (netdev_dev->vport_stats_error) {
return error;
} else {
return 0;
* them back here. This does not apply if we are getting stats from the
* vport layer because it always tracks stats from the perspective of the
* switch. */
- if (!netdev_dev->have_vport_stats) {
+ if (netdev_dev->vport_stats_error) {
*stats = dev_stats;
swap_uint64(&stats->rx_packets, &stats->tx_packets);
swap_uint64(&stats->rx_bytes, &stats->tx_bytes);
return 0;
}
+static int
+netdev_internal_get_stats(const struct netdev *netdev_,
+ struct netdev_stats *stats)
+{
+ struct netdev_dev_linux *netdev_dev =
+ netdev_dev_linux_cast(netdev_get_dev(netdev_));
+
+ get_stats_via_vport(netdev_, stats);
+ return netdev_dev->vport_stats_error;
+}
+
/* Stores the features supported by 'netdev' into each of '*current',
* '*advertised', '*supported', and '*peer' that are non-null. Each value is a
- * bitmap of "enum ofp_port_features" bits, in host byte order. Returns 0 if
- * successful, otherwise a positive errno value. */
+ * bitmap of NETDEV_* bits. Returns 0 if successful, otherwise a positive
+ * errno value. */
static int
netdev_linux_get_features(const struct netdev *netdev,
- uint32_t *current, uint32_t *advertised,
- uint32_t *supported, uint32_t *peer)
+ enum netdev_features *current,
+ enum netdev_features *advertised,
+ enum netdev_features *supported,
+ enum netdev_features *peer)
{
struct ethtool_cmd ecmd;
+ uint32_t speed;
int error;
memset(&ecmd, 0, sizeof ecmd);
/* Supported features. */
*supported = 0;
if (ecmd.supported & SUPPORTED_10baseT_Half) {
- *supported |= OFPPF_10MB_HD;
+ *supported |= NETDEV_F_10MB_HD;
}
if (ecmd.supported & SUPPORTED_10baseT_Full) {
- *supported |= OFPPF_10MB_FD;
+ *supported |= NETDEV_F_10MB_FD;
}
if (ecmd.supported & SUPPORTED_100baseT_Half) {
- *supported |= OFPPF_100MB_HD;
+ *supported |= NETDEV_F_100MB_HD;
}
if (ecmd.supported & SUPPORTED_100baseT_Full) {
- *supported |= OFPPF_100MB_FD;
+ *supported |= NETDEV_F_100MB_FD;
}
if (ecmd.supported & SUPPORTED_1000baseT_Half) {
- *supported |= OFPPF_1GB_HD;
+ *supported |= NETDEV_F_1GB_HD;
}
if (ecmd.supported & SUPPORTED_1000baseT_Full) {
- *supported |= OFPPF_1GB_FD;
+ *supported |= NETDEV_F_1GB_FD;
}
if (ecmd.supported & SUPPORTED_10000baseT_Full) {
- *supported |= OFPPF_10GB_FD;
+ *supported |= NETDEV_F_10GB_FD;
}
if (ecmd.supported & SUPPORTED_TP) {
- *supported |= OFPPF_COPPER;
+ *supported |= NETDEV_F_COPPER;
}
if (ecmd.supported & SUPPORTED_FIBRE) {
- *supported |= OFPPF_FIBER;
+ *supported |= NETDEV_F_FIBER;
}
if (ecmd.supported & SUPPORTED_Autoneg) {
- *supported |= OFPPF_AUTONEG;
+ *supported |= NETDEV_F_AUTONEG;
}
if (ecmd.supported & SUPPORTED_Pause) {
- *supported |= OFPPF_PAUSE;
+ *supported |= NETDEV_F_PAUSE;
}
if (ecmd.supported & SUPPORTED_Asym_Pause) {
- *supported |= OFPPF_PAUSE_ASYM;
+ *supported |= NETDEV_F_PAUSE_ASYM;
}
/* Advertised features. */
*advertised = 0;
if (ecmd.advertising & ADVERTISED_10baseT_Half) {
- *advertised |= OFPPF_10MB_HD;
+ *advertised |= NETDEV_F_10MB_HD;
}
if (ecmd.advertising & ADVERTISED_10baseT_Full) {
- *advertised |= OFPPF_10MB_FD;
+ *advertised |= NETDEV_F_10MB_FD;
}
if (ecmd.advertising & ADVERTISED_100baseT_Half) {
- *advertised |= OFPPF_100MB_HD;
+ *advertised |= NETDEV_F_100MB_HD;
}
if (ecmd.advertising & ADVERTISED_100baseT_Full) {
- *advertised |= OFPPF_100MB_FD;
+ *advertised |= NETDEV_F_100MB_FD;
}
if (ecmd.advertising & ADVERTISED_1000baseT_Half) {
- *advertised |= OFPPF_1GB_HD;
+ *advertised |= NETDEV_F_1GB_HD;
}
if (ecmd.advertising & ADVERTISED_1000baseT_Full) {
- *advertised |= OFPPF_1GB_FD;
+ *advertised |= NETDEV_F_1GB_FD;
}
if (ecmd.advertising & ADVERTISED_10000baseT_Full) {
- *advertised |= OFPPF_10GB_FD;
+ *advertised |= NETDEV_F_10GB_FD;
}
if (ecmd.advertising & ADVERTISED_TP) {
- *advertised |= OFPPF_COPPER;
+ *advertised |= NETDEV_F_COPPER;
}
if (ecmd.advertising & ADVERTISED_FIBRE) {
- *advertised |= OFPPF_FIBER;
+ *advertised |= NETDEV_F_FIBER;
}
if (ecmd.advertising & ADVERTISED_Autoneg) {
- *advertised |= OFPPF_AUTONEG;
+ *advertised |= NETDEV_F_AUTONEG;
}
if (ecmd.advertising & ADVERTISED_Pause) {
- *advertised |= OFPPF_PAUSE;
+ *advertised |= NETDEV_F_PAUSE;
}
if (ecmd.advertising & ADVERTISED_Asym_Pause) {
- *advertised |= OFPPF_PAUSE_ASYM;
+ *advertised |= NETDEV_F_PAUSE_ASYM;
}
/* Current settings. */
- if (ecmd.speed == SPEED_10) {
- *current = ecmd.duplex ? OFPPF_10MB_FD : OFPPF_10MB_HD;
- } else if (ecmd.speed == SPEED_100) {
- *current = ecmd.duplex ? OFPPF_100MB_FD : OFPPF_100MB_HD;
- } else if (ecmd.speed == SPEED_1000) {
- *current = ecmd.duplex ? OFPPF_1GB_FD : OFPPF_1GB_HD;
- } else if (ecmd.speed == SPEED_10000) {
- *current = OFPPF_10GB_FD;
+ speed = ecmd.speed;
+ if (speed == SPEED_10) {
+ *current = ecmd.duplex ? NETDEV_F_10MB_FD : NETDEV_F_10MB_HD;
+ } else if (speed == SPEED_100) {
+ *current = ecmd.duplex ? NETDEV_F_100MB_FD : NETDEV_F_100MB_HD;
+ } else if (speed == SPEED_1000) {
+ *current = ecmd.duplex ? NETDEV_F_1GB_FD : NETDEV_F_1GB_HD;
+ } else if (speed == SPEED_10000) {
+ *current = NETDEV_F_10GB_FD;
+ } else if (speed == 40000) {
+ *current = NETDEV_F_40GB_FD;
+ } else if (speed == 100000) {
+ *current = NETDEV_F_100GB_FD;
+ } else if (speed == 1000000) {
+ *current = NETDEV_F_1TB_FD;
} else {
*current = 0;
}
if (ecmd.port == PORT_TP) {
- *current |= OFPPF_COPPER;
+ *current |= NETDEV_F_COPPER;
} else if (ecmd.port == PORT_FIBRE) {
- *current |= OFPPF_FIBER;
+ *current |= NETDEV_F_FIBER;
}
if (ecmd.autoneg) {
- *current |= OFPPF_AUTONEG;
+ *current |= NETDEV_F_AUTONEG;
}
/* Peer advertisements. */
/* Set the features advertised by 'netdev' to 'advertise'. */
static int
-netdev_linux_set_advertisements(struct netdev *netdev, uint32_t advertise)
+netdev_linux_set_advertisements(struct netdev *netdev,
+ enum netdev_features advertise)
{
struct ethtool_cmd ecmd;
int error;
}
ecmd.advertising = 0;
- if (advertise & OFPPF_10MB_HD) {
+ if (advertise & NETDEV_F_10MB_HD) {
ecmd.advertising |= ADVERTISED_10baseT_Half;
}
- if (advertise & OFPPF_10MB_FD) {
+ if (advertise & NETDEV_F_10MB_FD) {
ecmd.advertising |= ADVERTISED_10baseT_Full;
}
- if (advertise & OFPPF_100MB_HD) {
+ if (advertise & NETDEV_F_100MB_HD) {
ecmd.advertising |= ADVERTISED_100baseT_Half;
}
- if (advertise & OFPPF_100MB_FD) {
+ if (advertise & NETDEV_F_100MB_FD) {
ecmd.advertising |= ADVERTISED_100baseT_Full;
}
- if (advertise & OFPPF_1GB_HD) {
+ if (advertise & NETDEV_F_1GB_HD) {
ecmd.advertising |= ADVERTISED_1000baseT_Half;
}
- if (advertise & OFPPF_1GB_FD) {
+ if (advertise & NETDEV_F_1GB_FD) {
ecmd.advertising |= ADVERTISED_1000baseT_Full;
}
- if (advertise & OFPPF_10GB_FD) {
+ if (advertise & NETDEV_F_10GB_FD) {
ecmd.advertising |= ADVERTISED_10000baseT_Full;
}
- if (advertise & OFPPF_COPPER) {
+ if (advertise & NETDEV_F_COPPER) {
ecmd.advertising |= ADVERTISED_TP;
}
- if (advertise & OFPPF_FIBER) {
+ if (advertise & NETDEV_F_FIBER) {
ecmd.advertising |= ADVERTISED_FIBRE;
}
- if (advertise & OFPPF_AUTONEG) {
+ if (advertise & NETDEV_F_AUTONEG) {
ecmd.advertising |= ADVERTISED_Autoneg;
}
- if (advertise & OFPPF_PAUSE) {
+ if (advertise & NETDEV_F_PAUSE) {
ecmd.advertising |= ADVERTISED_Pause;
}
- if (advertise & OFPPF_PAUSE_ASYM) {
+ if (advertise & NETDEV_F_PAUSE_ASYM) {
ecmd.advertising |= ADVERTISED_Asym_Pause;
}
return netdev_linux_do_ethtool(netdev_get_name(netdev), &ecmd,
const char *netdev_name = netdev_get_name(netdev);
int error;
- COVERAGE_INC(netdev_set_policing);
kbits_burst = (!kbits_rate ? 0 /* Force to 0 if no rate specified. */
: !kbits_burst ? 1000 /* Default to 1000 kbits if 0. */
return 0;
}
+ COVERAGE_INC(netdev_set_policing);
/* Remove any existing ingress qdisc. */
error = tc_add_del_ingress_qdisc(netdev, false);
if (error) {
NETDEV_LINUX_CLASS(
"tap",
netdev_linux_create_tap,
- netdev_pseudo_get_stats,
+ netdev_tap_get_stats,
NULL); /* set_stats */
const struct netdev_class netdev_internal_class =
NETDEV_LINUX_CLASS(
"internal",
netdev_linux_create,
- netdev_pseudo_get_stats,
+ netdev_internal_get_stats,
netdev_vport_set_stats);
\f
/* HTB traffic control class. */
}
static int
-get_flags(const struct netdev_dev *dev, int *flags)
+get_flags(const struct netdev_dev *dev, unsigned int *flags)
{
struct ifreq ifr;
int error;
}
static int
-set_flags(struct netdev *netdev, int flags)
+set_flags(struct netdev *netdev, unsigned int flags)
{
struct ifreq ifr;