summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Fischetti <antonio.fischetti@intel.com>2017-08-01 20:12:03 -0700
committerBen Pfaff <blp@ovn.org>2017-08-02 10:18:55 -0700
commitded30c74b1e57af84416cdf6c5babd66b1f48ee6 (patch)
tree8cb8adf3c3320a4c743bc9fa6aa188f8bea61a8e
parent324459a39d17559d1adcb42b9d141b0288a75127 (diff)
downloadopenvswitch-ded30c74b1e57af84416cdf6c5babd66b1f48ee6.tar.gz
dpctl: Add new 'ct-bkts' command.
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@intel.com> Signed-off-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy@intel.com> Co-authored-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy@intel.com> Signed-off-by: Darrell Ball <dlu998@gmail.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
-rw-r--r--lib/conntrack.c9
-rw-r--r--lib/conntrack.h2
-rw-r--r--lib/ct-dpif.c4
-rw-r--r--lib/ct-dpif.h3
-rw-r--r--lib/dpctl.c103
-rw-r--r--lib/dpctl.man7
-rw-r--r--lib/dpif-netdev.c4
-rw-r--r--lib/dpif-netlink.c4
-rw-r--r--lib/dpif-provider.h2
-rw-r--r--lib/netlink-conntrack.c6
-rw-r--r--lib/netlink-conntrack.h3
-rw-r--r--tests/test-netlink-conntrack.c3
-rw-r--r--utilities/ovs-dpctl.c1
13 files changed, 134 insertions, 17 deletions
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 554ea2bae..cce1f2ca5 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -1948,7 +1948,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;
@@ -1971,11 +1971,12 @@ 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
conntrack_dump_start(struct conntrack *ct, struct conntrack_dump *dump,
- const uint16_t *pzone)
+ const uint16_t *pzone, int *ptot_bkts)
{
memset(dump, 0, sizeof(*dump));
if (pzone) {
@@ -1984,6 +1985,8 @@ conntrack_dump_start(struct conntrack *ct, struct conntrack_dump *dump,
}
dump->ct = ct;
+ *ptot_bkts = CONNTRACK_BUCKETS;
+
return 0;
}
@@ -2008,7 +2011,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 defde4c5f..3f484442d 100644
--- a/lib/conntrack.h
+++ b/lib/conntrack.h
@@ -108,7 +108,7 @@ struct conntrack_dump {
struct ct_dpif_entry;
int conntrack_dump_start(struct conntrack *, struct conntrack_dump *,
- const uint16_t *pzone);
+ const uint16_t *pzone, int *);
int conntrack_dump_next(struct conntrack_dump *, struct ct_dpif_entry *);
int conntrack_dump_done(struct conntrack_dump *);
diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c
index f8d2cf12f..c79e69e23 100644
--- a/lib/ct-dpif.c
+++ b/lib/ct-dpif.c
@@ -65,12 +65,12 @@ static const struct flags ct_dpif_status_flags[] = {
* that represents the error. Otherwise it returns zero. */
int
ct_dpif_dump_start(struct dpif *dpif, struct ct_dpif_dump_state **dump,
- const uint16_t *zone)
+ const uint16_t *zone, int *ptot_bkts)
{
int err;
err = (dpif->dpif_class->ct_dump_start
- ? dpif->dpif_class->ct_dump_start(dpif, dump, zone)
+ ? dpif->dpif_class->ct_dump_start(dpif, dump, zone, ptot_bkts)
: EOPNOTSUPP);
if (!err) {
diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h
index cd35f3ece..d5f966175 100644
--- a/lib/ct-dpif.h
+++ b/lib/ct-dpif.h
@@ -169,6 +169,7 @@ struct ct_dpif_entry {
/* Timeout for this entry in seconds */
uint32_t timeout;
uint32_t mark;
+ uint32_t bkt; /* CT bucket number. */
};
enum {
@@ -191,7 +192,7 @@ struct ct_dpif_dump_state {
};
int ct_dpif_dump_start(struct dpif *, struct ct_dpif_dump_state **,
- const uint16_t *zone);
+ const uint16_t *zone, int *);
int ct_dpif_dump_next(struct ct_dpif_dump_state *, struct ct_dpif_entry *);
int ct_dpif_dump_done(struct ct_dpif_dump_state *);
int ct_dpif_flush(struct dpif *, const uint16_t *zone);
diff --git a/lib/dpctl.c b/lib/dpctl.c
index 6aa6c8e9e..59f09b7e5 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -1258,6 +1258,7 @@ dpctl_dump_conntrack(int argc, const char *argv[],
struct ct_dpif_dump_state *dump;
struct ct_dpif_entry cte;
uint16_t zone, *pzone = NULL;
+ int tot_bkts;
struct dpif *dpif;
char *name;
int error;
@@ -1277,7 +1278,7 @@ dpctl_dump_conntrack(int argc, const char *argv[],
return error;
}
- error = ct_dpif_dump_start(dpif, &dump, pzone);
+ error = ct_dpif_dump_start(dpif, &dump, pzone, &tot_bkts);
if (error) {
dpctl_error(dpctl_p, error, "starting conntrack dump");
dpif_close(dpif);
@@ -1339,6 +1340,7 @@ dpctl_ct_stats_show(int argc, const char *argv[],
struct ct_dpif_dump_state *dump;
struct ct_dpif_entry cte;
uint16_t zone, *pzone = NULL;
+ int tot_bkts;
bool verbose = false;
int lastargc = 0;
@@ -1373,7 +1375,7 @@ dpctl_ct_stats_show(int argc, const char *argv[],
memset(proto_stats, 0, sizeof(proto_stats));
memset(tcp_conn_per_states, 0, sizeof(tcp_conn_per_states));
- error = ct_dpif_dump_start(dpif, &dump, pzone);
+ error = ct_dpif_dump_start(dpif, &dump, pzone, &tot_bkts);
if (error) {
dpctl_error(dpctl_p, error, "starting conntrack dump");
dpif_close(dpif);
@@ -1464,6 +1466,102 @@ 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 tot_bkts = 0;
+ int error;
+
+ if (argc > 1 && !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 == 2) ? 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, &tot_bkts);
+ if (error) {
+ dpctl_error(dpctl_p, error, "starting conntrack dump");
+ dpif_close(dpif);
+ return error;
+ }
+ if (tot_bkts == -1) {
+ /* Command not available when called by kernel OvS. */
+ dpctl_print(dpctl_p,
+ "Command is available for UserSpace ConnTracker only.\n");
+ ct_dpif_dump_done(dump);
+ dpif_close(dpif);
+ return 0;
+ }
+
+ dpctl_print(dpctl_p, "Total Buckets: %d\n", tot_bkts);
+
+ int tot_conn = 0;
+ uint32_t *conn_per_bkts = xzalloc(tot_bkts * sizeof(uint32_t));
+
+ while (!ct_dpif_dump_next(dump, &cte)) {
+ ct_dpif_entry_uninit(&cte);
+ tot_conn++;
+ if (tot_bkts > 0) {
+ if (cte.bkt < tot_bkts) {
+ conn_per_bkts[cte.bkt]++;
+ } else {
+ dpctl_print(dpctl_p, "Bucket nr out of range: %d >= %d\n",
+ cte.bkt, tot_bkts);
+ }
+ }
+ }
+
+ dpctl_print(dpctl_p, "Current Connections: %d\n", tot_conn);
+ dpctl_print(dpctl_p, "\n");
+ if (tot_bkts && tot_conn) {
+ dpctl_print(dpctl_p, "+-----------+"
+ "-----------------------------------------+\n");
+ dpctl_print(dpctl_p, "| Buckets |"
+ " Connections per Buckets |\n");
+ dpctl_print(dpctl_p, "+-----------+"
+ "-----------------------------------------+");
+#define NUM_BKTS_DIPLAYED_PER_ROW 8
+ for (int i = 0; i < tot_bkts; i++) {
+ if (i % NUM_BKTS_DIPLAYED_PER_ROW == 0) {
+ dpctl_print(dpctl_p, "\n %3d..%3d | ",
+ i, i + NUM_BKTS_DIPLAYED_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);
+ free(conn_per_bkts);
+ return error;
+}
/* Undocumented commands for unit testing. */
@@ -1760,6 +1858,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 f95d54a81..675fe5af4 100644
--- a/lib/dpctl.man
+++ b/lib/dpctl.man
@@ -228,3 +228,10 @@ 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
+the number of connections in a bucket is greater than \fIThreshold\fR.
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 284cecc74..e0af1792f 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -5437,7 +5437,7 @@ struct dp_netdev_ct_dump {
static int
dpif_netdev_ct_dump_start(struct dpif *dpif, struct ct_dpif_dump_state **dump_,
- const uint16_t *pzone)
+ const uint16_t *pzone, int *ptot_bkts)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
struct dp_netdev_ct_dump *dump;
@@ -5446,7 +5446,7 @@ dpif_netdev_ct_dump_start(struct dpif *dpif, struct ct_dpif_dump_state **dump_,
dump->dp = dp;
dump->ct = &dp->conntrack;
- conntrack_dump_start(&dp->conntrack, &dump->dump, pzone);
+ conntrack_dump_start(&dp->conntrack, &dump->dump, pzone, ptot_bkts);
*dump_ = &dump->up;
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index a75d25f8b..29001fbe4 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -2848,13 +2848,13 @@ struct dpif_netlink_ct_dump_state {
static int
dpif_netlink_ct_dump_start(struct dpif *dpif OVS_UNUSED,
struct ct_dpif_dump_state **dump_,
- const uint16_t *zone)
+ const uint16_t *zone, int *ptot_bkts)
{
struct dpif_netlink_ct_dump_state *dump;
int err;
dump = xzalloc(sizeof *dump);
- err = nl_ct_dump_start(&dump->nl_ct_dump, zone);
+ err = nl_ct_dump_start(&dump->nl_ct_dump, zone, ptot_bkts);
if (err) {
free(dump);
return err;
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index 64ac2e2af..1d82a0939 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -419,7 +419,7 @@ struct dpif_class {
* ct_dump_done() should perform any cleanup necessary (including
* deallocating the 'state' structure, if applicable). */
int (*ct_dump_start)(struct dpif *, struct ct_dpif_dump_state **state,
- const uint16_t *zone);
+ const uint16_t *zone, int *);
int (*ct_dump_next)(struct dpif *, struct ct_dpif_dump_state *state,
struct ct_dpif_entry *entry);
int (*ct_dump_done)(struct dpif *, struct ct_dpif_dump_state *state);
diff --git a/lib/netlink-conntrack.c b/lib/netlink-conntrack.c
index f0e2aeac8..ac48b15bd 100644
--- a/lib/netlink-conntrack.c
+++ b/lib/netlink-conntrack.c
@@ -123,7 +123,8 @@ struct nl_ct_dump_state {
/* Initialize a conntrack netlink dump. */
int
-nl_ct_dump_start(struct nl_ct_dump_state **statep, const uint16_t *zone)
+nl_ct_dump_start(struct nl_ct_dump_state **statep, const uint16_t *zone,
+ int *ptot_bkts)
{
struct nl_ct_dump_state *state;
@@ -140,6 +141,9 @@ nl_ct_dump_start(struct nl_ct_dump_state **statep, const uint16_t *zone)
nl_dump_start(&state->dump, NETLINK_NETFILTER, &state->buf);
ofpbuf_clear(&state->buf);
+ /* Buckets to store connections are not used. */
+ *ptot_bkts = -1;
+
return 0;
}
diff --git a/lib/netlink-conntrack.h b/lib/netlink-conntrack.h
index 1263b2158..a95aa69a4 100644
--- a/lib/netlink-conntrack.h
+++ b/lib/netlink-conntrack.h
@@ -35,7 +35,8 @@ enum nl_ct_event_type {
struct nl_ct_dump_state;
-int nl_ct_dump_start(struct nl_ct_dump_state **, const uint16_t *zone);
+int nl_ct_dump_start(struct nl_ct_dump_state **, const uint16_t *zone,
+ int *ptot_bkts);
int nl_ct_dump_next(struct nl_ct_dump_state *, struct ct_dpif_entry *);
int nl_ct_dump_done(struct nl_ct_dump_state *);
diff --git a/tests/test-netlink-conntrack.c b/tests/test-netlink-conntrack.c
index 000062d26..0d9dacee9 100644
--- a/tests/test-netlink-conntrack.c
+++ b/tests/test-netlink-conntrack.c
@@ -106,6 +106,7 @@ test_nl_ct_dump(struct ovs_cmdl_context *ctx)
uint16_t zone, *pzone = NULL;
struct ct_dpif_entry entry;
int err;
+ int tot_bkts;
if (ctx->argc >= 2) {
if (!ovs_scan(ctx->argv[1], "zone=%"SCNu16, &zone)) {
@@ -113,7 +114,7 @@ test_nl_ct_dump(struct ovs_cmdl_context *ctx)
}
pzone = &zone;
}
- err = nl_ct_dump_start(&dump, pzone);
+ err = nl_ct_dump_start(&dump, pzone, &tot_bkts);
if (err) {
ovs_fatal(err, "Error creating conntrack netlink dump");
}
diff --git a/utilities/ovs-dpctl.c b/utilities/ovs-dpctl.c
index 7292fca3f..7b005ace3 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"