FD.io VPP  v20.09-64-g4f7b92f0a
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 <vnet/fib/ip4_fib.h>
23 #include <nat/nat.h>
24 #include <nat/nat_ha.h>
25 
28 {
29  ASSERT (fib_index <= (1 << 14) - 1);
30  ASSERT (proto <= (1 << 3) - 1);
31  return (u64) addr.as_u32 << 32 | (u64) port << 16 | fib_index << 3 |
32  (proto & 0x7);
33 }
34 
35 always_inline void
37  u32 * fib_index, nat_protocol_t * proto)
38 {
39  if (addr)
40  {
41  addr->as_u32 = key >> 32;
42  }
43  if (port)
44  {
45  *port = (key >> 16) & (u16) ~ 0;
46  }
47  if (fib_index)
48  {
49  *fib_index = key >> 3 & ((1 << 13) - 1);
50  }
51  if (proto)
52  {
53  *proto = key & 0x7;
54  }
55 }
56 
57 always_inline void
59  u32 fib_index, nat_protocol_t proto)
60 {
61  kv->key = calc_nat_key (addr, port, fib_index, proto);
62  kv->value = ~0ULL;
63 }
64 
65 always_inline void
67  u32 fib_index, nat_protocol_t proto, u64 value)
68 {
69  init_nat_k (kv, addr, port, fib_index, proto);
70  kv->value = value;
71 }
72 
73 always_inline void
74 init_nat_i2o_k (clib_bihash_kv_8_8_t * kv, snat_session_t * s)
75 {
76  return init_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index,
77  s->nat_proto);
78 }
79 
80 always_inline void
81 init_nat_i2o_kv (clib_bihash_kv_8_8_t * kv, snat_session_t * s, u64 value)
82 {
83  init_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index,
84  s->nat_proto);
85  kv->value = value;
86 }
87 
88 always_inline void
89 init_nat_o2i_k (clib_bihash_kv_8_8_t * kv, snat_session_t * s)
90 {
91  return init_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index,
92  s->nat_proto);
93 }
94 
95 always_inline void
96 init_nat_o2i_kv (clib_bihash_kv_8_8_t * kv, snat_session_t * s, u64 value)
97 {
98  init_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index,
99  s->nat_proto);
100  kv->value = value;
101 }
102 
103 static inline uword
106  vlib_frame_t * frame, u32 def_next)
107 {
108  u32 n_left_from, *from;
109 
110  from = vlib_frame_vector_args (frame);
111  n_left_from = frame->n_vectors;
112 
113  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b = bufs;
114  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
115  vlib_get_buffers (vm, from, b, n_left_from);
116 
117  while (n_left_from >= 2)
118  {
119  u32 next0, next1;
120  u32 arc_next0, arc_next1;
121  vlib_buffer_t *b0, *b1;
122 
123  b0 = *b;
124  b++;
125  b1 = *b;
126  b++;
127 
128  /* Prefetch next iteration. */
129  if (PREDICT_TRUE (n_left_from >= 4))
130  {
131  vlib_buffer_t *p2, *p3;
132 
133  p2 = *b;
134  p3 = *(b + 1);
135 
136  vlib_prefetch_buffer_header (p2, LOAD);
137  vlib_prefetch_buffer_header (p3, LOAD);
138 
141  }
142 
143  next0 = def_next;
144  next1 = def_next;
145 
146  vnet_feature_next (&arc_next0, b0);
147  vnet_feature_next (&arc_next1, b1);
148 
149  vnet_buffer2 (b0)->nat.arc_next = arc_next0;
150  vnet_buffer2 (b1)->nat.arc_next = arc_next1;
151 
152  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
153  {
154  if (b0->flags & VLIB_BUFFER_IS_TRACED)
155  {
156  nat_pre_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
157  t->next_index = next0;
158  t->arc_next_index = arc_next0;
159  }
160  if (b1->flags & VLIB_BUFFER_IS_TRACED)
161  {
162  nat_pre_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
163  t->next_index = next1;
164  t->arc_next_index = arc_next1;
165  }
166  }
167 
168  n_left_from -= 2;
169  next[0] = next0;
170  next[1] = next1;
171  next += 2;
172  }
173 
174  while (n_left_from > 0)
175  {
176  u32 next0;
177  u32 arc_next0;
178  vlib_buffer_t *b0;
179 
180  b0 = *b;
181  b++;
182 
183  next0 = def_next;
184  vnet_feature_next (&arc_next0, b0);
185  vnet_buffer2 (b0)->nat.arc_next = arc_next0;
186 
188  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
189  {
190  nat_pre_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
191  t->next_index = next0;
192  t->arc_next_index = arc_next0;
193  }
194 
195  n_left_from--;
196  next[0] = next0;
197  next++;
198  }
199  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
200  frame->n_vectors);
201 
202  return frame->n_vectors;
203 }
204 
207  u32 sw_if_index0, u32 ip4_addr)
208 {
210  ip4_address_t *first_int_addr;
211 
212  if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0))
213  {
214  first_int_addr =
215  ip4_interface_first_address (sm->ip4_main, sw_if_index0,
216  0 /* just want the address */ );
217  rt->cached_sw_if_index = sw_if_index0;
218  if (first_int_addr)
219  rt->cached_ip4_address = first_int_addr->as_u32;
220  else
221  rt->cached_ip4_address = 0;
222  }
223 
224  if (PREDICT_FALSE (ip4_addr == rt->cached_ip4_address))
225  return 1;
226  else
227  return 0;
228 }
229 
232 {
233  if (pool_elts (sm->per_thread_data[thread_index].sessions) >=
235  return 1;
236 
237  return 0;
238 }
239 
240 always_inline void
242 {
244  {
245  if (is_static)
246  u->nstaticsessions++;
247  else
248  u->nsessions++;
249  }
250 }
251 
252 always_inline void
254  u32 thread_index)
255 {
257  snat_user_key_t u_key;
259  thread_index);
260 
261  if (u->nstaticsessions == 0 && u->nsessions == 0)
262  {
263  u_key.addr.as_u32 = u->addr.as_u32;
264  u_key.fib_index = u->fib_index;
265  kv.key = u_key.as_u64;
267  pool_put (tsm->users, u);
268  clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0);
269  vlib_set_simple_counter (&sm->total_users, thread_index, 0,
270  pool_elts (tsm->users));
271  }
272 }
273 
274 always_inline void
275 nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
276  u32 thread_index)
277 {
279  thread_index);
281  snat_user_t *u;
282  const snat_user_key_t u_key = {
283  .addr = ses->in2out.addr,
284  .fib_index = ses->in2out.fib_index
285  };
286  const u8 u_static = snat_is_session_static (ses);
287 
288  clib_dlist_remove (tsm->list_pool, ses->per_user_index);
289  pool_put_index (tsm->list_pool, ses->per_user_index);
290  if (sm->endpoint_dependent)
291  {
292  clib_dlist_remove (tsm->lru_pool, ses->lru_index);
293  pool_put_index (tsm->lru_pool, ses->lru_index);
294  }
295  pool_put (tsm->sessions, ses);
296  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
297  pool_elts (tsm->sessions));
298 
299  kv.key = u_key.as_u64;
300  if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
301  {
302  u = pool_elt_at_index (tsm->users, value.value);
303  if (u_static)
304  u->nstaticsessions--;
305  else
306  u->nsessions--;
307 
308  nat44_delete_user_with_no_session (sm, u, thread_index);
309  }
310 }
311 
312 /** \brief Set TCP session state.
313  @return 1 if session was closed, otherwise 0
314 */
315 always_inline int
317  snat_session_t * ses, vlib_buffer_t * b,
318  u32 thread_index)
319 {
320  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
321  u8 tcp_flags = vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags;
322  u32 tcp_ack_number = vnet_buffer (b)->ip.reass.tcp_ack_number;
323  u32 tcp_seq_number = vnet_buffer (b)->ip.reass.tcp_seq_number;
324  if ((ses->state == 0) && (tcp_flags & TCP_FLAG_RST))
325  ses->state = NAT44_SES_RST;
326  if ((ses->state == NAT44_SES_RST) && !(tcp_flags & TCP_FLAG_RST))
327  ses->state = 0;
328  if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_SYN) &&
329  (ses->state & NAT44_SES_O2I_SYN))
330  ses->state = 0;
331  if (tcp_flags & TCP_FLAG_SYN)
332  ses->state |= NAT44_SES_I2O_SYN;
333  if (tcp_flags & TCP_FLAG_FIN)
334  {
335  ses->i2o_fin_seq = clib_net_to_host_u32 (tcp_seq_number);
336  ses->state |= NAT44_SES_I2O_FIN;
337  }
338  if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_O2I_FIN))
339  {
340  if (clib_net_to_host_u32 (tcp_ack_number) > ses->o2i_fin_seq)
341  {
342  ses->state |= NAT44_SES_O2I_FIN_ACK;
343  if (nat44_is_ses_closed (ses))
344  { // if session is now closed, save the timestamp
345  ses->tcp_closed_timestamp = now + sm->tcp_transitory_timeout;
346  ses->last_lru_update = now;
347  }
348  }
349  }
350 
351  // move the session to proper LRU
352  if (ses->state)
353  {
354  ses->lru_head_index = tsm->tcp_trans_lru_head_index;
355  }
356  else
357  {
358  ses->lru_head_index = tsm->tcp_estab_lru_head_index;
359  }
360  clib_dlist_remove (tsm->lru_pool, ses->lru_index);
361  clib_dlist_addtail (tsm->lru_pool, ses->lru_head_index, ses->lru_index);
362  return 0;
363 }
364 
365 always_inline int
367  snat_session_t * ses, u8 tcp_flags,
368  u32 tcp_ack_number, u32 tcp_seq_number,
369  u32 thread_index)
370 {
371  snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
372  if ((ses->state == 0) && (tcp_flags & TCP_FLAG_RST))
373  ses->state = NAT44_SES_RST;
374  if ((ses->state == NAT44_SES_RST) && !(tcp_flags & TCP_FLAG_RST))
375  ses->state = 0;
376  if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_SYN) &&
377  (ses->state & NAT44_SES_O2I_SYN))
378  ses->state = 0;
379  if (tcp_flags & TCP_FLAG_SYN)
380  ses->state |= NAT44_SES_O2I_SYN;
381  if (tcp_flags & TCP_FLAG_FIN)
382  {
383  ses->o2i_fin_seq = clib_net_to_host_u32 (tcp_seq_number);
384  ses->state |= NAT44_SES_O2I_FIN;
385  }
386  if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_FIN))
387  {
388  if (clib_net_to_host_u32 (tcp_ack_number) > ses->i2o_fin_seq)
389  ses->state |= NAT44_SES_I2O_FIN_ACK;
390  if (nat44_is_ses_closed (ses))
391  { // if session is now closed, save the timestamp
392  ses->tcp_closed_timestamp = now + sm->tcp_transitory_timeout;
393  ses->last_lru_update = now;
394  }
395  }
396  // move the session to proper LRU
397  if (ses->state)
398  {
399  ses->lru_head_index = tsm->tcp_trans_lru_head_index;
400  }
401  else
402  {
403  ses->lru_head_index = tsm->tcp_estab_lru_head_index;
404  }
405  clib_dlist_remove (tsm->lru_pool, ses->lru_index);
406  clib_dlist_addtail (tsm->lru_pool, ses->lru_head_index, ses->lru_index);
407  return 0;
408 }
409 
411 nat44_session_get_timeout (snat_main_t * sm, snat_session_t * s)
412 {
413  switch (s->nat_proto)
414  {
415  case NAT_PROTOCOL_ICMP:
416  return sm->icmp_timeout;
417  case NAT_PROTOCOL_UDP:
418  return sm->udp_timeout;
419  case NAT_PROTOCOL_TCP:
420  {
421  if (s->state)
422  return sm->tcp_transitory_timeout;
423  else
424  return sm->tcp_established_timeout;
425  }
426  default:
427  return sm->udp_timeout;
428  }
429 
430  return 0;
431 }
432 
433 always_inline void
434 nat44_session_update_counters (snat_session_t * s, f64 now, uword bytes,
435  u32 thread_index)
436 {
437  s->last_heard = now;
438  s->total_pkts++;
439  s->total_bytes += bytes;
440  nat_ha_sref (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
441  s->ext_host_port, s->nat_proto, s->out2in.fib_index,
442  s->total_pkts, s->total_bytes, thread_index,
443  &s->ha_last_refreshed, now);
444 }
445 
446 /** \brief Per-user LRU list maintenance */
447 always_inline void
448 nat44_session_update_lru (snat_main_t * sm, snat_session_t * s,
449  u32 thread_index)
450 {
451  /* don't update too often - timeout is in magnitude of seconds anyway */
452  if (s->last_heard > s->last_lru_update + 1)
453  {
454  if (!sm->endpoint_dependent)
455  {
456  clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
457  s->per_user_index);
458  clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
459  s->per_user_list_head_index, s->per_user_index);
460  }
461  else
462  {
463  clib_dlist_remove (sm->per_thread_data[thread_index].lru_pool,
464  s->lru_index);
465  clib_dlist_addtail (sm->per_thread_data[thread_index].lru_pool,
466  s->lru_head_index, s->lru_index);
467  }
468  s->last_lru_update = s->last_heard;
469  }
470 }
471 
472 always_inline void
474  ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto)
475 {
476  kv->key[0] = (u64) r_addr.as_u32 << 32 | l_addr.as_u32;
477  kv->key[1] =
478  (u64) r_port << 48 | (u64) l_port << 32 | fib_index << 8 | proto;
479 }
480 
481 always_inline void
483  ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto,
484  u32 thread_index, u32 session_index)
485 {
486  init_ed_k (kv, l_addr, l_port, r_addr, r_port, fib_index, proto);
487  kv->value = (u64) thread_index << 32 | session_index;
488 }
489 
492 {
493  return value->value >> 32;
494 }
495 
498 {
499  return value->value & ~(u32) 0;
500 }
501 
502 always_inline void
504  u32 * session_index)
505 {
506  if (thread_index)
507  {
508  *thread_index = ed_value_get_thread_index (value);
509  }
510  if (session_index)
511  {
512  *session_index = ed_value_get_session_index (value);
513  }
514 }
515 
516 always_inline void
518  ip4_address_t * l_addr, ip4_address_t * r_addr, u8 * proto,
519  u32 * fib_index, u16 * l_port, u16 * r_port)
520 {
521  if (l_addr)
522  {
523  l_addr->as_u32 = kv->key[0] & (u32) ~ 0;
524  }
525  if (r_addr)
526  {
527  r_addr->as_u32 = kv->key[0] >> 32;
528  }
529  if (r_port)
530  {
531  *r_port = kv->key[1] >> 48;
532  }
533  if (l_port)
534  {
535  *l_port = (kv->key[1] >> 32) & (u16) ~ 0;
536  }
537  if (fib_index)
538  {
539  *fib_index = (kv->key[1] >> 8) & ((1 << 24) - 1);
540  }
541  if (proto)
542  {
543  *proto = kv->key[1] & (u8) ~ 0;
544  }
545 }
546 
549  u32 thread_index, u32 session_index,
550  nat_protocol_t * nat_proto, u16 * l_port, u16 * r_port,
552 {
553  u8 proto;
554  u16 _l_port, _r_port;
555  ip4_address_t *l_addr, *r_addr;
556 
557  icmp46_header_t *icmp0;
558  icmp_echo_header_t *echo0, *inner_echo0 = 0;
559  ip4_header_t *inner_ip0 = 0;
560  void *l4_header = 0;
561  icmp46_header_t *inner_icmp0;
562 
563  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
564  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
565 
567  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
568  {
569  proto = IP_PROTOCOL_ICMP;
570  l_addr = &ip0->src_address;
571  r_addr = &ip0->dst_address;
572  _l_port = vnet_buffer (b)->ip.reass.l4_src_port;
573  _r_port = 0;
574  }
575  else
576  {
577  inner_ip0 = (ip4_header_t *) (echo0 + 1);
578  l4_header = ip4_next_header (inner_ip0);
579  proto = inner_ip0->protocol;
580  r_addr = &inner_ip0->src_address;
581  l_addr = &inner_ip0->dst_address;
582  switch (ip_proto_to_nat_proto (inner_ip0->protocol))
583  {
584  case NAT_PROTOCOL_ICMP:
585  inner_icmp0 = (icmp46_header_t *) l4_header;
586  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
587  _r_port = 0;
588  _l_port = inner_echo0->identifier;
589  break;
590  case NAT_PROTOCOL_UDP:
591  case NAT_PROTOCOL_TCP:
592  _l_port = ((tcp_udp_header_t *) l4_header)->dst_port;
593  _r_port = ((tcp_udp_header_t *) l4_header)->src_port;
594  break;
595  default:
596  return NAT_IN2OUT_ED_ERROR_UNSUPPORTED_PROTOCOL;
597  }
598  }
599  init_ed_kv (kv, *l_addr, _l_port, *r_addr, _r_port, rx_fib_index, proto,
600  thread_index, session_index);
601  if (nat_proto)
602  {
603  *nat_proto = ip_proto_to_nat_proto (proto);
604  }
605  if (l_port)
606  {
607  *l_port = _l_port;
608  }
609  if (r_port)
610  {
611  *r_port = _r_port;
612  }
613  return 0;
614 }
615 
618  u32 thread_index, u32 session_index,
619  nat_protocol_t * nat_proto, u16 * l_port, u16 * r_port,
621 {
622  icmp46_header_t *icmp0;
623  u8 proto;
624  ip4_address_t *l_addr, *r_addr;
625  u16 _l_port, _r_port;
626  icmp_echo_header_t *echo0, *inner_echo0 = 0;
627  ip4_header_t *inner_ip0;
628  void *l4_header = 0;
629  icmp46_header_t *inner_icmp0;
630 
631  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
632  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
633 
635  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
636  {
637  proto = IP_PROTOCOL_ICMP;
638  l_addr = &ip0->dst_address;
639  r_addr = &ip0->src_address;
640  _l_port = vnet_buffer (b)->ip.reass.l4_src_port;
641  _r_port = 0;
642  }
643  else
644  {
645  inner_ip0 = (ip4_header_t *) (echo0 + 1);
646  l4_header = ip4_next_header (inner_ip0);
647  proto = inner_ip0->protocol;
648  l_addr = &inner_ip0->src_address;
649  r_addr = &inner_ip0->dst_address;
650  switch (ip_proto_to_nat_proto (inner_ip0->protocol))
651  {
652  case NAT_PROTOCOL_ICMP:
653  inner_icmp0 = (icmp46_header_t *) l4_header;
654  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
655  _l_port = inner_echo0->identifier;
656  _r_port = 0;
657  break;
658  case NAT_PROTOCOL_UDP:
659  case NAT_PROTOCOL_TCP:
660  _l_port = ((tcp_udp_header_t *) l4_header)->src_port;
661  _r_port = ((tcp_udp_header_t *) l4_header)->dst_port;
662  break;
663  default:
664  return -1;
665  }
666  }
667  init_ed_kv (kv, *l_addr, _l_port, *r_addr, _r_port, rx_fib_index, proto,
668  thread_index, session_index);
669  if (nat_proto)
670  {
671  *nat_proto = ip_proto_to_nat_proto (proto);
672  }
673  if (l_port)
674  {
675  *l_port = _l_port;
676  }
677  if (r_port)
678  {
679  *r_port = _r_port;
680  }
681  return 0;
682 }
683 
684 /**
685  * @brief Check if packet should be translated
686  *
687  * Packets aimed at outside interface and external address with active session
688  * should be translated.
689  *
690  * @param sm NAT main
691  * @param rt NAT runtime data
692  * @param sw_if_index0 index of the inside interface
693  * @param ip0 IPv4 header
694  * @param proto0 NAT protocol
695  * @param rx_fib_index0 RX FIB index
696  *
697  * @returns 0 if packet should be translated otherwise 1
698  */
699 static inline int
701  u32 sw_if_index0, ip4_header_t * ip0, u32 proto0,
702  u32 rx_fib_index0)
703 {
704  if (sm->out2in_dpo)
705  return 0;
706 
708  nat_outside_fib_t *outside_fib;
709  fib_prefix_t pfx = {
711  .fp_len = 32,
712  .fp_addr = {
713  .ip4.as_u32 = ip0->dst_address.as_u32,
714  }
715  ,
716  };
717 
718  /* Don't NAT packet aimed at the intfc address */
719  if (PREDICT_FALSE (is_interface_addr (sm, node, sw_if_index0,
720  ip0->dst_address.as_u32)))
721  return 1;
722 
723  fei = fib_table_lookup (rx_fib_index0, &pfx);
724  if (FIB_NODE_INDEX_INVALID != fei)
725  {
727  if (sw_if_index == ~0)
728  {
729  vec_foreach (outside_fib, sm->outside_fibs)
730  {
731  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
732  if (FIB_NODE_INDEX_INVALID != fei)
733  {
734  sw_if_index = fib_entry_get_resolving_interface (fei);
735  if (sw_if_index != ~0)
736  break;
737  }
738  }
739  }
740  if (sw_if_index == ~0)
741  return 1;
742 
744  /* *INDENT-OFF* */
745  pool_foreach (i, sm->interfaces, ({
746  /* NAT packet aimed at outside interface */
747  if ((nat_interface_is_outside (i)) && (sw_if_index == i->sw_if_index))
748  return 0;
749  }));
750  /* *INDENT-ON* */
751  }
752 
753  return 1;
754 }
755 
756 static inline void
758 {
759  u32 v;
760 
761  v = clib_net_to_host_u32 (a->as_u32) + 1;
762  a->as_u32 = clib_host_to_net_u32 (v);
763 }
764 
767 {
768  snat_main_t *sm = &snat_main;
769  u32 rwide;
770  u16 r;
771 
772  rwide = random_u32 (&sm->random_seed);
773  r = rwide & 0xFFFF;
774  if (r >= min && r <= max)
775  return r;
776 
777  return min + (rwide % (max - min + 1));
778 }
779 
780 #endif /* __included_nat_inlines_h__ */
781 
782 /*
783  * fd.io coding-style-patch-verification: ON
784  *
785  * Local Variables:
786  * eval: (c-set-style "gnu")
787  * End:
788  */
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:124
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
nat_outside_fib_t * outside_fibs
Definition: nat.h:540
dlist_elt_t * lru_pool
Definition: nat.h:434
#define snat_is_session_static(s)
Check if SNAT session is created from static mapping.
Definition: nat.h:748
u32 sessions_per_user_list_head_index
Definition: nat.h:289
static u64 calc_nat_key(ip4_address_t addr, u16 port, u32 fib_index, u8 proto)
The NAT inline functions.
Definition: nat_inlines.h:27
u32 arc_next_index
Definition: nat.h:69
#define NAT44_SES_I2O_FIN
Definition: nat.h:174
a
Definition: bitmap.h:538
u32 icmp_timeout
Definition: nat.h:622
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:518
ip4_address_t src_address
Definition: ip4_packet.h:125
#define vnet_buffer2(b)
Definition: buffer.h:482
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
Definition: nat_inlines.h:411
#define TCP_FLAG_SYN
Definition: fa_node.h:13
#define PREDICT_TRUE(x)
Definition: clib.h:121
u32 nsessions
Definition: nat.h:290
static void init_nat_i2o_kv(clib_bihash_kv_8_8_t *kv, snat_session_t *s, u64 value)
Definition: nat_inlines.h:81
unsigned long u64
Definition: types.h:89
static_always_inline int get_icmp_o2i_ed_key(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index, u32 thread_index, u32 session_index, nat_protocol_t *nat_proto, u16 *l_port, u16 *r_port, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:617
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:281
u32 nstaticsessions
Definition: nat.h:291
static void init_nat_i2o_k(clib_bihash_kv_8_8_t *kv, snat_session_t *s)
Definition: nat_inlines.h:74
vlib_main_t * vm
Definition: in2out_ed.c:1582
u32 fib_index
Definition: nat.h:288
#define nat44_is_ses_closed(s)
Check if NAT44 endpoint-dependent TCP session is closed.
Definition: nat.h:808
#define NAT44_SES_O2I_FIN
Definition: nat.h:175
nat_protocol_t
Definition: lib.h:41
static void init_ed_kv(clib_bihash_kv_16_8_t *kv, ip4_address_t l_addr, u16 l_port, ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto, u32 thread_index, u32 session_index)
Definition: nat_inlines.h:482
dlist_elt_t * list_pool
Definition: nat.h:431
u32 max_translations_per_thread
Definition: nat.h:605
vhost_vring_addr_t addr
Definition: vhost_user.h:111
unsigned char u8
Definition: types.h:56
double f64
Definition: types.h:142
static void split_nat_key(u64 key, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto)
Definition: nat_inlines.h:36
clib_bihash_8_8_t user_hash
Definition: nat.h:422
u32 cached_sw_if_index
Definition: nat.h:708
u32 next_index
Definition: nat.h:68
void nat_ha_sref(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 total_pkts, u64 total_bytes, u32 thread_index, f64 *last_refreshed, f64 now)
Create session refresh HA event.
Definition: nat_ha.c:734
static int snat_not_translate_fast(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0)
Check if packet should be translated.
Definition: nat_inlines.h:700
u32 max_translations_per_user
Definition: nat.h:610
#define static_always_inline
Definition: clib.h:108
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:22
ip4_address_t dst_address
Definition: ip4_packet.h:125
static_always_inline u16 snat_random_port(u16 min, u16 max)
Definition: nat_inlines.h:766
#define TCP_FLAG_ACK
Definition: fa_node.h:16
static void init_nat_o2i_kv(clib_bihash_kv_8_8_t *kv, snat_session_t *s, u64 value)
Definition: nat_inlines.h:96
ip4_address_t addr
Definition: nat.h:287
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:203
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregate type for a prefix.
Definition: fib_types.h:203
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: inlines.h:53
static void init_nat_o2i_k(clib_bihash_kv_8_8_t *kv, snat_session_t *s)
Definition: nat_inlines.h:89
static void split_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:517
ip4_main_t * ip4_main
Definition: nat.h:695
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
unsigned int u32
Definition: types.h:88
static_always_inline int get_icmp_i2o_ed_key(vlib_buffer_t *b, ip4_header_t *ip0, u32 rx_fib_index, u32 thread_index, u32 session_index, nat_protocol_t *nat_proto, u16 *l_port, u16 *r_port, clib_bihash_kv_16_8_t *kv)
Definition: nat_inlines.h:548
#define VLIB_FRAME_SIZE
Definition: node.h:377
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: fib_table.c:68
#define NAT44_SES_RST
Definition: nat.h:180
static u8 maximum_sessions_exceeded(snat_main_t *sm, u32 thread_index)
Definition: nat_inlines.h:231
static void nat44_delete_session(snat_main_t *sm, snat_session_t *ses, u32 thread_index)
Definition: nat_inlines.h:275
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:534
u32 fib_index
Definition: nat.h:316
vl_api_ip_proto_t proto
Definition: acl_types.api:50
u64 key
the key
Definition: bihash_8_8.h:41
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
u8 out2in_dpo
Definition: nat.h:597
static u32 ed_value_get_session_index(clib_bihash_kv_16_8_t *value)
Definition: nat_inlines.h:497
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:302
u32 udp_timeout
Definition: nat.h:619
#define PREDICT_FALSE(x)
Definition: clib.h:120
#define always_inline
Definition: ipsec.h:28
#define TCP_FLAG_FIN
Definition: fa_node.h:12
#define NAT44_SES_O2I_SYN
Definition: nat.h:179
static void vlib_set_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 value)
Set a simple counter.
Definition: counter.h:94
static void init_nat_k(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto)
Definition: nat_inlines.h:58
static void split_ed_value(clib_bihash_kv_16_8_t *value, u32 *thread_index, u32 *session_index)
Definition: nat_inlines.h:503
#define TCP_FLAG_RST
Definition: fa_node.h:14
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1458
snat_main_t snat_main
Definition: nat.c:39
u64 value
the value
Definition: bihash_8_8.h:42
snat_user_t * users
Definition: nat.h:425
static int nat44_set_tcp_session_state_o2i(snat_main_t *sm, f64 now, snat_session_t *ses, u8 tcp_flags, u32 tcp_ack_number, u32 tcp_seq_number, u32 thread_index)
Definition: nat_inlines.h:366
static void nat44_delete_user_with_no_session(snat_main_t *sm, snat_user_t *u, u32 thread_index)
Definition: nat_inlines.h:253
u32 random_seed
Definition: nat.h:553
u16 n_vectors
Definition: node.h:396
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:339
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
Definition: nat_inlines.h:434
u8 data[]
Packet data.
Definition: buffer.h:181
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
static void init_nat_kv(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto, u64 value)
Definition: nat_inlines.h:66
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:39
static uword nat_pre_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 def_next)
Definition: nat_inlines.h:104
u32 tcp_transitory_timeout
Definition: nat.h:620
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1582
u8 value
Definition: qos.api:54
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:331
#define ASSERT(truth)
static int nat44_set_tcp_session_state_i2o(snat_main_t *sm, f64 now, snat_session_t *ses, vlib_buffer_t *b, u32 thread_index)
Set TCP session state.
Definition: nat_inlines.h:316
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:448
u64 as_u64
Definition: nat.h:82
ip4_address_t addr
Definition: nat.h:79
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
#define NAT44_SES_I2O_SYN
Definition: nat.h:178
typedef key
Definition: ipsec_types.api:85
vlib_simple_counter_main_t total_users
Definition: nat.h:628
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
static void user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
Definition: nat_inlines.h:241
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: in2out_ed.c:1583
VLIB buffer representation.
Definition: buffer.h:102
u64 uword
Definition: types.h:112
snat_main_per_thread_data_t * per_thread_data
Definition: nat.h:504
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:297
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:206
u32 fib_index
Definition: nat.h:80
u16 port
Definition: lb_types.api:72
static void init_ed_k(clib_bihash_kv_16_8_t *kv, ip4_address_t l_addr, u16 l_port, ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto)
Definition: nat_inlines.h:473
static void increment_v4_address(ip4_address_t *a)
Definition: nat_inlines.h:757
#define vnet_buffer(b)
Definition: buffer.h:417
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
#define NAT44_SES_I2O_FIN_ACK
Definition: nat.h:176
#define vec_foreach(var, vec)
Vector iterator.
u16 flags
Copy of main node flags.
Definition: node.h:500
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:577
u8 endpoint_dependent
Definition: nat.h:598
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:280
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:301
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
#define NAT44_SES_O2I_FIN_ACK
Definition: nat.h:177
vlib_simple_counter_main_t total_sessions
Definition: nat.h:629
snat_session_t * sessions
Definition: nat.h:428
u32 cached_ip4_address
Definition: nat.h:709
static u32 ed_value_get_thread_index(clib_bihash_kv_16_8_t *value)
Definition: nat_inlines.h:491
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:33
snat_interface_t * interfaces
Definition: nat.h:519
NAT active-passive HA.
u32 tcp_established_timeout
Definition: nat.h:621
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128