Protocol stats: Add OpenFlow protocol statistical information

collector

Fix BUG#49: Add OpenFlow protocol statistical information collector
and user interface. This feature use PRIVATE_VENDOR_ID to communicate
betwewn control plane process and user interface. PRIVATE_VENDOR_ID is
defined only for private use (and based on private OUI).
This commit is contained in:
Mikio Hara committed 2009-06-29 05:22:54 -07:00
1 parent e61c00c0bb
commit d56d5661df
18 files changed
+911

No files matched your search

+2
View File
@@ -45,6 +45,8 @@ lib_libopenflow_a_SOURCES = \
lib/ofp-print.h \
lib/ofpbuf.c \
lib/ofpbuf.h \
lib/ofpstat.c \
lib/ofpstat.h \
lib/packets.h \
lib/pcap.c \
lib/pcap.h \
+235
View File
@@ -0,0 +1,235 @@
/*-
* Copyright (c) 2008, 2009
* The Board of Trustees of The Leland Stanford Junior University
*
* We are making the OpenFlow specification and associated documentation
* (Software) available for public use and benefit with the expectation that
* others will use, modify and enhance the Software and contribute those
* enhancements back to the community. However, since we would like to make the
* Software available for broadest use, with as few restrictions as possible
* permission is hereby granted, free of charge, to any person obtaining a copy
* of this Software to deal in the Software under the copyrights without
* restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* The name and trademarks of copyright holder(s) may NOT be used in
* advertising or publicity pertaining to the Software or any derivatives
* without specific, written prior permission.
*/
#include <config.h>
#include <netinet/in.h>
#include "openflow/openflow.h"
#include "ofpstat.h"
#define INC_IFP_STAT(ifps, tag) do {++(ifps)->tag;} while (0)
static void inc_protocol_message(struct ofpstat *, struct ofp_header *);
static void inc_error_notification(struct ofpstat *, struct ofp_header *);
static void inc_flow_manipulation(struct ofpstat *, struct ofp_header *);
static void
inc_protocol_message(struct ofpstat *ifps, struct ofp_header *hdr)
{
switch (hdr->type) {
case OFPT_HELLO:
INC_IFP_STAT(ifps, ofps_hello);
break;
case OFPT_ERROR:
INC_IFP_STAT(ifps, ofps_error);
break;
case OFPT_ECHO_REQUEST:
INC_IFP_STAT(ifps, ofps_echo_request);
break;
case OFPT_ECHO_REPLY:
INC_IFP_STAT(ifps, ofps_echo_reply);
break;
case OFPT_VENDOR:
INC_IFP_STAT(ifps, ofps_vendor);
break;
case OFPT_FEATURES_REQUEST:
INC_IFP_STAT(ifps, ofps_feats_request);
break;
case OFPT_FEATURES_REPLY:
INC_IFP_STAT(ifps, ofps_feats_reply);
break;
case OFPT_GET_CONFIG_REQUEST:
INC_IFP_STAT(ifps, ofps_get_config_request);
break;
case OFPT_GET_CONFIG_REPLY:
INC_IFP_STAT(ifps, ofps_get_config_reply);
break;
case OFPT_SET_CONFIG:
INC_IFP_STAT(ifps, ofps_set_config);
break;
case OFPT_PACKET_IN:
INC_IFP_STAT(ifps, ofps_packet_in);
break;
case OFPT_FLOW_EXPIRED:
INC_IFP_STAT(ifps, ofps_flow_expired);
break;
case OFPT_PORT_STATUS:
INC_IFP_STAT(ifps, ofps_port_status);
break;
case OFPT_PACKET_OUT:
INC_IFP_STAT(ifps, ofps_packet_out);
break;
case OFPT_FLOW_MOD:
INC_IFP_STAT(ifps, ofps_flow_mod);
break;
case OFPT_PORT_MOD:
INC_IFP_STAT(ifps, ofps_port_mod);
break;
case OFPT_STATS_REQUEST:
INC_IFP_STAT(ifps, ofps_stats_request);
break;
case OFPT_STATS_REPLY:
INC_IFP_STAT(ifps, ofps_stats_reply);
break;
default:
INC_IFP_STAT(ifps, ofps_unknown);
break;
}
}
static void
inc_error_notification(struct ofpstat *ifps, struct ofp_header *hdr)
{
struct ofp_error_msg *errmsg = (struct ofp_error_msg *)hdr;
uint16_t errtype = ntohs(errmsg->type);
uint16_t errcode = ntohs(errmsg->code);
switch (errtype) {
case OFPET_HELLO_FAILED:
INC_IFP_STAT(ifps, ofps_error_type.hello_fail);
switch (errcode) {
case OFPHFC_INCOMPATIBLE:
INC_IFP_STAT(ifps, ofps_error_code.hf_incompat);
break;
default:
INC_IFP_STAT(ifps, ofps_error_code.unknown);
break;
}
break;
case OFPET_BAD_REQUEST:
INC_IFP_STAT(ifps, ofps_error_type.bad_request);
switch (errcode) {
case OFPBRC_BAD_VERSION:
INC_IFP_STAT(ifps, ofps_error_code.br_bad_version);
break;
case OFPBRC_BAD_TYPE:
INC_IFP_STAT(ifps, ofps_error_code.br_bad_type);
break;
case OFPBRC_BAD_STAT:
INC_IFP_STAT(ifps, ofps_error_code.br_bad_stat);
break;
case OFPBRC_BAD_VENDOR:
INC_IFP_STAT(ifps, ofps_error_code.br_bad_vendor);
break;
default:
INC_IFP_STAT(ifps, ofps_error_code.unknown);
break;
}
break;
case OFPET_BAD_ACTION:
INC_IFP_STAT(ifps, ofps_error_type.bad_action);
switch (errcode) {
case OFPBAC_BAD_TYPE:
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_type);
break;
case OFPBAC_BAD_LEN:
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_len);
break;
case OFPBAC_BAD_VENDOR:
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_vendor);
break;
case OFPBAC_BAD_VENDOR_TYPE:
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_vendor_type);
break;
case OFPBAC_BAD_OUT_PORT:
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_out_port);
break;
case OFPBAC_BAD_ARGUMENT:
INC_IFP_STAT(ifps, ofps_error_code.ba_bad_argument);
break;
default:
INC_IFP_STAT(ifps, ofps_error_code.unknown);
break;
}
break;
case OFPET_FLOW_MOD_FAILED:
INC_IFP_STAT(ifps, ofps_error_type.flow_mod_fail);
switch (errcode) {
case OFPFMFC_ALL_TABLES_FULL:
INC_IFP_STAT(ifps, ofps_error_code.fmf_all_tables_full);
break;
default:
INC_IFP_STAT(ifps, ofps_error_code.unknown);
break;
}
break;
default:
INC_IFP_STAT(ifps, ofps_error_type.unknown);
break;
}
}
static void
inc_flow_manipulation(struct ofpstat *ifps, struct ofp_header *hdr)
{
struct ofp_flow_mod *flowmodmsg = (struct ofp_flow_mod *)hdr;
uint16_t flowmodops = ntohs(flowmodmsg->command);
switch (flowmodops) {
case OFPFC_ADD:
INC_IFP_STAT(ifps, ofps_flow_mod_ops.add);
break;
case OFPFC_MODIFY:
INC_IFP_STAT(ifps, ofps_flow_mod_ops.modify);
break;
case OFPFC_MODIFY_STRICT:
INC_IFP_STAT(ifps, ofps_flow_mod_ops.modify_strict);
break;
case OFPFC_DELETE:
INC_IFP_STAT(ifps, ofps_flow_mod_ops.delete);
break;
case OFPFC_DELETE_STRICT:
INC_IFP_STAT(ifps, ofps_flow_mod_ops.delete_strict);
break;
default:
INC_IFP_STAT(ifps, ofps_flow_mod_ops.unknown);
break;
}
}
void
ofpstat_inc_protocol_stat(struct ofpstat *ifps, struct ofp_header *hdr)
{
++ifps->ofps_total;
inc_protocol_message(ifps, hdr);
switch (hdr->type) {
case OFPT_ERROR:
inc_error_notification(ifps, hdr);
break;
case OFPT_FLOW_MOD:
inc_flow_manipulation(ifps, hdr);
break;
default:
break;
}
}
+92
View File
@@ -0,0 +1,92 @@
/*-
* Copyright (c) 2008, 2009
* The Board of Trustees of The Leland Stanford Junior University
*
* We are making the OpenFlow specification and associated documentation
* (Software) available for public use and benefit with the expectation that
* others will use, modify and enhance the Software and contribute those
* enhancements back to the community. However, since we would like to make the
* Software available for broadest use, with as few restrictions as possible
* permission is hereby granted, free of charge, to any person obtaining a copy
* of this Software to deal in the Software under the copyrights without
* restriction, including without limitation the rights to use, copy, modify,
* merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* The name and trademarks of copyright holder(s) may NOT be used in
* advertising or publicity pertaining to the Software or any derivatives
* without specific, written prior permission.
*/
#ifndef OFPSTAT_H_
#define OFPSTAT_H_
struct ofpstat {
uint64_t ofps_total;
uint64_t ofps_unknown;
uint64_t ofps_hello;
uint64_t ofps_error;
struct {
uint64_t hello_fail;
uint64_t bad_request;
uint64_t bad_action;
uint64_t flow_mod_fail;
uint64_t unknown;
} ofps_error_type;
struct {
uint64_t hf_incompat;
uint64_t br_bad_version;
uint64_t br_bad_type;
uint64_t br_bad_stat;
uint64_t br_bad_vendor;
uint64_t ba_bad_type;
uint64_t ba_bad_len;
uint64_t ba_bad_vendor;
uint64_t ba_bad_vendor_type;
uint64_t ba_bad_out_port;
uint64_t ba_bad_argument;
uint64_t fmf_all_tables_full;
uint64_t unknown;
} ofps_error_code;
uint64_t ofps_echo_request;
uint64_t ofps_echo_reply;
uint64_t ofps_vendor;
uint64_t ofps_feats_request;
uint64_t ofps_feats_reply;
uint64_t ofps_get_config_request;
uint64_t ofps_get_config_reply;
uint64_t ofps_set_config;
uint64_t ofps_packet_in;
uint64_t ofps_flow_expired;
uint64_t ofps_port_status;
uint64_t ofps_packet_out;
uint64_t ofps_flow_mod;
struct {
uint64_t add;
uint64_t modify;
uint64_t modify_strict;
uint64_t delete;
uint64_t delete_strict;
uint64_t unknown;
} ofps_flow_mod_ops;
uint64_t ofps_port_mod;
uint64_t ofps_stats_request;
uint64_t ofps_stats_reply;
};
void ofpstat_inc_protocol_stat(struct ofpstat *, struct ofp_header *);
#endif
+37
View File
@@ -45,6 +45,7 @@
#include "timeval.h"
#include "util.h"
#include "vconn.h"
#include "vconn-provider.h"
#define THIS_MODULE VLM_rconn
#include "vlog.h"
@@ -476,6 +477,7 @@ rconn_recv(struct rconn *rc)
struct ofpbuf *buffer;
int error = vconn_recv(rc->vconn, &buffer);
if (!error) {
struct ofp_header *h = buffer->data;
copy_to_monitor(rc, buffer);
if (is_admitted_msg(buffer)
|| time_now() - rc->last_connected >= 30) {
@@ -484,6 +486,7 @@ rconn_recv(struct rconn *rc)
}
rc->last_received = time_now();
rc->packets_received++;
ofpstat_inc_protocol_stat(&rc->ofps_rcvd, h);
if (rc->state == S_IDLE) {
/* Check liveliness of a peer. */
if (h->type == OFPT_ECHO_REPLY) {
@@ -734,6 +737,39 @@ rconn_get_connection_seqno(const struct rconn *rc)
{
return rc->seqno;
}
/* Returns protocol statistical information. */
void
rconn_update_protocol_stat(struct rconn *rconn,
struct ofpstat *ofps_rcvd,
struct ofpstat *ofps_sent)
{
struct vconn *vconn = rconn->vconn;
if (vconn != NULL) {
rconn->ofps_rcvd.ofps_total += vconn->ofps_rcvd.ofps_total;
vconn->ofps_rcvd.ofps_total = 0;
rconn->ofps_rcvd.ofps_hello += vconn->ofps_rcvd.ofps_hello;
vconn->ofps_rcvd.ofps_hello = 0;
}
*ofps_rcvd = rconn->ofps_rcvd;
if (vconn != NULL) {
rconn->ofps_sent.ofps_total += vconn->ofps_sent.ofps_total;
vconn->ofps_sent.ofps_total = 0;
rconn->ofps_sent.ofps_hello += vconn->ofps_sent.ofps_hello;
vconn->ofps_sent.ofps_hello = 0;
rconn->ofps_sent.ofps_error += vconn->ofps_sent.ofps_error;
vconn->ofps_sent.ofps_error = 0;
rconn->ofps_sent.ofps_error_type.hello_fail
+= vconn->ofps_sent.ofps_error_type.hello_fail;
vconn->ofps_sent.ofps_error_type.hello_fail = 0;
rconn->ofps_sent.ofps_error_code.hf_incompat
+= vconn->ofps_sent.ofps_error_code.hf_incompat;
vconn->ofps_sent.ofps_error_code.hf_incompat = 0;
}
*ofps_sent = rconn->ofps_sent;
}
/* Tries to send a packet from 'rc''s send buffer. Returns 0 if successful,
* otherwise a positive errno value. */
@@ -742,6 +778,7 @@ try_send(struct rconn *rc)
{
int retval = 0;
struct ofpbuf *next = rc->txq.head->next;
struct ofp_header *h = rc->txq.head->data;
int *n_queued = rc->txq.head->private;
ofpstat_inc_protocol_stat(&rc->ofps_sent, h);
rc->idle_echo_xid = h->xid;
+3
View File
@@ -52,6 +52,7 @@
*/
struct vconn;
struct ofpstat;
struct rconn *rconn_new(const char *name,
int inactivity_probe_interval, int max_backoff);
@@ -92,5 +93,7 @@ unsigned long int rconn_get_total_time_connected(const struct rconn *);
int rconn_get_backoff(const struct rconn *);
unsigned int rconn_get_state_elapsed(const struct rconn *);
unsigned int rconn_get_connection_seqno(const struct rconn *);
void rconn_update_protocol_stat(struct rconn *,
struct ofpstat *, struct ofpstat *);
#endif /* rconn.h */
+4
View File
@@ -38,6 +38,8 @@
* OpenFlow device. */
#include <assert.h>
#include <stdint.h>
#include "ofpstat.h"
#include "vconn.h"
/* Active virtual connection to an OpenFlow device. */
@@ -54,6 +56,8 @@ struct vconn {
uint32_t ip;
char *name;
bool reconnectable;
struct ofpstat ofps_rcvd;
struct ofpstat ofps_sent;
};
void vconn_init(struct vconn *, struct vconn_class *, int connect_status,
+10
View File
@@ -308,6 +308,8 @@ vcs_send_hello(struct vconn *vconn)
make_openflow(sizeof(struct ofp_header), OFPT_HELLO, &b);
retval = do_send(vconn, b);
if (!retval) {
++vconn->ofps_sent.ofps_total;
++vconn->ofps_sent.ofps_hello;
vconn->state = VCS_RECV_HELLO;
} else {
ofpbuf_delete(b);
@@ -353,6 +355,8 @@ vcs_recv_hello(struct vconn *vconn)
OFP_VERSION, oh->version);
vconn->state = VCS_CONNECTED;
}
++vconn->ofps_rcvd.ofps_total;
++vconn->ofps_rcvd.ofps_hello;
ofpbuf_delete(b);
return;
} else {
@@ -389,6 +393,10 @@ vcs_send_error(struct vconn *vconn)
update_openflow_length(b);
retval = do_send(vconn, b);
if (retval) {
++vconn->ofps_sent.ofps_total;
++vconn->ofps_sent.ofps_error;
++vconn->ofps_sent.ofps_error_type.hello_fail;
++vconn->ofps_sent.ofps_error_code.hf_incompat;
ofpbuf_delete(b);
}
if (retval != EAGAIN) {
@@ -1138,6 +1146,8 @@ vconn_init(struct vconn *vconn, struct vconn_class *class, int connect_status,
vconn->ip = ip;
vconn->name = xstrdup(name);
vconn->reconnectable = reconnectable;
memset(&vconn->ofps_rcvd, 0, sizeof(vconn->ofps_rcvd));
memset(&vconn->ofps_sent, 0, sizeof(vconn->ofps_sent));
}
void
+1
View File
@@ -30,6 +30,7 @@ VLOG_MODULE(pcap)
VLOG_MODULE(poll_loop)
VLOG_MODULE(port_watcher)
VLOG_MODULE(process)
VLOG_MODULE(protocol_stat)
VLOG_MODULE(secchan)
VLOG_MODULE(rconn)
VLOG_MODULE(snat)