cnat: Disable default scanner process
[vpp.git] / src / plugins / cnat / cnat_types.h
1 /*
2  * Copyright (c) 2020 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #ifndef __CNAT_TYPES_H__
17 #define __CNAT_TYPES_H__
18
19 #include <vnet/fib/fib_node.h>
20 #include <vnet/fib/fib_source.h>
21 #include <vnet/ip/ip_types.h>
22 #include <vnet/ip/ip.h>
23
24 /* only in the default table for v4 and v6 */
25 #define CNAT_FIB_TABLE 0
26
27 /* default lifetime of NAT sessions (seconds) */
28 #define CNAT_DEFAULT_SESSION_MAX_AGE 30
29 /* lifetime of TCP conn NAT sessions after SYNACK (seconds) */
30 #define CNAT_DEFAULT_TCP_MAX_AGE 3600
31 /* lifetime of TCP conn NAT sessions after RST/FIN (seconds) */
32 #define CNAT_DEFAULT_TCP_RST_TIMEOUT 5
33 #define CNAT_DEFAULT_SCANNER_TIMEOUT (1.0)
34
35 #define CNAT_DEFAULT_SESSION_BUCKETS     1024
36 #define CNAT_DEFAULT_TRANSLATION_BUCKETS 1024
37 #define CNAT_DEFAULT_SNAT_BUCKETS        1024
38
39 #define CNAT_DEFAULT_SESSION_MEMORY      (1 << 20)
40 #define CNAT_DEFAULT_TRANSLATION_MEMORY  (256 << 10)
41 #define CNAT_DEFAULT_SNAT_MEMORY         (64 << 20)
42
43 /* This should be strictly lower than FIB_SOURCE_INTERFACE
44  * from fib_source.h */
45 #define CNAT_FIB_SOURCE_PRIORITY  0x02
46
47 /* Initial refcnt for timestamps (2 : session & rsession) */
48 #define CNAT_TIMESTAMP_INIT_REFCNT 2
49
50 #define MIN_SRC_PORT ((u16) 0xC000)
51
52 typedef struct cnat_endpoint_t_
53 {
54   ip_address_t ce_ip;
55   u16 ce_port;
56 } cnat_endpoint_t;
57
58 typedef struct cnat_endpoint_tuple_t_
59 {
60   cnat_endpoint_t dst_ep;
61   cnat_endpoint_t src_ep;
62 } cnat_endpoint_tuple_t;
63
64
65
66 typedef struct
67 {
68   u32 dst_address_length_refcounts[129];
69   u16 *prefix_lengths_in_search_order;
70   uword *non_empty_dst_address_length_bitmap;
71 } cnat_snat_pfx_table_meta_t;
72
73 typedef struct
74 {
75   /* Stores (ip family, prefix & mask) */
76   clib_bihash_24_8_t ip_hash;
77   /* family dependant cache */
78   cnat_snat_pfx_table_meta_t meta[2];
79   /* Precomputed ip masks (ip4 & ip6) */
80   ip6_address_t ip_masks[129];
81 } cnat_snat_pfx_table_t;
82
83 typedef struct cnat_main_
84 {
85   /* Memory size of the session bihash */
86   uword session_hash_memory;
87
88   /* Number of buckets of the  session bihash */
89   u32 session_hash_buckets;
90
91   /* Memory size of the translation bihash */
92   uword translation_hash_memory;
93
94   /* Number of buckets of the  translation bihash */
95   u32 translation_hash_buckets;
96
97   /* Memory size of the source NAT prefix bihash */
98   uword snat_hash_memory;
99
100   /* Number of buckets of the  source NAT prefix bihash */
101   u32 snat_hash_buckets;
102
103   /* Timeout after which to clear sessions (in seconds) */
104   u32 session_max_age;
105
106   /* Timeout after which to clear an established TCP
107    * session (in seconds) */
108   u32 tcp_max_age;
109
110   /* delay in seconds between two scans of session/clients tables */
111   f64 scanner_timeout;
112
113   /* Lock for the timestamp pool */
114   clib_rwlock_t ts_lock;
115
116   /* Source ports bitmap for snat */
117   clib_bitmap_t *src_ports;
118
119   /* Lock for src_ports access */
120   clib_spinlock_t src_ports_lock;
121
122   /* Ip4 Address to use for source NATing */
123   ip4_address_t snat_ip4;
124
125   /* Ip6 Address to use for source NATing */
126   ip6_address_t snat_ip6;
127
128   /* Longest prefix Match table for source NATing */
129   cnat_snat_pfx_table_t snat_pfx_table;
130
131   /* Index of the scanner process node */
132   uword scanner_node_index;
133
134   /* Did we do lazy init ? */
135   u8 lazy_init_done;
136
137   /* Enable or Disable the scanner on startup */
138   u8 default_scanner_state;
139 } cnat_main_t;
140
141 typedef struct cnat_timestamp_t_
142 {
143   /* Last time said session was seen */
144   f64 last_seen;
145   /* expire after N seconds */
146   u16 lifetime;
147   /* Users refcount, initially 3 (session, rsession, dpo) */
148   u16 refcnt;
149 } cnat_timestamp_t;
150
151 typedef struct cnat_node_ctx_t_
152 {
153   f64 now;
154   u64 seed;
155   u32 thread_index;
156   ip_address_family_t af;
157   u8 do_trace;
158 } cnat_node_ctx_t;
159
160 extern u8 *format_cnat_endpoint (u8 * s, va_list * args);
161 extern uword unformat_cnat_ep_tuple (unformat_input_t * input,
162                                      va_list * args);
163 extern uword unformat_cnat_ep (unformat_input_t * input, va_list * args);
164 extern cnat_timestamp_t *cnat_timestamps;
165 extern fib_source_t cnat_fib_source;
166 extern cnat_main_t cnat_main;
167 extern throttle_t cnat_throttle;
168
169 extern char *cnat_error_strings[];
170
171 typedef enum
172 {
173 #define cnat_error(n,s) CNAT_ERROR_##n,
174 #include <cnat/cnat_error.def>
175 #undef cnat_error
176   CNAT_N_ERROR,
177 } cnat_error_t;
178
179 typedef enum cnat_scanner_cmd_t_
180 {
181   CNAT_SCANNER_OFF,
182   CNAT_SCANNER_ON,
183 } cnat_scanner_cmd_t;
184
185 /**
186  * Lazy initialization when first adding a translation
187  * or using snat
188  */
189 extern void cnat_lazy_init ();
190
191 /**
192  * Enable/Disable session cleanup
193  */
194 extern void cnat_enable_disable_scanner (cnat_scanner_cmd_t event_type);
195
196 /*
197   Dataplane functions
198 */
199
200 always_inline u32
201 cnat_timestamp_new (f64 t)
202 {
203   u32 index;
204   cnat_timestamp_t *ts;
205   clib_rwlock_writer_lock (&cnat_main.ts_lock);
206   pool_get (cnat_timestamps, ts);
207   ts->last_seen = t;
208   ts->lifetime = cnat_main.session_max_age;
209   ts->refcnt = CNAT_TIMESTAMP_INIT_REFCNT;
210   index = ts - cnat_timestamps;
211   clib_rwlock_writer_unlock (&cnat_main.ts_lock);
212   return index;
213 }
214
215 always_inline void
216 cnat_timestamp_inc_refcnt (u32 index)
217 {
218   clib_rwlock_reader_lock (&cnat_main.ts_lock);
219   cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
220   ts->refcnt++;
221   clib_rwlock_reader_unlock (&cnat_main.ts_lock);
222 }
223
224 always_inline void
225 cnat_timestamp_update (u32 index, f64 t)
226 {
227   clib_rwlock_reader_lock (&cnat_main.ts_lock);
228   cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
229   ts->last_seen = t;
230   clib_rwlock_reader_unlock (&cnat_main.ts_lock);
231 }
232
233 always_inline void
234 cnat_timestamp_set_lifetime (u32 index, u16 lifetime)
235 {
236   clib_rwlock_reader_lock (&cnat_main.ts_lock);
237   cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
238   ts->lifetime = lifetime;
239   clib_rwlock_reader_unlock (&cnat_main.ts_lock);
240 }
241
242 always_inline f64
243 cnat_timestamp_exp (u32 index)
244 {
245   f64 t;
246   if (INDEX_INVALID == index)
247     return -1;
248   clib_rwlock_reader_lock (&cnat_main.ts_lock);
249   cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
250   t = ts->last_seen + (f64) ts->lifetime;
251   clib_rwlock_reader_unlock (&cnat_main.ts_lock);
252   return t;
253 }
254
255 always_inline void
256 cnat_timestamp_free (u32 index)
257 {
258   if (INDEX_INVALID == index)
259     return;
260   clib_rwlock_writer_lock (&cnat_main.ts_lock);
261   cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
262   ts->refcnt--;
263   if (0 == ts->refcnt)
264     pool_put (cnat_timestamps, ts);
265   clib_rwlock_writer_unlock (&cnat_main.ts_lock);
266 }
267
268 always_inline void
269 cnat_free_port (u16 port)
270 {
271   cnat_main_t *cm = &cnat_main;
272   clib_spinlock_lock (&cm->src_ports_lock);
273   clib_bitmap_set_no_check (cm->src_ports, port, 0);
274   clib_spinlock_unlock (&cm->src_ports_lock);
275 }
276
277 always_inline int
278 cnat_allocate_port (cnat_main_t * cm, u16 * port)
279 {
280   *port = clib_net_to_host_u16 (*port);
281   if (*port == 0)
282     *port = MIN_SRC_PORT;
283   clib_spinlock_lock (&cm->src_ports_lock);
284   if (clib_bitmap_get_no_check (cm->src_ports, *port))
285     {
286       *port = clib_bitmap_next_clear (cm->src_ports, *port);
287       if (PREDICT_FALSE (*port >= UINT16_MAX))
288         *port = clib_bitmap_next_clear (cm->src_ports, MIN_SRC_PORT);
289       if (PREDICT_FALSE (*port >= UINT16_MAX))
290         return -1;
291     }
292   clib_bitmap_set_no_check (cm->src_ports, *port, 1);
293   *port = clib_host_to_net_u16 (*port);
294   clib_spinlock_unlock (&cm->src_ports_lock);
295   return 0;
296 }
297
298 /*
299  * fd.io coding-style-patch-verification: ON
300  *
301  * Local Variables:
302  * eval: (c-set-style "gnu")
303  * End:
304  */
305
306 #endif