FD.io VPP  v18.07-rc0-415-g6c78436
Vector Packet Processing
nat_inlines.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 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  * @brief The NAT inline functions
17  */
18 
19 #ifndef __included_nat_inlines_h__
20 #define __included_nat_inlines_h__
21 
22 #include <nat/nat.h>
23 
26 {
27  u32 snat_proto = ~0;
28 
29  snat_proto = (ip_proto == IP_PROTOCOL_UDP) ? SNAT_PROTOCOL_UDP : snat_proto;
30  snat_proto = (ip_proto == IP_PROTOCOL_TCP) ? SNAT_PROTOCOL_TCP : snat_proto;
31  snat_proto =
32  (ip_proto == IP_PROTOCOL_ICMP) ? SNAT_PROTOCOL_ICMP : snat_proto;
33  snat_proto =
34  (ip_proto == IP_PROTOCOL_ICMP6) ? SNAT_PROTOCOL_ICMP : snat_proto;
35 
36  return snat_proto;
37 }
38 
41 {
42  u8 ip_proto = ~0;
43 
44  ip_proto = (snat_proto == SNAT_PROTOCOL_UDP) ? IP_PROTOCOL_UDP : ip_proto;
45  ip_proto = (snat_proto == SNAT_PROTOCOL_TCP) ? IP_PROTOCOL_TCP : ip_proto;
46  ip_proto = (snat_proto == SNAT_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP : ip_proto;
47 
48  return ip_proto;
49 }
50 
52 icmp_is_error_message (icmp46_header_t * icmp)
53 {
54  switch (icmp->type)
55  {
56  case ICMP4_destination_unreachable:
57  case ICMP4_time_exceeded:
58  case ICMP4_parameter_problem:
59  case ICMP4_source_quench:
60  case ICMP4_redirect:
61  case ICMP4_alternate_host_address:
62  return 1;
63  }
64  return 0;
65 }
66 
69  u32 sw_if_index0, u32 ip4_addr)
70 {
72  ip4_address_t *first_int_addr;
73 
74  if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0))
75  {
76  first_int_addr =
77  ip4_interface_first_address (sm->ip4_main, sw_if_index0,
78  0 /* just want the address */ );
79  rt->cached_sw_if_index = sw_if_index0;
80  if (first_int_addr)
81  rt->cached_ip4_address = first_int_addr->as_u32;
82  else
83  rt->cached_ip4_address = 0;
84  }
85 
86  if (PREDICT_FALSE (ip4_addr == rt->cached_ip4_address))
87  return 1;
88  else
89  return 0;
90 }
91 
94 {
95  if (pool_elts (sm->per_thread_data[thread_index].sessions) >=
96  sm->max_translations)
97  return 1;
98 
99  return 0;
100 }
101 
102 always_inline void
104  vlib_node_runtime_t * node, vlib_error_t * error,
105  u32 next)
106 {
107  u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
108 
109  from = bi_vector;
110  n_left_from = vec_len (bi_vector);
111  next_index = node->cached_next_index;
112  while (n_left_from > 0)
113  {
114  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
115  while (n_left_from > 0 && n_left_to_next > 0)
116  {
117  u32 bi0 = to_next[0] = from[0];
118  from += 1;
119  n_left_from -= 1;
120  to_next += 1;
121  n_left_to_next -= 1;
122  vlib_buffer_t *p0 = vlib_get_buffer (vm, bi0);
123  p0->error = *error;
124  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
125  n_left_to_next, bi0, next);
126  }
127  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
128  }
129 }
130 
131 always_inline void
133 {
135  {
136  if (is_static)
137  u->nstaticsessions++;
138  else
139  u->nsessions++;
140  }
141 }
142 
143 always_inline void
144 nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
145  u32 thread_index)
146 {
148  thread_index);
149  clib_bihash_kv_8_8_t kv, value;
150  snat_user_key_t u_key;
151  snat_user_t *u;
152 
153  nat_log_debug ("session deleted %U", format_snat_session, tsm, ses);
154  u_key.addr = ses->in2out.addr;
155  u_key.fib_index = ses->in2out.fib_index;
156  kv.key = u_key.as_u64;
157  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
158  {
159  u = pool_elt_at_index (tsm->users, value.value);
160  if (snat_is_session_static (ses))
161  u->nstaticsessions--;
162  else
163  u->nsessions--;
164  }
165  clib_dlist_remove (tsm->list_pool, ses->per_user_index);
166  pool_put_index (tsm->list_pool, ses->per_user_index);
167  pool_put (tsm->sessions, ses);
168 }
169 
170 /** \brief Set TCP session state.
171  @return 1 if session was closed, otherwise 0
172 */
173 always_inline int
174 nat44_set_tcp_session_state_i2o (snat_main_t * sm, snat_session_t * ses,
175  tcp_header_t * tcp, u32 thread_index)
176 {
177  if (tcp->flags & TCP_FLAG_FIN)
178  {
179  ses->i2o_fin_seq = clib_net_to_host_u32 (tcp->seq_number);
180  ses->state |= NAT44_SES_I2O_FIN;
181  }
182  if ((tcp->flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_O2I_FIN))
183  {
184  if (clib_net_to_host_u32 (tcp->ack_number) > ses->o2i_fin_seq)
185  ses->state |= NAT44_SES_O2I_FIN_ACK;
186  }
187  if (nat44_is_ses_closed (ses))
188  {
189  nat_log_debug ("TCP close connection %U", format_snat_session,
190  &sm->per_thread_data[thread_index], ses);
191  nat_free_session_data (sm, ses, thread_index);
192  nat44_delete_session (sm, ses, thread_index);
193  return 1;
194  }
195  return 0;
196 }
197 
198 always_inline int
199 nat44_set_tcp_session_state_o2i (snat_main_t * sm, snat_session_t * ses,
200  tcp_header_t * tcp, u32 thread_index)
201 {
202  if (tcp->flags & TCP_FLAG_FIN)
203  {
204  ses->o2i_fin_seq = clib_net_to_host_u32 (tcp->seq_number);
205  ses->state |= NAT44_SES_O2I_FIN;
206  }
207  if ((tcp->flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_FIN))
208  {
209  if (clib_net_to_host_u32 (tcp->ack_number) > ses->i2o_fin_seq)
210  ses->state |= NAT44_SES_I2O_FIN_ACK;
211  }
212  if (nat44_is_ses_closed (ses))
213  {
214  nat_log_debug ("TCP close connection %U", format_snat_session,
215  &sm->per_thread_data[thread_index], ses);
216  nat_free_session_data (sm, ses, thread_index);
217  nat44_delete_session (sm, ses, thread_index);
218  return 1;
219  }
220  return 0;
221 }
222 
223 always_inline void
224 nat44_session_update_counters (snat_session_t * s, f64 now, uword bytes)
225 {
226  s->last_heard = now;
227  s->total_pkts++;
228  s->total_bytes += bytes;
229 }
230 
231 /** \brief Per-user LRU list maintenance */
232 always_inline void
233 nat44_session_update_lru (snat_main_t * sm, snat_session_t * s,
234  u32 thread_index)
235 {
236  clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
237  s->per_user_index);
238  clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
239  s->per_user_list_head_index, s->per_user_index);
240 }
241 
242 always_inline void
244  ip4_address_t * r_addr, u8 proto, u32 fib_index, u16 l_port,
245  u16 r_port)
246 {
247  nat_ed_ses_key_t *key = (nat_ed_ses_key_t *) kv->key;
248 
249  key->l_addr.as_u32 = l_addr->as_u32;
250  key->r_addr.as_u32 = r_addr->as_u32;
251  key->fib_index = fib_index;
252  key->proto = proto;
253  key->l_port = l_port;
254  key->r_port = r_port;
255 
256  kv->value = ~0ULL;
257 }
258 
259 always_inline void
261  u32 fib_index, u16 port)
262 {
263  snat_session_key_t key;
264 
265  key.addr.as_u32 = addr->as_u32;
266  key.port = port;
267  key.protocol = proto;
268  key.fib_index = fib_index;
269 
270  kv->key = key.as_u64;
271  kv->value = ~0ULL;
272 }
273 
274 #endif /* __included_nat_inlines_h__ */
275 
276 /*
277  * fd.io coding-style-patch-verification: ON
278  *
279  * Local Variables:
280  * eval: (c-set-style "gnu")
281  * End:
282  */
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:483
#define NAT44_SES_I2O_FIN
Definition: nat.h:132
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:500
u32 nsessions
Definition: nat.h:190
static_always_inline u8 icmp_is_error_message(icmp46_header_t *icmp)
Definition: nat_inlines.h:52
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
Definition: ip4_forward.c:320
static void make_sm_kv(clib_bihash_kv_8_8_t *kv, ip4_address_t *addr, u8 proto, u32 fib_index, u16 port)
Definition: nat_inlines.h:260
u32 nstaticsessions
Definition: nat.h:191
u16 vlib_error_t
Definition: error.h:44
#define nat44_is_ses_closed(s)
Definition: nat.h:137
#define NAT44_SES_O2I_FIN
Definition: nat.h:133
dlist_elt_t * list_pool
Definition: nat.h:290
struct _tcp_header tcp_header_t
u32 proto
Definition: nat.h:67
unsigned char u8
Definition: types.h:56
static int nat44_set_tcp_session_state_o2i(snat_main_t *sm, snat_session_t *ses, tcp_header_t *tcp, u32 thread_index)
Definition: nat_inlines.h:199
u16 l_port
Definition: nat.h:69
double f64
Definition: types.h:142
clib_bihash_8_8_t user_hash
Definition: nat.h:281
u32 cached_sw_if_index
Definition: nat.h:475
u32 max_translations_per_user
Definition: nat.h:394
#define static_always_inline
Definition: clib.h:93
u16 r_port
Definition: nat.h:70
#define always_inline
Definition: clib.h:92
#define TCP_FLAG_ACK
Definition: fa_node.h:16
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
ip4_main_t * ip4_main
Definition: nat.h:415
unsigned int u32
Definition: types.h:88
static u8 maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
Definition: nat_inlines.h:93
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
Definition: nat_inlines.h:144
u32 max_translations
Definition: nat.h:391
u32 fib_index
Definition: nat.h:67
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Definition: nat.c:187
u64 key
the key
Definition: bihash_8_8.h:35
static void clib_dlist_addtail(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:43
unsigned short u16
Definition: types.h:57
u16 protocol
Definition: nat.h:53
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
#define PREDICT_FALSE(x)
Definition: clib.h:105
#define TCP_FLAG_FIN
Definition: fa_node.h:12
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:364
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:135
u64 value
the value
Definition: bihash_8_8.h:36
snat_user_t * users
Definition: nat.h:284
#define nat_log_debug(...)
Definition: nat.h:526
static u8 snat_proto_to_ip_proto(snat_protocol_t snat_proto)
Definition: nat_inlines.h:40
vlib_main_t * vm
Definition: buffer.c:294
ip4_address_t l_addr
Definition: nat.h:65
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes)
Definition: nat_inlines.h:224
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:33
ip4_address_t addr
Definition: nat.h:51
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:454
static void make_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t *l_addr, ip4_address_t *r_addr, u8 proto, u32 fib_index, u16 l_port, u16 r_port)
Definition: nat_inlines.h:243
ip4_address_t r_addr
Definition: nat.h:66
static int nat44_set_tcp_session_state_i2o(snat_main_t *sm, snat_session_t *ses, tcp_header_t *tcp, u32 thread_index)
Set TCP session state.
Definition: nat_inlines.h:174
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:492
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:296
static void nat44_session_update_lru(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Per-user LRU list maintenance.
Definition: nat_inlines.h:233
u64 as_u64
Definition: nat.h:97
ip4_address_t addr
Definition: nat.h:94
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
format_function_t format_snat_session
Definition: nat.h:471
static u32 ip_proto_to_snat_proto(u8 ip_proto)
The NAT inline functions.
Definition: nat_inlines.h:25
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
Definition: nat_inlines.h:132
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:331
snat_protocol_t
Definition: nat.h:107
static u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
Definition: nat_inlines.h:68
u32 fib_index
Definition: nat.h:95
#define NAT44_SES_I2O_FIN_ACK
Definition: nat.h:134
static void nat_send_all_to_node(vlib_main_t *vm, u32 *bi_vector, vlib_node_runtime_t *node, vlib_error_t *error, u32 next)
Definition: nat_inlines.h:103
vhost_vring_addr_t addr
Definition: vhost-user.h:83
#define NAT44_SES_O2I_FIN_ACK
Definition: nat.h:135
snat_session_t * sessions
Definition: nat.h:287
u32 cached_ip4_address
Definition: nat.h:476
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
u16 fib_index
Definition: nat.h:53
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128