Hi Paolo,
There are two small question.
First the ct_lock lock/unlock as below maybe also can be dropped with this
patch ?
ovs_mutex_lock(&ct->ct_lock);
if (!conn_lookup(ct, &ctx->key, now, NULL, NULL)) {
conn = conn_not_found(ct, pkt, ctx, commit, now, nat_action_info,
helper, alg_exp, ct_alg_ctl, tp_id);
}
ovs_mutex_unlock(&ct->ct_lock);
Second one the zone_limit_lookup can be outof the conn_clean__ as below?
static void
conn_clean__(struct conntrack *ct, struct conn *conn)
OVS_REQUIRES(ct->ct_lock)
{
if (conn->alg) {
expectation_clean(ct, &conn->key);
}
uint32_t hash = conn_key_hash(&conn->key, ct->hash_basis);
cmap_remove(&ct->conns, &conn->cm_node, hash);
struct zone_limit *zl = zone_limit_lookup(ct, conn->admit_zone);
if (zl && zl->czl.zone_limit_seq == conn->zone_limit_seq) {
atomic_count_dec(&zl->czl.count);
}
}
BR
wenxu
At 2022-07-02 02:14:12, "Paolo Valerio" <[email protected]> wrote:
>From: Gaetan Rivet <[email protected]>
>
>This patch aims to replace the expiration lists as, due to the way
>they are used, besides being a source of contention, they have a known
>issue when used with non-default policies for different zones that
>could lead to retaining expired connections potentially for a long
>time.
>
>This patch replaces them with an array of rculist used to distribute
>all the newly created connections in order to, during the sweeping
>phase, scan them without locking, and evict the expired connections
>only locking during the actual removal. This allows to reduce the
>contention introduced by the pushback performed at every packet
>update, also solving the issue related to zones and timeout policies.
>
>Signed-off-by: Gaetan Rivet <[email protected]>
>Co-authored-by: Paolo Valerio <[email protected]>
>Signed-off-by: Paolo Valerio <[email protected]>
>---
>v6:
>- minor function renaming
>- removed conn->lock in conn_clean() as this was unneeded.
>- minor commit message rephrase
>---
> lib/conntrack-private.h | 84 +++++++++++++++++---------
> lib/conntrack-tp.c | 44 +-------------
> lib/conntrack.c | 152 +++++++++++++++++++++++------------------------
> 3 files changed, 133 insertions(+), 147 deletions(-)
>
>diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h
>index 34c688821..676f58d83 100644
>--- a/lib/conntrack-private.h
>+++ b/lib/conntrack-private.h
>@@ -29,6 +29,7 @@
> #include "openvswitch/list.h"
> #include "openvswitch/types.h"
> #include "packets.h"
>+#include "rculist.h"
> #include "unaligned.h"
> #include "dp-packet.h"
>
>@@ -86,6 +87,31 @@ struct alg_exp_node {
> bool nat_rpl_dst;
> };
>
>+/* Timeouts: all the possible timeout states passed to update_expiration()
>+ * are listed here. The name will be prefix by CT_TM_ and the value is in
>+ * milliseconds */
>+#define CT_TIMEOUTS \
>+ CT_TIMEOUT(TCP_FIRST_PACKET) \
>+ CT_TIMEOUT(TCP_OPENING) \
>+ CT_TIMEOUT(TCP_ESTABLISHED) \
>+ CT_TIMEOUT(TCP_CLOSING) \
>+ CT_TIMEOUT(TCP_FIN_WAIT) \
>+ CT_TIMEOUT(TCP_CLOSED) \
>+ CT_TIMEOUT(OTHER_FIRST) \
>+ CT_TIMEOUT(OTHER_MULTIPLE) \
>+ CT_TIMEOUT(OTHER_BIDIR) \
>+ CT_TIMEOUT(ICMP_FIRST) \
>+ CT_TIMEOUT(ICMP_REPLY)
>+
>+enum ct_timeout {
>+#define CT_TIMEOUT(NAME) CT_TM_##NAME,
>+ CT_TIMEOUTS
>+#undef CT_TIMEOUT
>+ N_CT_TM
>+};
>+
>+#define EXP_LISTS 100
>+
> enum OVS_PACKED_ENUM ct_conn_type {
> CT_CONN_TYPE_DEFAULT,
> CT_CONN_TYPE_UN_NAT,
>@@ -96,11 +122,16 @@ struct conn {
> struct conn_key key;
> struct conn_key rev_key;
> struct conn_key parent_key; /* Only used for orig_tuple support. */
>- struct ovs_list exp_node;
> struct cmap_node cm_node;
> uint16_t nat_action;
> char *alg;
> struct conn *nat_conn; /* The NAT 'conn' context, if there is one. */
>+ atomic_flag reclaimed; /* False during the lifetime of the connection,
>+ * True as soon as a thread has started freeing
>+ * its memory. */
>+
>+ /* Inserted once by a PMD, then managed by the 'ct_clean' thread. */
>+ struct rculist node;
>
> /* Mutable data. */
> struct ovs_mutex lock; /* Guards all mutable fields. */
>@@ -116,7 +147,6 @@ struct conn {
> /* Mutable data. */
> bool seq_skew_dir; /* TCP sequence skew direction due to NATTing of FTP
> * control messages; true if reply direction. */
>- bool cleaned; /* True if cleaned from expiry lists. */
>
> /* Immutable data. */
> bool alg_related; /* True if alg data connection. */
>@@ -132,22 +162,6 @@ enum ct_update_res {
> CT_UPDATE_VALID_NEW,
> };
>
>-/* Timeouts: all the possible timeout states passed to update_expiration()
>- * are listed here. The name will be prefix by CT_TM_ and the value is in
>- * milliseconds */
>-#define CT_TIMEOUTS \
>- CT_TIMEOUT(TCP_FIRST_PACKET) \
>- CT_TIMEOUT(TCP_OPENING) \
>- CT_TIMEOUT(TCP_ESTABLISHED) \
>- CT_TIMEOUT(TCP_CLOSING) \
>- CT_TIMEOUT(TCP_FIN_WAIT) \
>- CT_TIMEOUT(TCP_CLOSED) \
>- CT_TIMEOUT(OTHER_FIRST) \
>- CT_TIMEOUT(OTHER_MULTIPLE) \
>- CT_TIMEOUT(OTHER_BIDIR) \
>- CT_TIMEOUT(ICMP_FIRST) \
>- CT_TIMEOUT(ICMP_REPLY)
>-
> #define NAT_ACTION_SNAT_ALL (NAT_ACTION_SRC | NAT_ACTION_SRC_PORT)
> #define NAT_ACTION_DNAT_ALL (NAT_ACTION_DST | NAT_ACTION_DST_PORT)
>
>@@ -181,22 +195,17 @@ enum ct_ephemeral_range {
> #define FOR_EACH_PORT_IN_RANGE(curr, min, max) \
> FOR_EACH_PORT_IN_RANGE__(curr, min, max, OVS_JOIN(idx, __COUNTER__))
>
>-enum ct_timeout {
>-#define CT_TIMEOUT(NAME) CT_TM_##NAME,
>- CT_TIMEOUTS
>-#undef CT_TIMEOUT
>- N_CT_TM
>-};
>-
> struct conntrack {
> struct ovs_mutex ct_lock; /* Protects 2 following fields. */
> struct cmap conns OVS_GUARDED;
>- struct ovs_list exp_lists[N_CT_TM] OVS_GUARDED;
>+ struct rculist exp_lists[EXP_LISTS];
> struct cmap zone_limits OVS_GUARDED;
> struct cmap timeout_policies OVS_GUARDED;
> uint32_t hash_basis; /* Salt for hashing a connection key. */
> pthread_t clean_thread; /* Periodically cleans up connection tracker. */
> struct latch clean_thread_exit; /* To destroy the 'clean_thread'. */
>+ atomic_uint ct_next_list;
>+ unsigned int next_sweep;
>
> /* Counting connections. */
> atomic_count n_conn; /* Number of connections currently tracked. */
>@@ -216,8 +225,8 @@ struct conntrack {
> };
>
> /* Lock acquisition order:
>- * 1. 'ct_lock'
>- * 2. 'conn->lock'
>+ * 1. 'conn->lock'
>+ * 2. 'ct_lock'
> * 3. 'resources_lock'
> */
>
>@@ -237,4 +246,23 @@ struct ct_l4_proto {
> struct ct_dpif_protoinfo *);
> };
>
>+static unsigned int
>+ct_next_list(struct conntrack *ct)
>+{
>+ unsigned int old;
>+
>+ atomic_add_relaxed(&ct->ct_next_list, 1u, &old);
>+
>+ return old % EXP_LISTS;
>+}
>+
>+static inline void
>+conn_expire_push_front(struct conntrack *ct, struct conn *conn)
>+ OVS_REQUIRES(ct->ct_lock)
>+{
>+ unsigned int next = ct_next_list(ct);
>+
>+ rculist_push_front(&ct->exp_lists[next], &conn->node);
>+}
>+
> #endif /* conntrack-private.h */
>diff --git a/lib/conntrack-tp.c b/lib/conntrack-tp.c
>index c2245038b..7b8f9007b 100644
>--- a/lib/conntrack-tp.c
>+++ b/lib/conntrack-tp.c
>@@ -236,27 +236,6 @@ tm_to_ct_dpif_tp(enum ct_timeout tm)
> return CT_DPIF_TP_ATTR_MAX;
> }
>
>-static void
>-conn_update_expiration__(struct conntrack *ct, struct conn *conn,
>- enum ct_timeout tm, long long now,
>- uint32_t tp_value)
>- OVS_REQUIRES(conn->lock)
>-{
>- ovs_mutex_unlock(&conn->lock);
>-
>- ovs_mutex_lock(&ct->ct_lock);
>- ovs_mutex_lock(&conn->lock);
>- if (!conn->cleaned) {
>- conn->expiration = now + tp_value * 1000;
>- ovs_list_remove(&conn->exp_node);
>- ovs_list_push_back(&ct->exp_lists[tm], &conn->exp_node);
>- }
>- ovs_mutex_unlock(&conn->lock);
>- ovs_mutex_unlock(&ct->ct_lock);
>-
>- ovs_mutex_lock(&conn->lock);
>-}
>-
> /* The conn entry lock must be held on entry and exit. */
> void
> conn_update_expiration(struct conntrack *ct, struct conn *conn,
>@@ -266,41 +245,22 @@ conn_update_expiration(struct conntrack *ct, struct conn
>*conn,
> struct timeout_policy *tp;
> uint32_t val;
>
>- ovs_mutex_unlock(&conn->lock);
>-
>- ovs_mutex_lock(&ct->ct_lock);
>- ovs_mutex_lock(&conn->lock);
> tp = timeout_policy_lookup(ct, conn->tp_id);
> if (tp) {
> val = tp->policy.attrs[tm_to_ct_dpif_tp(tm)];
> } else {
> val = ct_dpif_netdev_tp_def[tm_to_ct_dpif_tp(tm)];
> }
>- ovs_mutex_unlock(&conn->lock);
>- ovs_mutex_unlock(&ct->ct_lock);
>-
>- ovs_mutex_lock(&conn->lock);
> VLOG_DBG_RL(&rl, "Update timeout %s zone=%u with policy id=%d "
> "val=%u sec.",
> ct_timeout_str[tm], conn->key.zone, conn->tp_id, val);
>
>- conn_update_expiration__(ct, conn, tm, now, val);
>+ conn->expiration = now + val * 1000;
> }
>
>-static void
>-conn_init_expiration__(struct conntrack *ct, struct conn *conn,
>- enum ct_timeout tm, long long now,
>- uint32_t tp_value)
>-{
>- conn->expiration = now + tp_value * 1000;
>- ovs_list_push_back(&ct->exp_lists[tm], &conn->exp_node);
>-}
>-
>-/* ct_lock must be held. */
> void
> conn_init_expiration(struct conntrack *ct, struct conn *conn,
> enum ct_timeout tm, long long now)
>- OVS_REQUIRES(ct->ct_lock)
> {
> struct timeout_policy *tp;
> uint32_t val;
>@@ -315,5 +275,5 @@ conn_init_expiration(struct conntrack *ct, struct conn
>*conn,
> VLOG_DBG_RL(&rl, "Init timeout %s zone=%u with policy id=%d val=%u sec.",
> ct_timeout_str[tm], conn->key.zone, conn->tp_id, val);
>
>- conn_init_expiration__(ct, conn, tm, now, val);
>+ conn->expiration = now + val * 1000;
> }
>diff --git a/lib/conntrack.c b/lib/conntrack.c
>index 38ddc9b91..819c356c1 100644
>--- a/lib/conntrack.c
>+++ b/lib/conntrack.c
>@@ -39,12 +39,12 @@
> #include "ovs-thread.h"
> #include "openvswitch/poll-loop.h"
> #include "random.h"
>+#include "rculist.h"
> #include "timeval.h"
>
> VLOG_DEFINE_THIS_MODULE(conntrack);
>
> COVERAGE_DEFINE(conntrack_full);
>-COVERAGE_DEFINE(conntrack_long_cleanup);
> COVERAGE_DEFINE(conntrack_l3csum_err);
> COVERAGE_DEFINE(conntrack_l4csum_err);
> COVERAGE_DEFINE(conntrack_lookup_natted_miss);
>@@ -94,9 +94,8 @@ static bool valid_new(struct dp_packet *pkt, struct conn_key
>*);
> static struct conn *new_conn(struct conntrack *ct, struct dp_packet *pkt,
> struct conn_key *, long long now,
> uint32_t tp_id);
>-static void delete_conn_cmn(struct conn *);
>+static void delete_conn__(struct conn *);
> static void delete_conn(struct conn *);
>-static void delete_conn_one(struct conn *conn);
> static enum ct_update_res conn_update(struct conntrack *ct, struct conn *conn,
> struct dp_packet *pkt,
> struct conn_lookup_ctx *ctx,
>@@ -309,7 +308,7 @@ conntrack_init(void)
> ovs_mutex_lock(&ct->ct_lock);
> cmap_init(&ct->conns);
> for (unsigned i = 0; i < ARRAY_SIZE(ct->exp_lists); i++) {
>- ovs_list_init(&ct->exp_lists[i]);
>+ rculist_init(&ct->exp_lists[i]);
> }
> cmap_init(&ct->zone_limits);
> ct->zone_limit_seq = 0;
>@@ -319,6 +318,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->ct_next_list, 0);
> latch_init(&ct->clean_thread_exit);
> ct->clean_thread = ovs_thread_create("ct_clean", clean_thread_main, ct);
> ct->ipf = ipf_init();
>@@ -467,7 +467,7 @@ zone_limit_delete(struct conntrack *ct, uint16_t zone)
> }
>
> static void
>-conn_clean_cmn(struct conntrack *ct, struct conn *conn)
>+conn_clean__(struct conntrack *ct, struct conn *conn)
> OVS_REQUIRES(ct->ct_lock)
> {
> if (conn->alg) {
>@@ -487,32 +487,34 @@ conn_clean_cmn(struct conntrack *ct, struct conn *conn)
> * removes the associated nat 'conn' from the lookup datastructures. */
> static void
> conn_clean(struct conntrack *ct, struct conn *conn)
>- OVS_REQUIRES(ct->ct_lock)
>+ OVS_EXCLUDED(conn->lock, ct->ct_lock)
> {
> ovs_assert(conn->conn_type == CT_CONN_TYPE_DEFAULT);
>
>- conn_clean_cmn(ct, conn);
>+ if (atomic_flag_test_and_set(&conn->reclaimed)) {
>+ return;
>+ }
>+
>+ ovs_mutex_lock(&ct->ct_lock);
>+ conn_clean__(ct, conn);
> if (conn->nat_conn) {
> uint32_t hash = conn_key_hash(&conn->nat_conn->key, ct->hash_basis);
> cmap_remove(&ct->conns, &conn->nat_conn->cm_node, hash);
> }
>- ovs_list_remove(&conn->exp_node);
>- conn->cleaned = true;
>+
>+ rculist_remove(&conn->node);
>+ ovs_mutex_unlock(&ct->ct_lock);
>+
> ovsrcu_postpone(delete_conn, conn);
> atomic_count_dec(&ct->n_conn);
> }
>
> static void
>-conn_clean_one(struct conntrack *ct, struct conn *conn)
>- OVS_REQUIRES(ct->ct_lock)
>+conn_force_expire(struct conn *conn)
> {
>- conn_clean_cmn(ct, conn);
>- if (conn->conn_type == CT_CONN_TYPE_DEFAULT) {
>- ovs_list_remove(&conn->exp_node);
>- conn->cleaned = true;
>- atomic_count_dec(&ct->n_conn);
>- }
>- ovsrcu_postpone(delete_conn_one, conn);
>+ ovs_mutex_lock(&conn->lock);
>+ conn->expiration = 0;
>+ ovs_mutex_unlock(&conn->lock);
> }
>
> /* Destroys the connection tracker 'ct' and frees all the allocated memory.
>@@ -522,15 +524,16 @@ void
> conntrack_destroy(struct conntrack *ct)
> {
> struct conn *conn;
>+
> latch_set(&ct->clean_thread_exit);
> pthread_join(ct->clean_thread, NULL);
> latch_destroy(&ct->clean_thread_exit);
>
>- ovs_mutex_lock(&ct->ct_lock);
>- CMAP_FOR_EACH (conn, cm_node, &ct->conns) {
>- conn_clean_one(ct, conn);
>+ for (unsigned i = 0; i < EXP_LISTS; i++) {
>+ RCULIST_FOR_EACH (conn, node, &ct->exp_lists[i]) {
>+ conn_clean(ct, conn);
>+ }
> }
>- cmap_destroy(&ct->conns);
>
> struct zone_limit *zl;
> CMAP_FOR_EACH (zl, node, &ct->zone_limits) {
>@@ -539,7 +542,6 @@ conntrack_destroy(struct conntrack *ct)
> cmap_remove(&ct->zone_limits, &zl->node, hash);
> ovsrcu_postpone(free, zl);
> }
>- cmap_destroy(&ct->zone_limits);
>
> struct timeout_policy *tp;
> CMAP_FOR_EACH (tp, node, &ct->timeout_policies) {
>@@ -548,6 +550,11 @@ conntrack_destroy(struct conntrack *ct)
> cmap_remove(&ct->timeout_policies, &tp->node, hash);
> ovsrcu_postpone(free, tp);
> }
>+
>+ ovs_mutex_lock(&ct->ct_lock);
>+
>+ cmap_destroy(&ct->conns);
>+ cmap_destroy(&ct->zone_limits);
> cmap_destroy(&ct->timeout_policies);
>
> ovs_mutex_unlock(&ct->ct_lock);
>@@ -1087,7 +1094,9 @@ conn_not_found(struct conntrack *ct, struct dp_packet
>*pkt,
> nc->nat_conn = nat_conn;
> ovs_mutex_init_adaptive(&nc->lock);
> nc->conn_type = CT_CONN_TYPE_DEFAULT;
>+ atomic_flag_clear(&nc->reclaimed);
> cmap_insert(&ct->conns, &nc->cm_node, ctx->hash);
>+ conn_expire_push_front(ct, nc);
> atomic_count_inc(&ct->n_conn);
> ctx->conn = nc; /* For completeness. */
> if (zl) {
>@@ -1108,8 +1117,7 @@ conn_not_found(struct conntrack *ct, struct dp_packet
>*pkt,
> * can limit DoS impact. */
> nat_res_exhaustion:
> free(nat_conn);
>- ovs_list_remove(&nc->exp_node);
>- delete_conn_cmn(nc);
>+ delete_conn__(nc);
> static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
> VLOG_WARN_RL(&rl, "Unable to NAT due to tuple space exhaustion - "
> "if DoS attack, use firewalling and/or zone partitioning.");
>@@ -1148,11 +1156,9 @@ conn_update_state(struct conntrack *ct, struct
>dp_packet *pkt,
> pkt->md.ct_state = CS_INVALID;
> break;
> case CT_UPDATE_NEW:
>- ovs_mutex_lock(&ct->ct_lock);
> if (conn_lookup(ct, &conn->key, now, NULL, NULL)) {
>- conn_clean(ct, conn);
>+ conn_force_expire(conn);
> }
>- ovs_mutex_unlock(&ct->ct_lock);
> create_new_conn = true;
> break;
> case CT_UPDATE_VALID_NEW:
>@@ -1363,11 +1369,9 @@ process_one(struct conntrack *ct, struct dp_packet *pkt,
>
> /* Delete found entry if in wrong direction. 'force' implies commit. */
> if (OVS_UNLIKELY(force && ctx->reply && conn)) {
>- ovs_mutex_lock(&ct->ct_lock);
> if (conn_lookup(ct, &conn->key, now, NULL, NULL)) {
>- conn_clean(ct, conn);
>+ conn_force_expire(conn);
> }
>- ovs_mutex_unlock(&ct->ct_lock);
> conn = NULL;
> }
>
>@@ -1553,39 +1557,21 @@ set_label(struct dp_packet *pkt, struct conn *conn,
> * LLONG_MAX if 'ctb' is empty. The return value might be smaller than 'now',
> * if 'limit' is reached */
> static long long
>-ct_sweep(struct conntrack *ct, long long now, size_t limit)
>+ct_sweep(struct conntrack *ct, struct rculist *list, long long now)
>+ OVS_NO_THREAD_SAFETY_ANALYSIS
> {
> struct conn *conn;
>- long long min_expiration = LLONG_MAX;
> size_t count = 0;
>
>- ovs_mutex_lock(&ct->ct_lock);
>-
>- for (unsigned i = 0; i < N_CT_TM; i++) {
>- LIST_FOR_EACH_SAFE (conn, exp_node, &ct->exp_lists[i]) {
>- ovs_mutex_lock(&conn->lock);
>- if (now < conn->expiration || count >= limit) {
>- min_expiration = MIN(min_expiration, conn->expiration);
>- ovs_mutex_unlock(&conn->lock);
>- if (count >= limit) {
>- /* Do not check other lists. */
>- COVERAGE_INC(conntrack_long_cleanup);
>- goto out;
>- }
>- break;
>- } else {
>- ovs_mutex_unlock(&conn->lock);
>- conn_clean(ct, conn);
>- }
>- count++;
>+ RCULIST_FOR_EACH (conn, node, list) {
>+ if (conn_expired(conn, now)) {
>+ conn_clean(ct, conn);
> }
>+
>+ count++;
> }
>
>-out:
>- VLOG_DBG("conntrack cleanup %"PRIuSIZE" entries in %lld msec", count,
>- time_msec() - now);
>- ovs_mutex_unlock(&ct->ct_lock);
>- return min_expiration;
>+ return count;
> }
>
> /* Cleans up old connection entries from 'ct'. Returns the time when the
>@@ -1595,11 +1581,26 @@ out:
> static long long
> conntrack_clean(struct conntrack *ct, long long now)
> {
>- unsigned int n_conn_limit;
>+ long long next_wakeup = now + 30 * 1000;
>+ unsigned int n_conn_limit, i, count = 0;
>+ size_t clean_end;
>+
> atomic_read_relaxed(&ct->n_conn_limit, &n_conn_limit);
>- size_t clean_max = n_conn_limit > 10 ? n_conn_limit / 10 : 1;
>- long long min_exp = ct_sweep(ct, now, clean_max);
>- long long next_wakeup = MIN(min_exp, now + CT_DPIF_NETDEV_TP_MIN);
>+ clean_end = n_conn_limit / 64;
>+
>+ for (i = ct->next_sweep; i < EXP_LISTS; i++) {
>+ count += ct_sweep(ct, &ct->exp_lists[i], now);
>+
>+ if (count > clean_end) {
>+ next_wakeup = 0;
>+ break;
>+ }
>+ }
>+
>+ ct->next_sweep = (i < EXP_LISTS) ? i : 0;
>+
>+ VLOG_DBG("conntrack cleanup %"PRIu32" entries in %lld msec", count,
>+ time_msec() - now);
>
> return next_wakeup;
> }
>@@ -1628,6 +1629,7 @@ conntrack_clean(struct conntrack *ct, long long now)
>
> static void *
> clean_thread_main(void *f_)
>+ OVS_NO_THREAD_SAFETY_ANALYSIS
> {
> struct conntrack *ct = f_;
>
>@@ -2539,7 +2541,7 @@ new_conn(struct conntrack *ct, struct dp_packet *pkt,
>struct conn_key *key,
> }
>
> static void
>-delete_conn_cmn(struct conn *conn)
>+delete_conn__(struct conn *conn)
> {
> free(conn->alg);
> free(conn);
>@@ -2551,18 +2553,9 @@ delete_conn(struct conn *conn)
> ovs_assert(conn->conn_type == CT_CONN_TYPE_DEFAULT);
> ovs_mutex_destroy(&conn->lock);
> free(conn->nat_conn);
>- delete_conn_cmn(conn);
>+ delete_conn__(conn);
> }
>
>-/* Only used by conn_clean_one(). */
>-static void
>-delete_conn_one(struct conn *conn)
>-{
>- if (conn->conn_type == CT_CONN_TYPE_DEFAULT) {
>- ovs_mutex_destroy(&conn->lock);
>- }
>- delete_conn_cmn(conn);
>-}
>
> /* Convert a conntrack address 'a' into an IP address 'b' based on 'dl_type'.
> *
>@@ -2714,6 +2707,11 @@ conntrack_dump_next(struct conntrack_dump *dump, struct
>ct_dpif_entry *entry)
> }
> struct conn *conn;
> INIT_CONTAINER(conn, cm_node, cm_node);
>+
>+ if (conn_expired(conn, now)) {
>+ continue;
>+ }
>+
> 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);
>@@ -2735,13 +2733,15 @@ conntrack_flush(struct conntrack *ct, const uint16_t
>*zone)
> {
> struct conn *conn;
>
>- ovs_mutex_lock(&ct->ct_lock);
> CMAP_FOR_EACH (conn, cm_node, &ct->conns) {
>+ if (conn->conn_type != CT_CONN_TYPE_DEFAULT) {
>+ continue;
>+ }
>+
> if (!zone || *zone == conn->key.zone) {
>- conn_clean_one(ct, conn);
>+ conn_clean(ct, conn);
> }
> }
>- ovs_mutex_unlock(&ct->ct_lock);
>
> return 0;
> }
>@@ -2756,7 +2756,6 @@ conntrack_flush_tuple(struct conntrack *ct, const struct
>ct_dpif_tuple *tuple,
>
> memset(&key, 0, sizeof(key));
> tuple_to_conn_key(tuple, zone, &key);
>- ovs_mutex_lock(&ct->ct_lock);
> conn_lookup(ct, &key, time_msec(), &conn, NULL);
>
> if (conn && conn->conn_type == CT_CONN_TYPE_DEFAULT) {
>@@ -2766,7 +2765,6 @@ conntrack_flush_tuple(struct conntrack *ct, const struct
>ct_dpif_tuple *tuple,
> error = ENOENT;
> }
>
>- ovs_mutex_unlock(&ct->ct_lock);
> return error;
> }
>
>
>_______________________________________________
>dev mailing list
>[email protected]
>https://mail.openvswitch.org/mailman/listinfo/ovs-dev
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev