[ovs-dev] [PATCH] Extended statistics patch.

mweglicx michalx.weglicki at intel.com
Thu May 5 08:46:01 UTC 2016


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 at intel.com>
---
 include/openflow/automake.mk       |   1 +
 include/openflow/intel-ext.h       |  73 +++++++++++++++
 include/openflow/openflow-common.h |   1 +
 include/openvswitch/netdev.h       |  27 ++++++
 lib/netdev-dpdk.c                  | 182 ++++++++++++++++++++++++++++++-------
 lib/netdev-linux.c                 |   3 +
 lib/netdev-vport.c                 |   6 +-
 lib/netdev.c                       |   5 +
 lib/ofp-print.c                    |  82 +++++++++++++++++
 lib/ofp-util.c                     | 139 +++++++++++++++++++++++++---
 tests/ofproto-dpif.at              |   8 +-
 tests/ofproto.at                   |   2 +-
 tests/tunnel-push-pop-ipv6.at      |   6 +-
 tests/tunnel-push-pop.at           |   6 +-
 vswitchd/bridge.c                  |  45 ++++++---
 15 files changed, 518 insertions(+), 68 deletions(-)
 create mode 100644 include/openflow/intel-ext.h

diff --git a/include/openflow/automake.mk b/include/openflow/automake.mk
index d7dac91..18cc649 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 0000000..974e63e
--- /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 089ff18..7b619a9 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 fa5e8f2..88a25dd 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 b488c60..8040866 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-linux.c b/lib/netdev-linux.c
index 2953964..5db1887 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 e398562..678c3f9 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 4fc06ce..3aacd9c 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 69f90f3..6cd136d 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -1685,6 +1685,21 @@ 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,
+                     uint64_t filter, int more)
+{
+    if (stat != filter) {
+        print_port_stat(string, leader, stat, more);
+    } else {
+        if (0 == more) {
+            /* Line will be terminated even if filtering
+             * condition isn't met. */
+            print_port_stat(string, "", stat, more);
+        }
+    }
+}
+
+static void
 ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh)
 {
     ofp_port_t ofp10_port;
@@ -1749,6 +1764,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, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
+                             ps.stats.rx_65_to_127_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
+                             ps.stats.rx_128_to_255_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
+                             ps.stats.rx_256_to_511_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
+                             ps.stats.rx_512_to_1023_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
+                             ps.stats.rx_1024_to_1522_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
+                             ps.stats.rx_1523_to_max_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
+                             ps.stats.rx_broadcast_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "undersized_errors=",
+                             ps.stats.rx_undersized_errors, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "oversize_errors=",
+                             ps.stats.rx_oversize_errors, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "rx_fragmented_errors=",
+                             ps.stats.rx_fragmented_errors, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "rx_jabber_errors=",
+                             ps.stats.rx_jabber_errors, UINT64_MAX, 1);
+
+        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, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
+                             ps.stats.tx_65_to_127_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
+                             ps.stats.tx_128_to_255_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
+                             ps.stats.tx_256_to_511_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
+                             ps.stats.tx_512_to_1023_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
+                             ps.stats.tx_1024_to_1522_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
+                             ps.stats.tx_1523_to_max_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "multicast_packets=",
+                             ps.stats.tx_multicast_packets, UINT64_MAX, 1);
+        print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
+                             ps.stats.tx_broadcast_packets, UINT64_MAX, 1);
+
+        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 bb1535d..2c6fb1f 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/ofproto-dpif.at b/tests/ofproto-dpif.at
index 014903b..ea01a53 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -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 c4260ab..0f3cecf 100644
--- a/tests/ofproto.at
+++ b/tests/ofproto.at
@@ -104,7 +104,7 @@ AT_CLEANUP
 AT_SETUP([ofproto - port stats - (OpenFlow 1.4)])
 OVS_VSWITCHD_START
 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/'],
+AT_CHECK([strip_xids < stdout | sed 's/duration=[[0-9.]]*s/duration=?s/' | sed '/rfc2819/d'],
   [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
diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
index ee8c48f..f8bb800 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 a7909d3..9952306 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 b4e5ea7..41ec4ba 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 };
-- 
1.9.3




More information about the dev mailing list