diff mbox

[ovs-dev,RFC,v2] ofproto: RFC extended statistics patch.

Message ID 1448269840-12750-1-git-send-email-michalx.weglicki@intel.com
State RFC
Headers show

Commit Message

Weglicki, MichalX Nov. 23, 2015, 9:10 a.m. UTC
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.weglicki@intel.com>
Signed-off-by: Timo Puha <timox.puha@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

Comments

Ben Pfaff Nov. 30, 2015, 1:05 a.m. UTC | #1
On Mon, Nov 23, 2015 at 09:10:40AM +0000, mweglicx wrote:
> 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.weglicki@intel.com>
> Signed-off-by: Timo Puha <timox.puha@intel.com>

This version seems quite reasonable.

I'm confused by the tentative choice of vendor ID, because it doesn't
seem to be an Ethernet OUI for Intel.  Rather, it seems to belong to:

00-15-1D   (hex)		M2I CORPORATION
00151D     (base 16)		M2I CORPORATION
				Kyonggi Venture Anyang technical center, 13th Floor, 572-5, Anyang 8-Dong, Manan-Gu
				Anyang-Shi  Kyonggi-Do  430-731
				KR

It seems like you could just choose any Ethernet OUI for Intel and put
it in the openflow header; not sure why you're putting it in ofp-util.c
instead.

There is a lot of code duplication here among all of the netdev
implementations, to initialize the added statistics to "unknown"
values.  It would be better to avoid the duplication.  One way would be
to add a global helper function; another would be for netdev_get_stats()
to initialize the whole structure to 0xff before passing it to the
netdev implementation.

I'll look forward to the next revision.
Weglicki, MichalX Dec. 2, 2015, 11:11 a.m. UTC | #2
Hello, 

Thank you for the comments. 

"I'm confused by the tentative choice of vendor ID, because it doesn't
seem to be an Ethernet OUI for Intel."
[MW] To be honest I didn't put too much attention to VENDOR_ID 
because my initial plan was to re-submit patch with all relevant 
RFC2819 counters when Vendor ID  for Intel would be approved. 
That is also why I've put it into ofp-util.c, so no special reason 
behind this. I will choose Intel OUI and put it into openflow 
header. 

"There is a lot of code duplication here among all of the netdev..."
At the beginning I did the initialization in netdev_get_stats 
(setting buffer to all "1s") before  counters are passed to 
particular netdev "client", that approach makes sense
to me, because: 
* a lot of code is simplified, 
* clients care only for filling counters which should be reported. 
However I found it problematic because netdev-linux is "appending" 
Values: 
stats->rx_errors           += dev_stats.rx_errors;
....
But it seems that I didn't analyse it carefully enough, and it is initialized
In other location. I will check that once again and I will try to put 
initialization in netdev_get_stats. 

"This version seems quite reasonable."
[MW] Thank you, I think that right now I can proceed with final patch, 
I will re-work the patch based on your comments, I will add all 
Missing counters relevant for RFC2819, and I will apply this patch in 
separate mailing thread (not RFC patch). 

Br, 
Michal.

-----Original Message-----
From: Ben Pfaff [mailto:blp@ovn.org] 
Sent: Monday, November 30, 2015 1:05 AM
To: Weglicki, MichalX <michalx.weglicki@intel.com>
Cc: dev@openvswitch.org
Subject: Re: [ovs-dev] [PATCH RFC v2] ofproto: RFC extended statistics patch.

On Mon, Nov 23, 2015 at 09:10:40AM +0000, mweglicx wrote:
> 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.weglicki@intel.com>
> Signed-off-by: Timo Puha <timox.puha@intel.com>

This version seems quite reasonable.

I'm confused by the tentative choice of vendor ID, because it doesn't
seem to be an Ethernet OUI for Intel.  Rather, it seems to belong to:

00-15-1D   (hex)		M2I CORPORATION
00151D     (base 16)		M2I CORPORATION
				Kyonggi Venture Anyang technical center, 13th Floor, 572-5, Anyang 8-Dong, Manan-Gu
				Anyang-Shi  Kyonggi-Do  430-731
				KR

It seems like you could just choose any Ethernet OUI for Intel and put
it in the openflow header; not sure why you're putting it in ofp-util.c
instead.

There is a lot of code duplication here among all of the netdev
implementations, to initialize the added statistics to "unknown"
values.  It would be better to avoid the duplication.  One way would be
to add a global helper function; another would be for netdev_get_stats()
to initialize the whole structure to 0xff before passing it to the
netdev implementation.

I'll look forward to the next revision.
--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.
Ben Pfaff Dec. 2, 2015, 4:49 p.m. UTC | #3
Sounds good!

On Wed, Dec 02, 2015 at 11:11:41AM +0000, Weglicki, MichalX wrote:
> Hello, 
> 
> Thank you for the comments. 
> 
> "I'm confused by the tentative choice of vendor ID, because it doesn't
> seem to be an Ethernet OUI for Intel."
> [MW] To be honest I didn't put too much attention to VENDOR_ID 
> because my initial plan was to re-submit patch with all relevant 
> RFC2819 counters when Vendor ID  for Intel would be approved. 
> That is also why I've put it into ofp-util.c, so no special reason 
> behind this. I will choose Intel OUI and put it into openflow 
> header. 
> 
> "There is a lot of code duplication here among all of the netdev..."
> At the beginning I did the initialization in netdev_get_stats 
> (setting buffer to all "1s") before  counters are passed to 
> particular netdev "client", that approach makes sense
> to me, because: 
> * a lot of code is simplified, 
> * clients care only for filling counters which should be reported. 
> However I found it problematic because netdev-linux is "appending" 
> Values: 
> stats->rx_errors           += dev_stats.rx_errors;
> ....
> But it seems that I didn't analyse it carefully enough, and it is initialized
> In other location. I will check that once again and I will try to put 
> initialization in netdev_get_stats. 
> 
> "This version seems quite reasonable."
> [MW] Thank you, I think that right now I can proceed with final patch, 
> I will re-work the patch based on your comments, I will add all 
> Missing counters relevant for RFC2819, and I will apply this patch in 
> separate mailing thread (not RFC patch). 
> 
> Br, 
> Michal.
> 
> -----Original Message-----
> From: Ben Pfaff [mailto:blp@ovn.org] 
> Sent: Monday, November 30, 2015 1:05 AM
> To: Weglicki, MichalX <michalx.weglicki@intel.com>
> Cc: dev@openvswitch.org
> Subject: Re: [ovs-dev] [PATCH RFC v2] ofproto: RFC extended statistics patch.
> 
> On Mon, Nov 23, 2015 at 09:10:40AM +0000, mweglicx wrote:
> > 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.weglicki@intel.com>
> > Signed-off-by: Timo Puha <timox.puha@intel.com>
> 
> This version seems quite reasonable.
> 
> I'm confused by the tentative choice of vendor ID, because it doesn't
> seem to be an Ethernet OUI for Intel.  Rather, it seems to belong to:
> 
> 00-15-1D   (hex)		M2I CORPORATION
> 00151D     (base 16)		M2I CORPORATION
> 				Kyonggi Venture Anyang technical center, 13th Floor, 572-5, Anyang 8-Dong, Manan-Gu
> 				Anyang-Shi  Kyonggi-Do  430-731
> 				KR
> 
> It seems like you could just choose any Ethernet OUI for Intel and put
> it in the openflow header; not sure why you're putting it in ofp-util.c
> instead.
> 
> There is a lot of code duplication here among all of the netdev
> implementations, to initialize the added statistics to "unknown"
> values.  It would be better to avoid the duplication.  One way would be
> to add a global helper function; another would be for netdev_get_stats()
> to initialize the whole structure to 0xff before passing it to the
> netdev implementation.
> 
> I'll look forward to the next revision.
> --------------------------------------------------------------
> Intel Research and Development Ireland Limited
> Registered in Ireland
> Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
> Registered Number: 308263
> 
> 
> This e-mail and any attachments may contain confidential material for the sole
> use of the intended recipient(s). Any review or distribution by others is
> strictly prohibited. If you are not the intended recipient, please contact the
> sender and delete all copies.
>
diff mbox

Patch

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];