[ovs-dev] [PATCH v2] dpctl: Add new 'ct-bkts' command.

antonio.fischetti at intel.com antonio.fischetti at intel.com
Mon Jul 17 13:48:12 UTC 2017


With the command:
 ovs-appctl dpctl/ct-bkts
shows the number of connections per bucket.

By using a threshold:
 ovs-appctl dpctl/ct-bkts gt=N
for each bucket shows the number of connections when they
are greater than N.

Signed-off-by: Antonio Fischetti <antonio.fischetti at intel.com>
Signed-off-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy at intel.com>
Co-authored-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy at intel.com>
---
 lib/conntrack.c       |  5 +--
 lib/conntrack.h       |  4 +--
 lib/ct-dpif.h         |  4 +++
 lib/dpctl.c           | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/dpctl.man         |  8 +++++
 utilities/ovs-dpctl.c |  1 +
 6 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/lib/conntrack.c b/lib/conntrack.c
index de46a6b..e986115 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1931,7 +1931,7 @@ conn_key_to_tuple(const struct conn_key *key, struct ct_dpif_tuple *tuple)
 
 static void
 conn_to_ct_dpif_entry(const struct conn *conn, struct ct_dpif_entry *entry,
-                      long long now)
+                      long long now, int bkt)
 {
     struct ct_l4_proto *class;
     long long expiration;
@@ -1954,6 +1954,7 @@ conn_to_ct_dpif_entry(const struct conn *conn, struct ct_dpif_entry *entry,
     if (class->conn_get_protoinfo) {
         class->conn_get_protoinfo(conn, &entry->protoinfo);
     }
+    entry->bkt = bkt;
 }
 
 int
@@ -1991,7 +1992,7 @@ conntrack_dump_next(struct conntrack_dump *dump, struct ct_dpif_entry *entry)
             INIT_CONTAINER(conn, node, node);
             if ((!dump->filter_zone || conn->key.zone == dump->zone) &&
                  (conn->conn_type != CT_CONN_TYPE_UN_NAT)) {
-                conn_to_ct_dpif_entry(conn, entry, now);
+                conn_to_ct_dpif_entry(conn, entry, now, dump->bucket);
                 break;
             }
             /* Else continue, until we find an entry in the appropriate zone
diff --git a/lib/conntrack.h b/lib/conntrack.h
index defde4c..81eb9df 100644
--- a/lib/conntrack.h
+++ b/lib/conntrack.h
@@ -28,6 +28,7 @@
 #include "ovs-atomic.h"
 #include "ovs-thread.h"
 #include "packets.h"
+#include "ct-dpif.h"
 
 /* Userspace connection tracker
  * ============================
@@ -242,9 +243,6 @@ struct conntrack_bucket {
     long long next_cleanup OVS_GUARDED;
 };
 
-#define CONNTRACK_BUCKETS_SHIFT 8
-#define CONNTRACK_BUCKETS (1 << CONNTRACK_BUCKETS_SHIFT)
-
 struct conntrack {
     /* Independent buckets containing the connections */
     struct conntrack_bucket buckets[CONNTRACK_BUCKETS];
diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h
index cd35f3e..b2a2f9e 100644
--- a/lib/ct-dpif.h
+++ b/lib/ct-dpif.h
@@ -20,6 +20,9 @@
 #include "openvswitch/types.h"
 #include "packets.h"
 
+#define CONNTRACK_BUCKETS_SHIFT 8
+#define CONNTRACK_BUCKETS (1 << CONNTRACK_BUCKETS_SHIFT)
+
 union ct_dpif_inet_addr {
     ovs_be32 ip;
     ovs_be32 ip6[4];
@@ -169,6 +172,7 @@ struct ct_dpif_entry {
     /* Timeout for this entry in seconds */
     uint32_t timeout;
     uint32_t mark;
+    int bkt; /* Number of CT bucket. */
 };
 
 enum {
diff --git a/lib/dpctl.c b/lib/dpctl.c
index 6aa6c8e..c3efc5b 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -1464,6 +1464,93 @@ dpctl_ct_stats_show(int argc, const char *argv[],
     dpif_close(dpif);
     return error;
 }
+
+#define CT_BKTS_GT "gt="
+static int
+dpctl_ct_bkts(int argc, const char *argv[],
+                     struct dpctl_params *dpctl_p)
+{
+    struct dpif *dpif;
+    char *name;
+
+    struct ct_dpif_dump_state *dump;
+    struct ct_dpif_entry cte;
+    uint16_t gt = 0; /* Threshold: display value when greater than gt. */
+    uint16_t *pzone = NULL;
+    int lastargc = 0;
+
+    int conn_per_bkts[CONNTRACK_BUCKETS];
+    int error;
+
+    if (!dpctl_p->is_appctl) {
+        /* Not called by ovs-appctl command then exit. */
+        dpctl_print(dpctl_p,
+            "Command is available for UserSpace ConnTracker only.\n");
+        return 0;
+    }
+
+    while (argc > 1 && lastargc != argc) {
+        lastargc = argc;
+        if (!strncmp(argv[argc - 1], CT_BKTS_GT, strlen(CT_BKTS_GT))) {
+            if (ovs_scan(argv[argc - 1], CT_BKTS_GT"%"SCNu16, &gt)) {
+                argc--;
+            }
+        }
+    }
+
+    name = (argc > 1) ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
+    if (!name) {
+        return EINVAL;
+    }
+
+    error = parsed_dpif_open(name, false, &dpif);
+    free(name);
+    if (error) {
+        dpctl_error(dpctl_p, error, "opening datapath");
+        return error;
+    }
+
+    error = ct_dpif_dump_start(dpif, &dump, pzone);
+    if (error) {
+        dpctl_error(dpctl_p, error, "starting conntrack dump");
+        dpif_close(dpif);
+        return error;
+    }
+
+    memset(conn_per_bkts, 0, sizeof(conn_per_bkts));
+    int tot_conn = 0;
+    while (!ct_dpif_dump_next(dump, &cte)) {
+        ct_dpif_entry_uninit(&cte);
+        tot_conn++;
+        if (cte.bkt < CONNTRACK_BUCKETS) {
+            conn_per_bkts[cte.bkt]++;
+        } else {
+            dpctl_print(dpctl_p, "Bucket nr out of range: %d\n", cte.bkt);
+        }
+    }
+
+    dpctl_print(dpctl_p, "Current Connections: %d\n", tot_conn);
+    dpctl_print(dpctl_p, "|  Buckets  |"
+            "         Connections per Buckets         |\n");
+    dpctl_print(dpctl_p, "+-----------+"
+            "-----------------------------------------+");
+#define NUM_BKTS_PER_ROW 8
+    for (int i = 0; i < CONNTRACK_BUCKETS; i++) {
+        if (i % NUM_BKTS_PER_ROW == 0) {
+             dpctl_print(dpctl_p, "\n %3d..%3d   | ",
+                     i, i + NUM_BKTS_PER_ROW - 1);
+        }
+        if (conn_per_bkts[i] > gt) {
+            dpctl_print(dpctl_p, "%5d", conn_per_bkts[i]);
+        } else {
+            dpctl_print(dpctl_p, "%5s", ".");
+        }
+    }
+    dpctl_print(dpctl_p, "\n\n");
+    ct_dpif_dump_done(dump);
+    dpif_close(dpif);
+    return error;
+}
 
 /* Undocumented commands for unit testing. */
 
@@ -1760,6 +1847,7 @@ static const struct dpctl_command all_commands[] = {
     { "flush-conntrack", "[dp] [zone=N]", 0, 2, dpctl_flush_conntrack, DP_RW },
     { "ct-stats-show", "[dp] [zone=N] [verbose]",
       0, 3, dpctl_ct_stats_show, DP_RO },
+    { "ct-bkts", "[dp] [gt=N]", 0, 2, dpctl_ct_bkts, DP_RO },
     { "help", "", 0, INT_MAX, dpctl_help, DP_RO },
     { "list-commands", "", 0, INT_MAX, dpctl_list_commands, DP_RO },
 
diff --git a/lib/dpctl.man b/lib/dpctl.man
index f95d54a..1c77085 100644
--- a/lib/dpctl.man
+++ b/lib/dpctl.man
@@ -228,3 +228,11 @@ Displays the number of connections grouped by protocol used by \fIdp\fR.
 If \fBzone=\fIzone\fR is specified, numbers refer to the connections in
 \fBzone\fR. The \fBverbose\fR option allows to group by connection state
 for each protocol.
+.
+.TP
+\*(DX\fBct\-bkts\fR [\fIdp\fR] [\fBgt=\fIThreshold\fR]
+For each ConnTracker bucket, displays the number of connections used
+by \fIdp\fR.
+If \fBgt=\fIThreshold\fR is specified, bucket numbers are displayed when
+greater than \fIThreshold\fR.
+
diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c
index 7292fca..7b005ac 100644
--- a/utilities/ovs-dpctl.c
+++ b/utilities/ovs-dpctl.c
@@ -202,6 +202,7 @@ usage(void *userdata OVS_UNUSED)
                "delete all conntrack entries in ZONE\n"
            "  ct-stats-show [DP] [zone=ZONE] [verbose] " \
                "CT connections grouped by protocol\n"
+           "  ct-bkts [DP] [gt=N] display connections per CT bucket\n"
            "Each IFACE on add-dp, add-if, and set-if may be followed by\n"
            "comma-separated options.  See ovs-dpctl(8) for syntax, or the\n"
            "Interface table in ovs-vswitchd.conf.db(5) for an options list.\n"
-- 
2.4.11



More information about the dev mailing list