FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
det44.h
Go to the documentation of this file.
1 /*
2  * det44.h - deterministic NAT definitions
3  *
4  * Copyright (c) 2020 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /**
19  * @file
20  * @brief Deterministic NAT (CGN) definitions
21  */
22 
23 #ifndef __included_det44_h__
24 #define __included_det44_h__
25 
26 #include <vnet/vnet.h>
27 #include <vnet/ip/ip.h>
28 #include <vnet/ethernet/ethernet.h>
29 #include <vnet/ip/icmp46_packet.h>
30 #include <vnet/api_errno.h>
31 #include <vnet/fib/fib_source.h>
32 #include <vppinfra/dlist.h>
33 #include <vppinfra/error.h>
34 #include <vlibapi/api.h>
35 #include <vlib/log.h>
36 #include <vnet/fib/fib_table.h>
37 #include <vnet/fib/ip4_fib.h>
39 
40 #include <nat/lib/lib.h>
41 #include <nat/lib/inlines.h>
42 
43 /* Session state */
44 #define foreach_det44_session_state \
45  _(0, UNKNOWN, "unknown") \
46  _(1, UDP_ACTIVE, "udp-active") \
47  _(2, TCP_SYN_SENT, "tcp-syn-sent") \
48  _(3, TCP_ESTABLISHED, "tcp-established") \
49  _(4, TCP_FIN_WAIT, "tcp-fin-wait") \
50  _(5, TCP_CLOSE_WAIT, "tcp-close-wait") \
51  _(6, TCP_CLOSING, "tcp-closing") \
52  _(7, TCP_LAST_ACK, "tcp-last-ack") \
53  _(8, TCP_CLOSED, "tcp-closed") \
54  _(9, ICMP_ACTIVE, "icmp-active")
55 
56 typedef enum
57 {
58 #define _(v, N, s) DET44_SESSION_##N = v,
60 #undef _
62 
63 #define DET44_SES_PER_USER 1000
64 
65 typedef struct
66 {
70 
71 typedef struct
72 {
75 
76 typedef struct
77 {
81 
82 typedef struct nat_timeouts_s
83 {
85 
86  struct
87  {
90  } tcp;
91 
93 
95 
96 /* deterministic session outside key */
97 typedef struct
98 {
99  union
100  {
101  struct
102  {
106  };
108  };
110 
111 typedef struct
112 {
113  /* Inside network port */
115  /* Outside network address and port */
117  /* Session state */
119  /* Expire timeout */
122 
123 typedef struct
124 {
125  /* inside IP address range */
128  /* outside IP address range */
131  /* inside IP addresses / outside IP addresses */
133  /* number of ports available to internal host */
135  /* session counter */
137  /* vector of sessions */
140 
141 typedef struct
142 {
146 
147 typedef struct
148 {
149 
152 
154 
155 typedef struct
156 {
159 } det44_fib_t;
160 
161 typedef struct det44_main_s
162 {
164 
167 
168  /* Vector of outside fibs */
170 
173 
176 
177  /* Deterministic NAT mappings */
179 
180  /* TCP MSS clamping */
182 
183  /* Protocol timeouts */
185 
186  /* Expire walk process node index */
188 
190 
191  /* API message ID base */
193 
194  /* log class */
196 
198 
199  /* convenience */
201  /* required */
203 
204 } det44_main_t;
205 
206 extern det44_main_t det44_main;
207 
208 /* logging */
209 #define det44_log_err(...) \
210  vlib_log(VLIB_LOG_LEVEL_ERR, det44_main.log_class, __VA_ARGS__)
211 #define det44_log_warn(...) \
212  vlib_log(VLIB_LOG_LEVEL_WARNING, det44_main.log_class, __VA_ARGS__)
213 #define det44_log_notice(...) \
214  vlib_log(VLIB_LOG_LEVEL_NOTICE, det44_main.log_class, __VA_ARGS__)
215 #define det44_log_info(...) \
216  vlib_log(VLIB_LOG_LEVEL_INFO, det44_main.log_class, __VA_ARGS__)
217 #define det44_log_debug(...)\
218  vlib_log(VLIB_LOG_LEVEL_DEBUG, det44_main.log_class, __VA_ARGS__)
219 
220 /* Deterministic NAT interface flags */
221 #define DET44_INTERFACE_FLAG_IS_INSIDE 1
222 #define DET44_INTERFACE_FLAG_IS_OUTSIDE 2
223 
224 /** \brief Check if Deterministic NAT interface is inside.
225  @param i Deterministic NAT interface
226  @return 1 if inside interface
227 */
228 #define det44_interface_is_inside(i) i->flags & DET44_INTERFACE_FLAG_IS_INSIDE
229 
230 /** \brief Check if Deterministic NAT interface is outside.
231  @param i Deterministic NAT interface
232  @return 1 if outside interface
233 */
234 #define det44_interface_is_outside(i) i->flags & DET44_INTERFACE_FLAG_IS_OUTSIDE
235 
238 {
239  det44_main_t *dm = &det44_main;
240  return dm->enabled;
241 }
242 
245 
246 int det44_plugin_enable ();
247 int det44_plugin_disable ();
248 
249 int det44_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del);
250 
251 int det44_set_timeouts (nat_timeouts_t * timeouts);
253 void det44_reset_timeouts ();
254 
255 /* format functions */
257 
258 int snat_det_add_map (ip4_address_t * in_addr, u8 in_plen,
259  ip4_address_t * out_addr, u8 out_plen, int is_add);
260 
261 /* icmp session match functions */
263  u32 thread_index, vlib_buffer_t * b0,
265  u16 * port, u32 * fib_index,
266  nat_protocol_t * proto, void *d, void *e,
267  u8 * dont_translate);
269  u32 thread_index, vlib_buffer_t * b0,
271  u16 * port, u32 * fib_index,
272  nat_protocol_t * proto, void *d, void *e,
273  u8 * dont_translate);
275  icmp46_header_t * icmp0, u32 sw_if_index0,
276  u32 rx_fib_index0, vlib_node_runtime_t * node,
277  u32 next0, u32 thread_index, void *d, void *e);
279  icmp46_header_t * icmp0, u32 sw_if_index0,
280  u32 rx_fib_index0, vlib_node_runtime_t * node,
281  u32 next0, u32 thread_index, void *d, void *e);
282 
285 {
286  if (net->as_u32 == (addr->as_u32 & ip4_main.fib_masks[plen]))
287  return 1;
288  return 0;
289 }
290 
293 {
294  det44_main_t *dm = &det44_main;
295  snat_det_map_t *mp;
296  /* *INDENT-OFF* */
297  pool_foreach (mp, dm->det_maps,
298  ({
299  if (is_addr_in_net(user_addr, &mp->in_addr, mp->in_plen))
300  return mp;
301  }));
302  /* *INDENT-ON* */
303  return 0;
304 }
305 
308 {
309  det44_main_t *dm = &det44_main;
310  snat_det_map_t *mp;
311  /* *INDENT-OFF* */
312  pool_foreach (mp, dm->det_maps,
313  ({
314  if (is_addr_in_net(out_addr, &mp->out_addr, mp->out_plen))
315  return mp;
316  }));
317  /* *INDENT-ON* */
318  return 0;
319 }
320 
323  ip4_address_t * out_addr, u16 * lo_port)
324 {
325  u32 in_offset, out_offset;
326 
327  in_offset = clib_net_to_host_u32 (in_addr->as_u32) -
328  clib_net_to_host_u32 (dm->in_addr.as_u32);
329  out_offset = in_offset / dm->sharing_ratio;
330  out_addr->as_u32 =
331  clib_host_to_net_u32 (clib_net_to_host_u32 (dm->out_addr.as_u32) +
332  out_offset);
333  *lo_port = 1024 + dm->ports_per_host * (in_offset % dm->sharing_ratio);
334 }
335 
337 snat_det_reverse (snat_det_map_t * dm, ip4_address_t * out_addr, u16 out_port,
338  ip4_address_t * in_addr)
339 {
340  u32 in_offset1, in_offset2, out_offset;
341 
342  out_offset = clib_net_to_host_u32 (out_addr->as_u32) -
343  clib_net_to_host_u32 (dm->out_addr.as_u32);
344  in_offset1 = out_offset * dm->sharing_ratio;
345  in_offset2 = (out_port - 1024) / dm->ports_per_host;
346  in_addr->as_u32 =
347  clib_host_to_net_u32 (clib_net_to_host_u32 (dm->in_addr.as_u32) +
348  in_offset1 + in_offset2);
349 }
350 
353 {
354  return (clib_net_to_host_u32 (addr->as_u32) & pow2_mask (32 - plen)) *
356 }
357 
360  u64 out_key)
361 {
362  u32 user_offset;
363  u16 i;
364 
365  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
366  for (i = 0; i < DET44_SES_PER_USER; i++)
367  {
368  if (dm->sessions[i + user_offset].out.as_u64 == out_key)
369  return &dm->sessions[i + user_offset];
370  }
371 
372  return 0;
373 }
374 
377  u16 in_port, snat_det_out_key_t out_key)
378 {
379  snat_det_session_t *ses;
380  u32 user_offset;
381  u16 i;
382 
383  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
384  for (i = 0; i < DET44_SES_PER_USER; i++)
385  {
386  ses = &dm->sessions[i + user_offset];
387  if (ses->in_port == in_port &&
388  ses->out.ext_host_addr.as_u32 == out_key.ext_host_addr.as_u32 &&
389  ses->out.ext_host_port == out_key.ext_host_port)
390  return &dm->sessions[i + user_offset];
391  }
392 
393  return 0;
394 }
395 
398  ip4_address_t * in_addr, u16 in_port,
399  snat_det_out_key_t * out)
400 {
401  u32 user_offset;
402  u16 i;
403 
404  user_offset = snat_det_user_ses_offset (in_addr, dm->in_plen);
405 
406  for (i = 0; i < DET44_SES_PER_USER; i++)
407  {
408  if (!dm->sessions[i + user_offset].in_port)
409  {
411  (&dm->sessions[i + user_offset].in_port, 0, in_port))
412  {
413  dm->sessions[i + user_offset].out.as_u64 = out->as_u64;
414  dm->sessions[i + user_offset].state = DET44_SESSION_UNKNOWN;
415  dm->sessions[i + user_offset].expire = 0;
416  clib_atomic_add_fetch (&dm->ses_num, 1);
417  return &dm->sessions[i + user_offset];
418  }
419  }
420  }
421 
422  // TODO:
423  /*snat_ipfix_logging_max_entries_per_user (thread_index,
424  DET44_SES_PER_USER,
425  in_addr->as_u32); */
426  return 0;
427 }
428 
431 {
432  if (clib_atomic_bool_cmp_and_swap (&ses->in_port, ses->in_port, 0))
433  {
434  ses->out.as_u64 = 0;
435  clib_atomic_add_fetch (&dm->ses_num, -1);
436  }
437 }
438 
440 
441 #endif /* __included_det44_h__ */
442 
443 /*
444  * fd.io coding-style-patch-verification: ON
445  *
446  * Local Variables:
447  * eval: (c-set-style "gnu")
448  * End:
449  */
enum fib_source_t_ fib_source_t
The different sources that can create a route.
static_always_inline snat_det_session_t * snat_det_get_ses_by_out(snat_det_map_t *dm, ip4_address_t *in_addr, u64 out_key)
Definition: det44.h:359
fib_source_t fib_src_low
Definition: det44.h:172
static_always_inline void snat_det_reverse(snat_det_map_t *dm, ip4_address_t *out_addr, u16 out_port, ip4_address_t *in_addr)
Definition: det44.h:337
nat_timeouts_t det44_get_timeouts()
Definition: det44.c:181
u32 inside_vrf_id
Definition: det44.h:151
#define clib_atomic_add_fetch(a, b)
Definition: atomics.h:30
vnet_main_t * vnet_main
Definition: det44.h:202
unsigned long u64
Definition: types.h:89
vl_api_ip_port_and_mask_t dst_port
Definition: flow_types.api:92
u32 established
Definition: det44.h:89
u32 det44_icmp_in2out(vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, u32 thread_index, void *d, void *e)
Definition: det44_in2out.c:255
struct det44_main_s det44_main_t
nat_protocol_t
Definition: lib.h:41
NAT port/address allocation lib.
format_function_t format_det_map_ses
Definition: det44.h:256
struct nat_timeouts_s::@74 tcp
vhost_vring_addr_t addr
Definition: vhost_user.h:111
unsigned char u8
Definition: types.h:56
det44_main_t det44_main
Definition: det44.c:30
static_always_inline u32 snat_det_user_ses_offset(ip4_address_t *addr, u8 plen)
Definition: det44.h:352
nat_timeouts_t timeouts
Definition: det44.h:184
u8 *() format_function_t(u8 *s, va_list *args)
Definition: format.h:48
u32 icmp_match_in2out_det(vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto, void *d, void *e, u8 *dont_translate)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: det44_in2out.c:100
det44_fib_t * outside_fibs
Definition: det44.h:169
static_always_inline u8 plugin_enabled()
Definition: det44.h:237
u32 vlib_log_class_t
Definition: vlib.h:51
#define static_always_inline
Definition: clib.h:108
u16 mss_clamping
Definition: det44.h:181
int det44_plugin_disable()
Definition: det44.c:388
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
ip4_address_t ext_host_addr
Definition: det44.h:103
int det44_plugin_enable()
static uword pow2_mask(uword x)
Definition: clib.h:237
static_always_inline snat_det_session_t * snat_det_find_ses_by_in(snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t out_key)
Definition: det44.h:376
static_always_inline snat_det_session_t * snat_det_ses_create(u32 thread_index, snat_det_map_t *dm, ip4_address_t *in_addr, u16 in_port, snat_det_out_key_t *out)
Definition: det44.h:397
static_always_inline snat_det_map_t * snat_det_map_by_out(ip4_address_t *out_addr)
Definition: det44.h:307
u32 out2in_node_index
Definition: det44.h:174
u32 det44_icmp_out2in(vlib_buffer_t *b0, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 sw_if_index0, u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0, u32 thread_index, void *d, void *e)
Definition: det44_out2in.c:233
u16 msg_id_base
Definition: det44.h:192
unsigned int u32
Definition: types.h:88
u32 outside_vrf_id
Definition: det44.h:150
u32 fib_index
Definition: det44.h:157
snat_det_session_t * sessions
Definition: det44.h:138
vl_api_ip_proto_t proto
Definition: acl_types.api:50
IPv4 shallow virtual reassembly.
unsigned short u16
Definition: types.h:57
static_always_inline int is_addr_in_net(ip4_address_t *addr, ip4_address_t *net, u8 plen)
Definition: det44.h:284
struct nat_timeouts_s nat_timeouts_t
snat_det_map_t * det_maps
Definition: det44.h:178
u16 src_port
Definition: det44.h:73
static_always_inline void snat_det_forward(snat_det_map_t *dm, ip4_address_t *in_addr, ip4_address_t *out_addr, u16 *lo_port)
Definition: det44.h:322
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
u32 in2out_node_index
Definition: det44.h:175
int snat_det_add_map(ip4_address_t *in_addr, u8 in_plen, ip4_address_t *out_addr, u8 out_plen, int is_add)
Add/delete deterministic NAT mapping.
Definition: det44.c:99
u32 sharing_ratio
Definition: det44.h:132
ip4_address_t out_addr
Definition: det44.h:129
u32 icmp
Definition: det44.h:92
u32 outside_fib_index
Definition: det44.h:165
static_always_inline void snat_det_ses_close(snat_det_map_t *dm, snat_det_session_t *ses)
Definition: det44.h:430
u32 cached_sw_if_index
Definition: det44.h:78
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
vlib_node_registration_t det44_out2in_node
(constructor) VLIB_REGISTER_NODE (det44_out2in_node)
Definition: det44_out2in.c:819
#define DET44_SES_PER_USER
Definition: det44.h:63
IPv4 main type.
Definition: ip4.h:106
u32 cached_ip4_address
Definition: det44.h:79
u32 transitory
Definition: det44.h:88
u32 refcount
Definition: det44.h:158
ip4_address_t in_addr
Definition: det44.h:126
u32 icmp_match_out2in_det(vlib_node_runtime_t *node, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto, void *d, void *e, u8 *dont_translate)
Get address and port values to be used for ICMP packet translation and create session if needed...
Definition: det44_out2in.c:100
#define foreach_det44_session_state
Definition: det44.h:44
void det44_reset_timeouts()
Definition: det44.c:188
vlib_node_registration_t det44_in2out_node
(constructor) VLIB_REGISTER_NODE (det44_in2out_node)
struct _vlib_node_registration vlib_node_registration_t
det44_interface_t * interfaces
Definition: det44.h:197
#define clib_atomic_bool_cmp_and_swap(addr, old, new)
Definition: atomics.h:38
u16 ports_per_host
Definition: det44.h:134
VLIB buffer representation.
Definition: buffer.h:102
snat_det_out_key_t out
Definition: det44.h:116
ip4_main_t * ip4_main
Definition: det44.h:200
u16 port
Definition: lb_types.api:72
u32 enabled
Definition: det44.h:189
clib_error_t * det44_api_hookup(vlib_main_t *vm)
Definition: det44_api.c:620
vlib_log_class_t log_class
Definition: det44.h:195
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1144
int det44_set_timeouts(nat_timeouts_t *timeouts)
Definition: det44.c:166
u32 expire_walk_node_index
Definition: det44.h:187
u32 inside_fib_index
Definition: det44.h:166
u32 ses_num
Definition: det44.h:136
int det44_interface_add_del(u32 sw_if_index, u8 is_inside, int is_del)
Definition: det44.c:198
static_always_inline snat_det_map_t * snat_det_map_by_user(ip4_address_t *user_addr)
Definition: det44.h:292
det44_session_state_t
Definition: det44.h:56
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
fib_source_t fib_src_hi
Definition: det44.h:171
det44_config_t config
Definition: det44.h:163
u32 fib_masks[33]
Definition: ip4.h:119