Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2015, 2016 Nicira, Inc.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at:
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #ifndef CONNTRACK_H
18 : : #define CONNTRACK_H 1
19 : :
20 : : #include <stdbool.h>
21 : :
22 : : #include "latch.h"
23 : : #include "odp-netlink.h"
24 : : #include "openvswitch/hmap.h"
25 : : #include "openvswitch/list.h"
26 : : #include "openvswitch/thread.h"
27 : : #include "openvswitch/types.h"
28 : : #include "ovs-atomic.h"
29 : :
30 : : /* Userspace connection tracker
31 : : * ============================
32 : : *
33 : : * This is a connection tracking module that keeps all the state in userspace.
34 : : *
35 : : * Usage
36 : : * =====
37 : : *
38 : : * struct conntrack ct;
39 : : *
40 : : * Initialization:
41 : : *
42 : : * conntrack_init(&ct);
43 : : *
44 : : * It is necessary to periodically issue a call to
45 : : *
46 : : * conntrack_run(&ct);
47 : : *
48 : : * to allow the module to clean up expired connections.
49 : : *
50 : : * To send a group of packets through the connection tracker:
51 : : *
52 : : * conntrack_execute(&ct, pkts, n_pkts, ...);
53 : : *
54 : : * Thread-safety
55 : : * =============
56 : : *
57 : : * conntrack_execute() can be called by multiple threads simultaneoulsy.
58 : : */
59 : :
60 : : struct dp_packet_batch;
61 : :
62 : : struct conntrack;
63 : :
64 : : void conntrack_init(struct conntrack *);
65 : : void conntrack_destroy(struct conntrack *);
66 : :
67 : : int conntrack_execute(struct conntrack *, struct dp_packet_batch *,
68 : : ovs_be16 dl_type, bool commit,
69 : : uint16_t zone, const uint32_t *setmark,
70 : : const struct ovs_key_ct_labels *setlabel,
71 : : const char *helper);
72 : :
73 : : struct conntrack_dump {
74 : : struct conntrack *ct;
75 : : unsigned bucket;
76 : : struct hmap_position bucket_pos;
77 : : bool filter_zone;
78 : : uint16_t zone;
79 : : };
80 : :
81 : : struct ct_dpif_entry;
82 : :
83 : : int conntrack_dump_start(struct conntrack *, struct conntrack_dump *,
84 : : const uint16_t *pzone);
85 : : int conntrack_dump_next(struct conntrack_dump *, struct ct_dpif_entry *);
86 : : int conntrack_dump_done(struct conntrack_dump *);
87 : :
88 : : int conntrack_flush(struct conntrack *, const uint16_t *zone);
89 : :
90 : : /* 'struct ct_lock' is a wrapper for an adaptive mutex. It's useful to try
91 : : * different types of locks (e.g. spinlocks) */
92 : :
93 : : struct OVS_LOCKABLE ct_lock {
94 : : struct ovs_mutex lock;
95 : : };
96 : :
97 : 141568 : static inline void ct_lock_init(struct ct_lock *lock)
98 : : {
99 : 141568 : ovs_mutex_init_adaptive(&lock->lock);
100 : 141568 : }
101 : :
102 : 164254 : static inline void ct_lock_lock(struct ct_lock *lock)
103 : : OVS_ACQUIRES(lock)
104 : : OVS_NO_THREAD_SAFETY_ANALYSIS
105 : : {
106 : 164254 : ovs_mutex_lock(&lock->lock);
107 : 164254 : }
108 : :
109 : 164254 : static inline void ct_lock_unlock(struct ct_lock *lock)
110 : : OVS_RELEASES(lock)
111 : : OVS_NO_THREAD_SAFETY_ANALYSIS
112 : : {
113 : 164254 : ovs_mutex_unlock(&lock->lock);
114 : 164254 : }
115 : :
116 : 512 : static inline void ct_lock_destroy(struct ct_lock *lock)
117 : : {
118 : 512 : ovs_mutex_destroy(&lock->lock);
119 : 512 : }
120 : :
121 : : /* Timeouts: all the possible timeout states passed to update_expiration()
122 : : * are listed here. The name will be prefix by CT_TM_ and the value is in
123 : : * milliseconds */
124 : : #define CT_TIMEOUTS \
125 : : CT_TIMEOUT(TCP_FIRST_PACKET, 30 * 1000) \
126 : : CT_TIMEOUT(TCP_OPENING, 30 * 1000) \
127 : : CT_TIMEOUT(TCP_ESTABLISHED, 24 * 60 * 60 * 1000) \
128 : : CT_TIMEOUT(TCP_CLOSING, 15 * 60 * 1000) \
129 : : CT_TIMEOUT(TCP_FIN_WAIT, 45 * 1000) \
130 : : CT_TIMEOUT(TCP_CLOSED, 30 * 1000) \
131 : : CT_TIMEOUT(OTHER_FIRST, 60 * 1000) \
132 : : CT_TIMEOUT(OTHER_MULTIPLE, 60 * 1000) \
133 : : CT_TIMEOUT(OTHER_BIDIR, 30 * 1000) \
134 : : CT_TIMEOUT(ICMP_FIRST, 60 * 1000) \
135 : : CT_TIMEOUT(ICMP_REPLY, 30 * 1000)
136 : :
137 : : /* The smallest of the above values: it is used as an upper bound for the
138 : : * interval between two rounds of cleanup of expired entries */
139 : : #define CT_TM_MIN (30 * 1000)
140 : :
141 : : #define CT_TIMEOUT(NAME, VAL) BUILD_ASSERT_DECL(VAL >= CT_TM_MIN);
142 : : CT_TIMEOUTS
143 : : #undef CT_TIMEOUT
144 : :
145 : : enum ct_timeout {
146 : : #define CT_TIMEOUT(NAME, VALUE) CT_TM_##NAME,
147 : : CT_TIMEOUTS
148 : : #undef CT_TIMEOUT
149 : : N_CT_TM
150 : : };
151 : :
152 : : /* Locking:
153 : : *
154 : : * The connections are kept in different buckets, which are completely
155 : : * independent. The connection bucket is determined by the hash of its key.
156 : : *
157 : : * Each bucket has two locks. Acquisition order is, from outermost to
158 : : * innermost:
159 : : *
160 : : * cleanup_mutex
161 : : * lock
162 : : *
163 : : * */
164 : : struct conntrack_bucket {
165 : : /* Protects 'connections' and 'exp_lists'. Used in the fast path */
166 : : struct ct_lock lock;
167 : : /* Contains the connections in the bucket, indexed by 'struct conn_key' */
168 : : struct hmap connections OVS_GUARDED;
169 : : /* For each possible timeout we have a list of connections. When the
170 : : * timeout of a connection is updated, we move it to the back of the list.
171 : : * Since the connection in a list have the same relative timeout, the list
172 : : * will be ordered, with the oldest connections to the front. */
173 : : struct ovs_list exp_lists[N_CT_TM] OVS_GUARDED;
174 : :
175 : : /* Protects 'next_cleanup'. Used to make sure that there's only one thread
176 : : * performing the cleanup. */
177 : : struct ovs_mutex cleanup_mutex;
178 : : long long next_cleanup OVS_GUARDED;
179 : : };
180 : :
181 : : #define CONNTRACK_BUCKETS_SHIFT 8
182 : : #define CONNTRACK_BUCKETS (1 << CONNTRACK_BUCKETS_SHIFT)
183 : :
184 : : struct conntrack {
185 : : /* Independent buckets containing the connections */
186 : : struct conntrack_bucket buckets[CONNTRACK_BUCKETS];
187 : :
188 : : /* Salt for hashing a connection key. */
189 : : uint32_t hash_basis;
190 : :
191 : : /* The thread performing periodic cleanup of the connection
192 : : * tracker */
193 : : pthread_t clean_thread;
194 : : /* Latch to destroy the 'clean_thread' */
195 : : struct latch clean_thread_exit;
196 : :
197 : : /* Number of connections currently in the connection tracker. */
198 : : atomic_count n_conn;
199 : : /* Connections limit. When this limit is reached, no new connection
200 : : * will be accepted. */
201 : : atomic_uint n_conn_limit;
202 : : };
203 : :
204 : : #endif /* conntrack.h */
|