summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormweglicx <michalx.weglicki@intel.com>2016-05-05 09:46:01 +0100
committerBen Pfaff <blp@ovn.org>2016-05-06 15:28:56 -0700
commitd6e3feb57c44e18580015d8e99dd751cff4f2c9e (patch)
tree2d243eed928b2b3fad094e9990f98713176adbc4
parent104aec4e0c57bc92a3c22cea9dff69f74adda861 (diff)
downloadopenvswitch-d6e3feb57c44e18580015d8e99dd751cff4f2c9e.tar.gz
Add support for extended netdev statistics based on RFC 2819.
Implementation of new statistics extension for DPDK ports: - Add new counters definition to netdev struct and open flow, based on RFC2819. - Initialize netdev statistics as "filtered out" before passing it to particular netdev implementation (because of that change, statistics which are not collected are reported as filtered out, and some unit tests were modified in this respect). - New statistics are retrieved using experimenter code and are printed as a result to ofctl dump-ports. - New counters are available for OpenFlow 1.4+. - Add new vendor id: INTEL_VENDOR_ID. - New statistics are printed to output via ofctl only if those are present in reply message. - Add new file header: include/openflow/intel-ext.h which contains new statistics definition. - Extended statistics are implemented only for dpdk-physical and dpdk-vhost port types. - Dpdk-physical implementation uses xstats to collect statistics. - Dpdk-vhost implements only part of statistics (RX packet sized based counters). Signed-off-by: Michal Weglicki <michalx.weglicki@intel.com> [blp@ovn.org made software devices more consistent] Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--include/openflow/automake.mk1
-rw-r--r--include/openflow/intel-ext.h73
-rw-r--r--include/openflow/openflow-common.h1
-rw-r--r--include/openvswitch/netdev.h27
-rw-r--r--lib/netdev-dpdk.c182
-rw-r--r--lib/netdev-dummy.c6
-rw-r--r--lib/netdev-linux.c3
-rw-r--r--lib/netdev-vport.c6
-rw-r--r--lib/netdev.c5
-rw-r--r--lib/ofp-print.c75
-rw-r--r--lib/ofp-util.c139
-rw-r--r--tests/learn.at24
-rw-r--r--tests/ofproto-dpif.at68
-rw-r--r--tests/ofproto.at12
-rw-r--r--tests/tunnel-push-pop-ipv6.at6
-rw-r--r--tests/tunnel-push-pop.at6
-rw-r--r--vswitchd/bridge.c45
17 files changed, 563 insertions, 116 deletions
diff --git a/include/openflow/automake.mk b/include/openflow/automake.mk
index d7dac9132..18cc64989 100644
--- a/include/openflow/automake.mk
+++ b/include/openflow/automake.mk
@@ -1,5 +1,6 @@
openflowincludedir = $(includedir)/openflow
openflowinclude_HEADERS = \
+ include/openflow/intel-ext.h \
include/openflow/netronome-ext.h \
include/openflow/nicira-ext.h \
include/openflow/openflow-1.0.h \
diff --git a/include/openflow/intel-ext.h b/include/openflow/intel-ext.h
new file mode 100644
index 000000000..974e63e0d
--- /dev/null
+++ b/include/openflow/intel-ext.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OPENFLOW_INTEL_EXT_H
+#define OPENFLOW_INTEL_EXT_H
+
+/* This file presents Intel vendor extension. It is not anyhow
+ * standardized, so all those definitions are not part of
+ * official openflow headers (openflow.h). Nevertheless below
+ * features introduces real value so it could be suitable for
+ * standardization */
+
+/* Intel extended statistics type */
+
+enum intel_port_stats_subtype {
+ INTEL_PORT_STATS_RFC2819 = 1,
+};
+
+#define INTEL_PORT_STATS_RFC2819_SIZE 184
+
+/* Struct implements custom property type based on
+ * 'ofp_prop_experimenter'. */
+struct intel_port_stats_rfc2819 {
+ ovs_be16 type; /* OFPPSPT14_EXPERIMENTER. */
+ ovs_be16 length; /* Length in bytes of this property excluding
+ * trailing padding. */
+ ovs_be32 experimenter; /* INTEL_VENDOR_ID. */
+ ovs_be32 exp_type; /* INTEL_PORT_STATS_*. */
+
+ uint8_t pad[4];
+
+ ovs_be64 rx_1_to_64_packets;
+ ovs_be64 rx_65_to_127_packets;
+ ovs_be64 rx_128_to_255_packets;
+ ovs_be64 rx_256_to_511_packets;
+ ovs_be64 rx_512_to_1023_packets;
+ ovs_be64 rx_1024_to_1522_packets;
+ ovs_be64 rx_1523_to_max_packets;
+
+ ovs_be64 tx_1_to_64_packets;
+ ovs_be64 tx_65_to_127_packets;
+ ovs_be64 tx_128_to_255_packets;
+ ovs_be64 tx_256_to_511_packets;
+ ovs_be64 tx_512_to_1023_packets;
+ ovs_be64 tx_1024_to_1522_packets;
+ ovs_be64 tx_1523_to_max_packets;
+
+ ovs_be64 tx_multicast_packets;
+ ovs_be64 rx_broadcast_packets;
+ ovs_be64 tx_broadcast_packets;
+ ovs_be64 rx_undersized_errors;
+ ovs_be64 rx_oversize_errors;
+ ovs_be64 rx_fragmented_errors;
+ ovs_be64 rx_jabber_errors;
+
+};
+OFP_ASSERT(sizeof (struct intel_port_stats_rfc2819) ==
+ INTEL_PORT_STATS_RFC2819_SIZE);
+
+#endif /* openflow/intel-ext.h */
diff --git a/include/openflow/openflow-common.h b/include/openflow/openflow-common.h
index 089ff1889..7b619a997 100644
--- a/include/openflow/openflow-common.h
+++ b/include/openflow/openflow-common.h
@@ -108,6 +108,7 @@ enum ofp_version {
#define NTR_COMPAT_VENDOR_ID 0x00001540 /* Incorrect value used in v2.4. */
#define NX_VENDOR_ID 0x00002320 /* Nicira. */
#define ONF_VENDOR_ID 0x4f4e4600 /* Open Networking Foundation. */
+#define INTEL_VENDOR_ID 0x0000AA01 /* Intel */
#define OFP_MAX_TABLE_NAME_LEN 32
#define OFP_MAX_PORT_NAME_LEN 16
diff --git a/include/openvswitch/netdev.h b/include/openvswitch/netdev.h
index fa5e8f289..88a25dd25 100644
--- a/include/openvswitch/netdev.h
+++ b/include/openvswitch/netdev.h
@@ -52,6 +52,33 @@ struct netdev_stats {
uint64_t tx_fifo_errors;
uint64_t tx_heartbeat_errors;
uint64_t tx_window_errors;
+
+ /* Extended statistics based on RFC2819. */
+ uint64_t rx_1_to_64_packets;
+ uint64_t rx_65_to_127_packets;
+ uint64_t rx_128_to_255_packets;
+ uint64_t rx_256_to_511_packets;
+ uint64_t rx_512_to_1023_packets;
+ uint64_t rx_1024_to_1522_packets;
+ uint64_t rx_1523_to_max_packets;
+
+ uint64_t tx_1_to_64_packets;
+ uint64_t tx_65_to_127_packets;
+ uint64_t tx_128_to_255_packets;
+ uint64_t tx_256_to_511_packets;
+ uint64_t tx_512_to_1023_packets;
+ uint64_t tx_1024_to_1522_packets;
+ uint64_t tx_1523_to_max_packets;
+
+ uint64_t tx_multicast_packets;
+
+ uint64_t rx_broadcast_packets;
+ uint64_t tx_broadcast_packets;
+
+ uint64_t rx_undersized_errors;
+ uint64_t rx_oversize_errors;
+ uint64_t rx_fragmented_errors;
+ uint64_t rx_jabber_errors;
};
/* Features. */
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index b488c601a..804086676 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -99,6 +99,33 @@ BUILD_ASSERT_DECL(MAX_NB_MBUF % ROUND_DOWN_POW2(MAX_NB_MBUF/MIN_NB_MBUF) == 0);
BUILD_ASSERT_DECL((MAX_NB_MBUF / ROUND_DOWN_POW2(MAX_NB_MBUF/MIN_NB_MBUF))
% MP_CACHE_SZ == 0);
+/*
+ * DPDK XSTATS Counter names definition
+ */
+#define XSTAT_RX_64_PACKETS "rx_size_64_packets"
+#define XSTAT_RX_65_TO_127_PACKETS "rx_size_65_to_127_packets"
+#define XSTAT_RX_128_TO_255_PACKETS "rx_size_128_to_255_packets"
+#define XSTAT_RX_256_TO_511_PACKETS "rx_size_256_to_511_packets"
+#define XSTAT_RX_512_TO_1023_PACKETS "rx_size_512_to_1023_packets"
+#define XSTAT_RX_1024_TO_1522_PACKETS "rx_size_1024_to_1522_packets"
+#define XSTAT_RX_1523_TO_MAX_PACKETS "rx_size_1523_to_max_packets"
+
+#define XSTAT_TX_64_PACKETS "tx_size_64_packets"
+#define XSTAT_TX_65_TO_127_PACKETS "tx_size_65_to_127_packets"
+#define XSTAT_TX_128_TO_255_PACKETS "tx_size_128_to_255_packets"
+#define XSTAT_TX_256_TO_511_PACKETS "tx_size_256_to_511_packets"
+#define XSTAT_TX_512_TO_1023_PACKETS "tx_size_512_to_1023_packets"
+#define XSTAT_TX_1024_TO_1522_PACKETS "tx_size_1024_to_1522_packets"
+#define XSTAT_TX_1523_TO_MAX_PACKETS "tx_size_1523_to_max_packets"
+
+#define XSTAT_TX_MULTICAST_PACKETS "tx_multicast_packets"
+#define XSTAT_RX_BROADCAST_PACKETS "rx_broadcast_packets"
+#define XSTAT_TX_BROADCAST_PACKETS "tx_broadcast_packets"
+#define XSTAT_RX_UNDERSIZED_ERRORS "rx_undersized_errors"
+#define XSTAT_RX_OVERSIZE_ERRORS "rx_oversize_errors"
+#define XSTAT_RX_FRAGMENTED_ERRORS "rx_fragmented_errors"
+#define XSTAT_RX_JABBER_ERRORS "rx_jabber_errors"
+
#define SOCKET0 0
#define NIC_PORT_RX_Q_SIZE 2048 /* Size of Physical NIC RX Queue, Max (n+32<=4096)*/
@@ -1143,17 +1170,45 @@ is_vhost_running(struct virtio_net *virtio_dev)
}
static inline void
+netdev_dpdk_vhost_update_rx_size_counters(struct netdev_stats *stats,
+ unsigned int packet_size)
+{
+ /* Hard-coded search for the size bucket. */
+ if (packet_size < 256) {
+ if (packet_size >= 128) {
+ stats->rx_128_to_255_packets++;
+ } else if (packet_size <= 64) {
+ stats->rx_1_to_64_packets++;
+ } else {
+ stats->rx_65_to_127_packets++;
+ }
+ } else {
+ if (packet_size >= 1523) {
+ stats->rx_1523_to_max_packets++;
+ } else if (packet_size >= 1024) {
+ stats->rx_1024_to_1522_packets++;
+ } else if (packet_size < 512) {
+ stats->rx_256_to_511_packets++;
+ } else {
+ stats->rx_512_to_1023_packets++;
+ }
+ }
+}
+
+static inline void
netdev_dpdk_vhost_update_rx_counters(struct netdev_stats *stats,
struct dp_packet **packets, int count)
{
int i;
+ unsigned int packet_size;
struct dp_packet *packet;
stats->rx_packets += count;
for (i = 0; i < count; i++) {
packet = packets[i];
+ packet_size = dp_packet_size(packet);
- if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) {
+ if (OVS_UNLIKELY(packet_size < ETH_HEADER_LEN)) {
/* This only protects the following multicast counting from
* too short packets, but it does not stop the packet from
* further processing. */
@@ -1162,12 +1217,14 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_stats *stats,
continue;
}
+ netdev_dpdk_vhost_update_rx_size_counters(stats, packet_size);
+
struct eth_header *eh = (struct eth_header *) dp_packet_data(packet);
if (OVS_UNLIKELY(eth_addr_is_multicast(eh->eth_dst))) {
stats->multicast++;
}
- stats->rx_bytes += dp_packet_size(packet);
+ stats->rx_bytes += packet_size;
}
}
@@ -1659,21 +1716,6 @@ netdev_dpdk_vhost_get_stats(const struct netdev *netdev,
struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
ovs_mutex_lock(&dev->mutex);
- memset(stats, 0, sizeof(*stats));
- /* Unsupported Stats */
- stats->collisions = UINT64_MAX;
- stats->rx_crc_errors = UINT64_MAX;
- stats->rx_fifo_errors = UINT64_MAX;
- stats->rx_frame_errors = UINT64_MAX;
- stats->rx_missed_errors = UINT64_MAX;
- stats->rx_over_errors = UINT64_MAX;
- stats->tx_aborted_errors = UINT64_MAX;
- stats->tx_carrier_errors = UINT64_MAX;
- stats->tx_errors = UINT64_MAX;
- stats->tx_fifo_errors = UINT64_MAX;
- stats->tx_heartbeat_errors = UINT64_MAX;
- stats->tx_window_errors = UINT64_MAX;
- stats->rx_dropped += UINT64_MAX;
rte_spinlock_lock(&dev->stats_lock);
/* Supported Stats */
@@ -1685,6 +1727,15 @@ netdev_dpdk_vhost_get_stats(const struct netdev *netdev,
stats->tx_bytes = dev->stats.tx_bytes;
stats->rx_errors = dev->stats.rx_errors;
stats->rx_length_errors = dev->stats.rx_length_errors;
+
+ stats->rx_1_to_64_packets = dev->stats.rx_1_to_64_packets;
+ stats->rx_65_to_127_packets = dev->stats.rx_65_to_127_packets;
+ stats->rx_128_to_255_packets = dev->stats.rx_128_to_255_packets;
+ stats->rx_256_to_511_packets = dev->stats.rx_256_to_511_packets;
+ stats->rx_512_to_1023_packets = dev->stats.rx_512_to_1023_packets;
+ stats->rx_1024_to_1522_packets = dev->stats.rx_1024_to_1522_packets;
+ stats->rx_1523_to_max_packets = dev->stats.rx_1523_to_max_packets;
+
rte_spinlock_unlock(&dev->stats_lock);
ovs_mutex_unlock(&dev->mutex);
@@ -1692,6 +1743,67 @@ netdev_dpdk_vhost_get_stats(const struct netdev *netdev,
return 0;
}
+static void
+netdev_dpdk_convert_xstats(struct netdev_stats *stats,
+ const struct rte_eth_xstats *xstats,
+ const unsigned int size)
+{
+ /* XXX Current implementation is simple search through an array
+ * to find hardcoded counter names. In future DPDK release (TBD)
+ * XSTATS API will change so each counter will be represented by
+ * unique ID instead of String. */
+
+ for (unsigned int i = 0; i < size; i++) {
+ if (strcmp(XSTAT_RX_64_PACKETS, xstats[i].name) == 0) {
+ stats->rx_1_to_64_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_65_TO_127_PACKETS, xstats[i].name) == 0) {
+ stats->rx_65_to_127_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_128_TO_255_PACKETS, xstats[i].name) == 0) {
+ stats->rx_128_to_255_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_256_TO_511_PACKETS, xstats[i].name) == 0) {
+ stats->rx_256_to_511_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_512_TO_1023_PACKETS,
+ xstats[i].name) == 0) {
+ stats->rx_512_to_1023_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_1024_TO_1522_PACKETS,
+ xstats[i].name) == 0) {
+ stats->rx_1024_to_1522_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_1523_TO_MAX_PACKETS,
+ xstats[i].name) == 0) {
+ stats->rx_1523_to_max_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_64_PACKETS, xstats[i].name) == 0) {
+ stats->tx_1_to_64_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_65_TO_127_PACKETS, xstats[i].name) == 0) {
+ stats->tx_65_to_127_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_128_TO_255_PACKETS, xstats[i].name) == 0) {
+ stats->tx_128_to_255_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_256_TO_511_PACKETS, xstats[i].name) == 0) {
+ stats->tx_256_to_511_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_512_TO_1023_PACKETS,
+ xstats[i].name) == 0) {
+ stats->tx_512_to_1023_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_1024_TO_1522_PACKETS,
+ xstats[i].name) == 0) {
+ stats->tx_1024_to_1522_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_1523_TO_MAX_PACKETS,
+ xstats[i].name) == 0) {
+ stats->tx_1523_to_max_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_MULTICAST_PACKETS, xstats[i].name) == 0) {
+ stats->tx_multicast_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_BROADCAST_PACKETS, xstats[i].name) == 0) {
+ stats->rx_broadcast_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_TX_BROADCAST_PACKETS, xstats[i].name) == 0) {
+ stats->tx_broadcast_packets = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_UNDERSIZED_ERRORS, xstats[i].name) == 0) {
+ stats->rx_undersized_errors = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_FRAGMENTED_ERRORS, xstats[i].name) == 0) {
+ stats->rx_fragmented_errors = xstats[i].value;
+ } else if (strcmp(XSTAT_RX_JABBER_ERRORS, xstats[i].name) == 0) {
+ stats->rx_jabber_errors = xstats[i].value;
+ }
+ }
+}
+
static int
netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
{
@@ -1701,9 +1813,28 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
netdev_dpdk_get_carrier(netdev, &gg);
ovs_mutex_lock(&dev->mutex);
- rte_eth_stats_get(dev->port_id, &rte_stats);
- memset(stats, 0, sizeof(*stats));
+ struct rte_eth_xstats *rte_xstats;
+ int rte_xstats_len, rte_xstats_ret;
+
+ if (rte_eth_stats_get(dev->port_id, &rte_stats)) {
+ VLOG_ERR("Can't get ETH statistics for port: %i.", dev->port_id);
+ return EPROTO;
+ }
+
+ rte_xstats_len = rte_eth_xstats_get(dev->port_id, NULL, 0);
+ if (rte_xstats_len > 0) {
+ rte_xstats = dpdk_rte_mzalloc(sizeof(*rte_xstats) * rte_xstats_len);
+ memset(rte_xstats, 0xff, sizeof(*rte_xstats) * rte_xstats_len);
+ rte_xstats_ret = rte_eth_xstats_get(dev->port_id, rte_xstats,
+ rte_xstats_len);
+ if (rte_xstats_ret > 0 && rte_xstats_ret <= rte_xstats_len) {
+ netdev_dpdk_convert_xstats(stats, rte_xstats, rte_xstats_ret);
+ }
+ rte_free(rte_xstats);
+ } else {
+ VLOG_WARN("Can't get XSTATS counters for port: %i.", dev->port_id);
+ }
stats->rx_packets = rte_stats.ipackets;
stats->tx_packets = rte_stats.opackets;
@@ -1721,21 +1852,8 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
/* These are the available DPDK counters for packets not received due to
* local resource constraints in DPDK and NIC respectively. */
stats->rx_dropped = rte_stats.rx_nombuf + rte_stats.imissed;
- stats->collisions = UINT64_MAX;
-
- stats->rx_length_errors = UINT64_MAX;
- stats->rx_over_errors = UINT64_MAX;
- stats->rx_crc_errors = UINT64_MAX;
- stats->rx_frame_errors = UINT64_MAX;
- stats->rx_fifo_errors = UINT64_MAX;
stats->rx_missed_errors = rte_stats.imissed;
- stats->tx_aborted_errors = UINT64_MAX;
- stats->tx_carrier_errors = UINT64_MAX;
- stats->tx_fifo_errors = UINT64_MAX;
- stats->tx_heartbeat_errors = UINT64_MAX;
- stats->tx_window_errors = UINT64_MAX;
-
ovs_mutex_unlock(&dev->mutex);
return 0;
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 5acb4e194..7f0ee764b 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -1075,7 +1075,11 @@ netdev_dummy_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
struct netdev_dummy *dev = netdev_dummy_cast(netdev);
ovs_mutex_lock(&dev->mutex);
- *stats = dev->stats;
+ /* Passing only collected counters */
+ stats->tx_packets = dev->stats.tx_packets;
+ stats->tx_bytes = dev->stats.tx_bytes;
+ stats->rx_packets = dev->stats.rx_packets;
+ stats->rx_bytes = dev->stats.rx_bytes;
ovs_mutex_unlock(&dev->mutex);
return 0;
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 2953964b6..5db18877d 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -5361,6 +5361,9 @@ get_stats_via_netlink(const struct netdev *netdev_, struct netdev_stats *stats)
struct ofpbuf *reply;
int error;
+ /* Filtering all counters by default */
+ memset(stats, 0xFF, sizeof(struct netdev_stats));
+
ofpbuf_init(&request, 0);
nl_msg_put_nlmsghdr(&request,
sizeof(struct ifinfomsg) + NL_ATTR_SIZE(IFNAMSIZ),
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index e398562c6..678c3f9cc 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -851,7 +851,11 @@ get_stats(const struct netdev *netdev, struct netdev_stats *stats)
struct netdev_vport *dev = netdev_vport_cast(netdev);
ovs_mutex_lock(&dev->mutex);
- *stats = dev->stats;
+ /* Passing only collected counters */
+ stats->tx_packets = dev->stats.tx_packets;
+ stats->tx_bytes = dev->stats.tx_bytes;
+ stats->rx_packets = dev->stats.rx_packets;
+ stats->rx_bytes = dev->stats.rx_bytes;
ovs_mutex_unlock(&dev->mutex);
return 0;
diff --git a/lib/netdev.c b/lib/netdev.c
index 4fc06ce3b..3aacd9cee 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -1331,11 +1331,16 @@ netdev_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
{
int error;
+ /* Statistics are initialized before passing it to particular device
+ * implementation so all values are filtered out by default. */
+ memset(stats, 0xFF, sizeof *stats);
+
COVERAGE_INC(netdev_get_stats);
error = (netdev->netdev_class->get_stats
? netdev->netdev_class->get_stats(netdev, stats)
: EOPNOTSUPP);
if (error) {
+ /* In case of error all statistics are filtered out */
memset(stats, 0xff, sizeof *stats);
}
return error;
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 69f90f301..b21d76f53 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -1685,6 +1685,14 @@ print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more)
}
static void
+print_port_stat_cond(struct ds *string, const char *leader, uint64_t stat)
+{
+ if (stat != UINT64_MAX) {
+ ds_put_format(string, "%s%"PRIu64", ", leader, stat);
+ }
+}
+
+static void
ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh)
{
ofp_port_t ofp10_port;
@@ -1749,6 +1757,73 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
ofp_print_duration(string, ps.duration_sec, ps.duration_nsec);
ds_put_char(string, '\n');
}
+ struct ds string_ext_stats = DS_EMPTY_INITIALIZER;
+
+ ds_init(&string_ext_stats);
+
+ print_port_stat_cond(&string_ext_stats, "1_to_64_packets=",
+ ps.stats.rx_1_to_64_packets);
+ print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
+ ps.stats.rx_65_to_127_packets);
+ print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
+ ps.stats.rx_128_to_255_packets);
+ print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
+ ps.stats.rx_256_to_511_packets);
+ print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
+ ps.stats.rx_512_to_1023_packets);
+ print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
+ ps.stats.rx_1024_to_1522_packets);
+ print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
+ ps.stats.rx_1523_to_max_packets);
+ print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
+ ps.stats.rx_broadcast_packets);
+ print_port_stat_cond(&string_ext_stats, "undersized_errors=",
+ ps.stats.rx_undersized_errors);
+ print_port_stat_cond(&string_ext_stats, "oversize_errors=",
+ ps.stats.rx_oversize_errors);
+ print_port_stat_cond(&string_ext_stats, "rx_fragmented_errors=",
+ ps.stats.rx_fragmented_errors);
+ print_port_stat_cond(&string_ext_stats, "rx_jabber_errors=",
+ ps.stats.rx_jabber_errors);
+
+ if (string_ext_stats.length != 0) {
+ /* If at least one statistics counter is reported: */
+ ds_put_cstr(string, " rx rfc2819 ");
+ ds_put_buffer(string, string_ext_stats.string,
+ string_ext_stats.length);
+ ds_put_cstr(string, "\n");
+ ds_destroy(&string_ext_stats);
+ }
+
+ ds_init(&string_ext_stats);
+
+ print_port_stat_cond(&string_ext_stats, "1_to_64_packets=",
+ ps.stats.tx_1_to_64_packets);
+ print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
+ ps.stats.tx_65_to_127_packets);
+ print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
+ ps.stats.tx_128_to_255_packets);
+ print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
+ ps.stats.tx_256_to_511_packets);
+ print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
+ ps.stats.tx_512_to_1023_packets);
+ print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
+ ps.stats.tx_1024_to_1522_packets);
+ print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
+ ps.stats.tx_1523_to_max_packets);
+ print_port_stat_cond(&string_ext_stats, "multicast_packets=",
+ ps.stats.tx_multicast_packets);
+ print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
+ ps.stats.tx_broadcast_packets);
+
+ if (string_ext_stats.length != 0) {
+ /* If at least one statistics counter is reported: */
+ ds_put_cstr(string, " tx rfc2819 ");
+ ds_put_buffer(string, string_ext_stats.string,
+ string_ext_stats.length);
+ ds_put_cstr(string, "\n");
+ ds_destroy(&string_ext_stats);
+ }
}
}
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index bb1535dfc..2c6fb1fea 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -43,6 +43,7 @@
#include "openvswitch/ofpbuf.h"
#include "openvswitch/type-props.h"
#include "openvswitch/vlog.h"
+#include "openflow/intel-ext.h"
#include "packets.h"
#include "pktbuf.h"
#include "random.h"
@@ -7513,13 +7514,16 @@ ofputil_append_ofp14_port_stats(const struct ofputil_port_stats *ops,
struct ovs_list *replies)
{
struct ofp14_port_stats_prop_ethernet *eth;
+ struct intel_port_stats_rfc2819 *stats_rfc2819;
struct ofp14_port_stats *ps14;
struct ofpbuf *reply;
- reply = ofpmp_reserve(replies, sizeof *ps14 + sizeof *eth);
+ reply = ofpmp_reserve(replies, sizeof *ps14 + sizeof *eth +
+ sizeof *stats_rfc2819);
ps14 = ofpbuf_put_uninit(reply, sizeof *ps14);
- ps14->length = htons(sizeof *ps14 + sizeof *eth);
+ ps14->length = htons(sizeof *ps14 + sizeof *eth +
+ sizeof *stats_rfc2819);
memset(ps14->pad, 0, sizeof ps14->pad);
ps14->port_no = ofputil_port_to_ofp11(ops->port_no);
ps14->duration_sec = htonl(ops->duration_sec);
@@ -7538,6 +7542,56 @@ ofputil_append_ofp14_port_stats(const struct ofputil_port_stats *ops,
eth->rx_over_err = htonll(ops->stats.rx_over_errors);
eth->rx_crc_err = htonll(ops->stats.rx_crc_errors);
eth->collisions = htonll(ops->stats.collisions);
+
+ uint64_t prop_type = OFPPROP_EXP(INTEL_VENDOR_ID,
+ INTEL_PORT_STATS_RFC2819);
+
+ stats_rfc2819 = ofpprop_put_zeros(reply, prop_type,
+ sizeof *stats_rfc2819);
+
+ memset(stats_rfc2819->pad, 0, sizeof stats_rfc2819->pad);
+ stats_rfc2819->rx_1_to_64_packets = htonll(ops->stats.rx_1_to_64_packets);
+ stats_rfc2819->rx_65_to_127_packets =
+ htonll(ops->stats.rx_65_to_127_packets);
+ stats_rfc2819->rx_128_to_255_packets =
+ htonll(ops->stats.rx_128_to_255_packets);
+ stats_rfc2819->rx_256_to_511_packets =
+ htonll(ops->stats.rx_256_to_511_packets);
+ stats_rfc2819->rx_512_to_1023_packets =
+ htonll(ops->stats.rx_512_to_1023_packets);
+ stats_rfc2819->rx_1024_to_1522_packets =
+ htonll(ops->stats.rx_1024_to_1522_packets);
+ stats_rfc2819->rx_1523_to_max_packets =
+ htonll(ops->stats.rx_1523_to_max_packets);
+
+ stats_rfc2819->tx_1_to_64_packets = htonll(ops->stats.tx_1_to_64_packets);
+ stats_rfc2819->tx_65_to_127_packets =
+ htonll(ops->stats.tx_65_to_127_packets);
+ stats_rfc2819->tx_128_to_255_packets =
+ htonll(ops->stats.tx_128_to_255_packets);
+ stats_rfc2819->tx_256_to_511_packets =
+ htonll(ops->stats.tx_256_to_511_packets);
+ stats_rfc2819->tx_512_to_1023_packets =
+ htonll(ops->stats.tx_512_to_1023_packets);
+ stats_rfc2819->tx_1024_to_1522_packets =
+ htonll(ops->stats.tx_1024_to_1522_packets);
+ stats_rfc2819->tx_1523_to_max_packets =
+ htonll(ops->stats.tx_1523_to_max_packets);
+
+ stats_rfc2819->tx_multicast_packets =
+ htonll(ops->stats.tx_multicast_packets);
+ stats_rfc2819->rx_broadcast_packets =
+ htonll(ops->stats.rx_broadcast_packets);
+ stats_rfc2819->tx_broadcast_packets =
+ htonll(ops->stats.tx_broadcast_packets);
+ stats_rfc2819->rx_undersized_errors =
+ htonll(ops->stats.rx_undersized_errors);
+ stats_rfc2819->rx_oversize_errors =
+ htonll(ops->stats.rx_oversize_errors);
+ stats_rfc2819->rx_fragmented_errors =
+ htonll(ops->stats.rx_fragmented_errors);
+ stats_rfc2819->rx_jabber_errors =
+ htonll(ops->stats.rx_jabber_errors);
}
/* Encode a ports stat for 'ops' and append it to 'replies'. */
@@ -7579,7 +7633,6 @@ static enum ofperr
ofputil_port_stats_from_ofp10(struct ofputil_port_stats *ops,
const struct ofp10_port_stats *ps10)
{
- memset(ops, 0, sizeof *ops);
ops->port_no = u16_to_ofp(ntohs(ps10->port_no));
ops->stats.rx_packets = ntohll(get_32aligned_be64(&ps10->rx_packets));
@@ -7606,7 +7659,6 @@ ofputil_port_stats_from_ofp11(struct ofputil_port_stats *ops,
{
enum ofperr error;
- memset(ops, 0, sizeof *ops);
error = ofputil_port_from_ofp11(ps11->port_no, &ops->port_no);
if (error) {
return error;
@@ -7660,6 +7712,68 @@ parse_ofp14_port_stats_ethernet_property(const struct ofpbuf *payload,
}
static enum ofperr
+parse_intel_port_stats_rfc2819_property(const struct ofpbuf *payload,
+ struct ofputil_port_stats *ops)
+{
+ const struct intel_port_stats_rfc2819 *rfc2819 = payload->data;
+
+ if (payload->size != sizeof *rfc2819) {
+ return OFPERR_OFPBPC_BAD_LEN;
+ }
+ ops->stats.rx_1_to_64_packets = ntohll(rfc2819->rx_1_to_64_packets);
+ ops->stats.rx_65_to_127_packets = ntohll(rfc2819->rx_65_to_127_packets);
+ ops->stats.rx_128_to_255_packets = ntohll(rfc2819->rx_128_to_255_packets);
+ ops->stats.rx_256_to_511_packets = ntohll(rfc2819->rx_256_to_511_packets);
+ ops->stats.rx_512_to_1023_packets =
+ ntohll(rfc2819->rx_512_to_1023_packets);
+ ops->stats.rx_1024_to_1522_packets =
+ ntohll(rfc2819->rx_1024_to_1522_packets);
+ ops->stats.rx_1523_to_max_packets =
+ ntohll(rfc2819->rx_1523_to_max_packets);
+
+ ops->stats.tx_1_to_64_packets = ntohll(rfc2819->tx_1_to_64_packets);
+ ops->stats.tx_65_to_127_packets = ntohll(rfc2819->tx_65_to_127_packets);
+ ops->stats.tx_128_to_255_packets = ntohll(rfc2819->tx_128_to_255_packets);
+ ops->stats.tx_256_to_511_packets = ntohll(rfc2819->tx_256_to_511_packets);
+ ops->stats.tx_512_to_1023_packets =
+ ntohll(rfc2819->tx_512_to_1023_packets);
+ ops->stats.tx_1024_to_1522_packets =
+ ntohll(rfc2819->tx_1024_to_1522_packets);
+ ops->stats.tx_1523_to_max_packets =
+ ntohll(rfc2819->tx_1523_to_max_packets);
+
+ ops->stats.tx_multicast_packets = ntohll(rfc2819->tx_multicast_packets);
+ ops->stats.rx_broadcast_packets = ntohll(rfc2819->rx_broadcast_packets);
+ ops->stats.tx_broadcast_packets = ntohll(rfc2819->tx_broadcast_packets);
+ ops->stats.rx_undersized_errors = ntohll(rfc2819->rx_undersized_errors);
+
+ ops->stats.rx_oversize_errors = ntohll(rfc2819->rx_oversize_errors);
+ ops->stats.rx_fragmented_errors = ntohll(rfc2819->rx_fragmented_errors);
+ ops->stats.rx_jabber_errors = ntohll(rfc2819->rx_jabber_errors);
+
+ return 0;
+}
+
+static enum ofperr
+parse_intel_port_stats_property(const struct ofpbuf *payload,
+ uint32_t exp_type,
+ struct ofputil_port_stats *ops)
+{
+ enum ofperr error;
+
+ switch (exp_type) {
+ case INTEL_PORT_STATS_RFC2819:
+ error = parse_intel_port_stats_rfc2819_property(payload, ops);
+ break;
+ default:
+ error = OFPERR_OFPBPC_BAD_EXP_TYPE;
+ break;
+ }
+
+ return error;
+}
+
+static enum ofperr
ofputil_pull_ofp14_port_stats(struct ofputil_port_stats *ops,
struct ofpbuf *msg)
{
@@ -7689,28 +7803,28 @@ ofputil_pull_ofp14_port_stats(struct ofputil_port_stats *ops,
ops->stats.tx_dropped = ntohll(ps14->tx_dropped);
ops->stats.rx_errors = ntohll(ps14->rx_errors);
ops->stats.tx_errors = ntohll(ps14->tx_errors);
- ops->stats.rx_frame_errors = UINT64_MAX;
- ops->stats.rx_over_errors = UINT64_MAX;
- ops->stats.rx_crc_errors = UINT64_MAX;
- ops->stats.collisions = UINT64_MAX;
+
struct ofpbuf properties = ofpbuf_const_initializer(ofpbuf_pull(msg, len),
len);
while (properties.size > 0) {
struct ofpbuf payload;
enum ofperr error;
- uint64_t type;
+ uint64_t type = 0;
error = ofpprop_pull(&properties, &payload, &type);
if (error) {
return error;
}
-
switch (type) {
case OFPPSPT14_ETHERNET:
error = parse_ofp14_port_stats_ethernet_property(&payload, ops);
break;
-
+ case OFPPROP_EXP(INTEL_VENDOR_ID, INTEL_PORT_STATS_RFC2819):
+ error = parse_intel_port_stats_property(&payload,
+ INTEL_PORT_STATS_RFC2819,
+ ops);
+ break;
default:
error = OFPPROP_UNKNOWN(true, "port stats", type);
break;
@@ -7756,6 +7870,8 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg)
enum ofperr error;
enum ofpraw raw;
+ memset(&(ps->stats), 0xFF, sizeof (ps->stats));
+
error = (msg->header ? ofpraw_decode(&raw, msg->header)
: ofpraw_pull(&raw, msg));
if (error) {
@@ -7768,7 +7884,6 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg)
return ofputil_pull_ofp14_port_stats(ps, msg);
} else if (raw == OFPRAW_OFPST13_PORT_REPLY) {
const struct ofp13_port_stats *ps13;
-
ps13 = ofpbuf_try_pull(msg, sizeof *ps13);
if (!ps13) {
goto bad_len;
diff --git a/tests/learn.at b/tests/learn.at
index 31ff4fd0c..68bde874a 100644
--- a/tests/learn.at
+++ b/tests/learn.at
@@ -329,11 +329,11 @@ NXST_FLOW reply:
AT_CHECK(
[(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | strip_xids], [0],
[OFPST_PORT reply: 1 ports
- port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=1, bytes=60, drop=0, errs=0, coll=0
+ port 2: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=1, bytes=60, drop=?, errs=?, coll=?
OFPST_PORT reply: 1 ports
- port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=9, bytes=540, drop=0, errs=0, coll=0
+ port 3: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=9, bytes=540, drop=?, errs=?, coll=?
])
OVS_VSWITCHD_STOP
@@ -380,11 +380,11 @@ done
AT_CHECK(
[(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | strip_xids], [0],
[OFPST_PORT reply: 1 ports
- port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=2, bytes=120, drop=0, errs=0, coll=0
+ port 2: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=2, bytes=120, drop=?, errs=?, coll=?
OFPST_PORT reply: 1 ports
- port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=18, bytes=1080, drop=0, errs=0, coll=0
+ port 3: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=18, bytes=1080, drop=?, errs=?, coll=?
])
# Check for the learning entry.
@@ -466,11 +466,11 @@ done
AT_CHECK(
[(ovs-ofctl dump-ports br0 2; ovs-ofctl dump-ports br0 3) | strip_xids], [0],
[OFPST_PORT reply: 1 ports
- port 2: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=3, bytes=180, drop=0, errs=0, coll=0
+ port 2: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=3, bytes=180, drop=?, errs=?, coll=?
OFPST_PORT reply: 1 ports
- port 3: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=17, bytes=1020, drop=0, errs=0, coll=0
+ port 3: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=17, bytes=1020, drop=?, errs=?, coll=?
])
# Check for the learning entry.
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 014903beb..29d936998 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -5163,17 +5163,17 @@ IFCOUNTERS
status=0
in_octets=0
in_unicasts=0
- in_multicasts=0
+ in_multicasts=4294967295
in_broadcasts=4294967295
- in_discards=0
- in_errors=0
+ in_discards=4294967295
+ in_errors=4294967295
in_unknownprotos=4294967295
out_octets=120
out_unicasts=2
out_multicasts=4294967295
out_broadcasts=4294967295
- out_discards=0
- out_errors=0
+ out_discards=4294967295
+ out_errors=4294967295
promiscuous=0
IFCOUNTERS
dgramSeqNo=2
@@ -5186,17 +5186,17 @@ IFCOUNTERS
status=0
in_octets=138
in_unicasts=3
- in_multicasts=0
+ in_multicasts=4294967295
in_broadcasts=4294967295
- in_discards=0
- in_errors=0
+ in_discards=4294967295
+ in_errors=4294967295
in_unknownprotos=4294967295
out_octets=120
out_unicasts=2
out_multicasts=4294967295
out_broadcasts=4294967295
- out_discards=0
- out_errors=0
+ out_discards=4294967295
+ out_errors=4294967295
promiscuous=0
IFCOUNTERS
dgramSeqNo=2
@@ -5209,17 +5209,17 @@ IFCOUNTERS
status=0
in_octets=84
in_unicasts=2
- in_multicasts=0
+ in_multicasts=4294967295
in_broadcasts=4294967295
- in_discards=0
- in_errors=0
+ in_discards=4294967295
+ in_errors=4294967295
in_unknownprotos=4294967295
out_octets=180
out_unicasts=3
out_multicasts=4294967295
out_broadcasts=4294967295
- out_discards=0
- out_errors=0
+ out_discards=4294967295
+ out_errors=4294967295
promiscuous=0
IFCOUNTERS
dgramSeqNo=3
@@ -5232,17 +5232,17 @@ IFCOUNTERS
status=0
in_octets=0
in_unicasts=0
- in_multicasts=0
+ in_multicasts=4294967295
in_broadcasts=4294967295
- in_discards=0
- in_errors=0
+ in_discards=4294967295
+ in_errors=4294967295
in_unknownprotos=4294967295
out_octets=120
out_unicasts=2
out_multicasts=4294967295
out_broadcasts=4294967295
- out_discards=0
- out_errors=0
+ out_discards=4294967295
+ out_errors=4294967295
promiscuous=0
IFCOUNTERS
dgramSeqNo=3
@@ -5255,17 +5255,17 @@ IFCOUNTERS
status=0
in_octets=138
in_unicasts=3
- in_multicasts=0
+ in_multicasts=4294967295
in_broadcasts=4294967295
- in_discards=0
- in_errors=0
+ in_discards=4294967295
+ in_errors=4294967295
in_unknownprotos=4294967295
out_octets=120
out_unicasts=2
out_multicasts=4294967295
out_broadcasts=4294967295
- out_discards=0
- out_errors=0
+ out_discards=4294967295
+ out_errors=4294967295
promiscuous=0
IFCOUNTERS
dgramSeqNo=3
@@ -5278,17 +5278,17 @@ IFCOUNTERS
status=0
in_octets=84
in_unicasts=2
- in_multicasts=0
+ in_multicasts=4294967295
in_broadcasts=4294967295
- in_discards=0
- in_errors=0
+ in_discards=4294967295
+ in_errors=4294967295
in_unknownprotos=4294967295
out_octets=180
out_unicasts=3
out_multicasts=4294967295
out_broadcasts=4294967295
- out_discards=0
- out_errors=0
+ out_discards=4294967295
+ out_errors=4294967295
promiscuous=0
OPENFLOWPORT
datapath_id=18364758544493064720
@@ -6212,14 +6212,14 @@ skb_priority(0/0),skb_mark(0/0),recirc_id(0),dp_hash(0/0),in_port(101),eth(src=5
AT_CHECK([ovs-ofctl dump-ports br0 pbr0], [0], [dnl
OFPST_PORT reply (xid=0x4): 1 ports
- port 1: rx pkts=5, bytes=300, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=10, bytes=600, drop=0, errs=0, coll=0
+ port 1: rx pkts=5, bytes=300, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=10, bytes=600, drop=?, errs=?, coll=?
])
AT_CHECK([ovs-ofctl dump-ports br1 pbr1], [0], [dnl
OFPST_PORT reply (xid=0x4): 1 ports
- port 1: rx pkts=10, bytes=600, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=5, bytes=300, drop=0, errs=0, coll=0
+ port 1: rx pkts=10, bytes=600, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=5, bytes=300, drop=?, errs=?, coll=?
])
OVS_VSWITCHD_STOP
diff --git a/tests/ofproto.at b/tests/ofproto.at
index c4260ab27..f8c0d0732 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -84,8 +84,8 @@ OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -vwarn dump-ports br0], [0], [stdout])
AT_CHECK([strip_xids < stdout], [0], [dnl
OFPST_PORT reply: 1 ports
- port LOCAL: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=0, bytes=0, drop=0, errs=0, coll=0
+ port LOCAL: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=0, bytes=0, drop=?, errs=?, coll=?
])
OVS_VSWITCHD_STOP
AT_CLEANUP
@@ -95,8 +95,8 @@ OVS_VSWITCHD_START
AT_CHECK([ovs-ofctl -O OpenFlow12 -vwarn dump-ports br0], [0], [stdout])
AT_CHECK([strip_xids < stdout], [0], [dnl
OFPST_PORT reply (OF1.2): 1 ports
- port LOCAL: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=0, bytes=0, drop=0, errs=0, coll=0
+ port LOCAL: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=0, bytes=0, drop=?, errs=?, coll=?
])
OVS_VSWITCHD_STOP
AT_CLEANUP
@@ -107,8 +107,8 @@ AT_CHECK([ovs-ofctl -O OpenFlow14 -vwarn dump-ports br0], [0], [stdout])
AT_CHECK([strip_xids < stdout | sed 's/duration=[[0-9.]]*s/duration=?s/'],
[0], [dnl
OFPST_PORT reply (OF1.4): 1 ports
- port LOCAL: rx pkts=0, bytes=0, drop=0, errs=0, frame=0, over=0, crc=0
- tx pkts=0, bytes=0, drop=0, errs=0, coll=0
+ port LOCAL: rx pkts=0, bytes=0, drop=?, errs=?, frame=?, over=?, crc=?
+ tx pkts=0, bytes=0, drop=?, errs=?, coll=?
duration=?s
])
OVS_VSWITCHD_STOP
diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
index ee8c48f4e..f8bb8004c 100644
--- a/tests/tunnel-push-pop-ipv6.at
+++ b/tests/tunnel-push-pop-ipv6.at
@@ -129,7 +129,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6486dd600000
ovs-appctl time/warp 1000
AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl
- port 3: rx pkts=1, bytes=98, drop=0, errs=0, frame=0, over=0, crc=0
+ port 3: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
dnl Check GRE only accepts encapsulated Ethernet frames
@@ -137,7 +137,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab6486dd600000
ovs-appctl time/warp 1000
AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl
- port 3: rx pkts=1, bytes=98, drop=0, errs=0, frame=0, over=0, crc=0
+ port 3: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
dnl Check decapsulation of Geneve packet with options
@@ -157,7 +157,7 @@ icmp,vlan_tci=0x0000,dl_src=be:b6:f4:e1:49:4a,dl_dst=fe:71:d8:83:72:4f,nw_src=30
])
AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 5'], [0], [dnl
- port 5: rx pkts=1, bytes=98, drop=0, errs=0, frame=0, over=0, crc=0
+ port 5: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
AT_CHECK([ovs-appctl dpif/dump-flows int-br], [0], [dnl
tunnel(tun_id=0x7b,ipv6_src=2001:cafe::92,ipv6_dst=2001:cafe::88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),skb_mark(0),recirc_id(0),in_port(6081),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,slow_path(controller))
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index a7909d326..99523067b 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -129,7 +129,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab640800450000
ovs-appctl time/warp 1000
AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl
- port 3: rx pkts=1, bytes=98, drop=0, errs=0, frame=0, over=0, crc=0
+ port 3: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
dnl Check GRE only accepts encapsulated Ethernet frames
@@ -137,7 +137,7 @@ AT_CHECK([ovs-appctl netdev-dummy/receive p0 'aa55aa550000001b213cab640800450000
ovs-appctl time/warp 1000
AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 3'], [0], [dnl
- port 3: rx pkts=1, bytes=98, drop=0, errs=0, frame=0, over=0, crc=0
+ port 3: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
dnl Check decapsulation of Geneve packet with options
@@ -157,7 +157,7 @@ icmp,vlan_tci=0x0000,dl_src=be:b6:f4:e1:49:4a,dl_dst=fe:71:d8:83:72:4f,nw_src=30
])
AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 5'], [0], [dnl
- port 5: rx pkts=1, bytes=98, drop=0, errs=0, frame=0, over=0, crc=0
+ port 5: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
AT_CHECK([ovs-appctl dpif/dump-flows int-br], [0], [dnl
tunnel(tun_id=0x7b,src=1.1.2.92,dst=1.1.2.88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),skb_mark(0),recirc_id(0),in_port(6081),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,slow_path(controller))
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index b4e5ea7ff..41ec4ba9a 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -2310,18 +2310,39 @@ static void
iface_refresh_stats(struct iface *iface)
{
#define IFACE_STATS \
- IFACE_STAT(rx_packets, "rx_packets") \
- IFACE_STAT(tx_packets, "tx_packets") \
- IFACE_STAT(rx_bytes, "rx_bytes") \
- IFACE_STAT(tx_bytes, "tx_bytes") \
- IFACE_STAT(rx_dropped, "rx_dropped") \
- IFACE_STAT(tx_dropped, "tx_dropped") \
- IFACE_STAT(rx_errors, "rx_errors") \
- IFACE_STAT(tx_errors, "tx_errors") \
- IFACE_STAT(rx_frame_errors, "rx_frame_err") \
- IFACE_STAT(rx_over_errors, "rx_over_err") \
- IFACE_STAT(rx_crc_errors, "rx_crc_err") \
- IFACE_STAT(collisions, "collisions")
+ IFACE_STAT(rx_packets, "rx_packets") \
+ IFACE_STAT(tx_packets, "tx_packets") \
+ IFACE_STAT(rx_bytes, "rx_bytes") \
+ IFACE_STAT(tx_bytes, "tx_bytes") \
+ IFACE_STAT(rx_dropped, "rx_dropped") \
+ IFACE_STAT(tx_dropped, "tx_dropped") \
+ IFACE_STAT(rx_errors, "rx_errors") \
+ IFACE_STAT(tx_errors, "tx_errors") \
+ IFACE_STAT(rx_frame_errors, "rx_frame_err") \
+ IFACE_STAT(rx_over_errors, "rx_over_err") \
+ IFACE_STAT(rx_crc_errors, "rx_crc_err") \
+ IFACE_STAT(collisions, "collisions") \
+ IFACE_STAT(rx_1_to_64_packets, "rx_1_to_64_packets") \
+ IFACE_STAT(rx_65_to_127_packets, "rx_65_to_127_packets") \
+ IFACE_STAT(rx_128_to_255_packets, "rx_128_to_255_packets") \
+ IFACE_STAT(rx_256_to_511_packets, "rx_256_to_511_packets") \
+ IFACE_STAT(rx_512_to_1023_packets, "rx_512_to_1023_packets") \
+ IFACE_STAT(rx_1024_to_1522_packets, "rx_1024_to_1518_packets") \
+ IFACE_STAT(rx_1523_to_max_packets, "rx_1523_to_max_packets") \
+ IFACE_STAT(tx_1_to_64_packets, "tx_1_to_64_packets") \
+ IFACE_STAT(tx_65_to_127_packets, "tx_65_to_127_packets") \
+ IFACE_STAT(tx_128_to_255_packets, "tx_128_to_255_packets") \
+ IFACE_STAT(tx_256_to_511_packets, "tx_256_to_511_packets") \
+ IFACE_STAT(tx_512_to_1023_packets, "tx_512_to_1023_packets") \
+ IFACE_STAT(tx_1024_to_1522_packets, "tx_1024_to_1518_packets") \
+ IFACE_STAT(tx_1523_to_max_packets, "tx_1523_to_max_packets") \
+ IFACE_STAT(tx_multicast_packets, "tx_multicast_packets") \
+ IFACE_STAT(rx_broadcast_packets, "rx_broadcast_packets") \
+ IFACE_STAT(tx_broadcast_packets, "tx_broadcast_packets") \
+ IFACE_STAT(rx_undersized_errors, "rx_undersized_errors") \
+ IFACE_STAT(rx_oversize_errors, "rx_oversize_errors") \
+ IFACE_STAT(rx_fragmented_errors, "rx_fragmented_errors") \
+ IFACE_STAT(rx_jabber_errors, "rx_jabber_errors")
#define IFACE_STAT(MEMBER, NAME) + 1
enum { N_IFACE_STATS = IFACE_STATS };