FD.io VPP  v21.06-1-gbb7418cf9
Vector Packet Processing
nat44_ei_in2out.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 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  * @file
17  * @brief NAT44 EI inside to outside network translation
18  */
19 
20 #include <vlib/vlib.h>
21 
22 #include <vnet/vnet.h>
23 #include <vnet/ip/ip.h>
24 #include <vnet/ethernet/ethernet.h>
25 #include <vnet/udp/udp_local.h>
26 #include <vnet/fib/ip4_fib.h>
27 
28 #include <vppinfra/hash.h>
29 #include <vppinfra/error.h>
30 
31 #include <nat/lib/log.h>
32 #include <nat/lib/nat_syslog.h>
33 #include <nat/lib/ipfix_logging.h>
34 #include <nat/lib/nat_inlines.h>
36 #include <nat/nat44-ei/nat44_ei.h>
38 
39 typedef struct
40 {
47 
48 /* packet trace format function */
49 static u8 *
50 format_nat44_ei_in2out_trace (u8 *s, va_list *args)
51 {
52  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
53  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
54  nat44_ei_in2out_trace_t *t = va_arg (*args, nat44_ei_in2out_trace_t *);
55  char *tag;
56 
57  tag = t->is_slow_path ? "NAT44_IN2OUT_SLOW_PATH" : "NAT44_IN2OUT_FAST_PATH";
58 
59  s = format (s, "%s: sw_if_index %d, next index %d, session %d", tag,
61  if (t->is_hairpinning)
62  {
63  s = format (s, ", with-hairpinning");
64  }
65 
66  return s;
67 }
68 
69 static u8 *
71 {
72  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
73  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
74  nat44_ei_in2out_trace_t *t = va_arg (*args, nat44_ei_in2out_trace_t *);
75 
76  s = format (s, "NAT44_IN2OUT_FAST: sw_if_index %d, next index %d",
77  t->sw_if_index, t->next_index);
78 
79  return s;
80 }
81 
82 #define foreach_nat44_ei_in2out_error \
83  _ (UNSUPPORTED_PROTOCOL, "unsupported protocol") \
84  _ (OUT_OF_PORTS, "out of ports") \
85  _ (BAD_OUTSIDE_FIB, "outside VRF ID not found") \
86  _ (BAD_ICMP_TYPE, "unsupported ICMP type") \
87  _ (NO_TRANSLATION, "no translation") \
88  _ (MAX_SESSIONS_EXCEEDED, "maximum sessions exceeded") \
89  _ (CANNOT_CREATE_USER, "cannot create NAT user")
90 
91 typedef enum
92 {
93 #define _(sym, str) NAT44_EI_IN2OUT_ERROR_##sym,
95 #undef _
98 
100 #define _(sym,string) string,
102 #undef _
103 };
104 
105 typedef enum
106 {
114 
115 typedef enum
116 {
121 
122 static inline int
124  ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0)
125 {
127 
128  if (nm->out2in_dpo)
129  return 0;
130 
132  nat44_ei_outside_fib_t *outside_fib;
133  fib_prefix_t pfx = {
135  .fp_len = 32,
136  .fp_addr = {
137  .ip4.as_u32 = ip0->dst_address.as_u32,
138  }
139  ,
140  };
141 
142  /* Don't NAT packet aimed at the intfc address */
144  nm->ip4_main, node, sw_if_index0, ip0->dst_address.as_u32)))
145  return 1;
146 
147  fei = fib_table_lookup (rx_fib_index0, &pfx);
148  if (FIB_NODE_INDEX_INVALID != fei)
149  {
151  if (sw_if_index == ~0)
152  {
153  vec_foreach (outside_fib, nm->outside_fibs)
154  {
155  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
156  if (FIB_NODE_INDEX_INVALID != fei)
157  {
158  sw_if_index = fib_entry_get_resolving_interface (fei);
159  if (sw_if_index != ~0)
160  break;
161  }
162  }
163  }
164  if (sw_if_index == ~0)
165  return 1;
166 
168  pool_foreach (i, nm->interfaces)
169  {
170  /* NAT packet aimed at outside interface */
171  if ((nat44_ei_interface_is_outside (i)) &&
172  (sw_if_index == i->sw_if_index))
173  return 0;
174  }
175  }
176 
177  return 1;
178 }
179 
180 static inline int
182  u32 sw_if_index0, ip4_header_t *ip0, u32 proto0,
183  u32 rx_fib_index0, u32 thread_index)
184 {
185  udp_header_t *udp0 = ip4_next_header (ip0);
186  clib_bihash_kv_8_8_t kv0, value0;
187 
188  init_nat_k (&kv0, ip0->dst_address, udp0->dst_port, nm->outside_fib_index,
189  proto0);
190 
191  /* NAT packet aimed at external address if */
192  /* has active sessions */
193  if (clib_bihash_search_8_8 (&nm->out2in, &kv0, &value0))
194  {
195  /* or is static mappings */
196  ip4_address_t placeholder_addr;
197  u16 placeholder_port;
198  u32 placeholder_fib_index;
200  nm->outside_fib_index, proto0,
201  &placeholder_addr, &placeholder_port,
202  &placeholder_fib_index, 1, 0, 0))
203  return 0;
204  }
205  else
206  return 0;
207 
208  if (nm->forwarding_enabled)
209  return 1;
210 
211  return nat44_ei_not_translate_fast (node, sw_if_index0, ip0, proto0,
212  rx_fib_index0);
213 }
214 
215 static inline int
217  u32 proto0, u16 src_port, u16 dst_port,
218  u32 thread_index, u32 sw_if_index)
219 {
220  clib_bihash_kv_8_8_t kv0, value0;
222 
223  /* src NAT check */
224  init_nat_k (&kv0, ip0->src_address, src_port,
225  ip4_fib_table_get_index_for_sw_if_index (sw_if_index), proto0);
226 
227  if (!clib_bihash_search_8_8 (&nm->out2in, &kv0, &value0))
228  return 1;
229 
230  /* dst NAT check */
231  init_nat_k (&kv0, ip0->dst_address, dst_port,
232  ip4_fib_table_get_index_for_sw_if_index (sw_if_index), proto0);
233  if (!clib_bihash_search_8_8 (&nm->in2out, &kv0, &value0))
234  {
235  /* hairpinning */
237  {
238  if ((nat44_ei_interface_is_inside (i)) &&
239  (sw_if_index == i->sw_if_index))
240  return 0;
241  }
242  return 1;
243  }
244 
245  return 0;
246 }
247 
248 #ifndef CLIB_MARCH_VARIANT
249 int
251 {
254  nat44_ei_session_t *s;
255  u64 sess_timeout_time;
259 
260  if (ctx->thread_index != nat_value_get_thread_index (kv))
261  {
262  return 0;
263  }
264 
266  sess_timeout_time = s->last_heard + (f64) nat_session_get_timeout (
267  &nm->timeouts, s->nat_proto, s->state);
268  if (ctx->now >= sess_timeout_time)
269  {
270  init_nat_o2i_k (&s_kv, s);
271  if (clib_bihash_add_del_8_8 (&nm->out2in, &s_kv, 0))
272  nat_elog_warn (nm, "out2in key del failed");
273 
275  s->in2out.addr.as_u32,
276  s->out2in.addr.as_u32,
277  s->nat_proto,
278  s->in2out.port,
279  s->out2in.port,
280  s->in2out.fib_index);
281 
282  nat_syslog_nat44_apmdel (s->user_index, s->in2out.fib_index,
283  &s->in2out.addr, s->in2out.port,
284  &s->out2in.addr, s->out2in.port, s->nat_proto);
285 
286  nat_ha_sdel (&s->out2in.addr, s->out2in.port, &s->ext_host_addr,
287  s->ext_host_port, s->nat_proto, s->out2in.fib_index,
288  ctx->thread_index);
289 
292  nm->addresses, ctx->thread_index, &s->out2in.addr, s->out2in.port,
293  s->nat_proto);
294 
296  return 1;
297  }
298 
299  return 0;
300 }
301 #endif
302 
303 static u32
305  ip4_address_t i2o_addr, u16 i2o_port, u32 rx_fib_index0,
306  nat_protocol_t nat_proto, nat44_ei_session_t **sessionp,
307  vlib_node_runtime_t *node, u32 next0, u32 thread_index, f64 now)
308 {
309  nat44_ei_user_t *u;
310  nat44_ei_session_t *s = 0;
312  u8 is_sm = 0;
313  nat44_ei_outside_fib_t *outside_fib;
315  u8 identity_nat;
316  fib_prefix_t pfx = {
318  .fp_len = 32,
319  .fp_addr = {
320  .ip4.as_u32 = ip0->dst_address.as_u32,
321  },
322  };
324  ip4_address_t sm_addr;
325  u16 sm_port;
326  u32 sm_fib_index;
327 
328  if (PREDICT_FALSE (nat44_ei_maximum_sessions_exceeded (nm, thread_index)))
329  {
330  b0->error = node->errors[NAT44_EI_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
331  nat_ipfix_logging_max_sessions (thread_index,
333  nat_elog_notice (nm, "maximum sessions exceeded");
335  }
336 
337  /* First try to match static mapping by local address and port */
338  if (nat44_ei_static_mapping_match (i2o_addr, i2o_port, rx_fib_index0,
339  nat_proto, &sm_addr, &sm_port,
340  &sm_fib_index, 0, 0, &identity_nat))
341  {
342  /* Try to create dynamic translation */
343  if (nm->alloc_addr_and_port (
344  nm->addresses, rx_fib_index0, thread_index, nat_proto,
345  ip0->src_address, &sm_addr, &sm_port, nm->port_per_thread,
346  nm->per_thread_data[thread_index].snat_thread_index))
347  {
348  b0->error = node->errors[NAT44_EI_IN2OUT_ERROR_OUT_OF_PORTS];
350  }
351  }
352  else
353  {
354  if (PREDICT_FALSE (identity_nat))
355  {
356  *sessionp = s;
357  return next0;
358  }
359 
360  is_sm = 1;
361  }
362 
363  u = nat44_ei_user_get_or_create (nm, &ip0->src_address, rx_fib_index0,
364  thread_index);
365  if (!u)
366  {
367  b0->error = node->errors[NAT44_EI_IN2OUT_ERROR_CANNOT_CREATE_USER];
369  }
370 
371  s = nat44_ei_session_alloc_or_recycle (nm, u, thread_index, now);
372  if (!s)
373  {
374  nat44_ei_delete_user_with_no_session (nm, u, thread_index);
375  nat_elog_warn (nm, "create NAT session failed");
377  }
378 
379  if (is_sm)
381  nat44_ei_user_session_increment (nm, u, is_sm);
382  s->in2out.addr = i2o_addr;
383  s->in2out.port = i2o_port;
384  s->in2out.fib_index = rx_fib_index0;
385  s->nat_proto = nat_proto;
386  s->out2in.addr = sm_addr;
387  s->out2in.port = sm_port;
388  s->out2in.fib_index = nm->outside_fib_index;
389  switch (vec_len (nm->outside_fibs))
390  {
391  case 0:
392  s->out2in.fib_index = nm->outside_fib_index;
393  break;
394  case 1:
395  s->out2in.fib_index = nm->outside_fibs[0].fib_index;
396  break;
397  default:
398  vec_foreach (outside_fib, nm->outside_fibs)
399  {
400  fei = fib_table_lookup (outside_fib->fib_index, &pfx);
401  if (FIB_NODE_INDEX_INVALID != fei)
402  {
403  if (fib_entry_get_resolving_interface (fei) != ~0)
404  {
405  s->out2in.fib_index = outside_fib->fib_index;
406  break;
407  }
408  }
409  }
410  break;
411  }
412  s->ext_host_addr.as_u32 = ip0->dst_address.as_u32;
413  s->ext_host_port = vnet_buffer (b0)->ip.reass.l4_dst_port;
414  *sessionp = s;
415 
416  /* Add to translation hashes */
417  ctx0.now = now;
418  ctx0.thread_index = thread_index;
419  init_nat_i2o_kv (&kv0, s, thread_index,
420  s - nm->per_thread_data[thread_index].sessions);
421  if (clib_bihash_add_or_overwrite_stale_8_8 (
422  &nm->in2out, &kv0, nat44_i2o_is_idle_session_cb, &ctx0))
423  nat_elog_notice (nm, "in2out key add failed");
424 
425  init_nat_o2i_kv (&kv0, s, thread_index,
426  s - nm->per_thread_data[thread_index].sessions);
427  if (clib_bihash_add_or_overwrite_stale_8_8 (
428  &nm->out2in, &kv0, nat44_o2i_is_idle_session_cb, &ctx0))
429  nat_elog_notice (nm, "out2in key add failed");
430 
431  /* log NAT event */
433  thread_index, s->in2out.addr.as_u32, s->out2in.addr.as_u32, s->nat_proto,
434  s->in2out.port, s->out2in.port, s->in2out.fib_index);
435 
436  nat_syslog_nat44_apmadd (s->user_index, s->in2out.fib_index, &s->in2out.addr,
437  s->in2out.port, &s->out2in.addr, s->out2in.port,
438  s->nat_proto);
439 
440  nat_ha_sadd (&s->in2out.addr, s->in2out.port, &s->out2in.addr,
441  s->out2in.port, &s->ext_host_addr, s->ext_host_port,
442  &s->ext_host_nat_addr, s->ext_host_nat_port, s->nat_proto,
443  s->in2out.fib_index, s->flags, thread_index, 0);
444 
445  return next0;
446 }
447 
448 #ifndef CLIB_MARCH_VARIANT
449 static_always_inline nat44_ei_in2out_error_t
451  u16 *port, nat_protocol_t *nat_proto)
452 {
453  icmp46_header_t *icmp0;
454  icmp_echo_header_t *echo0, *inner_echo0 = 0;
455  ip4_header_t *inner_ip0 = 0;
456  void *l4_header = 0;
457  icmp46_header_t *inner_icmp0;
458 
459  icmp0 = (icmp46_header_t *) ip4_next_header (ip0);
460  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
461 
463  (vnet_buffer (b)->ip.reass.icmp_type_or_tcp_flags))
464  {
465  *nat_proto = NAT_PROTOCOL_ICMP;
466  *addr = ip0->src_address;
467  *port = vnet_buffer (b)->ip.reass.l4_src_port;
468  }
469  else
470  {
471  inner_ip0 = (ip4_header_t *) (echo0 + 1);
472  l4_header = ip4_next_header (inner_ip0);
473  *nat_proto = ip_proto_to_nat_proto (inner_ip0->protocol);
474  *addr = inner_ip0->dst_address;
475  switch (*nat_proto)
476  {
477  case NAT_PROTOCOL_ICMP:
478  inner_icmp0 = (icmp46_header_t *) l4_header;
479  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
480  *port = inner_echo0->identifier;
481  break;
482  case NAT_PROTOCOL_UDP:
483  case NAT_PROTOCOL_TCP:
484  *port = ((tcp_udp_header_t *) l4_header)->dst_port;
485  break;
486  default:
487  return NAT44_EI_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL;
488  }
489  }
490  return -1; /* success */
491 }
492 
493 /**
494  * Get address and port values to be used for ICMP packet translation
495  * and create session if needed
496  *
497  * @param[in,out] nm NAT main
498  * @param[in,out] node NAT node runtime
499  * @param[in] thread_index thread index
500  * @param[in,out] b0 buffer containing packet to be translated
501  * @param[in,out] ip0 ip header
502  * @param[out] p_proto protocol used for matching
503  * @param[out] p_value address and port after NAT translation
504  * @param[out] p_dont_translate if packet should not be translated
505  * @param d optional parameter
506  * @param e optional parameter
507  */
508 u32
510  vlib_buffer_t *b0, ip4_header_t *ip0,
512  u32 *fib_index, nat_protocol_t *proto,
513  nat44_ei_session_t **p_s0, u8 *dont_translate)
514 {
517  u32 sw_if_index0;
518  nat44_ei_session_t *s0 = 0;
519  clib_bihash_kv_8_8_t kv0, value0;
520  u32 next0 = ~0;
521  int err;
522  vlib_main_t *vm = vlib_get_main ();
523  *dont_translate = 0;
524 
525  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
526  *fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
527 
528  err = icmp_get_key (b0, ip0, addr, port, proto);
529  if (err != -1)
530  {
531  b0->error = node->errors[err];
533  goto out;
534  }
535 
536  init_nat_k (&kv0, *addr, *port, *fib_index, *proto);
537  if (clib_bihash_search_8_8 (&nm->in2out, &kv0, &value0))
538  {
539  if (vnet_buffer (b0)->sw_if_index[VLIB_TX] != ~0)
540  {
542  nm, ip0, *proto, *port, *port, thread_index, sw_if_index0)))
543  {
544  *dont_translate = 1;
545  goto out;
546  }
547  }
548  else
549  {
551  nm, node, sw_if_index0, ip0, NAT_PROTOCOL_ICMP, *fib_index,
552  thread_index)))
553  {
554  *dont_translate = 1;
555  goto out;
556  }
557  }
558 
559  if (PREDICT_FALSE
561  (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags)))
562  {
563  b0->error = node->errors[NAT44_EI_IN2OUT_ERROR_BAD_ICMP_TYPE];
565  goto out;
566  }
567 
568  next0 = slow_path (nm, b0, ip0, *addr, *port, *fib_index, *proto, &s0,
569  node, next0, thread_index, vlib_time_now (vm));
570 
572  goto out;
573 
574  if (!s0)
575  {
576  *dont_translate = 1;
577  goto out;
578  }
579  }
580  else
581  {
582  if (PREDICT_FALSE
583  (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
584  ICMP4_echo_request
585  && vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
586  ICMP4_echo_reply
588  reass.icmp_type_or_tcp_flags)))
589  {
590  b0->error = node->errors[NAT44_EI_IN2OUT_ERROR_BAD_ICMP_TYPE];
592  goto out;
593  }
594 
595  s0 = pool_elt_at_index (tnm->sessions,
596  nat_value_get_session_index (&value0));
597  }
598 
599 out:
600  if (s0)
601  {
602  *addr = s0->out2in.addr;
603  *port = s0->out2in.port;
604  *fib_index = s0->out2in.fib_index;
605  }
606  if (p_s0)
607  *p_s0 = s0;
608  return next0;
609 }
610 #endif
611 
612 #ifndef CLIB_MARCH_VARIANT
613 u32
615  vlib_buffer_t *b0, ip4_header_t *ip0,
617  u32 *fib_index, nat_protocol_t *proto,
618  nat44_ei_session_t **s0, u8 *dont_translate)
619 {
620  u32 sw_if_index0;
621  u8 is_addr_only;
622  u32 next0 = ~0;
623  int err;
624  *dont_translate = 0;
625 
626  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
627  *fib_index = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
628 
629  err = icmp_get_key (b0, ip0, addr, port, proto);
630  if (err != -1)
631  {
632  b0->error = node->errors[err];
634  goto out;
635  }
636 
637  ip4_address_t sm_addr;
638  u16 sm_port;
639  u32 sm_fib_index;
640 
641  if (nat44_ei_static_mapping_match (*addr, *port, *fib_index, *proto,
642  &sm_addr, &sm_port, &sm_fib_index, 0,
643  &is_addr_only, 0))
644  {
646  node, sw_if_index0, ip0, IP_PROTOCOL_ICMP, *fib_index)))
647  {
648  *dont_translate = 1;
649  goto out;
650  }
651 
653  (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags))
654  {
656  goto out;
657  }
658 
659  b0->error = node->errors[NAT44_EI_IN2OUT_ERROR_NO_TRANSLATION];
661  goto out;
662  }
663 
664  if (PREDICT_FALSE
665  (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags != ICMP4_echo_request
666  && (vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags !=
667  ICMP4_echo_reply || !is_addr_only)
669  reass.icmp_type_or_tcp_flags)))
670  {
671  b0->error = node->errors[NAT44_EI_IN2OUT_ERROR_BAD_ICMP_TYPE];
673  goto out;
674  }
675 
676 out:
677  return next0;
678 }
679 #endif
680 
682  icmp46_header_t *icmp0, u32 sw_if_index0,
683  u32 rx_fib_index0, vlib_node_runtime_t *node,
684  u32 next0, u32 thread_index,
685  nat44_ei_session_t **p_s0);
686 
687 #ifndef CLIB_MARCH_VARIANT
688 u32
690  icmp46_header_t *icmp0, u32 sw_if_index0,
691  u32 rx_fib_index0, vlib_node_runtime_t *node, u32 next0,
692  u32 thread_index, nat44_ei_session_t **p_s0)
693 {
695  vlib_main_t *vm = vlib_get_main ();
697  u16 port;
698  u32 fib_index;
700  icmp_echo_header_t *echo0, *inner_echo0 = 0;
701  ip4_header_t *inner_ip0;
702  void *l4_header = 0;
703  icmp46_header_t *inner_icmp0;
704  u8 dont_translate;
705  u32 new_addr0, old_addr0;
706  u16 old_id0, new_id0;
707  u16 old_checksum0, new_checksum0;
708  ip_csum_t sum0;
709  u16 checksum0;
710  u32 next0_tmp;
711  u32 required_thread_index = thread_index;
712 
713  echo0 = (icmp_echo_header_t *) (icmp0 + 1);
714 
715  if (PREDICT_TRUE (nm->pat))
716  {
717  next0_tmp = nat44_ei_icmp_match_in2out_slow (
718  node, thread_index, b0, ip0, &addr, &port, &fib_index, &proto, p_s0,
719  &dont_translate);
720  }
721  else
722  {
723  next0_tmp = nat44_ei_icmp_match_in2out_fast (
724  node, thread_index, b0, ip0, &addr, &port, &fib_index, &proto, p_s0,
725  &dont_translate);
726  }
727 
728  if (next0_tmp != ~0)
729  next0 = next0_tmp;
730  if (next0 == NAT44_EI_IN2OUT_NEXT_DROP || dont_translate)
731  goto out;
732 
733  if (PREDICT_TRUE (!ip4_is_fragment (ip0)))
734  {
735  sum0 =
737  (u8 *) icmp0 -
738  (u8 *) vlib_buffer_get_current (b0),
739  ntohs (ip0->length) -
740  ip4_header_bytes (ip0), 0);
741  checksum0 = ~ip_csum_fold (sum0);
742  if (PREDICT_FALSE (checksum0 != 0 && checksum0 != 0xffff))
743  {
745  goto out;
746  }
747  }
748 
749  old_addr0 = ip0->src_address.as_u32;
750  new_addr0 = ip0->src_address.as_u32 = addr.as_u32;
751 
752  sum0 = ip0->checksum;
753  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
754  src_address /* changed member */ );
755  ip0->checksum = ip_csum_fold (sum0);
756 
757  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
758  {
759  if (icmp0->checksum == 0)
760  icmp0->checksum = 0xffff;
761 
762  if (!icmp_type_is_error_message (icmp0->type))
763  {
764  new_id0 = port;
765  if (PREDICT_FALSE (new_id0 != echo0->identifier))
766  {
767  old_id0 = echo0->identifier;
768  new_id0 = port;
769  echo0->identifier = new_id0;
770 
771  sum0 = icmp0->checksum;
772  sum0 =
773  ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
774  identifier);
775  icmp0->checksum = ip_csum_fold (sum0);
776  }
777  }
778  else
779  {
780  inner_ip0 = (ip4_header_t *) (echo0 + 1);
781  l4_header = ip4_next_header (inner_ip0);
782 
783  if (!ip4_header_checksum_is_valid (inner_ip0))
784  {
786  goto out;
787  }
788 
789  /* update inner destination IP address */
790  old_addr0 = inner_ip0->dst_address.as_u32;
791  inner_ip0->dst_address = addr;
792  new_addr0 = inner_ip0->dst_address.as_u32;
793  sum0 = icmp0->checksum;
794  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
795  dst_address /* changed member */ );
796  icmp0->checksum = ip_csum_fold (sum0);
797 
798  /* update inner IP header checksum */
799  old_checksum0 = inner_ip0->checksum;
800  sum0 = inner_ip0->checksum;
801  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
802  dst_address /* changed member */ );
803  inner_ip0->checksum = ip_csum_fold (sum0);
804  new_checksum0 = inner_ip0->checksum;
805  sum0 = icmp0->checksum;
806  sum0 =
807  ip_csum_update (sum0, old_checksum0, new_checksum0, ip4_header_t,
808  checksum);
809  icmp0->checksum = ip_csum_fold (sum0);
810 
811  switch (proto)
812  {
813  case NAT_PROTOCOL_ICMP:
814  inner_icmp0 = (icmp46_header_t *) l4_header;
815  inner_echo0 = (icmp_echo_header_t *) (inner_icmp0 + 1);
816 
817  old_id0 = inner_echo0->identifier;
818  new_id0 = port;
819  inner_echo0->identifier = new_id0;
820 
821  sum0 = icmp0->checksum;
822  sum0 =
823  ip_csum_update (sum0, old_id0, new_id0, icmp_echo_header_t,
824  identifier);
825  icmp0->checksum = ip_csum_fold (sum0);
826  break;
827  case NAT_PROTOCOL_UDP:
828  case NAT_PROTOCOL_TCP:
829  old_id0 = ((tcp_udp_header_t *) l4_header)->dst_port;
830  new_id0 = port;
831  ((tcp_udp_header_t *) l4_header)->dst_port = new_id0;
832 
833  sum0 = icmp0->checksum;
834  sum0 = ip_csum_update (sum0, old_id0, new_id0, tcp_udp_header_t,
835  dst_port);
836  icmp0->checksum = ip_csum_fold (sum0);
837  break;
838  default:
839  ASSERT (0);
840  }
841  }
842  }
843 
844  if (vnet_buffer (b0)->sw_if_index[VLIB_TX] == ~0)
845  {
846  if (0 != nat44_ei_icmp_hairpinning (nm, b0, thread_index, ip0, icmp0,
847  &required_thread_index))
848  vnet_buffer (b0)->sw_if_index[VLIB_TX] = fib_index;
849  if (thread_index != required_thread_index)
850  {
851  vnet_buffer (b0)->snat.required_thread_index = required_thread_index;
853  }
854  }
855 
856 out:
857  return next0;
858 }
859 #endif
860 
863  ip4_header_t *ip0, icmp46_header_t *icmp0,
864  u32 sw_if_index0, u32 rx_fib_index0,
865  vlib_node_runtime_t *node, u32 next0, f64 now,
866  u32 thread_index, nat44_ei_session_t **p_s0)
867 {
868  vlib_main_t *vm = vlib_get_main ();
869 
870  next0 = nat44_ei_icmp_in2out (b0, ip0, icmp0, sw_if_index0, rx_fib_index0,
871  node, next0, thread_index, p_s0);
872  nat44_ei_session_t *s0 = *p_s0;
873  if (PREDICT_TRUE (next0 != NAT44_EI_IN2OUT_NEXT_DROP && s0))
874  {
875  /* Accounting */
877  s0, now, vlib_buffer_length_in_chain (vm, b0), thread_index);
878  /* Per-user LRU list maintenance */
879  nat44_ei_session_update_lru (nm, s0, thread_index);
880  }
881  return next0;
882 }
883 
884 static int
886  ip4_header_t *ip, u32 rx_fib_index)
887 {
890  u32 old_addr, new_addr;
891  ip_csum_t sum;
892 
893  init_nat_k (&kv, ip->src_address, 0, rx_fib_index, 0);
894  if (clib_bihash_search_8_8 (&nm->static_mapping_by_local, &kv, &value))
895  return 1;
896 
897  m = pool_elt_at_index (nm->static_mappings, value.value);
898 
899  old_addr = ip->src_address.as_u32;
900  new_addr = ip->src_address.as_u32 = m->external_addr.as_u32;
901  sum = ip->checksum;
902  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, src_address);
903  ip->checksum = ip_csum_fold (sum);
904 
905 
906  /* Hairpinning */
907  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
908  {
909  vnet_buffer (b)->sw_if_index[VLIB_TX] = m->fib_index;
911  }
912 
913  return 0;
914 }
915 
916 static inline uword
918  vlib_frame_t *frame, int is_slow_path,
919  int is_output_feature)
920 {
921  u32 n_left_from, *from;
923  f64 now = vlib_time_now (vm);
924  u32 thread_index = vm->thread_index;
925 
926  from = vlib_frame_vector_args (frame);
927  n_left_from = frame->n_vectors;
928 
931  vlib_get_buffers (vm, from, b, n_left_from);
932 
933  while (n_left_from >= 2)
934  {
935  vlib_buffer_t *b0, *b1;
936  u32 next0, next1;
937  u32 sw_if_index0, sw_if_index1;
938  ip4_header_t *ip0, *ip1;
939  ip_csum_t sum0, sum1;
940  u32 new_addr0, old_addr0, new_addr1, old_addr1;
941  u16 old_port0, new_port0, old_port1, new_port1;
942  udp_header_t *udp0, *udp1;
943  tcp_header_t *tcp0, *tcp1;
944  icmp46_header_t *icmp0, *icmp1;
945  u32 rx_fib_index0, rx_fib_index1;
946  u32 proto0, proto1;
947  nat44_ei_session_t *s0 = 0, *s1 = 0;
948  clib_bihash_kv_8_8_t kv0, value0, kv1, value1;
949  u32 iph_offset0 = 0, iph_offset1 = 0;
950 
951  b0 = *b;
952  b++;
953  b1 = *b;
954  b++;
955 
956  /* Prefetch next iteration. */
957  if (PREDICT_TRUE (n_left_from >= 4))
958  {
959  vlib_buffer_t *p2, *p3;
960 
961  p2 = *b;
962  p3 = *(b + 1);
963 
964  vlib_prefetch_buffer_header (p2, LOAD);
965  vlib_prefetch_buffer_header (p3, LOAD);
966 
969  }
970 
971  if (is_output_feature)
972  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
973 
974  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
975  iph_offset0);
976 
977  udp0 = ip4_next_header (ip0);
978  tcp0 = (tcp_header_t *) udp0;
979  icmp0 = (icmp46_header_t *) udp0;
980 
981  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
982  rx_fib_index0 =
983  vec_elt (nm->ip4_main->fib_index_by_sw_if_index, sw_if_index0);
984 
985  next0 = next1 = NAT44_EI_IN2OUT_NEXT_LOOKUP;
986 
987  if (PREDICT_FALSE (ip0->ttl == 1))
988  {
989  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
990  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
991  ICMP4_time_exceeded_ttl_exceeded_in_transit,
992  0);
994  goto trace00;
995  }
996 
997  proto0 = ip_proto_to_nat_proto (ip0->protocol);
998 
999  /* Next configured feature, probably ip4-lookup */
1000  if (is_slow_path)
1001  {
1002  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1003  {
1004  if (nat_in2out_sm_unknown_proto (nm, b0, ip0, rx_fib_index0))
1005  {
1006  next0 = NAT44_EI_IN2OUT_NEXT_DROP;
1007  b0->error =
1008  node->errors[NAT44_EI_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1009  }
1011  is_slow_path ? &nm->counters.slowpath.in2out.other :
1012  &nm->counters.fastpath.in2out.other,
1013  thread_index, sw_if_index0, 1);
1014  goto trace00;
1015  }
1016 
1017  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1018  {
1020  nm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, next0,
1021  now, thread_index, &s0);
1023  is_slow_path ? &nm->counters.slowpath.in2out.icmp :
1024  &nm->counters.fastpath.in2out.icmp,
1025  thread_index, sw_if_index0, 1);
1026  goto trace00;
1027  }
1028  }
1029  else
1030  {
1031  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1032  {
1034  goto trace00;
1035  }
1036 
1037  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1038  {
1040  goto trace00;
1041  }
1042  }
1043 
1044  init_nat_k (&kv0, ip0->src_address,
1045  vnet_buffer (b0)->ip.reass.l4_src_port, rx_fib_index0,
1046  proto0);
1047  if (PREDICT_FALSE (clib_bihash_search_8_8 (&nm->in2out, &kv0, &value0) !=
1048  0))
1049  {
1050  if (is_slow_path)
1051  {
1052  if (is_output_feature)
1053  {
1055  nm, ip0, proto0,
1056  vnet_buffer (b0)->ip.reass.l4_src_port,
1057  vnet_buffer (b0)->ip.reass.l4_dst_port, thread_index,
1058  sw_if_index0)))
1059  goto trace00;
1060 
1061  /*
1062  * Send DHCP packets to the ipv4 stack, or we won't
1063  * be able to use dhcp client on the outside interface
1064  */
1065  if (PREDICT_FALSE
1066  (proto0 == NAT_PROTOCOL_UDP
1067  && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1068  clib_host_to_net_u16
1069  (UDP_DST_PORT_dhcp_to_server))
1070  && ip0->dst_address.as_u32 == 0xffffffff))
1071  goto trace00;
1072  }
1073  else
1074  {
1076  nm, node, sw_if_index0, ip0, proto0, rx_fib_index0,
1077  thread_index)))
1078  goto trace00;
1079  }
1080 
1081  next0 = slow_path (nm, b0, ip0, ip0->src_address,
1082  vnet_buffer (b0)->ip.reass.l4_src_port,
1083  rx_fib_index0, proto0, &s0, node, next0,
1084  thread_index, now);
1086  goto trace00;
1087 
1088  if (PREDICT_FALSE (!s0))
1089  goto trace00;
1090  }
1091  else
1092  {
1094  goto trace00;
1095  }
1096  }
1097  else
1098  s0 = pool_elt_at_index (nm->per_thread_data[thread_index].sessions,
1099  nat_value_get_session_index (&value0));
1100 
1101  b0->flags |= VNET_BUFFER_F_IS_NATED;
1102 
1103  old_addr0 = ip0->src_address.as_u32;
1104  ip0->src_address = s0->out2in.addr;
1105  new_addr0 = ip0->src_address.as_u32;
1106  if (!is_output_feature)
1107  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1108 
1109  sum0 = ip0->checksum;
1110  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1111  ip4_header_t, src_address /* changed member */ );
1112  ip0->checksum = ip_csum_fold (sum0);
1113 
1114 
1115  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1116  {
1117  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1118  {
1119  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1120  new_port0 = udp0->src_port = s0->out2in.port;
1121  sum0 = tcp0->checksum;
1122  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1123  ip4_header_t,
1124  dst_address /* changed member */ );
1125  sum0 = ip_csum_update (sum0, old_port0, new_port0,
1126  ip4_header_t /* cheat */ ,
1127  length /* changed member */ );
1128  mss_clamping (nm->mss_clamping, tcp0, &sum0);
1129  tcp0->checksum = ip_csum_fold (sum0);
1130  }
1131  vlib_increment_simple_counter (is_slow_path ?
1132  &nm->counters.slowpath.in2out.tcp :
1133  &nm->counters.fastpath.in2out.tcp,
1134  thread_index, sw_if_index0, 1);
1135  }
1136  else
1137  {
1138  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1139  {
1140  udp0->src_port = s0->out2in.port;
1141  if (PREDICT_FALSE (udp0->checksum))
1142  {
1143  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1144  new_port0 = udp0->src_port;
1145  sum0 = udp0->checksum;
1146  sum0 = ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t, dst_address /* changed member */
1147  );
1148  sum0 =
1149  ip_csum_update (sum0, old_port0, new_port0,
1150  ip4_header_t /* cheat */ ,
1151  length /* changed member */ );
1152  udp0->checksum = ip_csum_fold (sum0);
1153  }
1154  }
1155  vlib_increment_simple_counter (is_slow_path ?
1156  &nm->counters.slowpath.in2out.udp :
1157  &nm->counters.fastpath.in2out.udp,
1158  thread_index, sw_if_index0, 1);
1159  }
1160 
1161  /* Accounting */
1163  s0, now, vlib_buffer_length_in_chain (vm, b0), thread_index);
1164  /* Per-user LRU list maintenance */
1165  nat44_ei_session_update_lru (nm, s0, thread_index);
1166  trace00:
1167 
1169  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1170  {
1172  vlib_add_trace (vm, node, b0, sizeof (*t));
1173  t->is_slow_path = is_slow_path;
1174  t->sw_if_index = sw_if_index0;
1175  t->next_index = next0;
1176  t->session_index = ~0;
1177  if (s0)
1179  }
1180 
1181  if (next0 == NAT44_EI_IN2OUT_NEXT_DROP)
1182  {
1184  is_slow_path ? &nm->counters.slowpath.in2out.drops :
1185  &nm->counters.fastpath.in2out.drops,
1186  thread_index, sw_if_index0, 1);
1187  }
1188 
1189  if (is_output_feature)
1190  iph_offset1 = vnet_buffer (b1)->ip.reass.save_rewrite_length;
1191 
1192  ip1 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b1) +
1193  iph_offset1);
1194 
1195  udp1 = ip4_next_header (ip1);
1196  tcp1 = (tcp_header_t *) udp1;
1197  icmp1 = (icmp46_header_t *) udp1;
1198 
1199  sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
1200  rx_fib_index1 =
1201  vec_elt (nm->ip4_main->fib_index_by_sw_if_index, sw_if_index1);
1202 
1203  if (PREDICT_FALSE (ip1->ttl == 1))
1204  {
1205  vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1206  icmp4_error_set_vnet_buffer (b1, ICMP4_time_exceeded,
1207  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1208  0);
1210  goto trace01;
1211  }
1212 
1213  proto1 = ip_proto_to_nat_proto (ip1->protocol);
1214 
1215  /* Next configured feature, probably ip4-lookup */
1216  if (is_slow_path)
1217  {
1218  if (PREDICT_FALSE (proto1 == NAT_PROTOCOL_OTHER))
1219  {
1220  if (nat_in2out_sm_unknown_proto (nm, b1, ip1, rx_fib_index1))
1221  {
1222  next1 = NAT44_EI_IN2OUT_NEXT_DROP;
1223  b1->error =
1224  node->errors[NAT44_EI_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1225  }
1227  is_slow_path ? &nm->counters.slowpath.in2out.other :
1228  &nm->counters.fastpath.in2out.other,
1229  thread_index, sw_if_index1, 1);
1230  goto trace01;
1231  }
1232 
1233  if (PREDICT_FALSE (proto1 == NAT_PROTOCOL_ICMP))
1234  {
1236  nm, b1, ip1, icmp1, sw_if_index1, rx_fib_index1, node, next1,
1237  now, thread_index, &s1);
1239  is_slow_path ? &nm->counters.slowpath.in2out.icmp :
1240  &nm->counters.fastpath.in2out.icmp,
1241  thread_index, sw_if_index1, 1);
1242  goto trace01;
1243  }
1244  }
1245  else
1246  {
1247  if (PREDICT_FALSE (proto1 == NAT_PROTOCOL_OTHER))
1248  {
1250  goto trace01;
1251  }
1252 
1253  if (PREDICT_FALSE (proto1 == NAT_PROTOCOL_ICMP))
1254  {
1256  goto trace01;
1257  }
1258  }
1259 
1260  init_nat_k (&kv1, ip1->src_address,
1261  vnet_buffer (b1)->ip.reass.l4_src_port, rx_fib_index1,
1262  proto1);
1263  if (PREDICT_FALSE (clib_bihash_search_8_8 (&nm->in2out, &kv1, &value1) !=
1264  0))
1265  {
1266  if (is_slow_path)
1267  {
1268  if (is_output_feature)
1269  {
1271  nm, ip1, proto1,
1272  vnet_buffer (b1)->ip.reass.l4_src_port,
1273  vnet_buffer (b1)->ip.reass.l4_dst_port, thread_index,
1274  sw_if_index1)))
1275  goto trace01;
1276 
1277  /*
1278  * Send DHCP packets to the ipv4 stack, or we won't
1279  * be able to use dhcp client on the outside interface
1280  */
1281  if (PREDICT_FALSE
1282  (proto1 == NAT_PROTOCOL_UDP
1283  && (vnet_buffer (b1)->ip.reass.l4_dst_port ==
1284  clib_host_to_net_u16
1285  (UDP_DST_PORT_dhcp_to_server))
1286  && ip1->dst_address.as_u32 == 0xffffffff))
1287  goto trace01;
1288  }
1289  else
1290  {
1292  nm, node, sw_if_index1, ip1, proto1, rx_fib_index1,
1293  thread_index)))
1294  goto trace01;
1295  }
1296 
1297  next1 = slow_path (nm, b1, ip1, ip1->src_address,
1298  vnet_buffer (b1)->ip.reass.l4_src_port,
1299  rx_fib_index1, proto1, &s1, node, next1,
1300  thread_index, now);
1302  goto trace01;
1303 
1304  if (PREDICT_FALSE (!s1))
1305  goto trace01;
1306  }
1307  else
1308  {
1310  goto trace01;
1311  }
1312  }
1313  else
1314  s1 = pool_elt_at_index (nm->per_thread_data[thread_index].sessions,
1315  nat_value_get_session_index (&value1));
1316 
1317  b1->flags |= VNET_BUFFER_F_IS_NATED;
1318 
1319  old_addr1 = ip1->src_address.as_u32;
1320  ip1->src_address = s1->out2in.addr;
1321  new_addr1 = ip1->src_address.as_u32;
1322  if (!is_output_feature)
1323  vnet_buffer (b1)->sw_if_index[VLIB_TX] = s1->out2in.fib_index;
1324 
1325  sum1 = ip1->checksum;
1326  sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
1327  ip4_header_t, src_address /* changed member */ );
1328  ip1->checksum = ip_csum_fold (sum1);
1329 
1330  if (PREDICT_TRUE (proto1 == NAT_PROTOCOL_TCP))
1331  {
1332  if (!vnet_buffer (b1)->ip.reass.is_non_first_fragment)
1333  {
1334  old_port1 = vnet_buffer (b1)->ip.reass.l4_src_port;
1335  new_port1 = udp1->src_port = s1->out2in.port;
1336  sum1 = tcp1->checksum;
1337  sum1 = ip_csum_update (sum1, old_addr1, new_addr1,
1338  ip4_header_t,
1339  dst_address /* changed member */ );
1340  sum1 = ip_csum_update (sum1, old_port1, new_port1,
1341  ip4_header_t /* cheat */ ,
1342  length /* changed member */ );
1343  mss_clamping (nm->mss_clamping, tcp1, &sum1);
1344  tcp1->checksum = ip_csum_fold (sum1);
1345  }
1346  vlib_increment_simple_counter (is_slow_path ?
1347  &nm->counters.slowpath.in2out.tcp :
1348  &nm->counters.fastpath.in2out.tcp,
1349  thread_index, sw_if_index1, 1);
1350  }
1351  else
1352  {
1353  if (!vnet_buffer (b1)->ip.reass.is_non_first_fragment)
1354  {
1355  udp1->src_port = s1->out2in.port;
1356  if (PREDICT_FALSE (udp1->checksum))
1357  {
1358  old_port1 = vnet_buffer (b1)->ip.reass.l4_src_port;
1359  new_port1 = udp1->src_port;
1360  sum1 = udp1->checksum;
1361  sum1 = ip_csum_update (sum1, old_addr1, new_addr1, ip4_header_t, dst_address /* changed member */
1362  );
1363  sum1 =
1364  ip_csum_update (sum1, old_port1, new_port1,
1365  ip4_header_t /* cheat */ ,
1366  length /* changed member */ );
1367  udp1->checksum = ip_csum_fold (sum1);
1368  }
1369  }
1370  vlib_increment_simple_counter (is_slow_path ?
1371  &nm->counters.slowpath.in2out.udp :
1372  &nm->counters.fastpath.in2out.udp,
1373  thread_index, sw_if_index1, 1);
1374  }
1375 
1376  /* Accounting */
1378  s1, now, vlib_buffer_length_in_chain (vm, b1), thread_index);
1379  /* Per-user LRU list maintenance */
1380  nat44_ei_session_update_lru (nm, s1, thread_index);
1381  trace01:
1382 
1384  && (b1->flags & VLIB_BUFFER_IS_TRACED)))
1385  {
1387  vlib_add_trace (vm, node, b1, sizeof (*t));
1388  t->sw_if_index = sw_if_index1;
1389  t->next_index = next1;
1390  t->session_index = ~0;
1391  if (s1)
1393  }
1394 
1395  if (next1 == NAT44_EI_IN2OUT_NEXT_DROP)
1396  {
1398  is_slow_path ? &nm->counters.slowpath.in2out.drops :
1399  &nm->counters.fastpath.in2out.drops,
1400  thread_index, sw_if_index1, 1);
1401  }
1402 
1403  n_left_from -= 2;
1404  next[0] = next0;
1405  next[1] = next1;
1406  next += 2;
1407  }
1408 
1409  while (n_left_from > 0)
1410  {
1411  vlib_buffer_t *b0;
1412  u32 next0;
1413  u32 sw_if_index0;
1414  ip4_header_t *ip0;
1415  ip_csum_t sum0;
1416  u32 new_addr0, old_addr0;
1417  u16 old_port0, new_port0;
1418  udp_header_t *udp0;
1419  tcp_header_t *tcp0;
1420  icmp46_header_t *icmp0;
1421  u32 rx_fib_index0;
1422  u32 proto0;
1423  nat44_ei_session_t *s0 = 0;
1424  clib_bihash_kv_8_8_t kv0, value0;
1425  u32 iph_offset0 = 0;
1426 
1427  b0 = *b;
1428  b++;
1430 
1431  if (is_output_feature)
1432  iph_offset0 = vnet_buffer (b0)->ip.reass.save_rewrite_length;
1433 
1434  ip0 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b0) +
1435  iph_offset0);
1436 
1437  udp0 = ip4_next_header (ip0);
1438  tcp0 = (tcp_header_t *) udp0;
1439  icmp0 = (icmp46_header_t *) udp0;
1440 
1441  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1442  rx_fib_index0 =
1443  vec_elt (nm->ip4_main->fib_index_by_sw_if_index, sw_if_index0);
1444 
1445  if (PREDICT_FALSE (ip0->ttl == 1))
1446  {
1447  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1448  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1449  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1450  0);
1452  goto trace0;
1453  }
1454 
1455  proto0 = ip_proto_to_nat_proto (ip0->protocol);
1456 
1457  /* Next configured feature, probably ip4-lookup */
1458  if (is_slow_path)
1459  {
1460  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1461  {
1462  if (nat_in2out_sm_unknown_proto (nm, b0, ip0, rx_fib_index0))
1463  {
1464  next0 = NAT44_EI_IN2OUT_NEXT_DROP;
1465  b0->error =
1466  node->errors[NAT44_EI_IN2OUT_ERROR_UNSUPPORTED_PROTOCOL];
1467  }
1469  is_slow_path ? &nm->counters.slowpath.in2out.other :
1470  &nm->counters.fastpath.in2out.other,
1471  thread_index, sw_if_index0, 1);
1472  goto trace0;
1473  }
1474 
1475  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1476  {
1478  nm, b0, ip0, icmp0, sw_if_index0, rx_fib_index0, node, next0,
1479  now, thread_index, &s0);
1481  is_slow_path ? &nm->counters.slowpath.in2out.icmp :
1482  &nm->counters.fastpath.in2out.icmp,
1483  thread_index, sw_if_index0, 1);
1484  goto trace0;
1485  }
1486  }
1487  else
1488  {
1489  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1490  {
1492  goto trace0;
1493  }
1494 
1495  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1496  {
1498  goto trace0;
1499  }
1500  }
1501 
1502  init_nat_k (&kv0, ip0->src_address,
1503  vnet_buffer (b0)->ip.reass.l4_src_port, rx_fib_index0,
1504  proto0);
1505 
1506  if (clib_bihash_search_8_8 (&nm->in2out, &kv0, &value0))
1507  {
1508  if (is_slow_path)
1509  {
1510  if (is_output_feature)
1511  {
1513  nm, ip0, proto0,
1514  vnet_buffer (b0)->ip.reass.l4_src_port,
1515  vnet_buffer (b0)->ip.reass.l4_dst_port, thread_index,
1516  sw_if_index0)))
1517  goto trace0;
1518 
1519  /*
1520  * Send DHCP packets to the ipv4 stack, or we won't
1521  * be able to use dhcp client on the outside interface
1522  */
1523  if (PREDICT_FALSE
1524  (proto0 == NAT_PROTOCOL_UDP
1525  && (vnet_buffer (b0)->ip.reass.l4_dst_port ==
1526  clib_host_to_net_u16
1527  (UDP_DST_PORT_dhcp_to_server))
1528  && ip0->dst_address.as_u32 == 0xffffffff))
1529  goto trace0;
1530  }
1531  else
1532  {
1534  nm, node, sw_if_index0, ip0, proto0, rx_fib_index0,
1535  thread_index)))
1536  goto trace0;
1537  }
1538 
1539  next0 = slow_path (nm, b0, ip0, ip0->src_address,
1540  vnet_buffer (b0)->ip.reass.l4_src_port,
1541  rx_fib_index0, proto0, &s0, node, next0,
1542  thread_index, now);
1543 
1545  goto trace0;
1546 
1547  if (PREDICT_FALSE (!s0))
1548  goto trace0;
1549  }
1550  else
1551  {
1553  goto trace0;
1554  }
1555  }
1556  else
1557  s0 = pool_elt_at_index (nm->per_thread_data[thread_index].sessions,
1558  nat_value_get_session_index (&value0));
1559 
1560  b0->flags |= VNET_BUFFER_F_IS_NATED;
1561 
1562  old_addr0 = ip0->src_address.as_u32;
1563  ip0->src_address = s0->out2in.addr;
1564  new_addr0 = ip0->src_address.as_u32;
1565  if (!is_output_feature)
1566  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->out2in.fib_index;
1567 
1568  sum0 = ip0->checksum;
1569  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1570  ip4_header_t, src_address /* changed member */ );
1571  ip0->checksum = ip_csum_fold (sum0);
1572 
1573  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1574  {
1575  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1576  {
1577  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1578  new_port0 = udp0->src_port = s0->out2in.port;
1579  sum0 = tcp0->checksum;
1580  sum0 =
1581  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1582  dst_address /* changed member */ );
1583  sum0 =
1584  ip_csum_update (sum0, old_port0, new_port0,
1585  ip4_header_t /* cheat */ ,
1586  length /* changed member */ );
1587  mss_clamping (nm->mss_clamping, tcp0, &sum0);
1588  tcp0->checksum = ip_csum_fold (sum0);
1589  }
1590  vlib_increment_simple_counter (is_slow_path ?
1591  &nm->counters.slowpath.in2out.tcp :
1592  &nm->counters.fastpath.in2out.tcp,
1593  thread_index, sw_if_index0, 1);
1594  }
1595  else
1596  {
1597  if (!vnet_buffer (b0)->ip.reass.is_non_first_fragment)
1598  {
1599  udp0->src_port = s0->out2in.port;
1600  if (PREDICT_FALSE (udp0->checksum))
1601  {
1602  old_port0 = vnet_buffer (b0)->ip.reass.l4_src_port;
1603  new_port0 = udp0->src_port;
1604  sum0 = udp0->checksum;
1605  sum0 =
1606  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t,
1607  dst_address /* changed member */ );
1608  sum0 =
1609  ip_csum_update (sum0, old_port0, new_port0,
1610  ip4_header_t /* cheat */ ,
1611  length /* changed member */ );
1612  udp0->checksum = ip_csum_fold (sum0);
1613  }
1614  }
1615  vlib_increment_simple_counter (is_slow_path ?
1616  &nm->counters.slowpath.in2out.udp :
1617  &nm->counters.fastpath.in2out.udp,
1618  thread_index, sw_if_index0, 1);
1619  }
1620 
1621  /* Accounting */
1623  s0, now, vlib_buffer_length_in_chain (vm, b0), thread_index);
1624  /* Per-user LRU list maintenance */
1625  nat44_ei_session_update_lru (nm, s0, thread_index);
1626 
1627  trace0:
1629  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1630  {
1632  vlib_add_trace (vm, node, b0, sizeof (*t));
1633  t->is_slow_path = is_slow_path;
1634  t->sw_if_index = sw_if_index0;
1635  t->next_index = next0;
1636  t->session_index = ~0;
1637  if (s0)
1639  }
1640 
1641  if (next0 == NAT44_EI_IN2OUT_NEXT_DROP)
1642  {
1644  is_slow_path ? &nm->counters.slowpath.in2out.drops :
1645  &nm->counters.fastpath.in2out.drops,
1646  thread_index, sw_if_index0, 1);
1647  }
1648 
1649  n_left_from--;
1650  next[0] = next0;
1651  next++;
1652  }
1653 
1654  vlib_buffer_enqueue_to_next (vm, node, from, (u16 *) nexts,
1655  frame->n_vectors);
1656  return frame->n_vectors;
1657 }
1658 
1662  return nat44_ei_in2out_node_fn_inline (vm, node, frame, 0 /* is_slow_path */,
1663  0);
1664 }
1665 
1667  .name = "nat44-ei-in2out",
1668  .vector_size = sizeof (u32),
1669  .format_trace = format_nat44_ei_in2out_trace,
1671 
1673  .error_strings = nat44_ei_in2out_error_strings,
1674 
1675  .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
1676 
1677  .n_next_nodes = NAT44_EI_IN2OUT_N_NEXT,
1678 
1679  /* edit / add dispositions here */
1680  .next_nodes = {
1681  [NAT44_EI_IN2OUT_NEXT_DROP] = "error-drop",
1682  [NAT44_EI_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
1683  [NAT44_EI_IN2OUT_NEXT_SLOW_PATH] = "nat44-ei-in2out-slowpath",
1684  [NAT44_EI_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1685  [NAT44_EI_IN2OUT_NEXT_HAIRPINNING_HANDOFF] = "nat44-ei-in2out-hairpinning-handoff-ip4-lookup",
1686  },
1687 };
1688 
1691 {
1692  return nat44_ei_in2out_node_fn_inline (vm, node, frame, 0 /* is_slow_path */,
1693  1);
1694 }
1695 
1697  .name = "nat44-ei-in2out-output",
1698  .vector_size = sizeof (u32),
1699  .format_trace = format_nat44_ei_in2out_trace,
1701 
1703  .error_strings = nat44_ei_in2out_error_strings,
1704 
1705  .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
1706 
1707  .n_next_nodes = NAT44_EI_IN2OUT_N_NEXT,
1708 
1709  /* edit / add dispositions here */
1710  .next_nodes = {
1711  [NAT44_EI_IN2OUT_NEXT_DROP] = "error-drop",
1712  [NAT44_EI_IN2OUT_NEXT_LOOKUP] = "interface-output",
1713  [NAT44_EI_IN2OUT_NEXT_SLOW_PATH] = "nat44-ei-in2out-output-slowpath",
1714  [NAT44_EI_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1715  [NAT44_EI_IN2OUT_NEXT_HAIRPINNING_HANDOFF] = "nat44-ei-in2out-hairpinning-handoff-interface-output",
1716  },
1717 };
1718 
1721 {
1722  return nat44_ei_in2out_node_fn_inline (vm, node, frame, 1 /* is_slow_path */,
1723  0);
1724 }
1725 
1727  .name = "nat44-ei-in2out-slowpath",
1728  .vector_size = sizeof (u32),
1729  .format_trace = format_nat44_ei_in2out_trace,
1731 
1733  .error_strings = nat44_ei_in2out_error_strings,
1734 
1735  .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
1736 
1737  .n_next_nodes = NAT44_EI_IN2OUT_N_NEXT,
1738 
1739  /* edit / add dispositions here */
1740  .next_nodes = {
1741  [NAT44_EI_IN2OUT_NEXT_DROP] = "error-drop",
1742  [NAT44_EI_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
1743  [NAT44_EI_IN2OUT_NEXT_SLOW_PATH] = "nat44-ei-in2out-slowpath",
1744  [NAT44_EI_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1745  [NAT44_EI_IN2OUT_NEXT_HAIRPINNING_HANDOFF] = "nat44-ei-in2out-hairpinning-handoff-ip4-lookup",
1746  },
1747 };
1748 
1751 {
1752  return nat44_ei_in2out_node_fn_inline (vm, node, frame, 1 /* is_slow_path */,
1753  1);
1754 }
1755 
1757  .name = "nat44-ei-in2out-output-slowpath",
1758  .vector_size = sizeof (u32),
1759  .format_trace = format_nat44_ei_in2out_trace,
1761 
1763  .error_strings = nat44_ei_in2out_error_strings,
1764 
1765  .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
1766 
1767  .n_next_nodes = NAT44_EI_IN2OUT_N_NEXT,
1768 
1769  /* edit / add dispositions here */
1770  .next_nodes = {
1771  [NAT44_EI_IN2OUT_NEXT_DROP] = "error-drop",
1772  [NAT44_EI_IN2OUT_NEXT_LOOKUP] = "interface-output",
1773  [NAT44_EI_IN2OUT_NEXT_SLOW_PATH] = "nat44-ei-in2out-output-slowpath",
1774  [NAT44_EI_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1775  [NAT44_EI_IN2OUT_NEXT_HAIRPINNING_HANDOFF] = "nat44-ei-in2out-hairpinning-handoff-interface-output",
1776  },
1777 };
1778 
1781 {
1782  u32 n_left_from, *from, *to_next;
1787 
1789  n_left_from = frame->n_vectors;
1790  next_index = node->cached_next_index;
1791 
1792  while (n_left_from > 0)
1793  {
1794  u32 n_left_to_next;
1795 
1796  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1797 
1798  while (n_left_from > 0 && n_left_to_next > 0)
1799  {
1800  u32 bi0;
1801  vlib_buffer_t *b0;
1802  u32 next0;
1803  u32 sw_if_index0;
1804  ip4_header_t *ip0;
1805  ip_csum_t sum0;
1806  u32 new_addr0, old_addr0;
1807  u16 old_port0, new_port0;
1808  udp_header_t *udp0;
1809  tcp_header_t *tcp0;
1810  icmp46_header_t *icmp0;
1811  u32 proto0;
1812  u32 rx_fib_index0;
1813  ip4_address_t sm0_addr;
1814  u16 sm0_port;
1815  u32 sm0_fib_index;
1816  u32 required_thread_index = thread_index;
1817 
1818  /* speculatively enqueue b0 to the current next frame */
1819  bi0 = from[0];
1820  to_next[0] = bi0;
1821  from += 1;
1822  to_next += 1;
1823  n_left_from -= 1;
1824  n_left_to_next -= 1;
1825 
1826  b0 = vlib_get_buffer (vm, bi0);
1828 
1829  ip0 = vlib_buffer_get_current (b0);
1830  udp0 = ip4_next_header (ip0);
1831  tcp0 = (tcp_header_t *) udp0;
1832  icmp0 = (icmp46_header_t *) udp0;
1833 
1834  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
1835  rx_fib_index0 =
1837 
1838  if (PREDICT_FALSE (ip0->ttl == 1))
1839  {
1840  vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1841  icmp4_error_set_vnet_buffer (b0, ICMP4_time_exceeded,
1842  ICMP4_time_exceeded_ttl_exceeded_in_transit,
1843  0);
1845  goto trace0;
1846  }
1847 
1848  proto0 = ip_proto_to_nat_proto (ip0->protocol);
1849 
1850  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_OTHER))
1851  goto trace0;
1852 
1853  if (PREDICT_FALSE (proto0 == NAT_PROTOCOL_ICMP))
1854  {
1855  next0 = nat44_ei_icmp_in2out (b0, ip0, icmp0, sw_if_index0,
1856  rx_fib_index0, node, next0, ~0, 0);
1857  goto trace0;
1858  }
1859 
1861  ip0->src_address, udp0->src_port, rx_fib_index0, proto0,
1862  &sm0_addr, &sm0_port, &sm0_fib_index, 0, 0, 0))
1863  {
1864  b0->error = node->errors[NAT44_EI_IN2OUT_ERROR_NO_TRANSLATION];
1865  next0 = NAT44_EI_IN2OUT_NEXT_DROP;
1866  goto trace0;
1867  }
1868 
1869  new_addr0 = sm0_addr.as_u32;
1870  new_port0 = sm0_port;
1871  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sm0_fib_index;
1872  old_addr0 = ip0->src_address.as_u32;
1873  ip0->src_address.as_u32 = new_addr0;
1874 
1875  sum0 = ip0->checksum;
1876  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1877  ip4_header_t,
1878  src_address /* changed member */ );
1879  ip0->checksum = ip_csum_fold (sum0);
1880 
1881  if (PREDICT_FALSE (new_port0 != udp0->dst_port))
1882  {
1883  old_port0 = udp0->src_port;
1884  udp0->src_port = new_port0;
1885 
1886  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1887  {
1888  sum0 = tcp0->checksum;
1889  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1890  ip4_header_t,
1891  dst_address /* changed member */ );
1892  sum0 = ip_csum_update (sum0, old_port0, new_port0,
1893  ip4_header_t /* cheat */ ,
1894  length /* changed member */ );
1895  mss_clamping (nm->mss_clamping, tcp0, &sum0);
1896  tcp0->checksum = ip_csum_fold (sum0);
1897  }
1898  else if (udp0->checksum)
1899  {
1900  sum0 = udp0->checksum;
1901  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1902  ip4_header_t,
1903  dst_address /* changed member */ );
1904  sum0 = ip_csum_update (sum0, old_port0, new_port0,
1905  ip4_header_t /* cheat */ ,
1906  length /* changed member */ );
1907  udp0->checksum = ip_csum_fold (sum0);
1908  }
1909  }
1910  else
1911  {
1912  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
1913  {
1914  sum0 = tcp0->checksum;
1915  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1916  ip4_header_t,
1917  dst_address /* changed member */ );
1918  mss_clamping (nm->mss_clamping, tcp0, &sum0);
1919  tcp0->checksum = ip_csum_fold (sum0);
1920  }
1921  else if (udp0->checksum)
1922  {
1923  sum0 = udp0->checksum;
1924  sum0 = ip_csum_update (sum0, old_addr0, new_addr0,
1925  ip4_header_t,
1926  dst_address /* changed member */ );
1927  udp0->checksum = ip_csum_fold (sum0);
1928  }
1929  }
1930 
1931  /* Hairpinning */
1932  is_hairpinning = nat44_ei_hairpinning (
1933  vm, node, nm, thread_index, b0, ip0, udp0, tcp0, proto0,
1934  0 /* do_trace */, &required_thread_index);
1935 
1936  if (thread_index != required_thread_index)
1937  {
1938  vnet_buffer (b0)->snat.required_thread_index =
1939  required_thread_index;
1941  }
1942 
1943  trace0:
1945  && (b0->flags & VLIB_BUFFER_IS_TRACED)))
1946  {
1948  vlib_add_trace (vm, node, b0, sizeof (*t));
1949  t->sw_if_index = sw_if_index0;
1950  t->next_index = next0;
1952  }
1953 
1954  if (next0 != NAT44_EI_IN2OUT_NEXT_DROP)
1955  {
1956 
1958  &nm->counters.fastpath.in2out.other, sw_if_index0,
1959  vm->thread_index, 1);
1960  }
1961 
1962  /* verify speculative enqueue, maybe switch current next frame */
1963  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1964  to_next, n_left_to_next,
1965  bi0, next0);
1966  }
1967 
1968  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1969  }
1970 
1971  return frame->n_vectors;
1972 }
1973 
1975  .name = "nat44-ei-in2out-fast",
1976  .vector_size = sizeof (u32),
1977  .format_trace = format_nat44_ei_in2out_fast_trace,
1979 
1981  .error_strings = nat44_ei_in2out_error_strings,
1982 
1983  .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
1984 
1985  .n_next_nodes = NAT44_EI_IN2OUT_N_NEXT,
1986 
1987  /* edit / add dispositions here */
1988  .next_nodes = {
1989  [NAT44_EI_IN2OUT_NEXT_DROP] = "error-drop",
1990  [NAT44_EI_IN2OUT_NEXT_LOOKUP] = "ip4-lookup",
1991  [NAT44_EI_IN2OUT_NEXT_SLOW_PATH] = "nat44-ei-in2out-slowpath",
1992  [NAT44_EI_IN2OUT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
1993  [NAT44_EI_IN2OUT_NEXT_HAIRPINNING_HANDOFF] = "nat44-ei-in2out-hairpinning-handoff-ip4-lookup",
1994  },
1995 };
1996 
1999 {
2001  vm, node, frame,
2003 }
2004 
2006  .name = "nat44-ei-in2out-hairpinning-handoff-ip4-lookup",
2007  .vector_size = sizeof (u32),
2011 
2012  .n_next_nodes = 1,
2013 
2014  .next_nodes = {
2015  [0] = "error-drop",
2016  },
2017 };
2018 
2021 {
2023  vm, node, frame,
2025 }
2026 
2028  .name = "nat44-ei-in2out-hairpinning-handoff-interface-output",
2029  .vector_size = sizeof (u32),
2033 
2034  .n_next_nodes = 1,
2035 
2036  .next_nodes = {
2037  [0] = "error-drop",
2038  },
2039 };
2040 
2043  vlib_node_runtime_t *node,
2045 {
2046  u32 n_left_from, *from, *to_next;
2047  u32 thread_index = vm->thread_index;
2050  int is_hairpinning = 0;
2051 
2052  from = vlib_frame_vector_args (frame);
2053  n_left_from = frame->n_vectors;
2054  next_index = node->cached_next_index;
2055 
2056  while (n_left_from > 0)
2057  {
2058  u32 n_left_to_next;
2059 
2060  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2061 
2062  while (n_left_from > 0 && n_left_to_next > 0)
2063  {
2064  u32 bi0;
2065  vlib_buffer_t *b0;
2066  u32 next0;
2067  u32 sw_if_index0;
2068  ip4_header_t *ip0;
2069  udp_header_t *udp0;
2070  tcp_header_t *tcp0;
2071  icmp46_header_t *icmp0;
2072  u32 proto0;
2073  u32 required_thread_index = thread_index;
2074 
2075  /* speculatively enqueue b0 to the current next frame */
2076  bi0 = from[0];
2077  to_next[0] = bi0;
2078  from += 1;
2079  to_next += 1;
2080  n_left_from -= 1;
2081  n_left_to_next -= 1;
2082 
2083  b0 = vlib_get_buffer (vm, bi0);
2085 
2086  ip0 = vlib_buffer_get_current (b0);
2087  udp0 = ip4_next_header (ip0);
2088  tcp0 = (tcp_header_t *) udp0;
2089  icmp0 = (icmp46_header_t *) udp0;
2090 
2091  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
2092  proto0 = ip_proto_to_nat_proto (ip0->protocol);
2093 
2094  switch (proto0)
2095  {
2096  case NAT_PROTOCOL_TCP:
2097  // fallthrough
2098  case NAT_PROTOCOL_UDP:
2099  is_hairpinning = nat44_ei_hairpinning (
2100  vm, node, nm, thread_index, b0, ip0, udp0, tcp0, proto0,
2101  0 /* do_trace */, &required_thread_index);
2102  break;
2103  case NAT_PROTOCOL_ICMP:
2104  is_hairpinning = (0 == nat44_ei_icmp_hairpinning (
2105  nm, b0, thread_index, ip0, icmp0,
2106  &required_thread_index));
2107  break;
2108  case NAT_PROTOCOL_OTHER:
2109  // this should never happen
2111  break;
2112  }
2113 
2114  if (thread_index != required_thread_index)
2115  {
2116  // but we already did a handoff ...
2118  }
2119 
2120  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
2121  (b0->flags & VLIB_BUFFER_IS_TRACED)))
2122  {
2124  vlib_add_trace (vm, node, b0, sizeof (*t));
2125  t->sw_if_index = sw_if_index0;
2126  t->next_index = next0;
2128  }
2129 
2131  {
2133  &nm->counters.fastpath.in2out.other, sw_if_index0,
2134  vm->thread_index, 1);
2135  }
2136 
2137  /* verify speculative enqueue, maybe switch current next frame */
2138  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2139  n_left_to_next, bi0, next0);
2140  }
2141 
2142  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2143  }
2144 
2145  return frame->n_vectors;
2146 }
2147 
2150 {
2152 }
2153 
2155  .name = "nat44-ei-in2out-hairpinning-finish-ip4-lookup",
2156  .vector_size = sizeof (u32),
2157  .format_trace = format_nat44_ei_in2out_fast_trace,
2159 
2161  .error_strings = nat44_ei_in2out_error_strings,
2162 
2163  .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
2164 
2166 
2167  /* edit / add dispositions here */
2168  .next_nodes = {
2171  },
2172 };
2173 
2176 {
2178 }
2179 
2181  .name = "nat44-ei-in2out-hairpinning-finish-interface-output",
2182  .vector_size = sizeof (u32),
2183  .format_trace = format_nat44_ei_in2out_fast_trace,
2185 
2187  .error_strings = nat44_ei_in2out_error_strings,
2188 
2189  .runtime_data_bytes = sizeof (nat44_ei_runtime_t),
2190 
2192 
2193  /* edit / add dispositions here */
2194  .next_nodes = {
2196  [NAT44_EI_IN2OUT_HAIRPINNING_FINISH_NEXT_LOOKUP] = "interface-output",
2197  },
2198 };
2199 
2200 /*
2201  * fd.io coding-style-patch-verification: ON
2202  *
2203  * Local Variables:
2204  * eval: (c-set-style "gnu")
2205  * End:
2206  */
static void mss_clamping(u16 mss_clamping, tcp_header_t *tcp, ip_csum_t *sum)
Definition: nat_inlines.h:32
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
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
static ip_csum_t ip_incremental_checksum_buffer(vlib_main_t *vm, vlib_buffer_t *first_buffer, u32 first_buffer_offset, u32 n_bytes_to_checksum, ip_csum_t sum)
Definition: ip.h:152
static u8 * format_nat44_ei_in2out_trace(u8 *s, va_list *args)
static void nat44_ei_delete_user_with_no_session(nat44_ei_main_t *nm, nat44_ei_user_t *u, u32 thread_index)
int nat44_o2i_is_idle_session_cb(clib_bihash_kv_8_8_t *kv, void *arg)
#define CLIB_UNUSED(x)
Definition: clib.h:90
u16 port_per_thread
Definition: nat44_ei.h:359
struct nat44_ei_main_s::@81::@82 fastpath
vlib_node_registration_t nat44_ei_in2out_fast_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_fast_node)
#define ntohs(x)
Definition: af_xdp.bpf.c:29
ip4_address_t src_address
Definition: ip4_packet.h:125
vlib_node_registration_t nat44_ei_in2out_hairpinning_finish_ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_hairpinning_finish_ip4_lookup_node) ...
static int nat44_ei_not_translate_output_feature(nat44_ei_main_t *nm, ip4_header_t *ip0, u32 proto0, u16 src_port, u16 dst_port, u32 thread_index, u32 sw_if_index)
static char * nat44_ei_in2out_error_strings[]
nat44_ei_interface_t * interfaces
Definition: nat44_ei.h:339
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
int nat44_i2o_is_idle_session_cb(clib_bihash_kv_8_8_t *kv, void *arg)
#define PREDICT_TRUE(x)
Definition: clib.h:125
int nat44_ei_hairpinning(vlib_main_t *vm, vlib_node_runtime_t *node, nat44_ei_main_t *nm, u32 thread_index, vlib_buffer_t *b0, ip4_header_t *ip0, udp_header_t *udp0, tcp_header_t *tcp0, u32 proto0, int do_trace, u32 *required_thread_index)
unsigned long u64
Definition: types.h:89
vl_api_ip_port_and_mask_t dst_port
Definition: flow_types.api:92
u16 nexts[VLIB_FRAME_SIZE]
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:325
u32 nat44_ei_icmp_match_in2out_fast(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, nat44_ei_session_t **s0, u8 *dont_translate)
u32 outside_fib_index
Definition: nat44_ei.h:353
static uword nat44_ei_hairpinning_handoff_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 fq_index)
static int nat44_ei_not_translate(nat44_ei_main_t *nm, vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0, u32 thread_index)
u32 thread_index
Definition: main.h:213
NAT44 endpoint independent plugin declarations.
nat44_ei_session_t * sessions
Definition: nat44_ei.h:283
static void init_nat_i2o_kv(clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s, u32 thread_index, u32 session_index)
nat44_ei_in2out_hairpinnig_finish_next_t
uword ip_csum_t
Definition: ip_packet.h:245
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:123
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
Definition: counter.h:74
static u32 nat_value_get_thread_index(clib_bihash_kv_8_8_t *value)
nat_protocol_t
Definition: lib.h:63
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
#define VLIB_NODE_FN(node)
Definition: node.h:202
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:461
int is_hairpinning
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:433
static u8 * format_nat44_ei_in2out_fast_trace(u8 *s, va_list *args)
struct _tcp_header tcp_header_t
vhost_vring_addr_t addr
Definition: vhost_user.h:130
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
n_left_from
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: cnat_node.h:109
nat44_ei_static_mapping_t * static_mappings
Definition: nat44_ei.h:336
double f64
Definition: types.h:142
static int ip4_is_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:168
unsigned int u32
Definition: types.h:88
static void init_nat_o2i_kv(clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s, u32 thread_index, u32 session_index)
vlib_node_registration_t nat44_ei_in2out_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_slowpath_node)
#define static_always_inline
Definition: clib.h:112
static void nat44_ei_user_session_increment(nat44_ei_main_t *nm, nat44_ei_user_t *u, u8 is_static)
static uword ip4_header_checksum_is_valid(ip4_header_t *i)
Definition: ip4_packet.h:396
static_always_inline u8 nat44_ei_maximum_sessions_exceeded(nat44_ei_main_t *nm, u32 thread_index)
nat44_ei_main_per_thread_data_t * tnm
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:24
void nat_syslog_nat44_apmdel(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *xsaddr, u16 xsport, nat_protocol_t proto)
Definition: nat_syslog.c:116
nat44_ei_address_t * addresses
Definition: nat44_ei.h:369
vlib_node_registration_t nat44_ei_in2out_hairpinning_handoff_interface_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_hairpinning_handoff_interface_output_node) ...
vlib_get_buffers(vm, from, b, n_left_from)
nat44_ei_in2out_next_t
ip4_address_t dst_address
Definition: ip4_packet.h:125
u32 thread_index
description fragment has unexpected format
Definition: map.api:433
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
#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:202
#define nat_elog_warn(_pm, nat_elog_str)
Definition: log.h:177
u32 nat44_ei_icmp_hairpinning(nat44_ei_main_t *nm, vlib_buffer_t *b0, u32 thread_index, ip4_header_t *ip0, icmp46_header_t *icmp0, u32 *required_thread_index)
static u32 nat_value_get_session_index(clib_bihash_kv_8_8_t *value)
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
struct nat44_ei_main_s::@81::@83 slowpath
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
#define nat44_ei_is_session_static(sp)
Definition: nat44_ei.h:666
struct nat44_ei_main_s::@81 counters
static_always_inline u32 nat_session_get_timeout(nat_timeouts_t *timeouts, nat_protocol_t proto, u8 state)
Definition: lib.h:99
static_always_inline nat44_ei_in2out_error_t icmp_get_key(vlib_buffer_t *b, ip4_header_t *ip0, ip4_address_t *addr, u16 *port, nat_protocol_t *nat_proto)
#define VLIB_FRAME_SIZE
Definition: node.h:369
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
vl_api_fib_path_type_t type
Definition: fib_types.api:123
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:145
#define NAT44_EI_SESSION_FLAG_STATIC_MAPPING
Definition: nat44_ei.h:60
u16 * next
void nat_syslog_nat44_apmadd(u32 ssubix, u32 sfibix, ip4_address_t *isaddr, u16 isport, ip4_address_t *xsaddr, u16 xsport, nat_protocol_t proto)
Definition: nat_syslog.c:107
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
static_always_inline u32 nat44_ei_icmp_in2out_slow_path(nat44_ei_main_t *nm, 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, f64 now, u32 thread_index, nat44_ei_session_t **p_s0)
vl_api_ip_proto_t proto
Definition: acl_types.api:51
vlib_node_registration_t nat44_ei_in2out_hairpinning_handoff_ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_hairpinning_handoff_ip4_lookup_node) ...
long ctx[MAX_CONNS]
Definition: main.c:144
nat44_ei_interface_t * output_feature_interfaces
Definition: nat44_ei.h:340
vlib_node_registration_t nat44_ei_in2out_output_slowpath_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_output_slowpath_node)
void nat44_ei_free_outside_address_and_port(nat44_ei_address_t *addresses, u32 thread_index, ip4_address_t *addr, u16 port, nat_protocol_t protocol)
Definition: nat44_ei.c:1043
unsigned short u16
Definition: types.h:57
nat44_ei_main_t * nm
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
#define PREDICT_FALSE(x)
Definition: clib.h:124
vl_api_address_union_t src_address
Definition: ip_types.api:122
#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:224
#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:395
static u8 * format_nat44_ei_hairpinning_handoff_trace(u8 *s, va_list *args)
static char * nat44_ei_hairpinning_handoff_error_strings[]
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1474
clib_bihash_8_8_t static_mapping_by_local
Definition: nat44_ei.h:330
static int nat_in2out_sm_unknown_proto(nat44_ei_main_t *nm, vlib_buffer_t *b, ip4_header_t *ip, u32 rx_fib_index)
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
u64 value
the value
Definition: bihash_8_8.h:44
vlib_node_registration_t nat44_ei_in2out_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_node)
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
nat44_ei_main_per_thread_data_t * per_thread_data
Definition: nat44_ei.h:366
u16 n_vectors
Definition: node.h:388
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:80
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
vlib_main_t * vm
u8 data[]
Packet data.
Definition: buffer.h:204
void nat_ipfix_logging_nat44_ses_create(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 fib_index)
Generate NAT44 session create event.
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
u32 in2out_hairpinning_finish_interface_output_node_fq_index
Definition: nat44_ei.h:475
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
#define ARRAY_LEN(x)
Definition: clib.h:70
static u8 nat44_ei_is_interface_addr(ip4_main_t *im, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr)
u32 nat44_ei_icmp_match_in2out_slow(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, nat44_ei_session_t **p_s0, u8 *dont_translate)
Get address and port values to be used for ICMP packet translation and create session if needed...
static int nat44_ei_not_translate_fast(vlib_node_runtime_t *node, u32 sw_if_index0, ip4_header_t *ip0, u32 proto0, u32 rx_fib_index0)
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:498
u8 value
Definition: qos.api:54
#define ASSERT(truth)
nat_timeouts_t timeouts
Definition: nat44_ei.h:405
u32 in2out_hairpinning_finish_ip4_lookup_node_fq_index
Definition: nat44_ei.h:474
ip4_main_t * ip4_main
Definition: nat44_ei.h:456
clib_bihash_8_8_t out2in
Definition: nat44_ei.h:362
nat44_ei_in2out_next_t next_index
ip4_address_t external_addr
Definition: nat44_ei.h:168
vlib_put_next_frame(vm, node, next_index, 0)
char const int length
Definition: cJSON.h:163
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:38
void nat_ipfix_logging_max_sessions(u32 thread_index, u32 limit)
Generate maximum session entries exceeded event.
#define vec_elt(v, i)
Get vector value at index i.
void nat44_ei_delete_session(nat44_ei_main_t *nm, nat44_ei_session_t *ses, u32 thread_index)
Definition: nat44_ei.c:1753
static void nat44_ei_session_update_counters(nat44_ei_session_t *s, f64 now, uword bytes, u32 thread_index)
vlib_node_registration_t nat44_ei_in2out_hairpinning_finish_interface_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_hairpinning_finish_interface_output_node) ...
Definition: defs.h:47
void nat_ha_sadd(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index, u8 is_resync)
Create session add HA event.
Definition: nat44_ei_ha.c:834
static_always_inline int nat44_ei_in2out_hairpinning_finish_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
vl_api_address_t ip
Definition: l2.api:558
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:30
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void nat44_ei_session_update_lru(nat44_ei_main_t *nm, nat44_ei_session_t *s, u32 thread_index)
Per-user LRU list maintenance.
VLIB buffer representation.
Definition: buffer.h:111
nat44_ei_outside_fib_t * outside_fibs
Definition: nat44_ei.h:386
u64 uword
Definition: types.h:112
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:295
nat44_ei_main_t nat44_ei_main
Definition: nat44_ei.c:40
NAT syslog logging.
static void init_nat_o2i_k(clib_bihash_kv_8_8_t *kv, nat44_ei_session_t *s)
u16 port
Definition: lb_types.api:73
nat44_ei_session_t * nat44_ei_session_alloc_or_recycle(nat44_ei_main_t *nm, nat44_ei_user_t *u, u32 thread_index, f64 now)
Definition: nat44_ei.c:1180
#define vnet_buffer(b)
Definition: buffer.h:437
NAT port/address allocation lib.
clib_bihash_8_8_t in2out
Definition: nat44_ei.h:363
f64 now
#define vec_foreach(var, vec)
Vector iterator.
#define nat_elog_notice(_pm, nat_elog_str)
Definition: log.h:175
nat44_ei_in2out_error_t
u16 flags
Copy of main node flags.
Definition: node.h:492
void nat_ha_sdel(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 session_thread_index)
Create session delete HA event.
Definition: nat44_ei_ha.c:860
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 int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:190
nat44_ei_alloc_out_addr_and_port_function_t * alloc_addr_and_port
Definition: nat44_ei.h:371
static u32 slow_path(nat44_ei_main_t *nm, vlib_buffer_t *b0, ip4_header_t *ip0, ip4_address_t i2o_addr, u16 i2o_port, u32 rx_fib_index0, nat_protocol_t nat_proto, nat44_ei_session_t **sessionp, vlib_node_runtime_t *node, u32 next0, u32 thread_index, f64 now)
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:292
void nat44_ei_hairpinning_sm_unknown_proto(nat44_ei_main_t *nm, vlib_buffer_t *b, ip4_header_t *ip)
vlib_main_t vlib_node_runtime_t * node
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static uword nat44_ei_in2out_node_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_slow_path, int is_output_feature)
u32 max_translations_per_thread
Definition: nat44_ei.h:346
int nat44_ei_static_mapping_match(ip4_address_t match_addr, u16 match_port, u32 match_fib_index, nat_protocol_t match_protocol, ip4_address_t *mapping_addr, u16 *mapping_port, u32 *mapping_fib_index, u8 by_external, u8 *is_addr_only, u8 *is_identity_nat)
Match NAT44-EI static mapping.
Definition: nat44_ei.c:2253
u8 forwarding_enabled
Definition: nat44_ei.h:323
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
#define nat44_ei_interface_is_inside(ip)
Definition: nat44_ei.h:671
vlib_node_registration_t nat44_ei_in2out_output_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_in2out_output_node)
u32 nat44_ei_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, nat44_ei_session_t **p_s0)
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)
static_always_inline void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.h:51
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
Definition: defs.h:46
nat44_ei_user_t * nat44_ei_user_get_or_create(nat44_ei_main_t *nm, ip4_address_t *addr, u32 fib_index, u32 thread_index)
Definition: nat44_ei.c:1121
#define nat44_ei_interface_is_outside(ip)
Definition: nat44_ei.h:673
#define foreach_nat44_ei_in2out_error
void nat_ipfix_logging_nat44_ses_delete(u32 thread_index, u32 src_ip, u32 nat_src_ip, nat_protocol_t nat_proto, u16 src_port, u16 nat_src_port, u32 fib_index)
Generate NAT44 session delete event.