@@ -67,6 +67,13 @@ enum ct_alg_mode {
CT_TFTP_MODE,
};
+/* Variable to manage read/write on CT parameters. */
+struct ct_cfg_params {
+ char *cli; /* Parameter name in human format. */
+ int (*wr)(struct conntrack *, uint32_t);
+ int (*rd)(struct conntrack *, uint32_t *);
+};
+
static bool conn_key_extract(struct conntrack *, struct dp_packet *,
ovs_be16 dl_type, struct conn_lookup_ctx *,
uint16_t zone);
@@ -2391,6 +2398,59 @@ conntrack_flush(struct conntrack *ct, const uint16_t *zone)
return 0;
}
+/* List of parameters that can be read/written at run-time. */
+struct ct_cfg_params cfg_params[] = {};
+
+int
+conntrack_set_param(struct conntrack *ct,
+ const char *set_param)
+{
+ uint32_t max_conn;
+ char buf[16] = "";
+
+ /* Check if the specified param can be managed. */
+ for (int i = 0; i < sizeof(cfg_params) / sizeof(struct ct_cfg_params);
+ i++) {
+ if (!strncmp(set_param, cfg_params[i].cli,
+ strlen(cfg_params[i].cli))) {
+ ovs_strzcpy(buf, cfg_params[i].cli, sizeof(buf) - 1);
+ strncat(buf, "=%"SCNu32, sizeof(buf) - 1 - strlen(buf));
+ if (ovs_scan(set_param, buf, &max_conn)) {
+ return (cfg_params[i].wr
+ ? cfg_params[i].wr(ct, max_conn)
+ : EOPNOTSUPP);
+ } else {
+ return EINVAL;
+ }
+ }
+ }
+ /* The entered param didn't match any in the list. */
+ VLOG_WARN("%s parameter is not managed by this command.", set_param);
+
+ return EINVAL;
+}
+
+int
+conntrack_get_param(struct conntrack *ct,
+ const char *get_param, uint32_t *val)
+{
+ /* Check if the specified param can be managed. */
+ for (int i = 0; i < sizeof(cfg_params) / sizeof(struct ct_cfg_params);
+ i++) {
+ if (!strncmp(get_param, cfg_params[i].cli,
+ strlen(cfg_params[i].cli))) {
+
+ return (cfg_params[i].rd
+ ? cfg_params[i].rd(ct, val)
+ : EOPNOTSUPP);
+ }
+ }
+ /* The entered param didn't match any in the list. */
+ VLOG_WARN("%s parameter is not managed by this command.", get_param);
+
+ return EINVAL;
+}
+
/* This function must be called with the ct->resources read lock taken. */
static struct alg_exp_node *
expectation_lookup(struct hmap *alg_expectations,
@@ -114,6 +114,9 @@ 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_param(struct conntrack *, const char *set_param);
+int conntrack_get_param(struct conntrack *, const char *get_param,
+ uint32_t *val);
/* 'struct ct_lock' is a wrapper for an adaptive mutex. It's useful to try
* different types of locks (e.g. spinlocks) */
@@ -127,6 +127,34 @@ ct_dpif_flush(struct dpif *dpif, const uint16_t *zone)
: EOPNOTSUPP);
}
+int
+ct_dpif_set_param(struct dpif *dpif, const char *set_param)
+{
+ if (!set_param) {
+ VLOG_DBG("%s: ct_set_param: no input param", dpif_name(dpif));
+ return EINVAL;
+ }
+ VLOG_DBG("%s: ct_set_param: %s", dpif_name(dpif), set_param);
+
+ return (dpif->dpif_class->ct_set_param
+ ? dpif->dpif_class->ct_set_param(dpif, set_param)
+ : EOPNOTSUPP);
+}
+
+int
+ct_dpif_get_param(struct dpif *dpif, const char *get_param, uint32_t *val)
+{
+ if (!get_param) {
+ VLOG_DBG("%s: ct_get_param: no input param", dpif_name(dpif));
+ return EINVAL;
+ }
+ VLOG_DBG("%s: ct_get_param: %s", dpif_name(dpif), get_param);
+
+ return (dpif->dpif_class->ct_get_param
+ ? dpif->dpif_class->ct_get_param(dpif, get_param, val)
+ : EOPNOTSUPP);
+}
+
void
ct_dpif_entry_uninit(struct ct_dpif_entry *entry)
{
@@ -196,6 +196,8 @@ int ct_dpif_dump_start(struct dpif *, struct ct_dpif_dump_state **,
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);
+int ct_dpif_set_param(struct dpif *dpif, const char *set_param);
+int ct_dpif_get_param(struct dpif *dpif, const char *get_param, uint32_t *val);
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);
@@ -1589,6 +1589,80 @@ dpctl_ct_bkts(int argc, const char *argv[],
free(conn_per_bkts);
return error;
}
+
+static int
+dpctl_ct_set_param(int argc, const char *argv[],
+ struct dpctl_params *dpctl_p)
+{
+ struct dpif *dpif;
+ char *name;
+ int error;
+
+ /* The datapath name is not a mandatory parameter for this command.
+ * If it is not specified - so argc < 3 - we retrieve it from the
+ * current setup, assuming only one exists. */
+ name = argc == 3 ? 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_set_param(dpif, argv[argc - 1]);
+
+ if (!error) {
+ dpctl_print(dpctl_p, "Ok");
+ } else {
+ dpctl_print(dpctl_p, "CT set global cfg failed (%s)",
+ ovs_strerror(error));
+ }
+
+ dpif_close(dpif);
+
+ return error;
+}
+
+static int
+dpctl_ct_get_param(int argc, const char *argv[],
+ struct dpctl_params *dpctl_p)
+{
+ struct dpif *dpif;
+ uint32_t param_val;
+ char *name;
+ int error;
+
+ /* The datapath name is not a mandatory parameter for this command.
+ * If it is not specified - so argc < 3 - we retrieve it from the
+ * current setup, assuming only one exists. */
+ name = argc == 3 ? 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_get_param(dpif, argv[argc - 1], ¶m_val);
+
+ if (!error) {
+ dpctl_print(dpctl_p, "Current value: %d", param_val);
+ } else {
+ dpctl_print(dpctl_p, "CT get global cfg failed (%s)",
+ ovs_strerror(error));
+ }
+
+ dpif_close(dpif);
+
+ return error;
+}
+
/* Undocumented commands for unit testing. */
@@ -1885,6 +1959,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-glbl-cfg", "[dp] param=..", 1, 2, dpctl_ct_set_param, DP_RW },
+ { "ct-get-glbl-cfg", "[dp] param", 1, 2, dpctl_ct_get_param, DP_RO },
{ "help", "", 0, INT_MAX, dpctl_help, DP_RO },
{ "list-commands", "", 0, INT_MAX, dpctl_list_commands, DP_RO },
@@ -5689,6 +5689,23 @@ dpif_netdev_ct_flush(struct dpif *dpif, const uint16_t *zone)
return conntrack_flush(&dp->conntrack, zone);
}
+static int
+dpif_netdev_ct_set_param(struct dpif *dpif, const char *set_param)
+{
+ struct dp_netdev *dp = get_dp_netdev(dpif);
+
+ return conntrack_set_param(&dp->conntrack, set_param);
+}
+
+static int
+dpif_netdev_ct_get_param(struct dpif *dpif, const char *get_param,
+ uint32_t *val)
+{
+ struct dp_netdev *dp = get_dp_netdev(dpif);
+
+ return conntrack_get_param(&dp->conntrack, get_param, val);
+}
+
const struct dpif_class dpif_netdev_class = {
"netdev",
dpif_netdev_init,
@@ -5734,6 +5751,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_param,
+ dpif_netdev_ct_get_param,
dpif_netdev_meter_get_features,
dpif_netdev_meter_set,
dpif_netdev_meter_get,
@@ -2986,6 +2986,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_param */
+ NULL, /* ct_get_param */
dpif_netlink_meter_get_features,
dpif_netlink_meter_set,
dpif_netlink_meter_get,
@@ -427,6 +427,10 @@ struct dpif_class {
/* Flushes the connection tracking tables. If 'zone' is not NULL,
* only deletes connections in '*zone'. */
int (*ct_flush)(struct dpif *, const uint16_t *zone);
+ /* Set a value to a connection tracking working parameter. */
+ int (*ct_set_param)(struct dpif *, const char *set_param);
+ /* Read the current value of a connection tracking working parameter. */
+ int (*ct_get_param)(struct dpif *, const char *get_param, uint32_t *val);
/* Meters */
Add infrastructure to implement: - dpctl/ct-get-glbl-cfg to read a current value of available conntrack parameters. - dpctl/ct-set-glbl-cfg to set a value to the available conntrack parameters. CC: Kevin Traynor <ktraynor@redhat.com> Signed-off-by: Antonio Fischetti <antonio.fischetti@intel.com> --- lib/conntrack.c | 60 ++++++++++++++++++++++++++++++++++++++++++ lib/conntrack.h | 3 +++ lib/ct-dpif.c | 28 ++++++++++++++++++++ lib/ct-dpif.h | 2 ++ lib/dpctl.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/dpif-netdev.c | 19 ++++++++++++++ lib/dpif-netlink.c | 2 ++ lib/dpif-provider.h | 4 +++ 8 files changed, 194 insertions(+)