[ovs-dev] [PATCH] Adding cli for displaying LACP counters

Nitin Katiyar nitin.katiyar at ericsson.com
Wed Apr 18 18:27:43 UTC 2018


Currently OVS does not provide any command to display stats for LACP
without which it is difficult to debug LACP issues. Here we propose
to display various statistics about LACP PDUs and slave state change.

Sample output:

ovs_lacp # ovs-appctl lacp/stats-show
---- bond-prv statistics ----

slave: dpdk0:
        RX PDUs: 128
        RX Bad PDUs: 0
        TX PDUs: 5
        Link Expired: 2
        Link Defaulted: 1
        Carrier Status Changed: 0

Signed-off-by: Nitin Katiyar <nitin.katiyar at ericsson.com>
---
 NEWS                       |  2 ++
 lib/lacp.c                 | 79 ++++++++++++++++++++++++++++++++++++++++++++--
 vswitchd/ovs-vswitchd.8.in |  6 ++++
 3 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 77c2b43..bdbe7e2 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,8 @@ Post-v2.9.0
        default it always accepts names and in interactive use it displays them;
        use --names or --no-names to override.  See ovs-ofctl(8) for details.
    - ovs-vsctl: New commands "add-bond-iface" and "del-bond-iface".
+   - ovs-appctl:
+     * New command "lacp/show-stats"
    - OpenFlow:
      * OFPT_ROLE_STATUS is now available in OpenFlow 1.3.
    - Linux kernel 4.14
diff --git a/lib/lacp.c b/lib/lacp.c
index fdefeda..8353746 100644
--- a/lib/lacp.c
+++ b/lib/lacp.c
@@ -127,9 +127,12 @@ struct slave {
     struct timer tx;              /* Next message transmission timer. */
     struct timer rx;              /* Expected message receive timer. */
 
-    uint32_t count_rx_pdus;       /* dot3adAggPortStatsLACPDUsRx */
-    uint32_t count_rx_pdus_bad;   /* dot3adAggPortStatsIllegalRx */
-    uint32_t count_tx_pdus;       /* dot3adAggPortStatsLACPDUsTx */
+    uint32_t count_rx_pdus;         /* dot3adAggPortStatsLACPDUsRx */
+    uint32_t count_rx_pdus_bad;     /* dot3adAggPortStatsIllegalRx */
+    uint32_t count_tx_pdus;         /* dot3adAggPortStatsLACPDUsTx */
+    uint32_t count_link_expired;    /* Num of times link expired */
+    uint32_t count_link_defaulted;  /* Num of times link defaulted */
+    uint32_t count_carrier_changed; /* Num of times link status changed */
 };
 
 static struct ovs_mutex mutex;
@@ -153,6 +156,7 @@ static bool info_tx_equal(struct lacp_info *, struct lacp_info *)
     OVS_REQUIRES(mutex);
 
 static unixctl_cb_func lacp_unixctl_show;
+static unixctl_cb_func lacp_unixctl_show_stats;
 
 /* Populates 'pdu' with a LACP PDU comprised of 'actor' and 'partner'. */
 static void
@@ -206,6 +210,8 @@ lacp_init(void)
 {
     unixctl_command_register("lacp/show", "[port]", 0, 1,
                              lacp_unixctl_show, NULL);
+    unixctl_command_register("lacp/show-stats", "[port]", 0, 1,
+                             lacp_unixctl_show_stats, NULL);
 }
 
 static void
@@ -459,6 +465,7 @@ lacp_slave_carrier_changed(const struct lacp *lacp, const void *slave_)
     if (slave->status == LACP_CURRENT || slave->lacp->active) {
         slave_set_expired(slave);
     }
+    slave->count_carrier_changed++;
 
 out:
     lacp_unlock();
@@ -525,8 +532,10 @@ lacp_run(struct lacp *lacp, lacp_send_pdu *send_pdu) OVS_EXCLUDED(mutex)
 
             if (slave->status == LACP_CURRENT) {
                 slave_set_expired(slave);
+                slave->count_link_expired++;
             } else if (slave->status == LACP_EXPIRED) {
                 slave_set_defaulted(slave);
+                slave->count_link_defaulted++;
             }
             if (slave->status != old_status) {
                 seq_change(connectivity_seq_get());
@@ -994,6 +1003,40 @@ lacp_print_details(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
 }
 
 static void
+lacp_print_stats(struct ds *ds, struct lacp *lacp) OVS_REQUIRES(mutex)
+{
+    struct shash slave_shash = SHASH_INITIALIZER(&slave_shash);
+    const struct shash_node **sorted_slaves = NULL;
+
+    struct slave *slave;
+    int i;
+
+    ds_put_format(ds, "---- %s statistics ----\n", lacp->name);
+
+    HMAP_FOR_EACH (slave, node, &lacp->slaves) {
+        shash_add(&slave_shash, slave->name, slave);
+    }
+    sorted_slaves = shash_sort(&slave_shash);
+
+    for (i = 0; i < shash_count(&slave_shash); i++) {
+        slave = sorted_slaves[i]->data;
+        ds_put_format(ds, "\nslave: %s:\n", slave->name);
+        ds_put_format(ds, "\tRX PDUs: %u\n", slave->count_rx_pdus);
+        ds_put_format(ds, "\tRX Bad PDUs: %u\n", slave->count_rx_pdus_bad);
+        ds_put_format(ds, "\tTX PDUs: %u\n", slave->count_tx_pdus);
+        ds_put_format(ds, "\tLink Expired: %u\n",
+                      slave->count_link_expired);
+        ds_put_format(ds, "\tLink Defaulted: %u\n",
+                      slave->count_link_defaulted);
+        ds_put_format(ds, "\tCarrier Status Changed: %u\n",
+                      slave->count_carrier_changed);
+    }
+
+    shash_destroy(&slave_shash);
+    free(sorted_slaves);
+}
+
+static void
 lacp_unixctl_show(struct unixctl_conn *conn, int argc, const char *argv[],
                   void *aux OVS_UNUSED) OVS_EXCLUDED(mutex)
 {
@@ -1021,6 +1064,36 @@ out:
     lacp_unlock();
 }
 
+static void
+lacp_unixctl_show_stats(struct unixctl_conn *conn,
+                  int argc,
+                  const char *argv[],
+                  void *aux OVS_UNUSED) OVS_EXCLUDED(mutex)
+{
+    struct ds ds = DS_EMPTY_INITIALIZER;
+    struct lacp *lacp;
+
+    lacp_lock();
+    if (argc > 1) {
+        lacp = lacp_find(argv[1]);
+        if (!lacp) {
+            unixctl_command_reply_error(conn, "no such lacp object");
+            goto out;
+        }
+        lacp_print_stats(&ds, lacp);
+    } else {
+        LIST_FOR_EACH (lacp, node, all_lacps) {
+            lacp_print_stats(&ds, lacp);
+        }
+    }
+
+    unixctl_command_reply(conn, ds_cstr(&ds));
+    ds_destroy(&ds);
+
+out:
+    lacp_unlock();
+}
+
 /* Extract a snapshot of the current state and counters for a slave port.
    Return false if the slave is not active. */
 bool
diff --git a/vswitchd/ovs-vswitchd.8.in b/vswitchd/ovs-vswitchd.8.in
index 80e5f53..b6f1929 100644
--- a/vswitchd/ovs-vswitchd.8.in
+++ b/vswitchd/ovs-vswitchd.8.in
@@ -240,6 +240,12 @@ whether it is attached or detached, port id and priority, actor
 information, and partner information.  If \fIport\fR is not specified,
 then displays detailed information about all interfaces with CFM
 enabled.
+.
+.IP "\fBlacp/stats-show\fR [\fIport\fR]"
+Lists various stats about LACP PDUs (number of RX/TX PDUs, bad PDUs received)
+and slave state (number of time slave's state expired/defaulted and carrier
+status changed) for the given \fIport\fR.  If \fIport\fR is not specified,
+then displays stats of all interfaces with LACP enabled.
 .SS "DPCTL DATAPATH DEBUGGING COMMANDS"
 The primary way to configure \fBovs\-vswitchd\fR is through the Open
 vSwitch database, e.g. using \fBovs\-vsctl\fR(8).  These commands
-- 
1.9.1



More information about the dev mailing list