Message ID | 1500299292-28094-1-git-send-email-antonio.fischetti@intel.com |
---|---|
State | Superseded |
Headers | show |
I have not tested it yet, but will do that later today or tomorrow. I have a few comments inline. On 7/17/17, 6:48 AM, "ovs-dev-bounces@openvswitch.org on behalf of antonio.fischetti@intel.com" <ovs-dev-bounces@openvswitch.org on behalf of antonio.fischetti@intel.com> wrote: 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> --- 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) The parameters can also include the number of buckets. { 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) Please don’t move these defines from the Userspace conntrack module itself. The associated datastructures are in the Userspace conntrack module itself and hence the defines belong here. The API conn_to_ct_dpif_entry() can also return the number of buckets. - 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, >)) { + 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 _______________________________________________ dev mailing list dev@openvswitch.org https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.openvswitch.org_mailman_listinfo_ovs-2Ddev&d=DwICAg&c=uilaK90D4TOVoH58JNXRgQ&r=BVhFA09CGX7JQ5Ih-uZnsw&m=mpxzw0ihtwMc63o5o0OOvPxnPY4M4Wy_F9JJ_3A5QGo&s=Molb6s0sAKhqp9Id74o8zTklq4M-O2e38H5OoddYP_s&e=
Thanks Darrel for your feedback, I'll post a v3 soon. Antonio > -----Original Message----- > From: Darrell Ball [mailto:dball@vmware.com] > Sent: Monday, July 17, 2017 6:03 PM > To: Fischetti, Antonio <antonio.fischetti@intel.com>; dev@openvswitch.org > Subject: Re: [ovs-dev] [PATCH v2] dpctl: Add new 'ct-bkts' command. > > I have not tested it yet, but will do that later today or tomorrow. > I have a few comments inline. > > On 7/17/17, 6:48 AM, "ovs-dev-bounces@openvswitch.org on behalf of > antonio.fischetti@intel.com" <ovs-dev-bounces@openvswitch.org on behalf of > antonio.fischetti@intel.com> wrote: > > 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> > --- > 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) > > The parameters can also include the number of buckets. > > > { > 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) > > Please don’t move these defines from the Userspace conntrack module > itself. > The associated datastructures are in the Userspace conntrack module itself > and hence > the defines belong here. > > The API conn_to_ct_dpif_entry() can also return the number of buckets. > > > - > 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, >)) { > + 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 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://urldefense.proofpoint.com/v2/url?u=https- > 3A__mail.openvswitch.org_mailman_listinfo_ovs- > 2Ddev&d=DwICAg&c=uilaK90D4TOVoH58JNXRgQ&r=BVhFA09CGX7JQ5Ih- > uZnsw&m=mpxzw0ihtwMc63o5o0OOvPxnPY4M4Wy_F9JJ_3A5QGo&s=Molb6s0sAKhqp9Id74o8 > zTklq4M-O2e38H5OoddYP_s&e= >
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, >)) { + 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"