OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_get_be16])
OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_find_nested])
- OVS_GREP_IFELSE([$KSRC/include/linux/if_link.h], [rtnl_link_stats64])
-
OVS_GREP_IFELSE([$KSRC/include/linux/if_vlan.h], [ADD_ALL_VLANS_CMD],
[OVS_DEFINE([HAVE_VLAN_BUG_WORKAROUND])])
OVS_CHECK_NETLINK
OVS_CHECK_OPENSSL
OVS_CHECK_LOGDIR
-OVS_CHECK_RTNL_LINK_STATS64
OVS_CHECK_PYTHON
OVS_CHECK_PYUIC4
OVS_CHECK_OVSDBMONITOR
[OVS_VPORT_ATTR_NAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ - 1 },
[OVS_VPORT_ATTR_PORT_NO] = { .type = NLA_U32 },
[OVS_VPORT_ATTR_TYPE] = { .type = NLA_U32 },
- [OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct rtnl_link_stats64) },
+ [OVS_VPORT_ATTR_STATS] = { .len = sizeof(struct ovs_vport_stats) },
[OVS_VPORT_ATTR_ADDRESS] = { .len = ETH_ALEN },
#else
- [OVS_VPORT_ATTR_STATS] = { .minlen = sizeof(struct rtnl_link_stats64) },
+ [OVS_VPORT_ATTR_STATS] = { .minlen = sizeof(struct ovs_vport_stats) },
[OVS_VPORT_ATTR_ADDRESS] = { .minlen = ETH_ALEN },
#endif
[OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED },
NLA_PUT_U32(skb, OVS_VPORT_ATTR_TYPE, vport_get_type(vport));
NLA_PUT_STRING(skb, OVS_VPORT_ATTR_NAME, vport_get_name(vport));
- nla = nla_reserve(skb, OVS_VPORT_ATTR_STATS, sizeof(struct rtnl_link_stats64));
+ nla = nla_reserve(skb, OVS_VPORT_ATTR_STATS, sizeof(struct ovs_vport_stats));
if (!nla)
goto nla_put_failure;
- if (vport_get_stats(vport, nla_data(nla)))
- __skb_trim(skb, skb->len - nla->nla_len);
+
+ vport_get_stats(vport, nla_data(nla));
NLA_PUT(skb, OVS_VPORT_ATTR_ADDRESS, ETH_ALEN, vport_get_addr(vport));
static int change_vport(struct vport *vport, struct nlattr *a[OVS_VPORT_ATTR_MAX + 1])
{
int err = 0;
+
if (a[OVS_VPORT_ATTR_STATS])
- err = vport_set_stats(vport, nla_data(a[OVS_VPORT_ATTR_STATS]));
- if (!err && a[OVS_VPORT_ATTR_ADDRESS])
+ vport_set_stats(vport, nla_data(a[OVS_VPORT_ATTR_STATS]));
+
+ if (a[OVS_VPORT_ATTR_ADDRESS])
err = vport_set_addr(vport, nla_data(a[OVS_VPORT_ATTR_ADDRESS]));
+
return err;
}
extern void dev_disable_lro(struct net_device *dev);
#endif
-/* Linux 2.6.28 introduced dev_get_stats():
- * const struct net_device_stats *dev_get_stats(struct net_device *dev);
- *
- * Linux 2.6.36 changed dev_get_stats() to:
- * struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
- * struct rtnl_link_stats64 *storage);
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
-#define dev_get_stats(dev, storage) rpl_dev_get_stats(dev, storage)
-struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
- struct rtnl_link_stats64 *storage);
-#endif
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
#define skb_checksum_help(skb) skb_checksum_help((skb), 0)
#endif
-#include <linux/if_link.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
-/* Linux 2.6.28 introduced dev_get_stats():
- * const struct net_device_stats *dev_get_stats(struct net_device *dev);
- *
- * Linux 2.6.36 changed dev_get_stats() to:
- * struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
- * struct rtnl_link_stats64 *storage);
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)
-struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev,
- struct rtnl_link_stats64 *storage)
-{
- const struct net_device_stats *stats;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
- stats = dev->get_stats(dev);
-#else /* 2.6.28 < kernel version < 2.6.36 */
- stats = (dev_get_stats)(dev);
-#endif /* 2.6.28 < kernel version < 2.6.36 */
-
- storage->rx_packets = stats->rx_packets;
- storage->tx_packets = stats->tx_packets;
- storage->rx_bytes = stats->rx_bytes;
- storage->tx_bytes = stats->tx_bytes;
- storage->rx_errors = stats->rx_errors;
- storage->tx_errors = stats->tx_errors;
- storage->rx_dropped = stats->rx_dropped;
- storage->tx_dropped = stats->tx_dropped;
- storage->multicast = stats->multicast;
- storage->collisions = stats->collisions;
- storage->rx_length_errors = stats->rx_length_errors;
- storage->rx_over_errors = stats->rx_over_errors;
- storage->rx_crc_errors = stats->rx_crc_errors;
- storage->rx_frame_errors = stats->rx_frame_errors;
- storage->rx_fifo_errors = stats->rx_fifo_errors;
- storage->rx_missed_errors = stats->rx_missed_errors;
- storage->tx_aborted_errors = stats->tx_aborted_errors;
- storage->tx_carrier_errors = stats->tx_carrier_errors;
- storage->tx_fifo_errors = stats->tx_fifo_errors;
- storage->tx_heartbeat_errors = stats->tx_heartbeat_errors;
- storage->tx_window_errors = stats->tx_window_errors;
- storage->rx_compressed = stats->rx_compressed;
- storage->tx_compressed = stats->tx_compressed;
-
- return storage;
-}
-#endif /* kernel version < 2.6.36 */
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38)
static bool can_checksum_protocol(unsigned long features, __be16 protocol)
{
const struct vport_ops capwap_vport_ops = {
.type = OVS_VPORT_TYPE_CAPWAP,
- .flags = VPORT_F_GEN_STATS | VPORT_F_TUN_ID,
+ .flags = VPORT_F_TUN_ID,
.init = capwap_init,
.exit = capwap_exit,
.create = capwap_create,
const struct vport_ops gre_vport_ops = {
.type = OVS_VPORT_TYPE_GRE,
- .flags = VPORT_F_GEN_STATS | VPORT_F_TUN_ID,
+ .flags = VPORT_F_TUN_ID,
.init = gre_init,
.exit = gre_exit,
.create = gre_create,
return netdev_priv(netdev);
}
-/* This function is only called by the kernel network layer. It is not a vport
- * get_stats() function. If a vport get_stats() function is defined that
- * results in this being called it will cause infinite recursion. */
+/* This function is only called by the kernel network layer.*/
static struct net_device_stats *internal_dev_sys_stats(struct net_device *netdev)
{
struct vport *vport = internal_dev_get_vport(netdev);
struct net_device_stats *stats = &internal_dev_priv(netdev)->stats;
if (vport) {
- struct rtnl_link_stats64 vport_stats;
+ struct ovs_vport_stats vport_stats;
vport_get_stats(vport, &vport_stats);
stats->tx_errors = vport_stats.rx_errors;
stats->rx_dropped = vport_stats.tx_dropped;
stats->tx_dropped = vport_stats.rx_dropped;
- stats->collisions = vport_stats.collisions;
}
return stats;
const struct vport_ops internal_vport_ops = {
.type = OVS_VPORT_TYPE_INTERNAL,
- .flags = VPORT_F_REQUIRED | VPORT_F_GEN_STATS | VPORT_F_FLOW,
+ .flags = VPORT_F_REQUIRED | VPORT_F_FLOW,
.create = internal_dev_create,
.destroy = internal_dev_destroy,
.set_addr = netdev_set_addr,
#define vlan_tso true
#endif
-/* If the native device stats aren't 64 bit use the vport stats tracking instead. */
-#define USE_VPORT_STATS (sizeof(((struct net_device_stats *)0)->rx_bytes) < sizeof(u64))
-
static void netdev_port_receive(struct vport *vport, struct sk_buff *skb);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)
goto error_put;
}
- /* If we are using the vport stats layer initialize it to the current
- * values so we are roughly consistent with the device stats. */
- if (USE_VPORT_STATS) {
- struct rtnl_link_stats64 stats;
-
- err = netdev_get_stats(vport, &stats);
- if (!err)
- vport_set_stats(vport, &stats);
- }
-
err = netdev_rx_handler_register(netdev_vport->dev, netdev_frame_hook,
vport);
if (err)
return &netdev_vport->dev->NETDEV_DEV_MEMBER.kobj;
}
-int netdev_get_stats(const struct vport *vport, struct rtnl_link_stats64 *stats)
-{
- const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
- dev_get_stats(netdev_vport->dev, stats);
- return 0;
-}
-
unsigned netdev_get_dev_flags(const struct vport *vport)
{
const struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
const struct vport_ops netdev_vport_ops = {
.type = OVS_VPORT_TYPE_NETDEV,
- .flags = (VPORT_F_REQUIRED |
- (USE_VPORT_STATS ? VPORT_F_GEN_STATS : 0)),
+ .flags = VPORT_F_REQUIRED,
.init = netdev_init,
.exit = netdev_exit,
.create = netdev_create,
.get_name = netdev_get_name,
.get_addr = netdev_get_addr,
.get_kobj = netdev_get_kobj,
- .get_stats = netdev_get_stats,
.get_dev_flags = netdev_get_dev_flags,
.is_running = netdev_is_running,
.get_operstate = netdev_get_operstate,
const unsigned char *netdev_get_addr(const struct vport *);
const char *netdev_get_config(const struct vport *);
struct kobject *netdev_get_kobj(const struct vport *);
-int netdev_get_stats(const struct vport *, struct rtnl_link_stats64 *);
unsigned netdev_get_dev_flags(const struct vport *);
int netdev_is_running(const struct vport *);
unsigned char netdev_get_operstate(const struct vport *);
const struct vport_ops patch_vport_ops = {
.type = OVS_VPORT_TYPE_PATCH,
- .flags = VPORT_F_GEN_STATS,
.init = patch_init,
.exit = patch_exit,
.create = patch_create,
vport->kobj.kset = NULL;
kobject_init(&vport->kobj, &brport_ktype);
- if (vport->ops->flags & VPORT_F_GEN_STATS) {
- vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
- if (!vport->percpu_stats)
- return ERR_PTR(-ENOMEM);
+ vport->percpu_stats = alloc_percpu(struct vport_percpu_stats);
+ if (!vport->percpu_stats)
+ return ERR_PTR(-ENOMEM);
- spin_lock_init(&vport->stats_lock);
- }
+ spin_lock_init(&vport->stats_lock);
return vport;
}
*/
void vport_free(struct vport *vport)
{
- if (vport->ops->flags & VPORT_F_GEN_STATS)
- free_percpu(vport->percpu_stats);
+ free_percpu(vport->percpu_stats);
kobject_put(&vport->kobj);
}
*
* Must be called with RTNL lock.
*/
-int vport_set_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
+void vport_set_stats(struct vport *vport, struct ovs_vport_stats *stats)
{
ASSERT_RTNL();
- if (vport->ops->flags & VPORT_F_GEN_STATS) {
- spin_lock_bh(&vport->stats_lock);
- vport->offset_stats = *stats;
- spin_unlock_bh(&vport->stats_lock);
-
- return 0;
- } else
- return -EOPNOTSUPP;
+ spin_lock_bh(&vport->stats_lock);
+ vport->offset_stats = *stats;
+ spin_unlock_bh(&vport->stats_lock);
}
/**
return NULL;
}
-static int vport_call_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
-{
- int err;
-
- rcu_read_lock();
- err = vport->ops->get_stats(vport, stats);
- rcu_read_unlock();
-
- return err;
-}
-
/**
* vport_get_stats - retrieve device stats
*
*
* Must be called with RTNL lock or rcu_read_lock.
*/
-int vport_get_stats(struct vport *vport, struct rtnl_link_stats64 *stats)
+void vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats)
{
int i;
- if (!(vport->ops->flags & VPORT_F_GEN_STATS))
- return vport_call_get_stats(vport, stats);
-
/* We potentially have 3 sources of stats that need to be
* combined: those we have collected (split into err_stats and
* percpu_stats), offset_stats from set_stats(), and device
- * error stats from get_stats() (for errors that happen
+ * error stats from netdev->get_stats() (for errors that happen
* downstream and therefore aren't reported through our
- * vport_record_error() function). */
+ * vport_record_error() function).
+ * Stats from first two sources are merged and reported by ovs over
+ * OVS_VPORT_ATTR_STATS.
+ * netdev-stats can be directly read over netlink-ioctl.
+ */
spin_lock_bh(&vport->stats_lock);
spin_unlock_bh(&vport->stats_lock);
- if (vport->ops->get_stats) {
- struct rtnl_link_stats64 dev_stats;
- int err;
-
- err = vport_call_get_stats(vport, &dev_stats);
- if (err)
- return err;
-
- stats->rx_errors += dev_stats.rx_errors;
- stats->tx_errors += dev_stats.tx_errors;
- stats->rx_dropped += dev_stats.rx_dropped;
- stats->tx_dropped += dev_stats.tx_dropped;
- stats->multicast += dev_stats.multicast;
- stats->collisions += dev_stats.collisions;
- stats->rx_length_errors += dev_stats.rx_length_errors;
- stats->rx_over_errors += dev_stats.rx_over_errors;
- stats->rx_crc_errors += dev_stats.rx_crc_errors;
- stats->rx_frame_errors += dev_stats.rx_frame_errors;
- stats->rx_fifo_errors += dev_stats.rx_fifo_errors;
- stats->rx_missed_errors += dev_stats.rx_missed_errors;
- stats->tx_aborted_errors += dev_stats.tx_aborted_errors;
- stats->tx_carrier_errors += dev_stats.tx_carrier_errors;
- stats->tx_fifo_errors += dev_stats.tx_fifo_errors;
- stats->tx_heartbeat_errors += dev_stats.tx_heartbeat_errors;
- stats->tx_window_errors += dev_stats.tx_window_errors;
- stats->rx_compressed += dev_stats.rx_compressed;
- stats->tx_compressed += dev_stats.tx_compressed;
- }
-
for_each_possible_cpu(i) {
const struct vport_percpu_stats *percpu_stats;
struct vport_percpu_stats local_stats;
stats->tx_bytes += local_stats.tx_bytes;
stats->tx_packets += local_stats.tx_packets;
}
-
- return 0;
}
/**
*/
void vport_receive(struct vport *vport, struct sk_buff *skb)
{
- if (vport->ops->flags & VPORT_F_GEN_STATS) {
- struct vport_percpu_stats *stats;
+ struct vport_percpu_stats *stats;
- local_bh_disable();
- stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
+ local_bh_disable();
+ stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
- write_seqcount_begin(&stats->seqlock);
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
- write_seqcount_end(&stats->seqlock);
+ write_seqcount_begin(&stats->seqlock);
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ write_seqcount_end(&stats->seqlock);
- local_bh_enable();
- }
+ local_bh_enable();
if (!(vport->ops->flags & VPORT_F_FLOW))
OVS_CB(skb)->flow = NULL;
*/
int vport_send(struct vport *vport, struct sk_buff *skb)
{
+ struct vport_percpu_stats *stats;
int sent = vport->ops->send(vport, skb);
- if (vport->ops->flags & VPORT_F_GEN_STATS && sent > 0) {
- struct vport_percpu_stats *stats;
-
- local_bh_disable();
- stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
+ local_bh_disable();
+ stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
- write_seqcount_begin(&stats->seqlock);
- stats->tx_packets++;
- stats->tx_bytes += sent;
- write_seqcount_end(&stats->seqlock);
+ write_seqcount_begin(&stats->seqlock);
+ stats->tx_packets++;
+ stats->tx_bytes += sent;
+ write_seqcount_end(&stats->seqlock);
- local_bh_enable();
- }
+ local_bh_enable();
return sent;
}
*/
void vport_record_error(struct vport *vport, enum vport_err_type err_type)
{
- if (vport->ops->flags & VPORT_F_GEN_STATS) {
-
- spin_lock_bh(&vport->stats_lock);
+ spin_lock_bh(&vport->stats_lock);
- switch (err_type) {
- case VPORT_E_RX_DROPPED:
- vport->err_stats.rx_dropped++;
- break;
+ switch (err_type) {
+ case VPORT_E_RX_DROPPED:
+ vport->err_stats.rx_dropped++;
+ break;
- case VPORT_E_RX_ERROR:
- vport->err_stats.rx_errors++;
- break;
+ case VPORT_E_RX_ERROR:
+ vport->err_stats.rx_errors++;
+ break;
- case VPORT_E_TX_DROPPED:
- vport->err_stats.tx_dropped++;
- break;
+ case VPORT_E_TX_DROPPED:
+ vport->err_stats.tx_dropped++;
+ break;
- case VPORT_E_TX_ERROR:
- vport->err_stats.tx_errors++;
- break;
- };
+ case VPORT_E_TX_ERROR:
+ vport->err_stats.tx_errors++;
+ break;
+ };
- spin_unlock_bh(&vport->stats_lock);
- }
+ spin_unlock_bh(&vport->stats_lock);
}
struct vport *vport_locate(const char *name);
int vport_set_addr(struct vport *, const unsigned char *);
-int vport_set_stats(struct vport *, struct rtnl_link_stats64 *);
+void vport_set_stats(struct vport *, struct ovs_vport_stats *);
const char *vport_get_name(const struct vport *);
enum ovs_vport_type vport_get_type(const struct vport *);
const unsigned char *vport_get_addr(const struct vport *);
struct kobject *vport_get_kobj(const struct vport *);
-int vport_get_stats(struct vport *, struct rtnl_link_stats64 *);
+void vport_get_stats(struct vport *, struct ovs_vport_stats *);
unsigned vport_get_flags(const struct vport *);
int vport_is_running(const struct vport *);
* regardless of whether they were actually chosen and sent down to userspace.
* @hash_node: Element in @dev_table hash table in vport.c.
* @ops: Class structure.
- * @percpu_stats: Points to per-CPU statistics used and maintained by the vport
- * code if %VPORT_F_GEN_STATS is set to 1 in @ops flags, otherwise unused.
+ * @percpu_stats: Points to per-CPU statistics used and maintained by vport
* @stats_lock: Protects @err_stats and @offset_stats.
- * @err_stats: Points to error statistics used and maintained by the vport code
- * if %VPORT_F_GEN_STATS is set to 1 in @ops flags, otherwise unused.
+ * @err_stats: Points to error statistics used and maintained by vport
* @offset_stats: Added to actual statistics as a sop to compatibility with
* XAPI for Citrix XenServer. Deprecated.
*/
spinlock_t stats_lock;
struct vport_err_stats err_stats;
- struct rtnl_link_stats64 offset_stats;
+ struct ovs_vport_stats offset_stats;
};
#define VPORT_F_REQUIRED (1 << 0) /* If init fails, module loading fails. */
-#define VPORT_F_GEN_STATS (1 << 1) /* Track stats at the generic layer. */
-#define VPORT_F_FLOW (1 << 2) /* Sets OVS_CB(skb)->flow. */
-#define VPORT_F_TUN_ID (1 << 3) /* Sets OVS_CB(skb)->tun_id. */
+#define VPORT_F_FLOW (1 << 1) /* Sets OVS_CB(skb)->flow. */
+#define VPORT_F_TUN_ID (1 << 2) /* Sets OVS_CB(skb)->tun_id. */
/**
* struct vport_parms - parameters for creating a new vport
* @get_addr: Get the device's MAC address.
* @get_config: Get the device's configuration.
* @get_kobj: Get the kobj associated with the device (may return null).
- * @get_stats: Fill in the transmit/receive stats. May be null if stats are
- * not supported or if generic stats are in use. If defined and
- * VPORT_F_GEN_STATS is also set, the error stats are added to those already
- * collected.
* @get_dev_flags: Get the device's flags.
* @is_running: Checks whether the device is running.
* @get_operstate: Get the device's operating state.
const unsigned char *(*get_addr)(const struct vport *);
void (*get_config)(const struct vport *, void *);
struct kobject *(*get_kobj)(const struct vport *);
- int (*get_stats)(const struct vport *, struct rtnl_link_stats64 *);
unsigned (*get_dev_flags)(const struct vport *);
int (*is_running)(const struct vport *);
-include include/linux/automake.mk
include include/openflow/automake.mk
include include/openvswitch/automake.mk
include include/sparse/automake.mk
+++ /dev/null
-noinst_HEADERS += \
- include/linux/if_link.h
+++ /dev/null
-#ifndef __LINUX_IF_LINK_WRAPPER_H
-#define __LINUX_IF_LINK_WRAPPER_H 1
-
-#include <linux/version.h>
-
-#ifdef HAVE_RTNL_LINK_STATS64
-#include_next <linux/if_link.h>
-#else /* !HAVE_RTNL_LINK_STATS64 */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
-#include_next <linux/if_link.h>
-#else
-/* Before 2.6.19 there was no <linux/if_link.h>. Instead all of the types now
- * declared there were in <linux/if.h>. Unfortunately <linux/if.h> from 2.6.18
- * conflicts badly enough with <net/if.h> to break the userspace build. All
- * we really need from <linux/if_link.h> is struct rtnl_link_stats64, which in
- * turn only really needs __u64. */
-#include <linux/types.h>
-#include <linux/netlink.h>
-#endif /* kernel < 2.6.19 */
-
-/* The main device statistics structure */
-struct rtnl_link_stats64 {
- __u64 rx_packets; /* total packets received */
- __u64 tx_packets; /* total packets transmitted */
- __u64 rx_bytes; /* total bytes received */
- __u64 tx_bytes; /* total bytes transmitted */
- __u64 rx_errors; /* bad packets received */
- __u64 tx_errors; /* packet transmit problems */
- __u64 rx_dropped; /* no space in linux buffers */
- __u64 tx_dropped; /* no space available in linux */
- __u64 multicast; /* multicast packets received */
- __u64 collisions;
-
- /* detailed rx_errors: */
- __u64 rx_length_errors;
- __u64 rx_over_errors; /* receiver ring buff overflow */
- __u64 rx_crc_errors; /* recved pkt with crc error */
- __u64 rx_frame_errors; /* recv'd frame alignment error */
- __u64 rx_fifo_errors; /* recv'r fifo overrun */
- __u64 rx_missed_errors; /* receiver missed packet */
-
- /* detailed tx_errors */
- __u64 tx_aborted_errors;
- __u64 tx_carrier_errors;
- __u64 tx_fifo_errors;
- __u64 tx_heartbeat_errors;
- __u64 tx_window_errors;
-
- /* for cslip etc */
- __u64 rx_compressed;
- __u64 tx_compressed;
-};
-#endif /* !HAVE_RTNL_LINK_STATS64 */
-
-#endif
#include <sys/socket.h>
#endif
-#include <linux/if_link.h>
#include <linux/netlink.h>
\f
/* datapaths. */
uint64_t n_flows; /* Number of flows present */
};
+struct ovs_vport_stats {
+ uint64_t rx_packets; /* total packets received */
+ uint64_t tx_packets; /* total packets transmitted */
+ uint64_t rx_bytes; /* total bytes received */
+ uint64_t tx_bytes; /* total bytes transmitted */
+ uint64_t rx_errors; /* bad packets received */
+ uint64_t tx_errors; /* packet transmit problems */
+ uint64_t rx_dropped; /* no space in linux buffers */
+ int64_t tx_dropped; /* no space available in linux */
+};
+
/* Logical ports. */
#define OVSP_LOCAL ((uint16_t)0)
\f
* @OVS_VPORT_ATTR_NAME: Name of vport. For a vport based on a network device
* this is the name of the network device. Maximum length %IFNAMSIZ-1 bytes
* plus a null terminator.
- * @OVS_VPORT_ATTR_STATS: A &struct rtnl_link_stats64 giving statistics for
+ * @OVS_VPORT_ATTR_STATS: A &struct ovs_vport_stats giving statistics for
* packets sent or received through the vport.
* @OVS_VPORT_ATTR_ADDRESS: A 6-byte Ethernet address for the vport.
* @OVS_VPORT_ATTR_IFINDEX: ifindex of the underlying network device, if any.
OVS_VPORT_ATTR_PORT_NO, /* port number within datapath */
OVS_VPORT_ATTR_TYPE, /* 32-bit OVS_VPORT_TYPE_* constant. */
OVS_VPORT_ATTR_NAME, /* string name, up to IFNAMSIZ bytes long */
- OVS_VPORT_ATTR_STATS, /* struct rtnl_link_stats64 */
+ OVS_VPORT_ATTR_STATS, /* struct ovs_vport_stats */
OVS_VPORT_ATTR_ADDRESS, /* hardware address */
OVS_VPORT_ATTR_OPTIONS, /* nested attributes, varies by vport type */
OVS_VPORT_ATTR_IFINDEX, /* 32-bit ifindex of backing netdev */
dpif_port->name = xstrdup(reply.name);
dpif_port->type = xstrdup(netdev_vport_get_netdev_type(&reply));
dpif_port->port_no = reply.port_no;
- if (reply.stats) {
- netdev_stats_from_rtnl_link_stats64(&dpif_port->stats,
- reply.stats);
- } else {
- memset(&dpif_port->stats, 0xff, sizeof dpif_port->stats);
- }
ofpbuf_delete(buf);
}
return error;
dpif_port->name = (char *) vport.name;
dpif_port->type = (char *) netdev_vport_get_netdev_type(&vport);
dpif_port->port_no = vport.port_no;
- if (vport.stats) {
- netdev_stats_from_rtnl_link_stats64(&dpif_port->stats, vport.stats);
- } else {
- memset(&dpif_port->stats, 0xff, sizeof dpif_port->stats);
- }
return 0;
}
[OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32 },
[OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .max_len = IFNAMSIZ },
[OVS_VPORT_ATTR_STATS] = { .type = NL_A_UNSPEC,
- .min_len = sizeof(struct rtnl_link_stats64),
- .max_len = sizeof(struct rtnl_link_stats64),
+ .min_len = sizeof(struct ovs_vport_stats),
+ .max_len = sizeof(struct ovs_vport_stats),
.optional = true },
[OVS_VPORT_ATTR_ADDRESS] = { .type = NL_A_UNSPEC,
.min_len = ETH_ADDR_LEN,
/* Attributes. */
const char *name; /* OVS_VPORT_ATTR_NAME. */
- const struct rtnl_link_stats64 *stats; /* OVS_VPORT_ATTR_STATS. */
+ const struct ovs_vport_stats *stats; /* OVS_VPORT_ATTR_STATS. */
const uint8_t *address; /* OVS_VPORT_ATTR_ADDRESS. */
const struct nlattr *options; /* OVS_VPORT_ATTR_OPTIONS. */
size_t options_len;
dst->name = xstrdup(src->name);
dst->type = xstrdup(src->type);
dst->port_no = src->port_no;
- dst->stats = src->stats;
}
/* Frees memory allocated to members of 'dpif_port'.
char *name; /* Network device name, e.g. "eth0". */
char *type; /* Network device type, e.g. "system". */
uint32_t port_no; /* Port number within datapath. */
- struct netdev_stats stats; /* Port statistics. */
};
void dpif_port_clone(struct dpif_port *, const struct dpif_port *);
void dpif_port_destroy(struct dpif_port *);
VALID_IN6 = 1 << 3,
VALID_MTU = 1 << 4,
VALID_CARRIER = 1 << 5,
- VALID_IS_PSEUDO = 1 << 6, /* Represents is_internal and is_tap. */
- VALID_POLICING = 1 << 7,
- VALID_HAVE_VPORT_STATS = 1 << 8
+ VALID_POLICING = 1 << 6,
+ VALID_HAVE_VPORT_STATS = 1 << 7
};
struct tap_state {
struct in6_addr in6;
int mtu;
int carrier;
- bool is_internal; /* Is this an openvswitch internal device? */
- bool is_tap; /* Is this a tuntap device? */
uint32_t kbits_rate; /* Policing data. */
uint32_t kbits_burst;
bool have_vport_stats;
}
}
-/* Brings the 'is_internal' and 'is_tap' members of 'netdev_dev' up-to-date. */
-static void
-netdev_linux_update_is_pseudo(struct netdev_dev_linux *netdev_dev)
-{
- if (!(netdev_dev->cache_valid & VALID_IS_PSEUDO)) {
- const char *name = netdev_dev_get_name(&netdev_dev->netdev_dev);
- const char *type = netdev_dev_get_type(&netdev_dev->netdev_dev);
-
- netdev_dev->is_tap = !strcmp(type, "tap");
- netdev_dev->is_internal = (!netdev_dev->is_tap
- && dpif_linux_is_internal_device(name));
- netdev_dev->cache_valid |= VALID_IS_PSEUDO;
- }
-}
-
static void
swap_uint64(uint64_t *a, uint64_t *b)
{
*b = tmp;
}
-/* Retrieves current device stats for 'netdev'. */
-static int
-netdev_linux_get_stats(const struct netdev *netdev_,
- struct netdev_stats *stats)
+static void
+get_stats_via_vport(const struct netdev *netdev_,
+ struct netdev_stats *stats)
{
struct netdev_dev_linux *netdev_dev =
netdev_dev_linux_cast(netdev_get_dev(netdev_));
- static int use_netlink_stats = -1;
- int error;
if (netdev_dev->have_vport_stats ||
!(netdev_dev->cache_valid & VALID_HAVE_VPORT_STATS)) {
+ int error;
error = netdev_vport_get_stats(netdev_, stats);
+ if (error) {
+ VLOG_WARN_RL(&rl, "%s: obtaining netdev stats via vport failed %d",
+ netdev_get_name(netdev_), error);
+ }
netdev_dev->have_vport_stats = !error;
netdev_dev->cache_valid |= VALID_HAVE_VPORT_STATS;
}
+}
- if (!netdev_dev->have_vport_stats) {
- if (use_netlink_stats < 0) {
- use_netlink_stats = check_for_working_netlink_stats();
+static int
+netdev_linux_sys_get_stats(const struct netdev *netdev_,
+ struct netdev_stats *stats)
+{
+ static int use_netlink_stats = -1;
+ int error;
+
+ if (use_netlink_stats < 0) {
+ use_netlink_stats = check_for_working_netlink_stats();
+ }
+
+ if (use_netlink_stats) {
+ int ifindex;
+
+ error = get_ifindex(netdev_, &ifindex);
+ if (!error) {
+ error = get_stats_via_netlink(ifindex, stats);
}
- if (use_netlink_stats) {
- int ifindex;
+ } else {
+ error = get_stats_via_proc(netdev_get_name(netdev_), stats);
+ }
- error = get_ifindex(netdev_, &ifindex);
- if (!error) {
- error = get_stats_via_netlink(ifindex, stats);
- }
+ if (error) {
+ VLOG_WARN_RL(&rl, "%s: linux-sys get stats failed %d",
+ netdev_get_name(netdev_), error);
+ }
+ return error;
+
+}
+
+/* Retrieves current device stats for 'netdev-linux'. */
+static int
+netdev_linux_get_stats(const struct netdev *netdev_,
+ struct netdev_stats *stats)
+{
+ struct netdev_dev_linux *netdev_dev =
+ netdev_dev_linux_cast(netdev_get_dev(netdev_));
+ struct netdev_stats dev_stats;
+ int error;
+
+ get_stats_via_vport(netdev_, stats);
+
+ error = netdev_linux_sys_get_stats(netdev_, &dev_stats);
+
+ if (error) {
+ if (!netdev_dev->have_vport_stats) {
+ return error;
} else {
- error = get_stats_via_proc(netdev_get_name(netdev_), stats);
+ return 0;
+ }
+ }
+
+ if (!netdev_dev->have_vport_stats) {
+ /* stats not available from OVS then use ioctl stats. */
+ *stats = dev_stats;
+ } else {
+ stats->rx_errors += dev_stats.rx_errors;
+ stats->tx_errors += dev_stats.tx_errors;
+ stats->rx_dropped += dev_stats.rx_dropped;
+ stats->tx_dropped += dev_stats.tx_dropped;
+ stats->multicast += dev_stats.multicast;
+ stats->collisions += dev_stats.collisions;
+ stats->rx_length_errors += dev_stats.rx_length_errors;
+ stats->rx_over_errors += dev_stats.rx_over_errors;
+ stats->rx_crc_errors += dev_stats.rx_crc_errors;
+ stats->rx_frame_errors += dev_stats.rx_frame_errors;
+ stats->rx_fifo_errors += dev_stats.rx_fifo_errors;
+ stats->rx_missed_errors += dev_stats.rx_missed_errors;
+ stats->tx_aborted_errors += dev_stats.tx_aborted_errors;
+ stats->tx_carrier_errors += dev_stats.tx_carrier_errors;
+ stats->tx_fifo_errors += dev_stats.tx_fifo_errors;
+ stats->tx_heartbeat_errors += dev_stats.tx_heartbeat_errors;
+ stats->tx_window_errors += dev_stats.tx_window_errors;
+ }
+ return 0;
+}
+
+/* Retrieves current device stats for 'netdev-tap' netdev or
+ * netdev-internal. */
+static int
+netdev_pseudo_get_stats(const struct netdev *netdev_,
+ struct netdev_stats *stats)
+{
+ struct netdev_dev_linux *netdev_dev =
+ netdev_dev_linux_cast(netdev_get_dev(netdev_));
+ struct netdev_stats dev_stats;
+ int error;
+
+ get_stats_via_vport(netdev_, stats);
+
+ error = netdev_linux_sys_get_stats(netdev_, &dev_stats);
+ if (error) {
+ if (!netdev_dev->have_vport_stats) {
+ 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. */
- netdev_linux_update_is_pseudo(netdev_dev);
- if (!error && !netdev_dev->have_vport_stats &&
- (netdev_dev->is_internal || netdev_dev->is_tap)) {
+ if (!netdev_dev->have_vport_stats) {
+ *stats = dev_stats;
swap_uint64(&stats->rx_packets, &stats->tx_packets);
swap_uint64(&stats->rx_bytes, &stats->tx_bytes);
swap_uint64(&stats->rx_errors, &stats->tx_errors);
stats->tx_fifo_errors = 0;
stats->tx_heartbeat_errors = 0;
stats->tx_window_errors = 0;
- }
+ } else {
+ stats->rx_dropped += dev_stats.tx_dropped;
+ stats->tx_dropped += dev_stats.rx_dropped;
- return error;
+ stats->rx_errors += dev_stats.tx_errors;
+ stats->tx_errors += dev_stats.rx_errors;
+
+ stats->multicast += dev_stats.multicast;
+ stats->collisions += dev_stats.collisions;
+ }
+ return 0;
}
/* Stores the features supported by 'netdev' into each of '*current',
return netdev_dev_linux_cast(netdev_get_dev(netdev))->change_seq;
}
-#define NETDEV_LINUX_CLASS(NAME, CREATE, ENUMERATE, SET_STATS) \
+#define NETDEV_LINUX_CLASS(NAME, CREATE, ENUMERATE, GET_STATS, SET_STATS) \
{ \
NAME, \
\
netdev_linux_get_ifindex, \
netdev_linux_get_carrier, \
netdev_linux_set_miimon_interval, \
- netdev_linux_get_stats, \
+ GET_STATS, \
SET_STATS, \
\
netdev_linux_get_features, \
"system",
netdev_linux_create,
netdev_linux_enumerate,
+ netdev_linux_get_stats,
NULL); /* set_stats */
const struct netdev_class netdev_tap_class =
"tap",
netdev_linux_create_tap,
NULL, /* enumerate */
+ netdev_pseudo_get_stats,
NULL); /* set_stats */
const struct netdev_class netdev_internal_class =
"internal",
netdev_linux_create,
NULL, /* enumerate */
+ netdev_pseudo_get_stats,
netdev_vport_set_stats);
\f
/* HTB traffic control class. */
return tc_bytes_to_ticks(Bps, MAX(burst_bytes, min_burst));
}
\f
-/* Public utility functions. */
-
-#define COPY_NETDEV_STATS \
- dst->rx_packets = src->rx_packets; \
- dst->tx_packets = src->tx_packets; \
- dst->rx_bytes = src->rx_bytes; \
- dst->tx_bytes = src->tx_bytes; \
- dst->rx_errors = src->rx_errors; \
- dst->tx_errors = src->tx_errors; \
- dst->rx_dropped = src->rx_dropped; \
- dst->tx_dropped = src->tx_dropped; \
- dst->multicast = src->multicast; \
- dst->collisions = src->collisions; \
- dst->rx_length_errors = src->rx_length_errors; \
- dst->rx_over_errors = src->rx_over_errors; \
- dst->rx_crc_errors = src->rx_crc_errors; \
- dst->rx_frame_errors = src->rx_frame_errors; \
- dst->rx_fifo_errors = src->rx_fifo_errors; \
- dst->rx_missed_errors = src->rx_missed_errors; \
- dst->tx_aborted_errors = src->tx_aborted_errors; \
- dst->tx_carrier_errors = src->tx_carrier_errors; \
- dst->tx_fifo_errors = src->tx_fifo_errors; \
- dst->tx_heartbeat_errors = src->tx_heartbeat_errors; \
- dst->tx_window_errors = src->tx_window_errors
-
/* Copies 'src' into 'dst', performing format conversion in the process. */
-void
+static void
netdev_stats_from_rtnl_link_stats(struct netdev_stats *dst,
const struct rtnl_link_stats *src)
{
- COPY_NETDEV_STATS;
-}
-
-/* Copies 'src' into 'dst', performing format conversion in the process. */
-void
-netdev_stats_from_rtnl_link_stats64(struct netdev_stats *dst,
- const struct rtnl_link_stats64 *src)
-{
- COPY_NETDEV_STATS;
+ dst->rx_packets = src->rx_packets;
+ dst->tx_packets = src->tx_packets;
+ dst->rx_bytes = src->rx_bytes;
+ dst->tx_bytes = src->tx_bytes;
+ dst->rx_errors = src->rx_errors;
+ dst->tx_errors = src->tx_errors;
+ dst->rx_dropped = src->rx_dropped;
+ dst->tx_dropped = src->tx_dropped;
+ dst->multicast = src->multicast;
+ dst->collisions = src->collisions;
+ dst->rx_length_errors = src->rx_length_errors;
+ dst->rx_over_errors = src->rx_over_errors;
+ dst->rx_crc_errors = src->rx_crc_errors;
+ dst->rx_frame_errors = src->rx_frame_errors;
+ dst->rx_fifo_errors = src->rx_fifo_errors;
+ dst->rx_missed_errors = src->rx_missed_errors;
+ dst->tx_aborted_errors = src->tx_aborted_errors;
+ dst->tx_carrier_errors = src->tx_carrier_errors;
+ dst->tx_fifo_errors = src->tx_fifo_errors;
+ dst->tx_heartbeat_errors = src->tx_heartbeat_errors;
+ dst->tx_window_errors = src->tx_window_errors;
}
-/* Copies 'src' into 'dst', performing format conversion in the process. */
-void
-netdev_stats_to_rtnl_link_stats64(struct rtnl_link_stats64 *dst,
- const struct netdev_stats *src)
-{
- COPY_NETDEV_STATS;
- dst->rx_compressed = 0;
- dst->tx_compressed = 0;
-}
\f
/* Utility functions. */
#include <stdint.h>
#include <stdbool.h>
+#include "openvswitch/datapath-protocol.h"
/* These functions are Linux specific, so they should be used directly only by
* Linux-specific code. */
struct netdev;
struct netdev_stats;
struct rtnl_link_stats;
-struct rtnl_link_stats64;
-
-void netdev_stats_from_rtnl_link_stats(struct netdev_stats *dst,
- const struct rtnl_link_stats *src);
-void netdev_stats_from_rtnl_link_stats64(struct netdev_stats *dst,
- const struct rtnl_link_stats64 *src);
-void netdev_stats_to_rtnl_link_stats64(struct rtnl_link_stats64 *dst,
- const struct netdev_stats *src);
int netdev_linux_ethtool_set_flag(struct netdev *netdev, uint32_t flag,
const char *flag_name, bool enable);
return error;
}
+#define COPY_OVS_STATS \
+ dst->rx_packets = src->rx_packets; \
+ dst->tx_packets = src->tx_packets; \
+ dst->rx_bytes = src->rx_bytes; \
+ dst->tx_bytes = src->tx_bytes; \
+ dst->rx_errors = src->rx_errors; \
+ dst->tx_errors = src->tx_errors; \
+ dst->rx_dropped = src->rx_dropped; \
+ dst->tx_dropped = src->tx_dropped;
+
+/* Copies 'src' into 'dst', performing format conversion in the process. */
+static void
+netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst,
+ const struct ovs_vport_stats *src)
+{
+ COPY_OVS_STATS
+ dst->multicast = 0;
+ dst->collisions = 0;
+ dst->rx_length_errors = 0;
+ dst->rx_over_errors = 0;
+ dst->rx_crc_errors = 0;
+ dst->rx_frame_errors = 0;
+ dst->rx_fifo_errors = 0;
+ dst->rx_missed_errors = 0;
+ dst->tx_aborted_errors = 0;
+ dst->tx_carrier_errors = 0;
+ dst->tx_fifo_errors = 0;
+ dst->tx_heartbeat_errors = 0;
+ dst->tx_window_errors = 0;
+}
+
+/* Copies 'src' into 'dst', performing format conversion in the process. */
+static void
+netdev_stats_to_ovs_vport_stats(struct ovs_vport_stats *dst,
+ const struct netdev_stats *src)
+{
+ COPY_OVS_STATS
+}
+
int
netdev_vport_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
{
return EOPNOTSUPP;
}
- netdev_stats_from_rtnl_link_stats64(stats, reply.stats);
+ netdev_stats_from_ovs_vport_stats(stats, reply.stats);
ofpbuf_delete(buf);
int
netdev_vport_set_stats(struct netdev *netdev, const struct netdev_stats *stats)
{
- struct rtnl_link_stats64 rtnl_stats;
+ struct ovs_vport_stats rtnl_stats;
struct dpif_linux_vport vport;
int err;
- netdev_stats_to_rtnl_link_stats64(&rtnl_stats, stats);
+ netdev_stats_to_ovs_vport_stats(&rtnl_stats, stats);
dpif_linux_vport_init(&vport);
vport.cmd = OVS_VPORT_CMD_SET;
[ndebug=false])
AM_CONDITIONAL([NDEBUG], [test x$ndebug = xtrue])])
-dnl Checks for struct rtnl_link_stats64.
-dnl
-dnl (OVS checks for this structure in both kernel and userspace headers. This
-dnl is not redundant, because the kernel and userspace builds have completely
-dnl different include paths. It is possible for the kernel to have this
-dnl structure but not userspace, and vice versa.)
-AC_DEFUN([OVS_CHECK_RTNL_LINK_STATS64],
- [AC_REQUIRE([OVS_CHECK_NETLINK])
- if test $HAVE_NETLINK = yes; then
- AC_CHECK_MEMBER(
- [struct rtnl_link_stats64.tx_packets],
- [AC_DEFINE([HAVE_RTNL_LINK_STATS64], [1],
- [Define to 1 if <linux/if_link.h> defines
- struct rtnl_link_stats64.])],
- [], [#include <sys/socket.h> /* Provides sa_family_t. */
-#include <linux/if_link.h>
-])
- fi])
-
dnl Checks for Netlink support.
AC_DEFUN([OVS_CHECK_NETLINK],
[AC_CHECK_HEADER([linux/netlink.h],
struct dpif_port_dump dump;
struct dpif_port dpif_port;
struct ovs_dp_stats stats;
+ struct netdev *netdev;
printf("%s:\n", dpif_name(dpif));
if (!dpif_get_dp_stats(dpif, &stats)) {
printf("\tport %u: %s", dpif_port.port_no, dpif_port.name);
if (strcmp(dpif_port.type, "system")) {
- struct netdev *netdev;
int error;
printf (" (%s", dpif_port.type);
putchar('\n');
if (print_statistics) {
- const struct netdev_stats *s = &dpif_port.stats;
+ struct netdev_stats s;
+ int error;
+
+ error = netdev_open(dpif_port.name, dpif_port.type, &netdev);
+ if (error) {
+ printf(", open failed (%s)", strerror(error));
+ continue;
+ }
+ error = netdev_get_stats(netdev, &s);
+ if (error) {
+ printf(", could not retrieve stats (%s)", strerror(error));
+ continue;
+ }
- print_stat("\t\tRX packets:", s->rx_packets);
- print_stat(" errors:", s->rx_errors);
- print_stat(" dropped:", s->rx_dropped);
- print_stat(" overruns:", s->rx_over_errors);
- print_stat(" frame:", s->rx_frame_errors);
+ netdev_close(netdev);
+ print_stat("\t\tRX packets:", s.rx_packets);
+ print_stat(" errors:", s.rx_errors);
+ print_stat(" dropped:", s.rx_dropped);
+ print_stat(" overruns:", s.rx_over_errors);
+ print_stat(" frame:", s.rx_frame_errors);
printf("\n");
- print_stat("\t\tTX packets:", s->tx_packets);
- print_stat(" errors:", s->tx_errors);
- print_stat(" dropped:", s->tx_dropped);
- print_stat(" aborted:", s->tx_aborted_errors);
- print_stat(" carrier:", s->tx_carrier_errors);
+ print_stat("\t\tTX packets:", s.tx_packets);
+ print_stat(" errors:", s.tx_errors);
+ print_stat(" dropped:", s.tx_dropped);
+ print_stat(" aborted:", s.tx_aborted_errors);
+ print_stat(" carrier:", s.tx_carrier_errors);
printf("\n");
- print_stat("\t\tcollisions:", s->collisions);
+ print_stat("\t\tcollisions:", s.collisions);
printf("\n");
- print_stat("\t\tRX bytes:", s->rx_bytes);
- print_human_size(s->rx_bytes);
- print_stat(" TX bytes:", s->tx_bytes);
- print_human_size(s->tx_bytes);
+ print_stat("\t\tRX bytes:", s.rx_bytes);
+ print_human_size(s.rx_bytes);
+ print_stat(" TX bytes:", s.tx_bytes);
+ print_human_size(s.tx_bytes);
printf("\n");
}
}