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
---
lib/stp.c | 21 +++++++++++++++++++++
lib/stp.h | 2 ++
ofproto/ofproto-dpif.c | 1 +
ofproto/ofproto.h | 3 +++
vswitchd/bridge.c | 35 ++++++++++++++++++++++++++---------
vswitchd/vswitch.ovsschema | 7 +++++--
vswitchd/vswitch.xml | 20 ++++++++++++++++++++
7 files changed, 78 insertions(+), 11 deletions(-)
diff --git a/lib/stp.c b/lib/stp.c
index 94b9a4b..62c2ea8 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 54f7f5b..ec29d9a 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 d525d4e..4cc7206 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 4b37bd7..eed4e50 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 5100b78..6a25b95 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 3a9c51f..19c5922 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 80d9cdc..9945eeb 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -986,6 +986,26 @@
</column>
</group>
+ <group title="Port Statistics">
+ <p>
+ Key-value pairs that report port statistics.
+ </p>
+ <group title="Statistics: STP transmit and receive counters">
+ <column name="statistics" key="stp_tx_count">
+ Number of STP BPDUs sent on this interface by the spanning
+ tree library.
+ </column>
+ <column name="statistics" key="stp_rx_count">
+ Number of STP BPDUs received on this interface and accepted by
+ the spanning tree library.
+ </column>
+ <column name="statistics" key="stp_error_count">
+ Number of bad STP BPDUs received on this interface. Bad BPDUs
+ include runt packets and those with an unexpected protocol ID.
+ </column>
+ </group>
+ </group>
+
<group title="Common Columns">
The overall purpose of these columns is described under <code>Common
Columns</code> at the beginning of this document.
--
1.7.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev