FD.io VPP  v21.06
Vector Packet Processing
nat44_ed_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_nat44_ed_inlines_h__
20 #define __included_nat44_ed_inlines_h__
21 
22 #include <float.h>
23 #include <vppinfra/clib.h>
24 #include <vnet/fib/ip4_fib.h>
25 
26 #include <nat/lib/log.h>
27 #include <nat/nat44-ed/nat44_ed.h>
28 
31 {
32  ASSERT (fib_index <= (1 << 14) - 1);
33  ASSERT (proto <= (1 << 3) - 1);
34  return (u64) addr.as_u32 << 32 | (u64) port << 16 | fib_index << 3 |
35  (proto & 0x7);
36 }
37 
38 always_inline void
41 {
42  if (addr)
43  {
44  addr->as_u32 = key >> 32;
45  }
46  if (port)
47  {
48  *port = (key >> 16) & (u16) ~0;
49  }
50  if (fib_index)
51  {
52  *fib_index = key >> 3 & ((1 << 13) - 1);
53  }
54  if (proto)
55  {
56  *proto = key & 0x7;
57  }
58 }
59 
60 always_inline void
62  u32 fib_index, nat_protocol_t proto)
63 {
64  kv->key = calc_nat_key (addr, port, fib_index, proto);
65  kv->value = ~0ULL;
66 }
67 
68 always_inline void
71  u32 session_index)
72 {
73  init_nat_k (kv, addr, port, fib_index, proto);
74  kv->value = (u64) thread_index << 32 | session_index;
75 }
76 
77 always_inline void
78 init_nat_i2o_k (clib_bihash_kv_8_8_t *kv, snat_session_t *s)
79 {
80  return init_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index,
81  s->nat_proto);
82 }
83 
84 always_inline void
86  u32 session_index)
87 {
88  init_nat_k (kv, s->in2out.addr, s->in2out.port, s->in2out.fib_index,
89  s->nat_proto);
90  kv->value = (u64) thread_index << 32 | session_index;
91 }
92 
93 always_inline void
94 init_nat_o2i_k (clib_bihash_kv_8_8_t *kv, snat_session_t *s)
95 {
96  return init_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index,
97  s->nat_proto);
98 }
99 
100 always_inline void
102  u32 session_index)
103 {
104  init_nat_k (kv, s->out2in.addr, s->out2in.port, s->out2in.fib_index,
105  s->nat_proto);
106  kv->value = (u64) thread_index << 32 | session_index;
107 }
108 
111 {
112  return value->value >> 32;
113 }
114 
117 {
118  return value->value & ~(u32) 0;
119 }
120 
121 always_inline void
123  ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto)
124 {
125  kv->key[0] = (u64) r_addr.as_u32 << 32 | l_addr.as_u32;
126  kv->key[1] =
127  (u64) r_port << 48 | (u64) l_port << 32 | fib_index << 8 | proto;
128 }
129 
130 always_inline void
132  ip4_address_t r_addr, u16 r_port, u32 fib_index, u8 proto,
133  u32 thread_index, u32 session_index)
134 {
135  init_ed_k (kv, l_addr, l_port, r_addr, r_port, fib_index, proto);
136  kv->value = (u64) thread_index << 32 | session_index;
137 }
138 
141 {
142  return value->value >> 32;
143 }
144 
147 {
148  return value->value & ~(u32) 0;
149 }
150 
151 always_inline void
153  ip4_address_t *r_addr, u8 *proto, u32 *fib_index, u16 *l_port,
154  u16 *r_port)
155 {
156  if (l_addr)
157  {
158  l_addr->as_u32 = kv->key[0] & (u32) ~0;
159  }
160  if (r_addr)
161  {
162  r_addr->as_u32 = kv->key[0] >> 32;
163  }
164  if (r_port)
165  {
166  *r_port = kv->key[1] >> 48;
167  }
168  if (l_port)
169  {
170  *l_port = (kv->key[1] >> 32) & (u16) ~0;
171  }
172  if (fib_index)
173  {
174  *fib_index = (kv->key[1] >> 8) & ((1 << 24) - 1);
175  }
176  if (proto)
177  {
178  *proto = kv->key[1] & (u8) ~0;
179  }
180 }
181 
184  ip4_address_t *lookup_saddr,
185  u16 *lookup_sport,
186  ip4_address_t *lookup_daddr,
187  u16 *lookup_dport, u8 *lookup_protocol)
188 {
189  icmp46_header_t *icmp0;
190  icmp_echo_header_t *echo0, *inner_echo0 = 0;
191  ip4_header_t *inner_ip0 = 0;
192  void *l4_header = 0;
193  icmp46_header_t *inner_icmp0;
194 
195  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
196  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
197 
198  // avoid warning about unused variables in caller by setting to bogus values
199  *lookup_sport = 0;
200  *lookup_dport = 0;
201 
203  vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
204  {
205  *lookup_protocol = IP_PROTOCOL_ICMP;
206  lookup_saddr->as_u32 = ip0->src_address.as_u32;
207  *lookup_sport = vnet_buffer (b)->ip.reass.l4_src_port;
208  lookup_daddr->as_u32 = ip0->dst_address.as_u32;
209  *lookup_dport = vnet_buffer (b)->ip.reass.l4_dst_port;
210  }
211  else
212  {
213  inner_ip0 = (ip4_header_t *) (echo0 + 1);
214  l4_header = ip4_next_header (inner_ip0);
215  *lookup_protocol = inner_ip0->protocol;
216  lookup_saddr->as_u32 = inner_ip0->dst_address.as_u32;
217  lookup_daddr->as_u32 = inner_ip0->src_address.as_u32;
218  switch (ip_proto_to_nat_proto (inner_ip0->protocol))
219  {
220  case NAT_PROTOCOL_ICMP:
221  inner_icmp0 = (icmp46_header_t *) l4_header;
222  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
223  *lookup_sport = inner_echo0->identifier;
224  *lookup_dport = inner_echo0->identifier;
225  break;
226  case NAT_PROTOCOL_UDP:
227  case NAT_PROTOCOL_TCP:
228  *lookup_sport = ((tcp_udp_header_t *) l4_header)->dst_port;
229  *lookup_dport = ((tcp_udp_header_t *) l4_header)->src_port;
230  break;
231  default:
232  return NAT_IN2OUT_ED_ERROR_UNSUPPORTED_PROTOCOL;
233  }
234  }
235  return 0;
236 }
237 
239 nat44_session_get_timeout (snat_main_t *sm, snat_session_t *s)
240 {
241  switch (s->nat_proto)
242  {
243  case NAT_PROTOCOL_ICMP:
244  return sm->timeouts.icmp;
245  case NAT_PROTOCOL_UDP:
246  return sm->timeouts.udp;
247  case NAT_PROTOCOL_TCP:
248  {
249  if (s->state)
250  return sm->timeouts.tcp.transitory;
251  else
252  return sm->timeouts.tcp.established;
253  }
254  default:
255  return sm->timeouts.udp;
256  }
257 
258  return 0;
259 }
260 
264 {
265  u32 translations;
266  translations = pool_elts (sm->per_thread_data[thread_index].sessions);
267  if (vec_len (sm->max_translations_per_fib) <= fib_index)
268  fib_index = 0;
269  return translations >= sm->max_translations_per_fib[fib_index];
270 }
271 
274  f64 now, u8 proto)
275 {
276  dlist_elt_t *lru_list_elt;
277  pool_get (tsm->lru_pool, lru_list_elt);
278  s->lru_index = lru_list_elt - tsm->lru_pool;
279  switch (proto)
280  {
281  case IP_PROTOCOL_UDP:
282  s->lru_head_index = tsm->udp_lru_head_index;
283  break;
284  case IP_PROTOCOL_TCP:
285  s->lru_head_index = tsm->tcp_trans_lru_head_index;
286  break;
287  case IP_PROTOCOL_ICMP:
288  s->lru_head_index = tsm->icmp_lru_head_index;
289  break;
290  default:
291  s->lru_head_index = tsm->unk_proto_lru_head_index;
292  break;
293  }
294  clib_dlist_addtail (tsm->lru_pool, s->lru_head_index, s->lru_index);
295  lru_list_elt->value = s - tsm->sessions;
296  s->last_lru_update = now;
297  return 1;
298 }
299 
302 {
303  init_ed_k (kv, f->match.saddr, f->match.sport, f->match.daddr,
304  f->match.dport, f->match.fib_index, f->match.proto);
305 }
306 
309  u32 thread_idx, u32 session_idx)
310 {
311  init_ed_kv (kv, f->match.saddr, f->match.sport, f->match.daddr,
312  f->match.dport, f->match.fib_index, f->match.proto, thread_idx,
313  session_idx);
314 }
315 
318  snat_session_t *s, int is_add)
319 {
321  vec_elt_at_index (sm->per_thread_data, thread_idx);
323  if (0 == is_add)
324  {
325  nat_6t_flow_to_ed_k (&kv, &s->i2o);
326  }
327  else
328  {
329  nat_6t_flow_to_ed_kv (&kv, &s->i2o, thread_idx, s - tsm->sessions);
330  nat_6t_l3_l4_csum_calc (&s->i2o);
331  }
332 
333  ASSERT (thread_idx == s->thread_index);
334  return clib_bihash_add_del_16_8 (&sm->flow_hash, &kv, is_add);
335 }
336 
339  snat_session_t *s, int is_add)
340 {
342  vec_elt_at_index (sm->per_thread_data, thread_idx);
344  if (0 == is_add)
345  {
346  nat_6t_flow_to_ed_k (&kv, &s->o2i);
347  }
348  else
349  {
350  nat_6t_flow_to_ed_kv (&kv, &s->o2i, thread_idx, s - tsm->sessions);
351  nat_6t_l3_l4_csum_calc (&s->o2i);
352  }
353  ASSERT (thread_idx == s->thread_index);
354  return clib_bihash_add_del_16_8 (&sm->flow_hash, &kv, is_add);
355 }
356 
357 always_inline void
359  int lru_delete
360  /* delete from global LRU list */)
361 {
363  vec_elt_at_index (sm->per_thread_data, thread_index);
364 
365  if (lru_delete)
366  {
367  clib_dlist_remove (tsm->lru_pool, ses->lru_index);
368  }
369  pool_put_index (tsm->lru_pool, ses->lru_index);
370  if (nat_ed_ses_i2o_flow_hash_add_del (sm, thread_index, ses, 0))
371  nat_elog_warn (sm, "flow hash del failed");
372  if (nat_ed_ses_o2i_flow_hash_add_del (sm, thread_index, ses, 0))
373  nat_elog_warn (sm, "flow hash del failed");
374  pool_put (tsm->sessions, ses);
375  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
376  pool_elts (tsm->sessions));
377 }
378 
381  u32 head_index)
382 {
383  snat_session_t *s = NULL;
384  dlist_elt_t *oldest_elt;
385  f64 sess_timeout_time;
386  u32 oldest_index;
388  oldest_index = clib_dlist_remove_head (tsm->lru_pool, head_index);
389  if (~0 != oldest_index)
390  {
391  oldest_elt = pool_elt_at_index (tsm->lru_pool, oldest_index);
392  s = pool_elt_at_index (tsm->sessions, oldest_elt->value);
393 
394  sess_timeout_time =
395  s->last_heard + (f64) nat44_session_get_timeout (sm, s);
396  if (now >= sess_timeout_time ||
397  (s->tcp_closed_timestamp && now >= s->tcp_closed_timestamp))
398  {
399  nat_free_session_data (sm, s, thread_index, 0);
400  nat_ed_session_delete (sm, s, thread_index, 0);
401  return 1;
402  }
403  else
404  {
405  clib_dlist_addhead (tsm->lru_pool, head_index, oldest_index);
406  }
407  }
408  return 0;
409 }
410 
413 {
415  int rc = 0;
416 #define _(p) \
417  if ((rc = nat_lru_free_one_with_head (sm, thread_index, now, \
418  tsm->p##_lru_head_index))) \
419  { \
420  return rc; \
421  }
422  _ (tcp_trans);
423  _ (udp);
424  _ (unk_proto);
425  _ (icmp);
426  _ (tcp_estab);
427 #undef _
428  return 0;
429 }
430 
431 static_always_inline snat_session_t *
433 {
434  snat_session_t *s;
436 
437  nat_lru_free_one (sm, thread_index, now);
438 
439  pool_get (tsm->sessions, s);
440  clib_memset (s, 0, sizeof (*s));
441 
442  nat_ed_lru_insert (tsm, s, now, proto);
443 
444  s->ha_last_refreshed = now;
445  vlib_set_simple_counter (&sm->total_sessions, thread_index, 0,
446  pool_elts (tsm->sessions));
447 #if CLIB_ASSERT_ENABLE
448  s->thread_index = thread_index;
449 #endif
450  return s;
451 }
452 
453 // slow path
456 {
457  snat_main_t *sm = &snat_main;
459  vec_elt_at_index (sm->per_thread_data, thread_index);
460  per_vrf_sessions_t *per_vrf_sessions;
461  u32 *to_free = 0, *i;
462 
463  vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
464  {
465  if (per_vrf_sessions->expired)
466  {
467  if (per_vrf_sessions->ses_count == 0)
468  {
469  vec_add1 (to_free, per_vrf_sessions - tsm->per_vrf_sessions_vec);
470  }
471  }
472  }
473 
474  if (vec_len (to_free))
475  {
476  vec_foreach (i, to_free)
477  {
479  }
480  }
481 
482  vec_free (to_free);
483 }
484 
485 // slow path
488 {
489  snat_main_t *sm = &snat_main;
491  vec_elt_at_index (sm->per_thread_data, thread_index);
492  per_vrf_sessions_t *per_vrf_sessions;
493 
494  per_vrf_sessions_cleanup (thread_index);
495 
496  // s->per_vrf_sessions_index == ~0 ... reuse of old session
497 
498  vec_foreach (per_vrf_sessions, tsm->per_vrf_sessions_vec)
499  {
500  // ignore already expired registrations
501  if (per_vrf_sessions->expired)
502  continue;
503 
504  if ((s->in2out.fib_index == per_vrf_sessions->rx_fib_index) &&
505  (s->out2in.fib_index == per_vrf_sessions->tx_fib_index))
506  {
507  goto done;
508  }
509  if ((s->in2out.fib_index == per_vrf_sessions->tx_fib_index) &&
510  (s->out2in.fib_index == per_vrf_sessions->rx_fib_index))
511  {
512  goto done;
513  }
514  }
515 
516  // create a new registration
517  vec_add2 (tsm->per_vrf_sessions_vec, per_vrf_sessions, 1);
518  clib_memset (per_vrf_sessions, 0, sizeof (*per_vrf_sessions));
519 
520  per_vrf_sessions->rx_fib_index = s->in2out.fib_index;
521  per_vrf_sessions->tx_fib_index = s->out2in.fib_index;
522 
523 done:
524  s->per_vrf_sessions_index = per_vrf_sessions - tsm->per_vrf_sessions_vec;
525  per_vrf_sessions->ses_count++;
526 }
527 
528 // fast path
531 {
532  snat_main_t *sm = &snat_main;
534  per_vrf_sessions_t *per_vrf_sessions;
535 
536  ASSERT (s->per_vrf_sessions_index != ~0);
537 
538  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
539  per_vrf_sessions =
540  vec_elt_at_index (tsm->per_vrf_sessions_vec, s->per_vrf_sessions_index);
541 
542  ASSERT (per_vrf_sessions->ses_count != 0);
543 
544  per_vrf_sessions->ses_count--;
545  s->per_vrf_sessions_index = ~0;
546 }
547 
548 // fast path
551 {
552  snat_main_t *sm = &snat_main;
554  per_vrf_sessions_t *per_vrf_sessions;
555 
556  ASSERT (s->per_vrf_sessions_index != ~0);
557 
558  tsm = vec_elt_at_index (sm->per_thread_data, thread_index);
559  per_vrf_sessions =
560  vec_elt_at_index (tsm->per_vrf_sessions_vec, s->per_vrf_sessions_index);
561  return per_vrf_sessions->expired;
562 }
563 
566  u16 sport, ip4_address_t daddr, u16 dport, u32 fib_index,
567  u8 proto, u32 session_idx)
568 {
569  clib_memset (f, 0, sizeof (*f));
570  f->match.saddr = saddr;
571  f->match.sport = sport;
572  f->match.daddr = daddr;
573  f->match.dport = dport;
574  f->match.proto = proto;
575  f->match.fib_index = fib_index;
576 }
577 
580  ip4_address_t saddr, u16 sport, ip4_address_t daddr,
581  u16 dport, u32 fib_index, u8 proto)
582 {
584  vec_elt_at_index (sm->per_thread_data, thread_idx);
585  nat_6t_flow_init (&s->i2o, thread_idx, saddr, sport, daddr, dport, fib_index,
586  proto, s - tsm->sessions);
587 }
588 
591  ip4_address_t saddr, u16 sport, ip4_address_t daddr,
592  u16 dport, u32 fib_index, u8 proto)
593 {
595  vec_elt_at_index (sm->per_thread_data, thread_idx);
596  nat_6t_flow_init (&s->o2i, thread_idx, saddr, sport, daddr, dport, fib_index,
597  proto, s - tsm->sessions);
598 }
599 
602 {
603  return t1->as_u64[0] == t2->as_u64[0] && t1->as_u64[1] == t2->as_u64[1];
604 }
605 
606 static inline uword
608  vlib_frame_t *frame, u32 def_next)
609 {
610  u32 n_left_from, *from;
611 
612  from = vlib_frame_vector_args (frame);
613  n_left_from = frame->n_vectors;
614 
617  vlib_get_buffers (vm, from, b, n_left_from);
618 
619  while (n_left_from >= 2)
620  {
621  u32 next0, next1;
622  u32 arc_next0, arc_next1;
623  vlib_buffer_t *b0, *b1;
624 
625  b0 = *b;
626  b++;
627  b1 = *b;
628  b++;
629 
630  /* Prefetch next iteration. */
631  if (PREDICT_TRUE (n_left_from >= 4))
632  {
633  vlib_buffer_t *p2, *p3;
634 
635  p2 = *b;
636  p3 = *(b + 1);
637 
638  vlib_prefetch_buffer_header (p2, LOAD);
639  vlib_prefetch_buffer_header (p3, LOAD);
640 
643  }
644 
645  next0 = def_next;
646  next1 = def_next;
647 
648  vnet_feature_next (&arc_next0, b0);
649  vnet_feature_next (&arc_next1, b1);
650 
651  vnet_buffer2 (b0)->nat.arc_next = arc_next0;
652  vnet_buffer2 (b1)->nat.arc_next = arc_next1;
653 
654  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
655  {
656  if (b0->flags & VLIB_BUFFER_IS_TRACED)
657  {
658  nat_pre_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
659  t->next_index = next0;
660  t->arc_next_index = arc_next0;
661  }
662  if (b1->flags & VLIB_BUFFER_IS_TRACED)
663  {
664  nat_pre_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
665  t->next_index = next1;
666  t->arc_next_index = arc_next1;
667  }
668  }
669 
670  n_left_from -= 2;
671  next[0] = next0;
672  next[1] = next1;
673  next += 2;
674  }
675 
676  while (n_left_from > 0)
677  {
678  u32 next0;
679  u32 arc_next0;
680  vlib_buffer_t *b0;
681 
682  b0 = *b;
683  b++;
684 
685  next0 = def_next;
686  vnet_feature_next (&arc_next0, b0);
687  vnet_buffer2 (b0)->nat.arc_next = arc_next0;
688 
689  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
690  (b0->flags & VLIB_BUFFER_IS_TRACED)))
691  {
692  nat_pre_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
693  t->next_index = next0;
694  t->arc_next_index = arc_next0;
695  }
696 
697  n_left_from--;
698  next[0] = next0;
699  next++;
700  }
701  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
702  frame->n_vectors);
703 
704  return frame->n_vectors;
705 }
706 
709 {
710  snat_main_t *sm = &snat_main;
711  u32 rwide;
712  u16 r;
713 
714  rwide = random_u32 (&sm->random_seed);
715  r = rwide & 0xFFFF;
716  if (r >= min && r <= max)
717  return r;
718 
719  return min + (rwide % (max - min + 1));
720 }
721 
724  u32 sw_if_index0, u32 ip4_addr)
725 {
727  ip4_address_t *first_int_addr;
728 
729  if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0))
730  {
731  first_int_addr = ip4_interface_first_address (
732  sm->ip4_main, sw_if_index0, 0 /* just want the address */);
733  rt->cached_sw_if_index = sw_if_index0;
734  if (first_int_addr)
735  rt->cached_ip4_address = first_int_addr->as_u32;
736  else
737  rt->cached_ip4_address = 0;
738  }
739 
740  if (PREDICT_FALSE (ip4_addr == rt->cached_ip4_address))
741  return 1;
742  else
743  return 0;
744 }
745 
746 always_inline void
749 {
751  u8 tcp_flags = vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags;
752  u32 tcp_ack_number = vnet_buffer (b)->ip.reass.tcp_ack_number;
753  u32 tcp_seq_number = vnet_buffer (b)->ip.reass.tcp_seq_number;
754  if ((ses->state == 0) && (tcp_flags & TCP_FLAG_RST))
755  ses->state = NAT44_SES_RST;
756  if ((ses->state == NAT44_SES_RST) && !(tcp_flags & TCP_FLAG_RST))
757  ses->state = 0;
758  if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_SYN) &&
759  (ses->state & NAT44_SES_O2I_SYN))
760  ses->state = 0;
761  if (tcp_flags & TCP_FLAG_SYN)
762  ses->state |= NAT44_SES_I2O_SYN;
763  if (tcp_flags & TCP_FLAG_FIN)
764  {
765  ses->i2o_fin_seq = clib_net_to_host_u32 (tcp_seq_number);
766  ses->state |= NAT44_SES_I2O_FIN;
767  }
768  if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_O2I_FIN))
769  {
770  if (clib_net_to_host_u32 (tcp_ack_number) > ses->o2i_fin_seq)
771  {
772  ses->state |= NAT44_SES_O2I_FIN_ACK;
773  if (nat44_is_ses_closed (ses))
774  { // if session is now closed, save the timestamp
775  ses->tcp_closed_timestamp = now + sm->timeouts.tcp.transitory;
776  ses->last_lru_update = now;
777  }
778  }
779  }
780 
781  // move the session to proper LRU
782  if (ses->state)
783  {
784  ses->lru_head_index = tsm->tcp_trans_lru_head_index;
785  }
786  else
787  {
788  ses->lru_head_index = tsm->tcp_estab_lru_head_index;
789  }
790  clib_dlist_remove (tsm->lru_pool, ses->lru_index);
791  clib_dlist_addtail (tsm->lru_pool, ses->lru_head_index, ses->lru_index);
792 }
793 
794 always_inline void
796  u8 tcp_flags, u32 tcp_ack_number,
797  u32 tcp_seq_number, u32 thread_index)
798 {
800  if ((ses->state == 0) && (tcp_flags & TCP_FLAG_RST))
801  ses->state = NAT44_SES_RST;
802  if ((ses->state == NAT44_SES_RST) && !(tcp_flags & TCP_FLAG_RST))
803  ses->state = 0;
804  if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_SYN) &&
805  (ses->state & NAT44_SES_O2I_SYN))
806  ses->state = 0;
807  if (tcp_flags & TCP_FLAG_SYN)
808  ses->state |= NAT44_SES_O2I_SYN;
809  if (tcp_flags & TCP_FLAG_FIN)
810  {
811  ses->o2i_fin_seq = clib_net_to_host_u32 (tcp_seq_number);
812  ses->state |= NAT44_SES_O2I_FIN;
813  }
814  if ((tcp_flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_FIN))
815  {
816  if (clib_net_to_host_u32 (tcp_ack_number) > ses->i2o_fin_seq)
817  ses->state |= NAT44_SES_I2O_FIN_ACK;
818  if (nat44_is_ses_closed (ses))
819  { // if session is now closed, save the timestamp
820  ses->tcp_closed_timestamp = now + sm->timeouts.tcp.transitory;
821  ses->last_lru_update = now;
822  }
823  }
824  // move the session to proper LRU
825  if (ses->state)
826  {
827  ses->lru_head_index = tsm->tcp_trans_lru_head_index;
828  }
829  else
830  {
831  ses->lru_head_index = tsm->tcp_estab_lru_head_index;
832  }
833  clib_dlist_remove (tsm->lru_pool, ses->lru_index);
834  clib_dlist_addtail (tsm->lru_pool, ses->lru_head_index, ses->lru_index);
835 }
836 
837 always_inline void
838 nat44_session_update_counters (snat_session_t *s, f64 now, uword bytes,
840 {
841  s->last_heard = now;
842  s->total_pkts++;
843  s->total_bytes += bytes;
844 }
845 
846 /** \brief Per-user LRU list maintenance */
847 always_inline void
849 {
850  /* don't update too often - timeout is in magnitude of seconds anyway */
851  if (s->last_heard > s->last_lru_update + 1)
852  {
853  clib_dlist_remove (sm->per_thread_data[thread_index].lru_pool,
854  s->lru_index);
855  clib_dlist_addtail (sm->per_thread_data[thread_index].lru_pool,
856  s->lru_head_index, s->lru_index);
857  s->last_lru_update = s->last_heard;
858  }
859 }
860 
861 #endif /* __included_nat44_ed_inlines_h__ */
862 
863 /*
864  * fd.io coding-style-patch-verification: ON
865  *
866  * Local Variables:
867  * eval: (c-set-style "gnu")
868  * End:
869  */
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:133
u32 * max_translations_per_fib
Definition: nat44_ed.h:598
dlist_elt_t * lru_pool
Definition: nat44_ed.h:474
static_always_inline void nat_6t_o2i_flow_init(snat_main_t *sm, u32 thread_idx, snat_session_t *s, ip4_address_t saddr, u16 sport, ip4_address_t daddr, u16 dport, u32 fib_index, u8 proto)
vnet_interface_output_runtime_t * rt
static u32 nat44_session_get_timeout(snat_main_t *sm, snat_session_t *s)
static void nat44_session_update_lru(snat_main_t *sm, snat_session_t *s, u32 thread_index)
Per-user LRU list maintenance.
static_always_inline u16 snat_random_port(u16 min, u16 max)
u32 arc_next_index
Definition: nat44_ed.h:91
static_always_inline void nat_6t_flow_init(nat_6t_flow_t *f, u32 thread_idx, ip4_address_t saddr, u16 sport, ip4_address_t daddr, u16 dport, u32 fib_index, u8 proto, u32 session_idx)
static void init_nat_o2i_k(clib_bihash_kv_8_8_t *kv, snat_session_t *s)
static_always_inline int nat_6t_t_eq(nat_6t_t *t1, nat_6t_t *t2)
u8 runtime_data[0]
Function dependent node-runtime data.
Definition: node.h:506
nat_timeouts_t timeouts
Definition: nat44_ed.h:605
ip4_address_t src_address
Definition: ip4_packet.h:125
vnet_hw_if_output_node_runtime_t * r
#define vnet_buffer2(b)
Definition: buffer.h:499
#define TCP_FLAG_SYN
Definition: fa_node.h:13
u32 thread_index
static void init_nat_i2o_k(clib_bihash_kv_8_8_t *kv, snat_session_t *s)
static_always_inline void nat_6t_i2o_flow_init(snat_main_t *sm, u32 thread_idx, snat_session_t *s, ip4_address_t saddr, u16 sport, ip4_address_t daddr, u16 dport, u32 fib_index, u8 proto)
#define PREDICT_TRUE(x)
Definition: clib.h:125
unsigned long u64
Definition: types.h:89
nat_6t_t match
Definition: nat44_ed.h:230
u64 as_u64[2]
Definition: nat44_ed.h:215
u16 nexts[VLIB_FRAME_SIZE]
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
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
per_vrf_sessions_t * per_vrf_sessions_vec
Definition: nat44_ed.h:487
#define thread_idx
Definition: tls_async.c:40
static u8 is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:607
static void init_nat_o2i_kv(clib_bihash_kv_8_8_t *kv, snat_session_t *s, u32 thread_index, u32 session_index)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:645
static_always_inline int nat_lru_free_one(snat_main_t *sm, int thread_index, f64 now)
static_always_inline int nat_lru_free_one_with_head(snat_main_t *sm, int thread_index, f64 now, u32 head_index)
nat_protocol_t
Definition: lib.h:63
static void nat44_session_update_counters(snat_session_t *s, f64 now, uword bytes, u32 thread_index)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
vhost_vring_addr_t addr
Definition: vhost_user.h:130
u32 established
Definition: lib.h:80
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: cnat_node.h:109
double f64
Definition: types.h:142
u32 cached_sw_if_index
Definition: nat44_ed.h:685
unsigned int u32
Definition: types.h:88
static_always_inline void per_vrf_sessions_unregister_session(snat_session_t *s, u32 thread_index)
static_always_inline void per_vrf_sessions_register_session(snat_session_t *s, u32 thread_index)
vlib_frame_t * f
if(node->flags &VLIB_NODE_FLAG_TRACE) vnet_interface_output_trace(vm
#define static_always_inline
Definition: clib.h:112
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:24
vlib_get_buffers(vm, from, b, n_left_from)
ip4_address_t dst_address
Definition: ip4_packet.h:125
#define TCP_FLAG_ACK
Definition: fa_node.h:16
static_always_inline void nat_6t_flow_to_ed_k(clib_bihash_kv_16_8_t *kv, nat_6t_flow_t *f)
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define nat_elog_warn(_pm, nat_elog_str)
Definition: log.h:177
ip4_main_t * ip4_main
Definition: nat44_ed.h:658
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
#define VLIB_FRAME_SIZE
Definition: node.h:369
u32 fib_index
Definition: nat44_ed.h:212
u8 proto
Definition: nat44_ed.h:213
#define NAT44_SES_I2O_SYN
Definition: nat44_ed.h:167
u16 * next
u32 transitory
Definition: lib.h:81
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
snat_main_t snat_main
Definition: nat44_ed.c:41
vl_api_ip_proto_t proto
Definition: acl_types.api:51
u64 key
the key
Definition: bihash_8_8.h:43
icmp
Definition: map.api:387
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
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
#define PREDICT_FALSE(x)
Definition: clib.h:124
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:897
#define TCP_FLAG_FIN
Definition: fa_node.h:12
u16 sport
Definition: pnat.api:43
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
static_always_inline void nat_6t_flow_to_ed_kv(clib_bihash_kv_16_8_t *kv, nat_6t_flow_t *f, u32 thread_idx, u32 session_idx)
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:109
static_always_inline int nat_get_icmp_session_lookup_values(vlib_buffer_t *b, ip4_header_t *ip0, ip4_address_t *lookup_saddr, u16 *lookup_sport, ip4_address_t *lookup_daddr, u16 *lookup_dport, u8 *lookup_protocol)
static void 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)
#define TCP_FLAG_RST
Definition: fa_node.h:14
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)
u64 value
the value
Definition: bihash_8_8.h:44
struct nat_timeouts_t::@732 tcp
u32 random_seed
Definition: nat44_ed.h:572
#define NAT44_SES_I2O_FIN_ACK
Definition: nat44_ed.h:165
u16 n_vectors
Definition: node.h:388
static void clib_dlist_addhead(dlist_elt_t *pool, u32 head_index, u32 new_index)
Definition: dlist.h:71
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
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)
u8 data[]
Packet data.
Definition: buffer.h:204
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)
static_always_inline void per_vrf_sessions_cleanup(u32 thread_index)
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
u16 dport
Definition: pnat.api:44
#define NAT44_SES_RST
Definition: nat44_ed.h:169
static void nat44_set_tcp_session_state_i2o(snat_main_t *sm, f64 now, snat_session_t *ses, vlib_buffer_t *b, u32 thread_index)
static_always_inline snat_session_t * nat_ed_session_alloc(snat_main_t *sm, u32 thread_index, f64 now, u8 proto)
#define NAT44_SES_O2I_SYN
Definition: nat44_ed.h:168
static u64 calc_nat_key(ip4_address_t addr, u16 port, u32 fib_index, u8 proto)
The NAT inline functions.
static void init_nat_i2o_kv(clib_bihash_kv_8_8_t *kv, snat_session_t *s, u32 thread_index, u32 session_index)
u8 value
Definition: qos.api:54
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:337
#define ASSERT(truth)
#define always_inline
Definition: rdma_mlx5dv.h:23
#define NAT44_SES_O2I_FIN
Definition: nat44_ed.h:164
static void clib_dlist_remove(dlist_elt_t *pool, u32 index)
Definition: dlist.h:99
u32 value
Definition: dlist.h:32
void nat_free_session_data(snat_main_t *sm, snat_session_t *s, u32 thread_index, u8 is_ha)
Free NAT44 session data (lookup keys, external address port)
Definition: nat44_ed.c:231
static u32 ed_value_get_session_index(clib_bihash_kv_16_8_t *value)
static u32 ed_value_get_thread_index(clib_bihash_kv_16_8_t *value)
typedef key
Definition: ipsec_types.api:88
#define NAT44_SES_I2O_FIN
Definition: nat44_ed.h:163
static_always_inline u8 per_vrf_sessions_is_expired(snat_session_t *s, u32 thread_index)
static_always_inline int nat_ed_ses_o2i_flow_hash_add_del(snat_main_t *sm, u32 thread_idx, snat_session_t *s, int is_add)
static void nat_ed_session_delete(snat_main_t *sm, snat_session_t *ses, u32 thread_index, int lru_delete)
u16 dport
Definition: nat44_ed.h:211
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)
static u32 nat_value_get_thread_index(clib_bihash_kv_8_8_t *value)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
VLIB buffer representation.
Definition: buffer.h:111
u64 uword
Definition: types.h:112
u16 sport
Definition: nat44_ed.h:210
snat_main_per_thread_data_t * per_thread_data
Definition: nat44_ed.h:519
static void split_nat_key(u64 key, ip4_address_t *addr, u16 *port, u32 *fib_index, nat_protocol_t *proto)
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
u16 port
Definition: lb_types.api:73
u32 udp
Definition: lib.h:84
#define vnet_buffer(b)
Definition: buffer.h:437
void nat_6t_l3_l4_csum_calc(nat_6t_flow_t *f)
Definition: nat44_ed.c:3205
static u32 random_u32(u32 *seed)
32-bit random number generator
Definition: random.h:69
NAT port/address allocation lib.
f64 now
static_always_inline u8 nat44_ed_maximum_sessions_exceeded(snat_main_t *sm, u32 fib_index, u32 thread_index)
#define vec_foreach(var, vec)
Vector iterator.
#define NAT44_SES_O2I_FIN_ACK
Definition: nat44_ed.h:166
u16 flags
Copy of main node flags.
Definition: node.h:492
static_always_inline int nat_ed_ses_i2o_flow_hash_add_del(snat_main_t *sm, u32 thread_idx, snat_session_t *s, int is_add)
clib_bihash_16_8_t flow_hash
Definition: nat44_ed.h:535
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace.c:628
static_always_inline int nat_ed_lru_insert(snat_main_per_thread_data_t *tsm, snat_session_t *s, f64 now, u8 proto)
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:292
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
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, u32 thread_index, u32 session_index)
static u32 nat_value_get_session_index(clib_bihash_kv_8_8_t *value)
vlib_simple_counter_main_t total_sessions
Definition: nat44_ed.h:611
static uword nat_pre_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 def_next)
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
snat_session_t * sessions
Definition: nat44_ed.h:468
u32 cached_ip4_address
Definition: nat44_ed.h:686
u32 icmp
Definition: lib.h:85
#define u8
Padding.
Definition: clib.h:121
#define nat44_is_ses_closed(s)
Check if NAT44 endpoint-dependent TCP session is closed.
Definition: nat44_ed.h:784
ip4_address_t daddr
Definition: nat44_ed.h:209
static u32 clib_dlist_remove_head(dlist_elt_t *pool, u32 head_index)
Definition: dlist.h:117
ip4_address_t saddr
Definition: nat44_ed.h:209
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127