[ovs-dev] [PATCH RFC] ofproto: RFC extended statistics patch
mweglicx
michalx.weglicki at intel.com
Fri Oct 9 12:49:33 UTC 2015
Implementation of new statistics extension:
- new counters definition based on RFC2819,
- new command line option for ovs-ofctl: port-dump-ext,
- new message definition has been created in nicira-ext.h,
- new raw types OFPRAW_NXST_PORT_REQUEST, OFPRAW_NXST_PORT_REPLY
have been created.
- new extended statistics calculation is implemented only for
dpdk-vhost-enabled ports.
Please note that this is just feature proposal, final patch will include
all relevant counters based on RFC2863, RFC3635 and RFC2819 in
nx_port_stats (defined in nicira-ext.h).
Signed-off-by: Michal Weglicki <michalx.weglicki at intel.com>
Signed-off-by: Timo Puha <timox.puha at intel.com>
---
include/openflow/nicira-ext.h | 29 ++++++++
lib/netdev-bsd.c | 14 ++++
lib/netdev-dpdk.c | 44 +++++++++--
lib/netdev-dummy.c | 14 +++-
lib/netdev-linux.c | 19 +++++
lib/netdev-vport.c | 13 ++++
lib/netdev.h | 8 ++
lib/ofp-msgs.h | 12 ++-
lib/ofp-print.c | 60 ++++++++++-----
lib/ofp-util.c | 166 ++++++++++++++++++++++++++++++++----------
lib/ofp-util.h | 2 +
utilities/ovs-ofctl.c | 69 ++++++++++++++----
vswitchd/bridge.c | 30 +++++---
13 files changed, 386 insertions(+), 94 deletions(-)
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index efb40fa..1cf45cb 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -576,6 +576,35 @@ struct nx_flow_removed {
};
OFP_ASSERT(sizeof(struct nx_flow_removed) == 40);
+/* Nicira vendor stats request of type NXST_PORT (analogous to OFPST_PORT
+ * request). */
+struct nx_port_stats_request {
+ ovs_be32 port_no; /* OFPST_PORT message must request statistics
+ * either for a single port (specified in
+ * port_no) or for all ports (if port_no ==
+ * OFPP_ANY). */
+ uint8_t pad[4]; /* Align to 64-bits. */
+};
+
+OFP_ASSERT(sizeof (struct nx_port_stats_request) == 8);
+
+/* Body of reply to NXST_PORT request (analogous to OFPST_PORT reply).
+ * If a counter is unsupported, set the field to all ones. */
+struct nx_port_stats {
+ ovs_be32 port_no;
+ uint8_t pad[4]; /* Align to 64-bits. */
+ /* Below counters are just example used in RFC patch based on RFC2819.
+ * Final statistics extension should contain more counters based on
+ * RFC2819, RFC2863 and RFC3635. */
+ 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;
+};
+OFP_ASSERT(sizeof(struct nx_port_stats) == 56);
+
/* Nicira vendor stats request of type NXST_FLOW (analogous to OFPST_FLOW
* request).
*
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 93b0589..2b4f07e 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -950,13 +950,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. */
@@ -965,12 +967,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;
}
}
@@ -1412,7 +1434,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;
@@ -1438,6 +1459,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,8 +1485,6 @@ netdev_dpdk_get_stats(const struct netdev *netdev, struct netdev_stats *stats)
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;
@@ -1491,6 +1518,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..d892517 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. */
@@ -1580,6 +1592,7 @@ netdev_stats_from_ovs_vport_stats(struct netdev_stats *dst,
dst->tx_window_errors = 0;
}
+
static int
get_stats_via_vport__(const struct netdev *netdev, struct netdev_stats *stats)
{
@@ -1671,6 +1684,8 @@ netdev_linux_get_stats(const struct netdev *netdev_,
}
ovs_mutex_unlock(&netdev->mutex);
+ netdev_linux_set_unused_stats(stats);
+
return error;
}
@@ -1733,6 +1748,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 +1765,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 ff50563..c1ecad1 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-msgs.h b/lib/ofp-msgs.h
index bce5283..4335ccd 100644
--- a/lib/ofp-msgs.h
+++ b/lib/ofp-msgs.h
@@ -443,6 +443,12 @@ enum ofpraw {
/* NXT 1.0+ (26): struct nx_geneve_table_reply, struct nx_geneve_map[]. */
OFPRAW_NXT_GENEVE_TABLE_REPLY,
+
+ /* NXST 1.0+ (3): struct nx_port_stats_request. */
+ OFPRAW_NXST_PORT_REQUEST,
+
+ /* NXST 1.0+ (3): struct nx_port_stats[]. */
+ OFPRAW_NXST_PORT_REPLY
};
/* Decoding messages into OFPRAW_* values. */
@@ -590,11 +596,13 @@ enum ofptype {
* OFPRAW_OFPST12_TABLE_REPLY.
* OFPRAW_OFPST13_TABLE_REPLY. */
OFPTYPE_PORT_STATS_REQUEST, /* OFPRAW_OFPST10_PORT_REQUEST.
- * OFPRAW_OFPST11_PORT_REQUEST. */
+ * OFPRAW_OFPST11_PORT_REQUEST.
+ * OFPRAW_NXST_PORT_REQUEST. */
OFPTYPE_PORT_STATS_REPLY, /* OFPRAW_OFPST10_PORT_REPLY.
* OFPRAW_OFPST11_PORT_REPLY.
* OFPRAW_OFPST13_PORT_REPLY.
- * OFPRAW_OFPST14_PORT_REPLY. */
+ * OFPRAW_OFPST14_PORT_REPLY.
+ * OFPRAW_NXST_PORT_REPLY */
OFPTYPE_QUEUE_STATS_REQUEST, /* OFPRAW_OFPST10_QUEUE_REQUEST.
* OFPRAW_OFPST11_QUEUE_REQUEST. */
OFPTYPE_QUEUE_STATS_REPLY, /* OFPRAW_OFPST10_QUEUE_REPLY.
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index d0c94ce..c7863e5 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -1565,6 +1565,7 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
int verbosity)
{
struct ofpbuf b;
+ enum ofpraw raw;
ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh));
if (verbosity < 1) {
@@ -1590,26 +1591,45 @@ ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
}
ofputil_format_port(ps.port_no, string);
- ds_put_cstr(string, ": rx ");
- print_port_stat(string, "pkts=", ps.stats.rx_packets, 1);
- print_port_stat(string, "bytes=", ps.stats.rx_bytes, 1);
- print_port_stat(string, "drop=", ps.stats.rx_dropped, 1);
- print_port_stat(string, "errs=", ps.stats.rx_errors, 1);
- print_port_stat(string, "frame=", ps.stats.rx_frame_errors, 1);
- print_port_stat(string, "over=", ps.stats.rx_over_errors, 1);
- print_port_stat(string, "crc=", ps.stats.rx_crc_errors, 0);
-
- ds_put_cstr(string, " tx ");
- print_port_stat(string, "pkts=", ps.stats.tx_packets, 1);
- print_port_stat(string, "bytes=", ps.stats.tx_bytes, 1);
- print_port_stat(string, "drop=", ps.stats.tx_dropped, 1);
- print_port_stat(string, "errs=", ps.stats.tx_errors, 1);
- print_port_stat(string, "coll=", ps.stats.collisions, 0);
-
- if (ps.duration_sec != UINT32_MAX) {
- ds_put_cstr(string, " duration=");
- ofp_print_duration(string, ps.duration_sec, ps.duration_nsec);
- ds_put_char(string, '\n');
+ if (!ofpraw_decode(&raw, b.header)) {
+ if (raw != OFPRAW_NXST_PORT_REPLY) {
+ ds_put_cstr(string, ": rx ");
+ print_port_stat(string, "pkts=", ps.stats.rx_packets, 1);
+ print_port_stat(string, "bytes=", ps.stats.rx_bytes, 1);
+ print_port_stat(string, "drop=", ps.stats.rx_dropped, 1);
+ print_port_stat(string, "errs=", ps.stats.rx_errors, 1);
+ print_port_stat(string, "frame=", ps.stats.rx_frame_errors, 1);
+ print_port_stat(string, "over=", ps.stats.rx_over_errors, 1);
+ print_port_stat(string, "crc=", ps.stats.rx_crc_errors, 0);
+
+ ds_put_cstr(string, " tx ");
+ print_port_stat(string, "pkts=", ps.stats.tx_packets, 1);
+ print_port_stat(string, "bytes=", ps.stats.tx_bytes, 1);
+ print_port_stat(string, "drop=", ps.stats.tx_dropped, 1);
+ print_port_stat(string, "errs=", ps.stats.tx_errors, 1);
+ print_port_stat(string, "coll=", ps.stats.collisions, 0);
+
+ if (ps.duration_sec != UINT32_MAX) {
+ ds_put_cstr(string, " duration=");
+ ofp_print_duration(string, ps.duration_sec,
+ ps.duration_nsec);
+ ds_put_char(string, '\n');
+ }
+ } else {
+ ds_put_cstr(string, ": rx ");
+ 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 b9dbcda..cae432a 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -6798,6 +6798,25 @@ ofputil_encode_dump_ports_request(enum ofp_version ofp_version, ofp_port_t port)
return request;
}
+/* Encode a dump ports request for 'port', the encoded message
+ * will be for OpenFlow version 'ofp_version'. Returns message
+ * as a struct ofpbuf. Returns encoded message on success, NULL on error */
+struct ofpbuf *
+ofputil_encode_dump_ports_ext_request(enum ofp_version ofp_version,
+ ofp_port_t port)
+{
+ struct ofpbuf *request;
+ struct nx_port_stats_request *npsr;
+
+ request =
+ ofpraw_alloc(OFPRAW_NXST_PORT_REQUEST, ofp_version, NXM_TYPICAL_LEN);
+ ofpbuf_put_zeros(request, sizeof *npsr);
+ npsr = request->msg;
+ npsr->port_no = htons(ofp_to_u16(port));
+
+ return request;
+}
+
static void
ofputil_port_stats_to_ofp10(const struct ofputil_port_stats *ops,
struct ofp10_port_stats *ps10)
@@ -6819,6 +6838,20 @@ ofputil_port_stats_to_ofp10(const struct ofputil_port_stats *ops,
}
static void
+ofputil_port_stats_to_nx10(const struct ofputil_port_stats *ops,
+ struct nx_port_stats *nx10stats)
+{
+ nx10stats->port_no = htons(ofp_to_u16(ops->port_no));
+ memset(nx10stats->pad, 0, sizeof nx10stats->pad);
+ nx10stats->rx_64_packets = htonll(ops->stats.rx_64_packets);
+ nx10stats->rx_65_to_127_packets = htonll(ops->stats.rx_65_to_127_packets);
+ nx10stats->rx_128_to_255_packets = htonll(ops->stats.rx_128_to_255_packets);
+ nx10stats->rx_256_to_511_packets = htonll(ops->stats.rx_256_to_511_packets);
+ nx10stats->rx_512_to_1023_packets = htonll(ops->stats.rx_512_to_1023_packets);
+ nx10stats->rx_1024_to_1518_packets = htonll(ops->stats.rx_1024_to_1518_packets);
+}
+
+static void
ofputil_port_stats_to_ofp11(const struct ofputil_port_stats *ops,
struct ofp11_port_stats *ps11)
{
@@ -6887,32 +6920,44 @@ void
ofputil_append_port_stat(struct ovs_list *replies,
const struct ofputil_port_stats *ops)
{
- switch (ofpmp_version(replies)) {
- case OFP13_VERSION: {
- struct ofp13_port_stats *reply = ofpmp_append(replies, sizeof *reply);
- ofputil_port_stats_to_ofp13(ops, reply);
- break;
- }
- case OFP12_VERSION:
- case OFP11_VERSION: {
- struct ofp11_port_stats *reply = ofpmp_append(replies, sizeof *reply);
- ofputil_port_stats_to_ofp11(ops, reply);
- break;
- }
+ enum ofpraw raw = OFPRAW_OFPST10_PORT_REQUEST;
- case OFP10_VERSION: {
- struct ofp10_port_stats *reply = ofpmp_append(replies, sizeof *reply);
- ofputil_port_stats_to_ofp10(ops, reply);
- break;
- }
+ raw = ofpmp_decode_raw(replies);
- case OFP14_VERSION:
- case OFP15_VERSION:
- ofputil_append_ofp14_port_stats(ops, replies);
- break;
+ if (OFPRAW_NXST_PORT_REPLY == raw) {
+ struct nx_port_stats *reply;
- default:
- OVS_NOT_REACHED();
+ reply = ofpmp_append(replies, sizeof *reply);
+ ofputil_port_stats_to_nx10(ops, reply);
+ } else {
+
+ switch (ofpmp_version(replies)) {
+ case OFP13_VERSION: {
+ struct ofp13_port_stats *reply = ofpmp_append(replies, sizeof *reply);
+ ofputil_port_stats_to_ofp13(ops, reply);
+ break;
+ }
+ case OFP12_VERSION:
+ case OFP11_VERSION: {
+ struct ofp11_port_stats *reply = ofpmp_append(replies, sizeof *reply);
+ ofputil_port_stats_to_ofp11(ops, reply);
+ break;
+ }
+
+ case OFP10_VERSION: {
+ struct ofp10_port_stats *reply = ofpmp_append(replies, sizeof *reply);
+ ofputil_port_stats_to_ofp10(ops, reply);
+ break;
+ }
+
+ case OFP14_VERSION:
+ case OFP15_VERSION:
+ ofputil_append_ofp14_port_stats(ops, replies);
+ break;
+
+ default:
+ OVS_NOT_REACHED();
+ }
}
}
@@ -6942,6 +6987,27 @@ ofputil_port_stats_from_ofp10(struct ofputil_port_stats *ops,
}
static enum ofperr
+ofputil_port_stats_from_nx10(struct ofputil_port_stats *ops,
+ const struct nx_port_stats *nx10stats)
+{
+ memset(ops, 0, sizeof *ops);
+
+ ops->port_no = u16_to_ofp(ntohs(nx10stats->port_no));
+ ops->stats.rx_64_packets = ntohll(nx10stats->rx_64_packets);
+ ops->stats.rx_65_to_127_packets = ntohll(nx10stats->rx_65_to_127_packets);
+ ops->stats.rx_128_to_255_packets =
+ ntohll(nx10stats->rx_128_to_255_packets);
+ ops->stats.rx_256_to_511_packets =
+ ntohll(nx10stats->rx_256_to_511_packets);
+ ops->stats.rx_512_to_1023_packets =
+ ntohll(nx10stats->rx_512_to_1023_packets);
+ ops->stats.rx_1024_to_1518_packets =
+ ntohll(nx10stats->rx_1024_to_1518_packets);
+
+ return 0;
+}
+
+static enum ofperr
ofputil_port_stats_from_ofp11(struct ofputil_port_stats *ops,
const struct ofp11_port_stats *ps11)
{
@@ -7115,13 +7181,13 @@ 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;
}
return ofputil_port_stats_from_ofp13(ps, ps13);
} else if (raw == OFPRAW_OFPST11_PORT_REPLY) {
+
const struct ofp11_port_stats *ps11;
ps11 = ofpbuf_try_pull(msg, sizeof *ps11);
@@ -7137,6 +7203,15 @@ ofputil_decode_port_stats(struct ofputil_port_stats *ps, struct ofpbuf *msg)
goto bad_len;
}
return ofputil_port_stats_from_ofp10(ps, ps10);
+ } else if (raw == OFPRAW_NXST_PORT_REPLY) {
+ const struct nx_port_stats *nxstats;
+
+ nxstats = ofpbuf_try_pull(msg, sizeof *nxstats);
+ if (!nxstats) {
+ goto bad_len;
+ }
+ return ofputil_port_stats_from_nx10(ps, nxstats);
+
} else {
OVS_NOT_REACHED();
}
@@ -7154,24 +7229,35 @@ enum ofperr
ofputil_decode_port_stats_request(const struct ofp_header *request,
ofp_port_t *ofp10_port)
{
- switch ((enum ofp_version)request->version) {
- case OFP15_VERSION:
- case OFP14_VERSION:
- case OFP13_VERSION:
- case OFP12_VERSION:
- case OFP11_VERSION: {
- const struct ofp11_port_stats_request *psr11 = ofpmsg_body(request);
- return ofputil_port_from_ofp11(psr11->port_no, ofp10_port);
- }
+ enum ofpraw raw;
+ struct ofpbuf b;
- case OFP10_VERSION: {
- const struct ofp10_port_stats_request *psr10 = ofpmsg_body(request);
- *ofp10_port = u16_to_ofp(ntohs(psr10->port_no));
- return 0;
- }
+ ofpbuf_use_const(&b, request, ntohs(request->length));
+ raw = ofpraw_pull_assert(&b);
- default:
- OVS_NOT_REACHED();
+ if (OFPRAW_NXST_PORT_REQUEST == raw) {
+ const struct nx_port_stats_request *nxpsr = ofpmsg_body(request);
+
+ *ofp10_port = u16_to_ofp(ntohs(nxpsr->port_no));
+ return 0;
+ } else {
+ switch ((enum ofp_version)request->version) {
+ case OFP15_VERSION:
+ case OFP14_VERSION:
+ case OFP13_VERSION:
+ case OFP12_VERSION:
+ case OFP11_VERSION: {
+ const struct ofp11_port_stats_request *psr11 = ofpmsg_body(request);
+ return ofputil_port_from_ofp11(psr11->port_no, ofp10_port);
+ }
+ case OFP10_VERSION: {
+ const struct ofp10_port_stats_request *psr10 = ofpmsg_body(request);
+ *ofp10_port = u16_to_ofp(ntohs(psr10->port_no));
+ return 0;
+ }
+ default:
+ OVS_NOT_REACHED();
+ }
}
}
diff --git a/lib/ofp-util.h b/lib/ofp-util.h
index 8914342..3211c9e 100644
--- a/lib/ofp-util.h
+++ b/lib/ofp-util.h
@@ -999,6 +999,8 @@ struct ofputil_port_stats {
struct ofpbuf *ofputil_encode_dump_ports_request(enum ofp_version ofp_version,
ofp_port_t port);
+struct ofpbuf *ofputil_encode_dump_ports_ext_request(enum ofp_version ofp_version,
+ ofp_port_t port);
void ofputil_append_port_stat(struct ovs_list *replies,
const struct ofputil_port_stats *ops);
size_t ofputil_count_port_stats(const struct ofp_header *);
diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c
index 0c315c1..2dd8783 100644
--- a/utilities/ovs-ofctl.c
+++ b/utilities/ovs-ofctl.c
@@ -349,6 +349,7 @@ usage(void)
" set-frags SWITCH FRAG_MODE set fragment handling behavior\n"
" FRAG_MODE: normal, drop, reassemble, nx-match\n"
" dump-ports SWITCH [PORT] print port statistics\n"
+ " dump-ports-ext SWITCH [PORT] print port extended statistics\n"
" dump-ports-desc SWITCH [PORT] print port descriptions\n"
" dump-flows SWITCH print all flow entries\n"
" dump-flows SWITCH FLOW print matching FLOWs\n"
@@ -1036,12 +1037,28 @@ try_set_protocol(struct vconn *vconn, enum ofputil_protocol want,
}
}
+static void
+set_protocol_print_error(enum ofputil_protocol usable_protocols)
+{
+ char *usable_s;
+
+ usable_s = ofputil_protocols_to_string(usable_protocols);
+ if (usable_protocols & allowed_protocols) {
+ ovs_fatal(0, "switch does not support any of the usable flow "
+ "formats (%s)", usable_s);
+ } else {
+ char *allowed_s = ofputil_protocols_to_string(allowed_protocols);
+
+ ovs_fatal(0, "none of the usable flow formats (%s) is among the "
+ "allowed flow formats (%s)", usable_s, allowed_s);
+ }
+}
+
static enum ofputil_protocol
set_protocol_for_flow_dump(struct vconn *vconn,
enum ofputil_protocol cur_protocol,
enum ofputil_protocol usable_protocols)
{
- char *usable_s;
int i;
for (i = 0; i < ofputil_n_flow_dump_protocols; i++) {
@@ -1052,15 +1069,8 @@ set_protocol_for_flow_dump(struct vconn *vconn,
}
}
- usable_s = ofputil_protocols_to_string(usable_protocols);
- if (usable_protocols & allowed_protocols) {
- ovs_fatal(0, "switch does not support any of the usable flow "
- "formats (%s)", usable_s);
- } else {
- char *allowed_s = ofputil_protocols_to_string(allowed_protocols);
- ovs_fatal(0, "none of the usable flow formats (%s) is among the "
- "allowed flow formats (%s)", usable_s, allowed_s);
- }
+ set_protocol_print_error(usable_protocols);
+ return OFPUTIL_P_NONE;
}
static struct vconn *
@@ -1782,21 +1792,50 @@ ofctl_snoop(struct ovs_cmdl_context *ctx)
monitor_vconn(vconn, false);
}
+static struct vconn *
+prepare_dump_ports(const char *name, ofp_port_t port,
+ struct ofpbuf **requestp, bool extended_stats)
+{
+ struct vconn *vconn;
+
+ open_vconn(name, &vconn);
+ if (extended_stats) {
+ *requestp =
+ ofputil_encode_dump_ports_ext_request(vconn_get_version(vconn),
+ port);
+ } else {
+ *requestp =
+ ofputil_encode_dump_ports_request(vconn_get_version(vconn), port);
+ }
+ return vconn;
+}
+
static void
-ofctl_dump_ports(struct ovs_cmdl_context *ctx)
+ofctl_dump_ports__(int argc, char *argv[], bool extended_stats)
{
struct ofpbuf *request;
struct vconn *vconn;
ofp_port_t port;
- open_vconn(ctx->argv[1], &vconn);
- port = ctx->argc > 2 ? str_to_port_no(ctx->argv[1], ctx->argv[2]) : OFPP_ANY;
- request = ofputil_encode_dump_ports_request(vconn_get_version(vconn), port);
+ port = argc > 2 ? str_to_port_no(argv[1], argv[2]) : OFPP_ANY;
+ vconn = prepare_dump_ports(argv[1], port, &request, extended_stats);
dump_stats_transaction(vconn, request);
vconn_close(vconn);
}
static void
+ofctl_dump_ports(struct ovs_cmdl_context *ctx)
+{
+ ofctl_dump_ports__(ctx->argc, ctx->argv, false);
+}
+
+static void
+ofctl_dump_ports_ext(struct ovs_cmdl_context *ctx)
+{
+ ofctl_dump_ports__(ctx->argc, ctx->argv, true);
+}
+
+static void
ofctl_dump_ports_desc(struct ovs_cmdl_context *ctx)
{
struct ofpbuf *request;
@@ -3738,6 +3777,8 @@ static const struct ovs_cmdl_command all_commands[] = {
4, INT_MAX, ofctl_packet_out },
{ "dump-ports", "switch [port]",
1, 2, ofctl_dump_ports },
+ { "dump-ports-ext", "switch [port]",
+ 1, 2, ofctl_dump_ports_ext },
{ "dump-ports-desc", "switch [port]",
1, 2, ofctl_dump_ports_desc },
{ "mod-port", "switch iface act",
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index 232a334..714c617 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -2335,18 +2335,24 @@ 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 };
--
1.9.3
More information about the dev
mailing list