diff --git a/NEWS b/NEWS index 7d62d8c84e4..618a2edfff5 100644 --- a/NEWS +++ b/NEWS @@ -22,8 +22,10 @@ Post-v2.8.0 * ovn-ctl: New commands run_nb_ovsdb and run_sb_ovsdb. - Linux kernel 4.13 * Add support for compiling OVS with the latest Linux 4.13 kernel - - "flush-conntrack" in ovs-dpctl and ovs-appctl now accept a 5-tuple to - delete a specific connection tracking entry. + - ovs-dpctl and related ovs-appctl commands: + * "flush-conntrack" now accept a 5-tuple to delete a specific + connection tracking entry. + * New "ct-set-maxconns" and "ct-get-maxconns" for userspace datapath. - DPDK: * Add support for DPDK v17.11 * Add support for vHost IOMMU diff --git a/lib/conntrack.c b/lib/conntrack.c index 6d078f5a85d..0b15dd692f9 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 990f6c208ef..c7f9b77659c 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 239c848d373..21f900f32aa 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 5e2de53834e..37001b4f3c2 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 b76954406b3..0fe86e014ad 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 d7c95ff1831..b859c5a3b7f 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 d06f585cacb..2496133561f 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 3f76128999d..c080e66b784 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 947bf5e3136..98f41151b72 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 */