From b41a6a0a6d23322da667c39d1c5e65496ae8b02f Mon Sep 17 00:00:00 2001 From: Justin Pettit Date: Thu, 14 Aug 2008 23:12:37 -0700 Subject: [PATCH] Added new interface statistics. --- datapath/datapath.c | 18 +++++++++++++----- include/openflow.h | 29 +++++++++++++++++++++-------- lib/ofp-print.c | 37 +++++++++++++++++++++++++++++++++---- switch/datapath.c | 32 ++++++++++++++++++++++---------- 4 files changed, 89 insertions(+), 27 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 2b40e3caa..5b5967605 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -554,7 +554,7 @@ int dp_output_port(struct datapath *dp, struct sk_buff *skb, int out_port) case OFPP_IN_PORT: /* Send it out the port it came in on, which is already set in * the skb. */ - if (!skb->dev) { + if (!skb->dev) { if (net_ratelimit()) printk("skb device not set forwarding to in_port\n"); kfree(skb); @@ -1299,10 +1299,18 @@ static int port_stats_dump(struct datapath *dp, void *state, stats = p->dev->get_stats(p->dev); ops->port_no = htons(p->port_no); memset(ops->pad, 0, sizeof ops->pad); - ops->rx_count = cpu_to_be64(stats->rx_packets); - ops->tx_count = cpu_to_be64(stats->tx_packets); - ops->drop_count = cpu_to_be64(stats->rx_dropped - + stats->tx_dropped); + ops->rx_packets = cpu_to_be64(stats->rx_packets); + ops->tx_packets = cpu_to_be64(stats->tx_packets); + ops->rx_bytes = cpu_to_be64(stats->rx_bytes); + ops->tx_bytes = cpu_to_be64(stats->tx_bytes); + ops->rx_dropped = cpu_to_be64(stats->rx_dropped); + ops->tx_dropped = cpu_to_be64(stats->tx_dropped); + ops->rx_errors = cpu_to_be64(stats->rx_errors); + ops->tx_errors = cpu_to_be64(stats->tx_errors); + ops->rx_frame_err = cpu_to_be64(stats->rx_frame_errors); + ops->rx_over_err = cpu_to_be64(stats->rx_over_errors); + ops->rx_crc_err = cpu_to_be64(stats->rx_crc_errors); + ops->collisions = cpu_to_be64(stats->collisions); n_ports++; ops++; } diff --git a/include/openflow.h b/include/openflow.h index e5d600fac..ba25687b5 100644 --- a/include/openflow.h +++ b/include/openflow.h @@ -68,7 +68,7 @@ /* The most significant bit being set in the version field indicates an * experimental OpenFlow version. */ -#define OFP_VERSION 0x87 +#define OFP_VERSION 0x88 #define OFP_MAX_TABLE_NAME_LEN 32 #define OFP_MAX_PORT_NAME_LEN 16 @@ -522,14 +522,27 @@ struct ofp_table_stats { }; OFP_ASSERT(sizeof(struct ofp_table_stats) == 56); -/* Statistics about a particular port */ +/* Statistics about a particular port. If a counter is unsupported, set + * the field to all ones. */ struct ofp_port_stats { uint16_t port_no; - uint8_t pad[6]; /* Align to 64-bits */ - uint64_t rx_count; /* Number of received packets */ - uint64_t tx_count; /* Number of transmitted packets */ - uint64_t drop_count; /* Number of packets dropped by interface */ -}; -OFP_ASSERT(sizeof(struct ofp_port_stats) == 32); + uint8_t pad[6]; /* Align to 64-bits. */ + uint64_t rx_packets; /* Number of received packets. */ + uint64_t tx_packets; /* Number of transmitted packets. */ + uint64_t rx_bytes; /* Number of received bytes. */ + uint64_t tx_bytes; /* Number of transmitted bytes. */ + uint64_t rx_dropped; /* Number of packets dropped by RX. */ + uint64_t tx_dropped; /* Number of packets dropped by TX. */ + uint64_t rx_errors; /* Number of receive errors. This is a super-set + of receive errors and should be great than or + equal to the sum of al rx_*_err values. */ + uint64_t tx_errors; /* Number of transmit errors. This is a super-set + of transmit errors. */ + uint64_t rx_frame_err; /* Number of frame alignment errors. */ + uint64_t rx_over_err; /* Number of packets with RX overrun. */ + uint64_t rx_crc_err; /* Number of CRC errors. */ + uint64_t collisions; /* Number of collisions. */ +}; +OFP_ASSERT(sizeof(struct ofp_port_stats) == 104); #endif /* openflow.h */ diff --git a/lib/ofp-print.c b/lib/ofp-print.c index 7e46999a5..01e49b78c 100644 --- a/lib/ofp-print.c +++ b/lib/ofp-print.c @@ -656,6 +656,22 @@ ofp_aggregate_stats_reply(struct ds *string, const void *body_, size_t len, ds_put_format(string, " flow_count=%"PRIu32, ntohl(asr->flow_count)); } +static void print_port_stat(struct ds *string, const char *leader, + uint64_t stat, int more) +{ + ds_put_cstr(string, leader); + if (stat != -1) { + ds_put_format(string, "%"PRIu64, stat); + } else { + ds_put_char(string, '?'); + } + if (more) { + ds_put_cstr(string, ", "); + } else { + ds_put_cstr(string, "\n"); + } +} + static void ofp_port_stats_reply(struct ds *string, const void *body, size_t len, int verbosity) @@ -668,10 +684,23 @@ ofp_port_stats_reply(struct ds *string, const void *body, size_t len, } for (; n--; ps++) { - ds_put_format(string, " port %"PRIu16": ", ntohs(ps->port_no)); - ds_put_format(string, "rx %"PRIu64", ", ntohll(ps->rx_count)); - ds_put_format(string, "tx %"PRIu64", ", ntohll(ps->tx_count)); - ds_put_format(string, "dropped %"PRIu64"\n", ntohll(ps->drop_count)); + ds_put_format(string, " port %2"PRIu16": ", ntohs(ps->port_no)); + + ds_put_cstr(string, "rx "); + print_port_stat(string, "pkts=", ntohll(ps->rx_packets), 1); + print_port_stat(string, "bytes=", ntohll(ps->rx_bytes), 1); + print_port_stat(string, "drop=", ntohll(ps->rx_dropped), 1); + print_port_stat(string, "errs=", ntohll(ps->rx_errors), 1); + print_port_stat(string, "frame=", ntohll(ps->rx_frame_err), 1); + print_port_stat(string, "over=", ntohll(ps->rx_over_err), 1); + print_port_stat(string, "crc=", ntohll(ps->rx_crc_err), 0); + + ds_put_cstr(string, " tx "); + print_port_stat(string, "pkts=", ntohll(ps->tx_packets), 1); + print_port_stat(string, "bytes=", ntohll(ps->tx_bytes), 1); + print_port_stat(string, "drop=", ntohll(ps->tx_dropped), 1); + print_port_stat(string, "errs=", ntohll(ps->tx_errors), 1); + print_port_stat(string, "coll=", ntohll(ps->collisions), 0); } } diff --git a/switch/datapath.c b/switch/datapath.c index e98106395..4e7b6256b 100644 --- a/switch/datapath.c +++ b/switch/datapath.c @@ -77,7 +77,9 @@ struct sw_port { struct datapath *dp; struct netdev *netdev; struct list node; /* Element in datapath.ports. */ - unsigned long long int rx_count, tx_count, drop_count; + unsigned long long int rx_packets, tx_packets; + unsigned long long int rx_bytes, tx_bytes; + unsigned long long int tx_dropped; }; /* The origin of a received OpenFlow message, to enable sending a reply. */ @@ -249,11 +251,10 @@ dp_add_port(struct datapath *dp, const char *name) } } + memset(p, '\0', sizeof *p); + p->dp = dp; p->netdev = netdev; - p->tx_count = 0; - p->rx_count = 0; - p->drop_count = 0; list_push_back(&dp->port_list, &p->node); /* Notify the ctlpath that this port has been added */ @@ -306,7 +307,8 @@ dp_run(struct datapath *dp) } error = netdev_recv(p->netdev, buffer); if (!error) { - p->rx_count++; + p->rx_packets++; + p->rx_bytes += buffer->size; fwd_port_input(dp, buffer, port_no(dp, p)); buffer = NULL; } else if (error != EAGAIN) { @@ -525,9 +527,10 @@ output_packet(struct datapath *dp, struct buffer *buffer, int out_port) struct sw_port *p = &dp->ports[out_port]; if (p->netdev != NULL) { if (!netdev_send(p->netdev, buffer)) { - p->tx_count++; + p->tx_packets++; + p->tx_bytes += buffer->size; } else { - p->drop_count++; + p->tx_dropped++; } return; } @@ -1323,9 +1326,18 @@ static int port_stats_dump(struct datapath *dp, void *state, ops = buffer_put_uninit(buffer, sizeof *ops); ops->port_no = htons(port_no(dp, p)); memset(ops->pad, 0, sizeof ops->pad); - ops->rx_count = htonll(p->rx_count); - ops->tx_count = htonll(p->tx_count); - ops->drop_count = htonll(p->drop_count); + ops->rx_packets = htonll(p->rx_packets); + ops->tx_packets = htonll(p->tx_packets); + ops->rx_bytes = htonll(p->rx_bytes); + ops->tx_bytes = htonll(p->tx_bytes); + ops->rx_dropped = htonll(-1); + ops->tx_dropped = htonll(p->tx_dropped); + ops->rx_errors = htonll(-1); + ops->tx_errors = htonll(-1); + ops->rx_frame_err = htonll(-1); + ops->rx_over_err = htonll(-1); + ops->rx_crc_err = htonll(-1); + ops->collisions = htonll(-1); ops++; } s->port = i; -- 2.43.0