Since 3d9c1b855a5f ("conntrack: Replace timeout based expiration lists with rculists.") the sweep interval changed as well as the constraints related to the sweeper. Being able to change the default reschedule time may be convenient in some conditions, like debugging. This patch introduces new commands allowing to get and set the sweep next run in ms.
Signed-off-by: Paolo Valerio <pvale...@redhat.com> --- v2: - resolved conflict in NEWS - added missing comment - added missing '\' in dpctl.man --- NEWS | 4 +++ lib/conntrack-private.h | 1 + lib/conntrack.c | 18 +++++++++++++- lib/conntrack.h | 2 ++ lib/ct-dpif.c | 14 +++++++++++ lib/ct-dpif.h | 1 + lib/dpctl.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++ lib/dpctl.man | 8 ++++++ lib/dpif-netdev.c | 17 +++++++++++++ lib/dpif-netlink.c | 2 ++ lib/dpif-provider.h | 4 +++ 11 files changed, 131 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 85b349621..4c4ef4b2b 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,10 @@ Post-v3.1.0 in order to create OVSDB sockets with access mode of 0770. - QoS: * Added new configuration option 'jitter' for a linux-netem QoS type. + - ovs-appctl: + * New commands "dpctl/{ct-get-sweep-next-run,ct-set-sweep-next-run}" that + allow to get and set, for the userspace datapath, the next run interval + for the conntrack garbage collector. v3.1.0 - 16 Feb 2023 diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h index fae8b3a9b..bb326868e 100644 --- a/lib/conntrack-private.h +++ b/lib/conntrack-private.h @@ -224,6 +224,7 @@ struct conntrack { struct ipf *ipf; /* Fragmentation handling context. */ uint32_t zone_limit_seq; /* Used to disambiguate zone limit counts. */ atomic_bool tcp_seq_chk; /* Check TCP sequence numbers. */ + atomic_uint32_t sweep_ms; /* Next sweep interval. */ }; /* Lock acquisition order: diff --git a/lib/conntrack.c b/lib/conntrack.c index 5029b2cda..9356c1282 100644 --- a/lib/conntrack.c +++ b/lib/conntrack.c @@ -320,6 +320,7 @@ conntrack_init(void) atomic_count_init(&ct->n_conn, 0); atomic_init(&ct->n_conn_limit, DEFAULT_N_CONN_LIMIT); atomic_init(&ct->tcp_seq_chk, true); + atomic_init(&ct->sweep_ms, 20000); latch_init(&ct->clean_thread_exit); ct->clean_thread = ovs_thread_create("ct_clean", clean_thread_main, ct); ct->ipf = ipf_init(); @@ -1480,6 +1481,21 @@ set_label(struct dp_packet *pkt, struct conn *conn, } +int +conntrack_set_sweep_next_run(struct conntrack *ct, uint32_t ms) +{ + atomic_store_relaxed(&ct->sweep_ms, ms); + return 0; +} + +uint32_t +conntrack_get_sweep_next_run(struct conntrack *ct) +{ + uint32_t ms; + atomic_read_relaxed(&ct->sweep_ms, &ms); + return ms; +} + static size_t ct_sweep(struct conntrack *ct, struct rculist *list, long long now) OVS_NO_THREAD_SAFETY_ANALYSIS @@ -1504,7 +1520,7 @@ ct_sweep(struct conntrack *ct, struct rculist *list, long long now) static long long conntrack_clean(struct conntrack *ct, long long now) { - long long next_wakeup = now + 20 * 1000; + long long next_wakeup = now + conntrack_get_sweep_next_run(ct); unsigned int n_conn_limit, i; size_t clean_end, count = 0; diff --git a/lib/conntrack.h b/lib/conntrack.h index b064abc9f..2306cf375 100644 --- a/lib/conntrack.h +++ b/lib/conntrack.h @@ -139,6 +139,8 @@ int conntrack_set_maxconns(struct conntrack *ct, uint32_t maxconns); int conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns); int conntrack_get_nconns(struct conntrack *ct, uint32_t *nconns); int conntrack_set_tcp_seq_chk(struct conntrack *ct, bool enabled); +int conntrack_set_sweep_next_run(struct conntrack *ct, uint32_t ms); +uint32_t conntrack_get_sweep_next_run(struct conntrack *ct); bool conntrack_get_tcp_seq_chk(struct conntrack *ct); struct ipf *conntrack_ipf_ctx(struct conntrack *ct); struct conntrack_zone_limit zone_limit_get(struct conntrack *ct, diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c index d3b2783ce..0a08eb11c 100644 --- a/lib/ct-dpif.c +++ b/lib/ct-dpif.c @@ -368,6 +368,20 @@ ct_dpif_del_limits(struct dpif *dpif, const struct ovs_list *zone_limits) : EOPNOTSUPP); } +int +ct_dpif_sweep(struct dpif *dpif, uint32_t *ms) +{ + if (*ms) { + return (dpif->dpif_class->ct_set_sweep_next_run + ? dpif->dpif_class->ct_set_sweep_next_run(dpif, *ms) + : EOPNOTSUPP); + } else { + return (dpif->dpif_class->ct_get_sweep_next_run + ? dpif->dpif_class->ct_get_sweep_next_run(dpif, ms) + : EOPNOTSUPP); + } +} + int ct_dpif_ipf_set_enabled(struct dpif *dpif, bool v6, bool enable) { diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h index 5edbbfd3b..1e265604f 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -298,6 +298,7 @@ int ct_dpif_set_limits(struct dpif *dpif, const uint32_t *default_limit, int ct_dpif_get_limits(struct dpif *dpif, uint32_t *default_limit, const struct ovs_list *, struct ovs_list *); int ct_dpif_del_limits(struct dpif *dpif, const struct ovs_list *); +int ct_dpif_sweep(struct dpif *dpif, uint32_t *ms); int ct_dpif_ipf_set_enabled(struct dpif *, bool v6, bool enable); int ct_dpif_ipf_set_min_frag(struct dpif *, bool v6, uint32_t min_frag); int ct_dpif_ipf_set_max_nfrags(struct dpif *, uint32_t max_frags); diff --git a/lib/dpctl.c b/lib/dpctl.c index c501a0cd7..5cc1a4afa 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -2294,6 +2294,65 @@ out: return error; } +static int +dpctl_ct_get_sweep(int argc, const char *argv[], + struct dpctl_params *dpctl_p) +{ + uint32_t sweep_ms = 0; + struct dpif *dpif; + + int error = opt_dpif_open(argc, argv, dpctl_p, 2, &dpif); + if (error) { + return error; + } + + error = ct_dpif_sweep(dpif, &sweep_ms); + if (error) { + dpctl_error(dpctl_p, error, "failed to get the sweep interval"); + } else { + dpctl_print(dpctl_p, "%"PRIu32, sweep_ms); + } + + dpif_close(dpif); + return error; +} + +static int +dpctl_ct_set_sweep(int argc, const char *argv[], + struct dpctl_params *dpctl_p) +{ + struct ds ds = DS_EMPTY_INITIALIZER; + uint32_t sweep_ms = 0; + struct dpif *dpif; + + int error = opt_dpif_open(argc, argv, dpctl_p, 3, &dpif); + if (error) { + return error; + } + + if (!ovs_scan(argv[argc - 1], "%"SCNu32, &sweep_ms) || + sweep_ms == 0) { + ds_put_format(&ds, "invalid sweep value"); + error = EINVAL; + goto error; + } + + error = ct_dpif_sweep(dpif, &sweep_ms); + if (!error) { + dpctl_print(dpctl_p, "setting sweep interval successful\n"); + goto out; + } + + ds_put_format(&ds, "failed to set the sweep interval"); + +error: + dpctl_error(dpctl_p, error, "%s", ds_cstr(&ds)); + ds_destroy(&ds); +out: + dpif_close(dpif); + return error; +} + static int ipf_set_enabled__(int argc, const char *argv[], struct dpctl_params *dpctl_p, bool enabled) @@ -2907,6 +2966,8 @@ static const struct dpctl_command all_commands[] = { DP_RO }, { "ct-get-limits", "[dp] [zone=N1[,N2]...]", 0, 2, dpctl_ct_get_limits, DP_RO }, + { "ct-get-sweep-next-run", "[dp]", 0, 1, dpctl_ct_get_sweep, DP_RO }, + { "ct-set-sweep-next-run", "[dp] ms", 1, 2, dpctl_ct_set_sweep, DP_RW }, { "ipf-set-enabled", "[dp] v4|v6", 1, 2, dpctl_ipf_set_enabled, DP_RW }, { "ipf-set-disabled", "[dp] v4|v6", 1, 2, dpctl_ipf_set_disabled, DP_RW }, { "ipf-set-min-frag", "[dp] v4|v6 minfragment", 2, 3, diff --git a/lib/dpctl.man b/lib/dpctl.man index 920446e8c..42dad3014 100644 --- a/lib/dpctl.man +++ b/lib/dpctl.man @@ -382,6 +382,14 @@ Prints whether TCP sequence checking is enabled or disabled on \fIdp\fR. Only supported for the userspace datapath. . .TP +\*(DX\fBct\-sweep\-set\-next\-run\fR [\fIdp\fR] \fIms\fR +Sets the next sweep interval. Only supported for the userspace datapath. +. +.TP +\*(DX\fBct\-sweep\-get\-next\-run\fR [\fIdp\fR] +Prints the current sweep interval. Only supported for the userspace datapath. +. +.TP \*(DX\fBct\-set\-limits\fR [\fIdp\fR] [\fBdefault=\fIdefault_limit\fR] [\fBzone=\fIzone\fR,\fBlimit=\fIlimit\fR]... Sets the maximum allowed number of connections in a connection tracking zone. A specific \fIzone\fR may be set to \fIlimit\fR, and multiple zones diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index c9f7179c3..8133b3328 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -9317,6 +9317,21 @@ dpif_netdev_ct_get_tcp_seq_chk(struct dpif *dpif, bool *enabled) return 0; } +static int +dpif_netdev_ct_set_sweep_next_run(struct dpif *dpif, uint32_t ms) +{ + struct dp_netdev *dp = get_dp_netdev(dpif); + return conntrack_set_sweep_next_run(dp->conntrack, ms); +} + +static int +dpif_netdev_ct_get_sweep_next_run(struct dpif *dpif, uint32_t *ms) +{ + struct dp_netdev *dp = get_dp_netdev(dpif); + *ms = conntrack_get_sweep_next_run(dp->conntrack); + return 0; +} + static int dpif_netdev_ct_set_limits(struct dpif *dpif, const uint32_t *default_limits, @@ -9667,6 +9682,8 @@ const struct dpif_class dpif_netdev_class = { dpif_netdev_ct_get_nconns, dpif_netdev_ct_set_tcp_seq_chk, dpif_netdev_ct_get_tcp_seq_chk, + dpif_netdev_ct_set_sweep_next_run, + dpif_netdev_ct_get_sweep_next_run, dpif_netdev_ct_set_limits, dpif_netdev_ct_get_limits, dpif_netdev_ct_del_limits, diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 586fb8893..5bc72f73f 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -4566,6 +4566,8 @@ const struct dpif_class dpif_netlink_class = { NULL, /* ct_get_nconns */ NULL, /* ct_set_tcp_seq_chk */ NULL, /* ct_get_tcp_seq_chk */ + NULL, /* ct_set_sweep_next_run */ + NULL, /* ct_get_sweep_next_run */ dpif_netlink_ct_set_limits, dpif_netlink_ct_get_limits, dpif_netlink_ct_del_limits, diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 12477a24f..39c167a14 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -485,6 +485,10 @@ struct dpif_class { int (*ct_set_tcp_seq_chk)(struct dpif *, bool enabled); /* Get the TCP sequence checking configuration. */ int (*ct_get_tcp_seq_chk)(struct dpif *, bool *enabled); + /* Updates the next run interval for the CT sweeper */ + int (*ct_set_sweep_next_run)(struct dpif *, uint32_t ms); + /* Get the current value of the next run interval for the CT sweeper */ + int (*ct_get_sweep_next_run)(struct dpif *, uint32_t *ms); /* Connection tracking per zone limit */ _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev