summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDarrell Ball <dlu998@gmail.com>2019-05-02 21:34:04 -0700
committerBen Pfaff <blp@ovn.org>2019-05-03 09:46:22 -0700
commit57593fd2437836a59e66e124228e433f246ee744 (patch)
tree1c10f7d361ef418d9ca533f3fb66132a793c28d2 /lib
parentabf11558c1515bf3b1ecfe4790fe9ec212d7d245 (diff)
downloadopenvswitch-57593fd2437836a59e66e124228e433f246ee744.tar.gz
conntrack: Stop exporting internal datastructures.
Stop the exporting of the main internal conntrack datastructure. Signed-off-by: Darrell Ball <dlu998@gmail.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/conntrack-private.h174
-rw-r--r--lib/conntrack.c8
-rw-r--r--lib/conntrack.h184
-rw-r--r--lib/dpif-netdev.c32
4 files changed, 198 insertions, 200 deletions
diff --git a/lib/conntrack-private.h b/lib/conntrack-private.h
index 96a6a9f79..059af9e9b 100644
--- a/lib/conntrack-private.h
+++ b/lib/conntrack-private.h
@@ -119,6 +119,180 @@ enum ct_conn_type {
CT_CONN_TYPE_UN_NAT,
};
+/* 'struct ct_lock' is a wrapper for an adaptive mutex. It's useful to try
+ * different types of locks (e.g. spinlocks) */
+
+struct OVS_LOCKABLE ct_lock {
+ struct ovs_mutex lock;
+};
+
+static inline void ct_lock_init(struct ct_lock *lock)
+{
+ ovs_mutex_init_adaptive(&lock->lock);
+}
+
+static inline void ct_lock_lock(struct ct_lock *lock)
+ OVS_ACQUIRES(lock)
+ OVS_NO_THREAD_SAFETY_ANALYSIS
+{
+ ovs_mutex_lock(&lock->lock);
+}
+
+static inline void ct_lock_unlock(struct ct_lock *lock)
+ OVS_RELEASES(lock)
+ OVS_NO_THREAD_SAFETY_ANALYSIS
+{
+ ovs_mutex_unlock(&lock->lock);
+}
+
+static inline void ct_lock_destroy(struct ct_lock *lock)
+{
+ ovs_mutex_destroy(&lock->lock);
+}
+
+struct OVS_LOCKABLE ct_rwlock {
+ struct ovs_rwlock lock;
+};
+
+static inline void ct_rwlock_init(struct ct_rwlock *lock)
+{
+ ovs_rwlock_init(&lock->lock);
+}
+
+
+static inline void ct_rwlock_wrlock(struct ct_rwlock *lock)
+ OVS_ACQ_WRLOCK(lock)
+ OVS_NO_THREAD_SAFETY_ANALYSIS
+{
+ ovs_rwlock_wrlock(&lock->lock);
+}
+
+static inline void ct_rwlock_rdlock(struct ct_rwlock *lock)
+ OVS_ACQ_RDLOCK(lock)
+ OVS_NO_THREAD_SAFETY_ANALYSIS
+{
+ ovs_rwlock_rdlock(&lock->lock);
+}
+
+static inline void ct_rwlock_unlock(struct ct_rwlock *lock)
+ OVS_RELEASES(lock)
+ OVS_NO_THREAD_SAFETY_ANALYSIS
+{
+ ovs_rwlock_unlock(&lock->lock);
+}
+
+static inline void ct_rwlock_destroy(struct ct_rwlock *lock)
+{
+ ovs_rwlock_destroy(&lock->lock);
+}
+
+/* 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, 30 * 1000) \
+ CT_TIMEOUT(TCP_OPENING, 30 * 1000) \
+ CT_TIMEOUT(TCP_ESTABLISHED, 24 * 60 * 60 * 1000) \
+ CT_TIMEOUT(TCP_CLOSING, 15 * 60 * 1000) \
+ CT_TIMEOUT(TCP_FIN_WAIT, 45 * 1000) \
+ CT_TIMEOUT(TCP_CLOSED, 30 * 1000) \
+ CT_TIMEOUT(OTHER_FIRST, 60 * 1000) \
+ CT_TIMEOUT(OTHER_MULTIPLE, 60 * 1000) \
+ CT_TIMEOUT(OTHER_BIDIR, 30 * 1000) \
+ CT_TIMEOUT(ICMP_FIRST, 60 * 1000) \
+ CT_TIMEOUT(ICMP_REPLY, 30 * 1000)
+
+/* The smallest of the above values: it is used as an upper bound for the
+ * interval between two rounds of cleanup of expired entries */
+#define CT_TM_MIN (30 * 1000)
+
+#define CT_TIMEOUT(NAME, VAL) BUILD_ASSERT_DECL(VAL >= CT_TM_MIN);
+ CT_TIMEOUTS
+#undef CT_TIMEOUT
+
+enum ct_timeout {
+#define CT_TIMEOUT(NAME, VALUE) CT_TM_##NAME,
+ CT_TIMEOUTS
+#undef CT_TIMEOUT
+ N_CT_TM
+};
+
+
+/* Locking:
+ *
+ * The connections are kept in different buckets, which are completely
+ * independent. The connection bucket is determined by the hash of its key.
+ *
+ * Each bucket has two locks. Acquisition order is, from outermost to
+ * innermost:
+ *
+ * cleanup_mutex
+ * lock
+ *
+ * */
+struct conntrack_bucket {
+ /* Protects 'connections' and 'exp_lists'. Used in the fast path */
+ struct ct_lock lock;
+ /* Contains the connections in the bucket, indexed by 'struct conn_key' */
+ struct hmap connections OVS_GUARDED;
+ /* For each possible timeout we have a list of connections. When the
+ * timeout of a connection is updated, we move it to the back of the list.
+ * Since the connection in a list have the same relative timeout, the list
+ * will be ordered, with the oldest connections to the front. */
+ struct ovs_list exp_lists[N_CT_TM] OVS_GUARDED;
+
+ /* Protects 'next_cleanup'. Used to make sure that there's only one thread
+ * performing the cleanup. */
+ struct ovs_mutex cleanup_mutex;
+ long long next_cleanup OVS_GUARDED;
+};
+
+#define CONNTRACK_BUCKETS_SHIFT 8
+#define CONNTRACK_BUCKETS (1 << CONNTRACK_BUCKETS_SHIFT)
+
+struct conntrack {
+ /* Independent buckets containing the connections */
+ struct conntrack_bucket buckets[CONNTRACK_BUCKETS];
+
+ /* Salt for hashing a connection key. */
+ uint32_t hash_basis;
+ /* The thread performing periodic cleanup of the connection
+ * tracker. */
+ pthread_t clean_thread;
+ /* Latch to destroy the 'clean_thread' */
+ struct latch clean_thread_exit;
+
+ /* Number of connections currently in the connection tracker. */
+ atomic_count n_conn;
+ /* Connections limit. When this limit is reached, no new connection
+ * will be accepted. */
+ atomic_uint n_conn_limit;
+
+ /* The following resources are referenced during nat connection
+ * creation and deletion. */
+ struct hmap nat_conn_keys OVS_GUARDED;
+ /* Hash table for alg expectations. Expectations are created
+ * by control connections to help create data connections. */
+ struct hmap alg_expectations OVS_GUARDED;
+ /* Used to lookup alg expectations from the control context. */
+ struct hindex alg_expectation_refs OVS_GUARDED;
+ /* Expiry list for alg expectations. */
+ struct ovs_list alg_exp_list OVS_GUARDED;
+ /* This lock is used during NAT connection creation and deletion;
+ * it is taken after a bucket lock and given back before that
+ * bucket unlock.
+ * This lock is similarly used to guard alg_expectations and
+ * alg_expectation_refs. If a bucket lock is also held during
+ * the normal code flow, then is must be taken first and released
+ * last.
+ */
+ struct ct_rwlock resources_lock;
+
+ /* Fragmentation handling context. */
+ struct ipf *ipf;
+
+};
+
struct ct_l4_proto {
struct conn *(*new_conn)(struct conntrack_bucket *, struct dp_packet *pkt,
long long now);
diff --git a/lib/conntrack.c b/lib/conntrack.c
index f0246b3ff..83fc8f277 100644
--- a/lib/conntrack.c
+++ b/lib/conntrack.c
@@ -308,11 +308,13 @@ ct_print_conn_info(const struct conn *c, const char *log_msg,
/* Initializes the connection tracker 'ct'. The caller is responsible for
* calling 'conntrack_destroy()', when the instance is not needed anymore */
-void
-conntrack_init(struct conntrack *ct)
+struct conntrack *
+conntrack_init(void)
{
long long now = time_msec();
+ struct conntrack *ct = xzalloc(sizeof *ct);
+
ct_rwlock_init(&ct->resources_lock);
ct_rwlock_wrlock(&ct->resources_lock);
hmap_init(&ct->nat_conn_keys);
@@ -342,6 +344,8 @@ conntrack_init(struct conntrack *ct)
latch_init(&ct->clean_thread_exit);
ct->clean_thread = ovs_thread_create("ct_clean", clean_thread_main, ct);
ct->ipf = ipf_init();
+
+ return ct;
}
/* Destroys the connection tracker 'ct' and frees all the allocated memory. */
diff --git a/lib/conntrack.h b/lib/conntrack.h
index 6442c808b..8f4095f02 100644
--- a/lib/conntrack.h
+++ b/lib/conntrack.h
@@ -44,15 +44,9 @@
*
* conntrack_init(&ct);
*
- * It is necessary to periodically issue a call to
- *
- * conntrack_run(&ct);
- *
- * to allow the module to clean up expired connections.
- *
* To send a group of packets through the connection tracker:
*
- * conntrack_execute(&ct, pkts, n_pkts, ...);
+ * conntrack_execute(&ct, pkt_batch, ...);
*
* Thread-safety
* =============
@@ -84,7 +78,7 @@ struct nat_action_info_t {
uint16_t nat_action;
};
-void conntrack_init(struct conntrack *);
+struct conntrack *conntrack_init(void);
void conntrack_destroy(struct conntrack *);
int conntrack_execute(struct conntrack *ct, struct dp_packet_batch *pkt_batch,
@@ -120,179 +114,5 @@ int conntrack_get_maxconns(struct conntrack *ct, uint32_t *maxconns);
int conntrack_get_nconns(struct conntrack *ct, uint32_t *nconns);
struct ipf *conntrack_ipf_ctx(struct conntrack *ct);
-/* 'struct ct_lock' is a wrapper for an adaptive mutex. It's useful to try
- * different types of locks (e.g. spinlocks) */
-
-struct OVS_LOCKABLE ct_lock {
- struct ovs_mutex lock;
-};
-
-struct OVS_LOCKABLE ct_rwlock {
- struct ovs_rwlock lock;
-};
-
-static inline void ct_lock_init(struct ct_lock *lock)
-{
- ovs_mutex_init_adaptive(&lock->lock);
-}
-
-static inline void ct_lock_lock(struct ct_lock *lock)
- OVS_ACQUIRES(lock)
- OVS_NO_THREAD_SAFETY_ANALYSIS
-{
- ovs_mutex_lock(&lock->lock);
-}
-
-static inline void ct_lock_unlock(struct ct_lock *lock)
- OVS_RELEASES(lock)
- OVS_NO_THREAD_SAFETY_ANALYSIS
-{
- ovs_mutex_unlock(&lock->lock);
-}
-
-static inline void ct_lock_destroy(struct ct_lock *lock)
-{
- ovs_mutex_destroy(&lock->lock);
-}
-
-static inline void ct_rwlock_init(struct ct_rwlock *lock)
-{
- ovs_rwlock_init(&lock->lock);
-}
-
-
-static inline void ct_rwlock_wrlock(struct ct_rwlock *lock)
- OVS_ACQ_WRLOCK(lock)
- OVS_NO_THREAD_SAFETY_ANALYSIS
-{
- ovs_rwlock_wrlock(&lock->lock);
-}
-
-static inline void ct_rwlock_rdlock(struct ct_rwlock *lock)
- OVS_ACQ_RDLOCK(lock)
- OVS_NO_THREAD_SAFETY_ANALYSIS
-{
- ovs_rwlock_rdlock(&lock->lock);
-}
-
-static inline void ct_rwlock_unlock(struct ct_rwlock *lock)
- OVS_RELEASES(lock)
- OVS_NO_THREAD_SAFETY_ANALYSIS
-{
- ovs_rwlock_unlock(&lock->lock);
-}
-
-static inline void ct_rwlock_destroy(struct ct_rwlock *lock)
-{
- ovs_rwlock_destroy(&lock->lock);
-}
-
-
-/* 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, 30 * 1000) \
- CT_TIMEOUT(TCP_OPENING, 30 * 1000) \
- CT_TIMEOUT(TCP_ESTABLISHED, 24 * 60 * 60 * 1000) \
- CT_TIMEOUT(TCP_CLOSING, 15 * 60 * 1000) \
- CT_TIMEOUT(TCP_FIN_WAIT, 45 * 1000) \
- CT_TIMEOUT(TCP_CLOSED, 30 * 1000) \
- CT_TIMEOUT(OTHER_FIRST, 60 * 1000) \
- CT_TIMEOUT(OTHER_MULTIPLE, 60 * 1000) \
- CT_TIMEOUT(OTHER_BIDIR, 30 * 1000) \
- CT_TIMEOUT(ICMP_FIRST, 60 * 1000) \
- CT_TIMEOUT(ICMP_REPLY, 30 * 1000)
-
-/* The smallest of the above values: it is used as an upper bound for the
- * interval between two rounds of cleanup of expired entries */
-#define CT_TM_MIN (30 * 1000)
-
-#define CT_TIMEOUT(NAME, VAL) BUILD_ASSERT_DECL(VAL >= CT_TM_MIN);
- CT_TIMEOUTS
-#undef CT_TIMEOUT
-
-enum ct_timeout {
-#define CT_TIMEOUT(NAME, VALUE) CT_TM_##NAME,
- CT_TIMEOUTS
-#undef CT_TIMEOUT
- N_CT_TM
-};
-
-/* Locking:
- *
- * The connections are kept in different buckets, which are completely
- * independent. The connection bucket is determined by the hash of its key.
- *
- * Each bucket has two locks. Acquisition order is, from outermost to
- * innermost:
- *
- * cleanup_mutex
- * lock
- *
- * */
-struct conntrack_bucket {
- /* Protects 'connections' and 'exp_lists'. Used in the fast path */
- struct ct_lock lock;
- /* Contains the connections in the bucket, indexed by 'struct conn_key' */
- struct hmap connections OVS_GUARDED;
- /* For each possible timeout we have a list of connections. When the
- * timeout of a connection is updated, we move it to the back of the list.
- * Since the connection in a list have the same relative timeout, the list
- * will be ordered, with the oldest connections to the front. */
- struct ovs_list exp_lists[N_CT_TM] OVS_GUARDED;
-
- /* Protects 'next_cleanup'. Used to make sure that there's only one thread
- * performing the cleanup. */
- struct ovs_mutex cleanup_mutex;
- long long next_cleanup OVS_GUARDED;
-};
-
-#define CONNTRACK_BUCKETS_SHIFT 8
-#define CONNTRACK_BUCKETS (1 << CONNTRACK_BUCKETS_SHIFT)
-
-struct conntrack {
- /* Independent buckets containing the connections */
- struct conntrack_bucket buckets[CONNTRACK_BUCKETS];
-
- /* Salt for hashing a connection key. */
- uint32_t hash_basis;
-
- /* The thread performing periodic cleanup of the connection
- * tracker */
- pthread_t clean_thread;
- /* Latch to destroy the 'clean_thread' */
- struct latch clean_thread_exit;
-
- /* Number of connections currently in the connection tracker. */
- atomic_count n_conn;
- /* Connections limit. When this limit is reached, no new connection
- * will be accepted. */
- atomic_uint n_conn_limit;
-
- /* The following resources are referenced during nat connection
- * creation and deletion. */
- struct hmap nat_conn_keys OVS_GUARDED;
- /* Hash table for alg expectations. Expectations are created
- * by control connections to help create data connections. */
- struct hmap alg_expectations OVS_GUARDED;
- /* Used to lookup alg expectations from the control context. */
- struct hindex alg_expectation_refs OVS_GUARDED;
- /* Expiry list for alg expectations. */
- struct ovs_list alg_exp_list OVS_GUARDED;
- /* This lock is used during NAT connection creation and deletion;
- * it is taken after a bucket lock and given back before that
- * bucket unlock.
- * This lock is similarly used to guard alg_expectations and
- * alg_expectation_refs. If a bucket lock is also held during
- * the normal code flow, then is must be taken first and released
- * last.
- */
- struct ct_rwlock resources_lock;
-
- /* Fragmentation handling context. */
- struct ipf *ipf;
-
-};
#endif /* conntrack.h */
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index f1422b2b1..5a6f2abac 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -381,7 +381,7 @@ struct dp_netdev {
uint64_t last_tnl_conf_seq;
- struct conntrack conntrack;
+ struct conntrack *conntrack;
struct pmd_auto_lb pmd_alb;
};
@@ -1520,7 +1520,7 @@ create_dp_netdev(const char *name, const struct dpif_class *class,
dp->upcall_aux = NULL;
dp->upcall_cb = NULL;
- conntrack_init(&dp->conntrack);
+ dp->conntrack = conntrack_init();
atomic_init(&dp->emc_insert_min, DEFAULT_EM_FLOW_INSERT_MIN);
atomic_init(&dp->tx_flush_interval, DEFAULT_TX_FLUSH_INTERVAL);
@@ -1638,7 +1638,7 @@ dp_netdev_free(struct dp_netdev *dp)
ovs_mutex_destroy(&dp->non_pmd_mutex);
ovsthread_key_delete(dp->per_pmd_key);
- conntrack_destroy(&dp->conntrack);
+ conntrack_destroy(dp->conntrack);
seq_destroy(dp->reconfigure_seq);
@@ -7213,7 +7213,7 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_,
VLOG_WARN_RL(&rl, "NAT specified without commit.");
}
- conntrack_execute(&dp->conntrack, packets_, aux->flow->dl_type, force,
+ conntrack_execute(dp->conntrack, packets_, aux->flow->dl_type, force,
commit, zone, setmark, setlabel, aux->flow->tp_src,
aux->flow->tp_dst, helper, nat_action_info_ref,
pmd->ctx.now / 1000);
@@ -7277,9 +7277,9 @@ dpif_netdev_ct_dump_start(struct dpif *dpif, struct ct_dpif_dump_state **dump_,
dump = xzalloc(sizeof *dump);
dump->dp = dp;
- dump->ct = &dp->conntrack;
+ dump->ct = dp->conntrack;
- conntrack_dump_start(&dp->conntrack, &dump->dump, pzone, ptot_bkts);
+ conntrack_dump_start(dp->conntrack, &dump->dump, pzone, ptot_bkts);
*dump_ = &dump->up;
@@ -7321,9 +7321,9 @@ dpif_netdev_ct_flush(struct dpif *dpif, const uint16_t *zone,
struct dp_netdev *dp = get_dp_netdev(dpif);
if (tuple) {
- return conntrack_flush_tuple(&dp->conntrack, tuple, zone ? *zone : 0);
+ return conntrack_flush_tuple(dp->conntrack, tuple, zone ? *zone : 0);
}
- return conntrack_flush(&dp->conntrack, zone);
+ return conntrack_flush(dp->conntrack, zone);
}
static int
@@ -7331,7 +7331,7 @@ 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);
+ return conntrack_set_maxconns(dp->conntrack, maxconns);
}
static int
@@ -7339,7 +7339,7 @@ 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);
+ return conntrack_get_maxconns(dp->conntrack, maxconns);
}
static int
@@ -7347,28 +7347,28 @@ dpif_netdev_ct_get_nconns(struct dpif *dpif, uint32_t *nconns)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
- return conntrack_get_nconns(&dp->conntrack, nconns);
+ return conntrack_get_nconns(dp->conntrack, nconns);
}
static int
dpif_netdev_ipf_set_enabled(struct dpif *dpif, bool v6, bool enable)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
- return ipf_set_enabled(conntrack_ipf_ctx(&dp->conntrack), v6, enable);
+ return ipf_set_enabled(conntrack_ipf_ctx(dp->conntrack), v6, enable);
}
static int
dpif_netdev_ipf_set_min_frag(struct dpif *dpif, bool v6, uint32_t min_frag)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
- return ipf_set_min_frag(conntrack_ipf_ctx(&dp->conntrack), v6, min_frag);
+ return ipf_set_min_frag(conntrack_ipf_ctx(dp->conntrack), v6, min_frag);
}
static int
dpif_netdev_ipf_set_max_nfrags(struct dpif *dpif, uint32_t max_frags)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
- return ipf_set_max_nfrags(conntrack_ipf_ctx(&dp->conntrack), max_frags);
+ return ipf_set_max_nfrags(conntrack_ipf_ctx(dp->conntrack), max_frags);
}
/* Adjust this function if 'dpif_ipf_status' and 'ipf_status' were to
@@ -7378,7 +7378,7 @@ dpif_netdev_ipf_get_status(struct dpif *dpif,
struct dpif_ipf_status *dpif_ipf_status)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
- ipf_get_status(conntrack_ipf_ctx(&dp->conntrack),
+ ipf_get_status(conntrack_ipf_ctx(dp->conntrack),
(struct ipf_status *) dpif_ipf_status);
return 0;
}
@@ -7394,7 +7394,7 @@ static int
dpif_netdev_ipf_dump_next(struct dpif *dpif, void *ipf_dump_ctx, char **dump)
{
struct dp_netdev *dp = get_dp_netdev(dpif);
- return ipf_dump_next(conntrack_ipf_ctx(&dp->conntrack), ipf_dump_ctx,
+ return ipf_dump_next(conntrack_ipf_ctx(dp->conntrack), ipf_dump_ctx,
dump);
}