Get and set dpctl commands are added for conntrack maxconns.
These commands are only supported in the userspace
datapath at this time.

Signed-off-by: Darrell Ball <[email protected]>
Signed-off-by: Antonio Fischetti <[email protected]>
Co-authored-by: Antonio Fischetti <[email protected]>
---
 NEWS                |  3 +++
 lib/conntrack.c     | 14 +++++++++++
 lib/conntrack.h     |  2 ++
 lib/ct-dpif.c       | 16 ++++++++++++
 lib/ct-dpif.h       |  2 ++
 lib/dpctl.c         | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/dpctl.man       | 16 ++++++++++++
 lib/dpif-netdev.c   | 18 ++++++++++++++
 lib/dpif-netlink.c  |  2 ++
 lib/dpif-provider.h |  4 +++
 10 files changed, 149 insertions(+)

diff --git a/NEWS b/NEWS
index a7f2def..886aacc 100644
--- a/NEWS
+++ b/NEWS
@@ -31,6 +31,9 @@ Post-v2.8.0
      * All the netdev-dpdk appctl commands described in ovs-vswitchd man page.
    - vswitchd:
      * Datapath IDs may now be specified as 0x1 (etc.) instead of 16 digits.
+   - Add dpctl/ct-set-maxconns and dpctl/ct-get-maxconns commands; supported in
+     userspace datapath.
+
 
 v2.8.0 - 31 Aug 2017
 --------------------
diff --git a/lib/conntrack.c b/lib/conntrack.c
index 6d078f5..0b15dd6 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -2562,6 +2562,20 @@ conntrack_flush(struct conntrack *ct, const uint16_t 
*zone)
     return 0;
 }
 
+int
+conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns)
+{
+    atomic_store_relaxed(&ct->n_conn_limit, maxconns);
+    return 0;
+}
+
+int
+conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns)
+{
+    atomic_read_relaxed(&ct->n_conn_limit, maxconns);
+    return 0;
+}
+
 /* This function must be called with the ct->resources read lock taken. */
 static struct alg_exp_node *
 expectation_lookup(struct hmap *alg_expectations,
diff --git a/lib/conntrack.h b/lib/conntrack.h
index 990f6c2..c7f9b77 100644
--- a/lib/conntrack.h
+++ b/lib/conntrack.h
@@ -114,6 +114,8 @@ int conntrack_dump_next(struct conntrack_dump *, struct 
ct_dpif_entry *);
 int conntrack_dump_done(struct conntrack_dump *);
 
 int conntrack_flush(struct conntrack *, const uint16_t *zone);
+int conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns);
+int conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns);
 
 /* 'struct ct_lock' is a wrapper for an adaptive mutex.  It's useful to try
  * different types of locks (e.g. spinlocks) */
diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c
index 239c848..21f900f 100644
--- a/lib/ct-dpif.c
+++ b/lib/ct-dpif.c
@@ -140,6 +140,22 @@ ct_dpif_flush(struct dpif *dpif, const uint16_t *zone,
             : EOPNOTSUPP);
 }
 
+int
+ct_dpif_set_maxconns(struct dpif *dpif, uint32_t maxconns)
+{
+    return (dpif->dpif_class->ct_set_maxconns
+            ? dpif->dpif_class->ct_set_maxconns(dpif, maxconns)
+            : EOPNOTSUPP);
+}
+
+int
+ct_dpif_get_maxconns(struct dpif *dpif, uint32_t *maxconns)
+{
+    return (dpif->dpif_class->ct_get_maxconns
+            ? dpif->dpif_class->ct_get_maxconns(dpif, maxconns)
+            : EOPNOTSUPP);
+}
+
 void
 ct_dpif_entry_uninit(struct ct_dpif_entry *entry)
 {
diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h
index 5e2de53..37001b4 100644
--- a/lib/ct-dpif.h
+++ b/lib/ct-dpif.h
@@ -197,6 +197,8 @@ 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,
                   const struct ct_dpif_tuple *);
+int ct_dpif_set_maxconns(struct dpif *dpif, uint32_t maxconns);
+int ct_dpif_get_maxconns(struct dpif *dpif, uint32_t *maxconns);
 void ct_dpif_entry_uninit(struct ct_dpif_entry *);
 void ct_dpif_format_entry(const struct ct_dpif_entry *, struct ds *,
                           bool verbose, bool print_stats);
diff --git a/lib/dpctl.c b/lib/dpctl.c
index b769544..0fe86e0 100644
--- a/lib/dpctl.c
+++ b/lib/dpctl.c
@@ -1655,6 +1655,76 @@ dpctl_ct_bkts(int argc, const char *argv[],
     return error;
 }
 
+static int
+dpctl_ct_open_dp(int argc, const char *argv[],
+                 struct dpctl_params *dpctl_p, struct dpif **dpif,
+                 uint8_t max_args)
+{
+    int error = 0;
+    /* The datapath name is not a mandatory parameter for this command.
+     * If it is not specified - so argc < max_args - we retrieve it from the
+     * current setup, assuming only one exists. */
+    char *dpname = argc >= max_args ? xstrdup(argv[1]) : get_one_dp(dpctl_p);
+    if (!dpname) {
+        error = EINVAL;
+        dpctl_error(dpctl_p, error, "datapath not found");
+    } else {
+        error = parsed_dpif_open(dpname, false, dpif);
+        free(dpname);
+        if (error) {
+            dpctl_error(dpctl_p, error, "opening datapath");
+        }
+    }
+    return error;
+}
+
+static int
+dpctl_ct_set_maxconns(int argc, const char *argv[],
+                      struct dpctl_params *dpctl_p)
+{
+    struct dpif *dpif;
+    int error = dpctl_ct_open_dp(argc, argv, dpctl_p, &dpif, 3);
+    if (!error) {
+        uint32_t maxconns;
+        if (ovs_scan(argv[argc - 1], "%"SCNu32, &maxconns)) {
+            error = ct_dpif_set_maxconns(dpif, maxconns);
+
+            if (!error) {
+                dpctl_print(dpctl_p, "setting maxconns successful");
+            } else {
+                dpctl_error(dpctl_p, error, "ct set maxconns failed");
+            }
+        } else {
+            error = EINVAL;
+            dpctl_error(dpctl_p, error, "maxconns missing or malformed");
+        }
+        dpif_close(dpif);
+    }
+
+    return error;
+}
+
+static int
+dpctl_ct_get_maxconns(int argc, const char *argv[],
+                    struct dpctl_params *dpctl_p)
+{
+    struct dpif *dpif;
+    int error = dpctl_ct_open_dp(argc, argv, dpctl_p, &dpif, 2);
+    if (!error) {
+        uint32_t maxconns;
+        error = ct_dpif_get_maxconns(dpif, &maxconns);
+
+        if (!error) {
+            dpctl_print(dpctl_p, "%u\n", maxconns);
+        } else {
+            dpctl_error(dpctl_p, error, "maxconns could not be retrieved");
+        }
+        dpif_close(dpif);
+    }
+
+    return error;
+}
+
 /* Undocumented commands for unit testing. */
 
 static int
@@ -1951,6 +2021,8 @@ static const struct dpctl_command all_commands[] = {
     { "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 },
+    { "ct-set-maxconns", "[dp] maxconns", 1, 2, dpctl_ct_set_maxconns, DP_RW },
+    { "ct-get-maxconns", "[dp]", 0, 1, dpctl_ct_get_maxconns, 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 d7c95ff..b859c5a 100644
--- a/lib/dpctl.man
+++ b/lib/dpctl.man
@@ -247,3 +247,19 @@ 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.
+.
+.TP
+\*(DX\fBct\-set\-maxconns\fR [\fIdp\fR] \fBparam\fR
+Set the maximum limit of connection tracker connections.
+Can be used to reduce the processing load on the system due to
+connection tracking or simply limiting connection tracking.
+If the number of connections is already beyond the new maximum limit
+request for the number of connections then the new maximum limit will
+be enforced when the number of connections decreases to that limit, which
+normally happens due to connection expiry.  Only supported for userspace
+datapath.
+.
+.TP
+\*(DX\fBct\-get\-maxconns\fR [\fIdp\fR]
+Read the maximum limit of connection tracker connections.
+Only supported for userspace datapath.
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 349e98a..bcfde03 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -5846,6 +5846,22 @@ dpif_netdev_ct_flush(struct dpif *dpif, const uint16_t 
*zone,
     return conntrack_flush(&dp->conntrack, zone);
 }
 
+static int
+dpif_netdev_ct_set_maxconns(struct dpif *dpif, uint32_t maxconns)
+{
+    struct dp_netdev *dp = get_dp_netdev(dpif);
+
+    return conntrack_set_maxconns(&dp->conntrack, maxconns);
+}
+
+static int
+dpif_netdev_ct_get_maxconns(struct dpif *dpif, uint32_t *maxconns)
+{
+    struct dp_netdev *dp = get_dp_netdev(dpif);
+
+    return conntrack_get_maxconns(&dp->conntrack, maxconns);
+}
+
 const struct dpif_class dpif_netdev_class = {
     "netdev",
     dpif_netdev_init,
@@ -5891,6 +5907,8 @@ const struct dpif_class dpif_netdev_class = {
     dpif_netdev_ct_dump_next,
     dpif_netdev_ct_dump_done,
     dpif_netdev_ct_flush,
+    dpif_netdev_ct_set_maxconns,
+    dpif_netdev_ct_get_maxconns,
     dpif_netdev_meter_get_features,
     dpif_netdev_meter_set,
     dpif_netdev_meter_get,
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index 3f76128..c080e66 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -2989,6 +2989,8 @@ const struct dpif_class dpif_netlink_class = {
     dpif_netlink_ct_dump_next,
     dpif_netlink_ct_dump_done,
     dpif_netlink_ct_flush,
+    NULL,                       /* ct_set_maxconns */
+    NULL,                       /* ct_get_maxconns */
     dpif_netlink_meter_get_features,
     dpif_netlink_meter_set,
     dpif_netlink_meter_get,
diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h
index 947bf5e..98f4115 100644
--- a/lib/dpif-provider.h
+++ b/lib/dpif-provider.h
@@ -437,6 +437,10 @@ struct dpif_class {
      *     (zone 0). */
     int (*ct_flush)(struct dpif *, const uint16_t *zone,
                     const struct ct_dpif_tuple *tuple);
+    /* Set max connections allowed. */
+    int (*ct_set_maxconns)(struct dpif *, uint32_t maxconns);
+    /* Get max connections allowed. */
+    int (*ct_get_maxconns)(struct dpif *, uint32_t *maxconns);
 
     /* Meters */
 
-- 
1.9.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to