From: Justin Pettit Date: Mon, 14 Nov 2011 23:04:14 +0000 (-0800) Subject: stp: Track BPDU tx and rx counts. X-Git-Tag: v1.4.0~154 X-Git-Url: http://git.cascardo.eti.br/?a=commitdiff_plain;h=80740385d2700b1a03d28a02338d02509fd0b697;p=cascardo%2Fovs.git stp: Track BPDU tx and rx counts. When debugging spanning tree, it's useful to have counters about how many BPDUs have been sent and received. This commit keeps track of these counters and stores them in a new "statistics" column of the Port table. Feature #8103 --- diff --git a/lib/stp.c b/lib/stp.c index 94b9a4b5b..62c2ea8ac 100644 --- a/lib/stp.c +++ b/lib/stp.c @@ -93,6 +93,10 @@ struct stp_port { struct stp_timer forward_delay_timer; /* 8.5.6.2: State change timer. */ struct stp_timer hold_timer; /* 8.5.6.3: BPDU rate limit timer. */ + int tx_count; /* Number of BPDUs transmitted. */ + int rx_count; /* Number of valid BPDUs received. */ + int error_count; /* Number of bad BPDUs received. */ + bool state_changed; }; @@ -562,6 +566,7 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) if (bpdu_size < sizeof(struct stp_bpdu_header)) { VLOG_WARN("%s: received runt %zu-byte BPDU", stp->name, bpdu_size); + p->error_count++; return; } @@ -569,6 +574,7 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) if (header->protocol_id != htons(STP_PROTOCOL_ID)) { VLOG_WARN("%s: received BPDU with unexpected protocol ID %"PRIu16, stp->name, ntohs(header->protocol_id)); + p->error_count++; return; } if (header->protocol_version != STP_PROTOCOL_VERSION) { @@ -581,6 +587,7 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) if (bpdu_size < sizeof(struct stp_config_bpdu)) { VLOG_WARN("%s: received config BPDU with invalid size %zu", stp->name, bpdu_size); + p->error_count++; return; } stp_received_config_bpdu(stp, p, bpdu); @@ -590,6 +597,7 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) if (bpdu_size != sizeof(struct stp_tcn_bpdu)) { VLOG_WARN("%s: received TCN BPDU with invalid size %zu", stp->name, bpdu_size); + p->error_count++; return; } stp_received_tcn_bpdu(stp, p); @@ -598,8 +606,10 @@ stp_received_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) default: VLOG_WARN("%s: received BPDU of unexpected type %"PRIu8, stp->name, header->bpdu_type); + p->error_count++; return; } + p->rx_count++; } /* Returns the STP entity in which 'p' is nested. */ @@ -667,6 +677,15 @@ stp_port_get_role(const struct stp_port *p) } } +/* Retrieves BPDU transmit and receive counts for 'p'. */ +void stp_port_get_counts(const struct stp_port *p, + int *tx_count, int *rx_count, int *error_count) +{ + *tx_count = p->tx_count; + *rx_count = p->rx_count; + *error_count = p->error_count; +} + /* Disables STP on port 'p'. */ void stp_port_disable(struct stp_port *p) @@ -1185,6 +1204,7 @@ stp_initialize_port(struct stp_port *p, enum stp_state state) stp_stop_timer(&p->message_age_timer); stp_stop_timer(&p->forward_delay_timer); stp_stop_timer(&p->hold_timer); + p->tx_count = p->rx_count = p->error_count = 0; } static void @@ -1299,4 +1319,5 @@ stp_send_bpdu(struct stp_port *p, const void *bpdu, size_t bpdu_size) llc->llc_cntl = STP_LLC_CNTL; p->stp->send_bpdu(pkt, stp_port_no(p), p->stp->aux); + p->tx_count++; } diff --git a/lib/stp.h b/lib/stp.h index 54f7f5b45..ec29d9a77 100644 --- a/lib/stp.h +++ b/lib/stp.h @@ -136,6 +136,8 @@ int stp_port_no(const struct stp_port *); int stp_port_get_id(const struct stp_port *); enum stp_state stp_port_get_state(const struct stp_port *); enum stp_role stp_port_get_role(const struct stp_port *); +void stp_port_get_counts(const struct stp_port *, + int *tx_count, int *rx_count, int *error_count); void stp_port_enable(struct stp_port *); void stp_port_disable(struct stp_port *); void stp_port_set_priority(struct stp_port *, uint8_t new_priority); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index d525d4e7d..4cc720667 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1105,6 +1105,7 @@ get_stp_port_status(struct ofport *ofport_, s->state = stp_port_get_state(sp); s->sec_in_state = (time_msec() - ofport->stp_state_entered) / 1000; s->role = stp_port_get_role(sp); + stp_port_get_counts(sp, &s->tx_count, &s->rx_count, &s->error_count); return 0; } diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index 4b37bd78f..eed4e5083 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -94,6 +94,9 @@ struct ofproto_port_stp_status { enum stp_state state; unsigned int sec_in_state; enum stp_role role; + int tx_count; /* Number of BPDUs transmitted. */ + int rx_count; /* Number of valid BPDUs received. */ + int error_count; /* Number of bad BPDUs received. */ }; /* How the switch should act if the controller cannot be contacted. */ diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 5100b7870..6a25b9590 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -240,6 +240,7 @@ bridge_init(const char *remote) ovsdb_idl_omit(idl, &ovsrec_bridge_col_external_ids); ovsdb_idl_omit_alert(idl, &ovsrec_port_col_status); + ovsdb_idl_omit_alert(idl, &ovsrec_port_col_statistics); ovsdb_idl_omit(idl, &ovsrec_port_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_port_col_fake_bridge); @@ -1598,7 +1599,9 @@ port_refresh_stp_status(struct port *port) struct ofproto *ofproto = port->bridge->ofproto; struct iface *iface; struct ofproto_port_stp_status status; - char *keys[4], *values[4]; + char *keys[4]; + char *str_values[4]; + int64_t int_values[3]; size_t i; if (port_is_synthetic(port)) { @@ -1619,23 +1622,37 @@ port_refresh_stp_status(struct port *port) if (!status.enabled) { ovsrec_port_set_status(port->cfg, NULL, NULL, 0); + ovsrec_port_set_statistics(port->cfg, NULL, NULL, 0); return; } - keys[0] = "stp_port_id"; - values[0] = xasprintf(STP_PORT_ID_FMT, status.port_id); + /* Set Status column. */ + keys[0] = "stp_port_id"; + str_values[0] = xasprintf(STP_PORT_ID_FMT, status.port_id); keys[1] = "stp_state"; - values[1] = xstrdup(stp_state_name(status.state)); + str_values[1] = xstrdup(stp_state_name(status.state)); keys[2] = "stp_sec_in_state"; - values[2] = xasprintf("%u", status.sec_in_state); + str_values[2] = xasprintf("%u", status.sec_in_state); keys[3] = "stp_role"; - values[3] = xstrdup(stp_role_name(status.role)); + str_values[3] = xstrdup(stp_role_name(status.role)); - ovsrec_port_set_status(port->cfg, keys, values, ARRAY_SIZE(values)); + ovsrec_port_set_status(port->cfg, keys, str_values, + ARRAY_SIZE(str_values)); - for (i = 0; i < ARRAY_SIZE(values); i++) { - free(values[i]); + for (i = 0; i < ARRAY_SIZE(str_values); i++) { + free(str_values[i]); } + + /* Set Statistics column. */ + keys[0] = "stp_tx_count"; + int_values[0] = status.tx_count; + keys[1] = "stp_rx_count"; + int_values[1] = status.rx_count; + keys[2] = "stp_error_count"; + int_values[2] = status.error_count; + + ovsrec_port_set_statistics(port->cfg, keys, int_values, + ARRAY_SIZE(int_values)); } static bool diff --git a/vswitchd/vswitch.ovsschema b/vswitchd/vswitch.ovsschema index 3a9c51fb0..19c59227c 100644 --- a/vswitchd/vswitch.ovsschema +++ b/vswitchd/vswitch.ovsschema @@ -1,6 +1,6 @@ {"name": "Open_vSwitch", - "version": "6.2.0", - "cksum": "145151998 15203", + "version": "6.3.0", + "cksum": "1659474737 15341", "tables": { "Open_vSwitch": { "columns": { @@ -150,6 +150,9 @@ "status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}, + "statistics": { + "type": {"key": "string", "value": "integer", "min": 0, "max": "unlimited"}, + "ephemeral": true}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index 80d9cdccf..7d2a72a73 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -986,6 +986,26 @@ + +

+ Key-value pairs that report port statistics. +

+ + + Number of STP BPDUs sent on this port by the spanning + tree library. + + + Number of STP BPDUs received on this port and accepted by the + spanning tree library. + + + Number of bad STP BPDUs received on this port. Bad BPDUs + include runt packets and those with an unexpected protocol ID. + + +
+ The overall purpose of these columns is described under Common Columns at the beginning of this document.