Implementation of new statistics extension:
- new counters definition based on RFC2819,
- new statistics are retrieved using experimenter code and
  are printed as a result to ofctl dump-ports,
- new statistics are printed to output via ofctl only if those
  are present in reply message,
- new file header created: include/openflow/intel-ext.h which
  contains new statistics definition,
- new extended statistics calculation is implemented only for
  dpdk-vhost-enabled ports.

Please note that this is just feature proposal:
- experimenter code is hardcoded in ofp-util.c, it will be
  changed when VENDOR_ID for intel will be defined,
- final patch will include also more counters based on
  RFC2863, RFC3635 and RFC2819.

v2:
- protocol extension in ofproto has been removed, existing
  mechanism with experimenter codes has been used,
- additional option in ofctl dump-ports-ext has been removed,
  new counters are retrieved via dump-ports.

Signed-off-by: Michal Weglicki <michalx.wegli...@intel.com>
Signed-off-by: Timo Puha <timox.p...@intel.com>
---
 include/openflow/automake.mk |   1 +
 include/openflow/intel-ext.h |  63 ++++++++++++++++++++++
 lib/netdev-bsd.c             |  14 +++++
 lib/netdev-dpdk.c            |  48 +++++++++++++++--
 lib/netdev-dummy.c           |  14 ++++-
 lib/netdev-linux.c           |  18 +++++++
 lib/netdev-vport.c           |  13 +++++
 lib/netdev.h                 |   8 +++
 lib/ofp-print.c              |  22 ++++++++
 lib/ofp-util.c               | 122 +++++++++++++++++++++++++++++++++++++++++--
 vswitchd/bridge.c            |  31 ++++++-----
 11 files changed, 331 insertions(+), 23 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..680e499
--- /dev/null
+++ b/include/openflow/intel-ext.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright(c) 2010-2015 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 1
+
+
+/* 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 64
+
+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_*. */
+
+    /* Followed by:
+     *   - Exactly (length - 12) bytes containing the experimenter data:
+     * Below counters are just example used in RFC patch based on RFC2819.
+     * This list can be extended during final patch implementation. */
+    uint8_t pad[4];
+
+    ovs_be64 rx_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_1518_packets;
+
+    /*, then
+     * - Exactly (length + 7)/8*8 - (length) (between 0 and 7)
+     * bytes of all-zero bytes */
+};
+OFP_ASSERT(sizeof(struct intel_port_stats_rfc2819) == 
INTEL_PORT_STATS_RFC2819_SIZE);
+
+#endif /* openflow/intel-ext.h */
diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
index 60e5615..153687a 100644
--- a/lib/netdev-bsd.c
+++ b/lib/netdev-bsd.c
@@ -896,6 +896,18 @@ netdev_bsd_get_carrier(const struct netdev *netdev_, bool 
*carrier)
     return error;
 }
 
+/* Initializes unused statistics to default values. */
+static void
+netdev_bsd_set_unused_stats(struct netdev_stats *dst)
+{
+    dst->rx_1024_to_1518_packets = UINT64_MAX;
+    dst->rx_512_to_1023_packets = UINT64_MAX;
+    dst->rx_256_to_511_packets = UINT64_MAX;
+    dst->rx_128_to_255_packets = UINT64_MAX;
+    dst->rx_65_to_127_packets = UINT64_MAX;
+    dst->rx_64_packets = UINT64_MAX;
+}
+
 static void
 convert_stats_system(struct netdev_stats *stats, const struct if_data *ifd)
 {
@@ -923,6 +935,7 @@ convert_stats_system(struct netdev_stats *stats, const 
struct if_data *ifd)
     stats->tx_fifo_errors = UINT64_MAX;
     stats->tx_heartbeat_errors = UINT64_MAX;
     stats->tx_window_errors = UINT64_MAX;
+    netdev_bsd_set_unused_stats(stats);
 }
 
 static void
@@ -957,6 +970,7 @@ convert_stats_tap(struct netdev_stats *stats, const struct 
if_data *ifd)
     stats->tx_fifo_errors = UINT64_MAX;
     stats->tx_heartbeat_errors = UINT64_MAX;
     stats->tx_window_errors = UINT64_MAX;
+    netdev_bsd_set_unused_stats(stats);
 }
 
 static void
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index 4658416..fc40620 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -954,13 +954,15 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_stats 
*stats,
                                      struct dp_packet **packets, int count)
 {
     int i;
+    unsigned size;
     struct dp_packet *packet;
 
     stats->rx_packets += count;
     for (i = 0; i < count; i++) {
         packet = packets[i];
+        size = dp_packet_size(packet);
 
-        if (OVS_UNLIKELY(dp_packet_size(packet) < ETH_HEADER_LEN)) {
+        if (OVS_UNLIKELY(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. */
@@ -969,12 +971,32 @@ netdev_dpdk_vhost_update_rx_counters(struct netdev_stats 
*stats,
             continue;
         }
 
+        /* Hard-coded binary search for the size bucket. */
+        if (size < 256) {
+            if (size >= 128) {
+                stats->rx_128_to_255_packets++;
+            } else if (size <= 64) {
+                stats->rx_64_packets++;
+            } else {
+                stats->rx_65_to_127_packets++;
+            }
+        } else {
+            if (size >= 1024) {
+                stats->rx_1024_to_1518_packets++;
+            } else if (size < 512) {
+                stats->rx_256_to_511_packets++;
+            } else {
+                stats->rx_512_to_1023_packets++;
+            }
+        }
+
         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 += size;
     }
 }
 
@@ -1415,8 +1437,9 @@ netdev_dpdk_vhost_get_stats(const struct netdev *netdev,
 {
     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
 
+    memset(stats, 0xFF, sizeof (*stats));
+
     ovs_mutex_lock(&dev->mutex);
-    memset(stats, 0, sizeof(*stats));
     /* Unsupported Stats */
     stats->collisions = UINT64_MAX;
     stats->rx_crc_errors = UINT64_MAX;
@@ -1442,6 +1465,14 @@ 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_64_packets = dev->stats.rx_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_1518_packets = dev->stats.rx_1024_to_1518_packets;
+
     rte_spinlock_unlock(&dev->stats_lock);
 
     ovs_mutex_unlock(&dev->mutex);
@@ -1456,12 +1487,12 @@ netdev_dpdk_get_stats(const struct netdev *netdev, 
struct netdev_stats *stats)
     struct rte_eth_stats rte_stats;
     bool gg;
 
+    memset(stats, 0xFF, sizeof (*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));
-
     stats->rx_packets = rte_stats.ipackets;
     stats->tx_packets = rte_stats.opackets;
     stats->rx_bytes = rte_stats.ibytes;
@@ -1495,6 +1526,13 @@ netdev_dpdk_get_stats(const struct netdev *netdev, 
struct netdev_stats *stats)
 
     ovs_mutex_unlock(&dev->mutex);
 
+    stats->rx_64_packets = UINT64_MAX;
+    stats->rx_65_to_127_packets = UINT64_MAX;
+    stats->rx_128_to_255_packets = UINT64_MAX;
+    stats->rx_256_to_511_packets = UINT64_MAX;
+    stats->rx_512_to_1023_packets = UINT64_MAX;
+    stats->rx_1024_to_1518_packets = UINT64_MAX;
+
     return 0;
 }
 
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 76815c2..b055abf 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -1020,6 +1020,18 @@ netdev_dummy_set_mtu(const struct netdev *netdev, int 
mtu)
     return 0;
 }
 
+/* Initializes unused statistics to default values. */
+static void
+netdev_dummy_set_unused_stats(struct netdev_stats *dst)
+{
+    dst->rx_1024_to_1518_packets = UINT64_MAX;
+    dst->rx_512_to_1023_packets = UINT64_MAX;
+    dst->rx_256_to_511_packets = UINT64_MAX;
+    dst->rx_128_to_255_packets = UINT64_MAX;
+    dst->rx_65_to_127_packets = UINT64_MAX;
+    dst->rx_64_packets = UINT64_MAX;
+}
+
 static int
 netdev_dummy_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
 {
@@ -1028,7 +1040,7 @@ netdev_dummy_get_stats(const struct netdev *netdev, 
struct netdev_stats *stats)
     ovs_mutex_lock(&dev->mutex);
     *stats = dev->stats;
     ovs_mutex_unlock(&dev->mutex);
-
+    netdev_dummy_set_unused_stats(stats);
     return 0;
 }
 
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 584e804..b26343a 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -1550,6 +1550,18 @@ swap_uint64(uint64_t *a, uint64_t *b)
     *b = tmp;
 }
 
+/* Initializes unused statistics to default values. */
+static void
+netdev_linux_set_unused_stats(struct netdev_stats *dst)
+{
+    dst->rx_1024_to_1518_packets = UINT64_MAX;
+    dst->rx_512_to_1023_packets = UINT64_MAX;
+    dst->rx_256_to_511_packets = UINT64_MAX;
+    dst->rx_128_to_255_packets = UINT64_MAX;
+    dst->rx_65_to_127_packets = UINT64_MAX;
+    dst->rx_64_packets = UINT64_MAX;
+}
+
 /* Copies 'src' into 'dst', performing format conversion in the process.
  *
  * 'src' is allowed to be misaligned. */
@@ -1671,6 +1683,8 @@ netdev_linux_get_stats(const struct netdev *netdev_,
     }
     ovs_mutex_unlock(&netdev->mutex);
 
+    netdev_linux_set_unused_stats(stats);
+
     return error;
 }
 
@@ -1733,6 +1747,8 @@ netdev_tap_get_stats(const struct netdev *netdev_, struct 
netdev_stats *stats)
     }
     ovs_mutex_unlock(&netdev->mutex);
 
+    netdev_linux_set_unused_stats(stats);
+
     return error;
 }
 
@@ -1748,6 +1764,8 @@ netdev_internal_get_stats(const struct netdev *netdev_,
     error = netdev->vport_stats_error;
     ovs_mutex_unlock(&netdev->mutex);
 
+    netdev_linux_set_unused_stats(stats);
+
     return error;
 }
 
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 07b72b3..6f640cc 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -812,6 +812,18 @@ set_patch_config(struct netdev *dev_, const struct smap 
*args)
     return 0;
 }
 
+/* Initializes unused statistics to default values. */
+static void
+netdev_vport_set_unused_stats(struct netdev_stats *dst)
+{
+    dst->rx_1024_to_1518_packets = UINT64_MAX;
+    dst->rx_512_to_1023_packets = UINT64_MAX;
+    dst->rx_256_to_511_packets = UINT64_MAX;
+    dst->rx_128_to_255_packets = UINT64_MAX;
+    dst->rx_65_to_127_packets = UINT64_MAX;
+    dst->rx_64_packets = UINT64_MAX;
+}
+
 static int
 get_stats(const struct netdev *netdev, struct netdev_stats *stats)
 {
@@ -820,6 +832,7 @@ get_stats(const struct netdev *netdev, struct netdev_stats 
*stats)
     ovs_mutex_lock(&dev->mutex);
     *stats = dev->stats;
     ovs_mutex_unlock(&dev->mutex);
+    netdev_vport_set_unused_stats(stats);
 
     return 0;
 }
diff --git a/lib/netdev.h b/lib/netdev.h
index 0fbcb65..107e81e 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -102,6 +102,14 @@ struct netdev_stats {
     uint64_t tx_fifo_errors;
     uint64_t tx_heartbeat_errors;
     uint64_t tx_window_errors;
+
+    /* Size bucket statistics. Based on RFC2819. */
+    uint64_t rx_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_1518_packets;
 };
 
 /* Configuration specific to tunnels. */
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index d0c94ce..66a4968 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -1611,6 +1611,28 @@ 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');
         }
+        /* Present extended statistics only if anything is reported */
+        if ((ps.stats.rx_64_packets != UINT64_MAX) ||
+            (ps.stats.rx_65_to_127_packets != UINT64_MAX) ||
+            (ps.stats.rx_128_to_255_packets != UINT64_MAX) ||
+            (ps.stats.rx_256_to_511_packets != UINT64_MAX) ||
+            (ps.stats.rx_512_to_1023_packets != UINT64_MAX) ||
+            (ps.stats.rx_1024_to_1518_packets != UINT64_MAX)) {
+
+            ds_put_cstr(string, "           rx rfc2819 ");
+            print_port_stat(string, "64_packets=",
+                            ps.stats.rx_64_packets, 1);
+            print_port_stat(string, "65_to_127_packets=",
+                            ps.stats.rx_65_to_127_packets, 1);
+            print_port_stat(string, "128_to_255_packets=",
+                            ps.stats.rx_128_to_255_packets, 1);
+            print_port_stat(string, "256_to_511_packets=",
+                            ps.stats.rx_256_to_511_packets, 1);
+            print_port_stat(string, "512_to_1023_packets=",
+                            ps.stats.rx_512_to_1023_packets, 1);
+            print_port_stat(string, "1024_to_1518_packets=",
+                            ps.stats.rx_1024_to_1518_packets, 0);
+        }
     }
 }
 
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 342be54..dd46a86 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -39,6 +39,7 @@
 #include "ofp-util.h"
 #include "ofpbuf.h"
 #include "openflow/netronome-ext.h"
+#include "openflow/intel-ext.h"
 #include "packets.h"
 #include "random.h"
 #include "tun-metadata.h"
@@ -47,6 +48,13 @@
 #include "openvswitch/vlog.h"
 #include "bitmap.h"
 
+/*
+ * This vendor ID is created only for RFC patch,
+ * it will be changed  when requested ID will be
+ * added to openflow-common.h.
+ */
+#define INTEL_VENDOR_ID 0x0000151d
+
 VLOG_DEFINE_THIS_MODULE(ofp_util);
 
 /* Rate limit for OpenFlow message parse errors.  These always indicate a bug
@@ -6852,13 +6860,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);
@@ -6880,6 +6891,24 @@ 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);
+
+    stats_rfc2819 = ofpbuf_put_uninit(reply, sizeof *stats_rfc2819);
+    stats_rfc2819->type = htons(OFPPSPT14_EXPERIMENTER);
+    stats_rfc2819->length = htons(sizeof *stats_rfc2819);
+    stats_rfc2819->experimenter = htonl(INTEL_VENDOR_ID);
+    stats_rfc2819->exp_type = htonl(INTEL_PORT_STATS_RFC2819);
+    memset(stats_rfc2819->pad, 0, sizeof stats_rfc2819->pad);
+    stats_rfc2819->rx_64_packets = htonll(ops->stats.rx_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_1518_packets =
+        htonll(ops->stats.rx_1024_to_1518_packets);
 }
 
 /* Encode a ports stat for 'ops' and append it to 'replies'. */
@@ -6920,7 +6949,8 @@ static enum ofperr
 ofputil_port_stats_from_ofp10(struct ofputil_port_stats *ops,
                               const struct ofp10_port_stats *ps10)
 {
-    memset(ops, 0, sizeof *ops);
+    /* Initialize with all ones to filter everything out */
+    memset(ops, 0xFF, sizeof *ops);
 
     ops->port_no = u16_to_ofp(ntohs(ps10->port_no));
     ops->stats.rx_packets = ntohll(get_32aligned_be64(&ps10->rx_packets));
@@ -6947,7 +6977,8 @@ ofputil_port_stats_from_ofp11(struct ofputil_port_stats 
*ops,
 {
     enum ofperr error;
 
-    memset(ops, 0, sizeof *ops);
+    /* Initialize with all ones to filter everything out */
+    memset(ops, 0xFF, sizeof *ops);
     error = ofputil_port_from_ofp11(ps11->port_no, &ops->port_no);
     if (error) {
         return error;
@@ -7001,6 +7032,79 @@ 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_64_packets = ntohll(rfc2819->rx_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_1518_packets =
+        ntohll(rfc2819->rx_1024_to_1518_packets);
+
+    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:
+        log_property(false, "unknown port stats experimenter type %" PRIu32,
+                     exp_type);
+        error = OFPERR_OFPBPC_BAD_EXP_TYPE;
+        break;
+    }
+
+    return error;
+}
+
+static enum ofperr
+parse_ofp14_port_stats_exp(struct ofpbuf *payload,
+                           struct ofputil_port_stats *ops)
+{
+    struct ofp_prop_experimenter *prop = payload->data;
+    uint16_t experimenter;
+    uint32_t exp_type;
+    enum ofperr error;
+
+    if (payload->size < sizeof *prop) {
+        return OFPERR_OFPBPC_BAD_LEN;
+    }
+
+    experimenter = ntohl(prop->experimenter);
+    exp_type = ntohl(prop->exp_type);
+
+    switch (experimenter) {
+    case INTEL_VENDOR_ID:
+        error = parse_intel_port_stats_property(payload, exp_type, ops);
+        break;
+
+    default:
+        log_property(false, "unknown group property experimenter %" PRIu16,
+                     experimenter);
+        error = OFPERR_OFPBPC_BAD_EXPERIMENTER;
+        break;
+    }
+
+    return error;
+}
+
+
+static enum ofperr
 ofputil_pull_ofp14_port_stats(struct ofputil_port_stats *ops,
                               struct ofpbuf *msg)
 {
@@ -7040,6 +7144,12 @@ ofputil_pull_ofp14_port_stats(struct ofputil_port_stats 
*ops,
     ops->stats.rx_over_errors = UINT64_MAX;
     ops->stats.rx_crc_errors = UINT64_MAX;
     ops->stats.collisions = UINT64_MAX;
+    ops->stats.rx_64_packets = UINT64_MAX;
+    ops->stats.rx_65_to_127_packets = UINT64_MAX;
+    ops->stats.rx_128_to_255_packets = UINT64_MAX;
+    ops->stats.rx_256_to_511_packets = UINT64_MAX;
+    ops->stats.rx_512_to_1023_packets = UINT64_MAX;
+    ops->stats.rx_1024_to_1518_packets = UINT64_MAX;
 
     while (properties.size > 0) {
         struct ofpbuf payload;
@@ -7055,7 +7165,9 @@ ofputil_pull_ofp14_port_stats(struct ofputil_port_stats 
*ops,
         case OFPPSPT14_ETHERNET:
             error = parse_ofp14_port_stats_ethernet_property(&payload, ops);
             break;
-
+        case OFPPSPT14_EXPERIMENTER:
+            error = parse_ofp14_port_stats_exp(&payload, ops);
+            break;
         default:
             log_property(true, "unknown port stats property %"PRIu16, type);
             error = 0;
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index b966d92..28a46e0 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -2336,21 +2336,28 @@ 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_64_packets,           "rx_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_1518_packets, "rx_1024_to_1518_packets")
 
 #define IFACE_STAT(MEMBER, NAME) + 1
     enum { N_IFACE_STATS = IFACE_STATS };
+
 #undef IFACE_STAT
     int64_t values[N_IFACE_STATS];
     const char *keys[N_IFACE_STATS];
-- 
1.9.3

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to