FD.io VPP  v21.06
Vector Packet Processing
nat44_ei_hairpinning.c
Go to the documentation of this file.
1 /*
2  * nat44_ei.c - nat44 endpoint dependent plugin
3  * * Copyright (c) 2020 Cisco and/or its affiliates. * Licensed under the
4  * Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License
6  * at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16 
17 #include <vlib/vlib.h>
18 #include <vnet/vnet.h>
19 #include <vnet/fib/ip4_fib.h>
20 
21 #include <nat/nat44-ei/nat44_ei.h>
24 
25 /* NAT buffer flags */
26 #define NAT44_EI_FLAG_HAIRPINNING (1 << 0)
27 
28 typedef enum
29 {
36 
37 typedef enum
38 {
44 
45 typedef struct
46 {
52 
53 static u8 *
54 format_nat44_ei_hairpin_trace (u8 *s, va_list *args)
55 {
56  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
57  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
59 
60  s = format (s, "new dst addr %U port %u fib-index %u", format_ip4_address,
61  &t->addr, clib_net_to_host_u16 (t->port), t->fib_index);
62  if (~0 == t->session_index)
63  {
64  s = format (s, " is-static-mapping");
65  }
66  else
67  {
68  s = format (s, " session-index %u", t->session_index);
69  }
70 
71  return s;
72 }
73 
75 
78 {
81 
82  vec_foreach (ap, nm->addresses)
83  {
84  if (ap->addr.as_u32 == dst_addr->as_u32)
85  return 1;
86  }
87 
88  init_nat_k (&kv, *dst_addr, 0, 0, 0);
89  if (!clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
90  return 1;
91 
92  return 0;
93 }
94 
95 #ifndef CLIB_MARCH_VARIANT
96 void
98  ip4_header_t *ip)
99 {
102  u32 old_addr, new_addr;
103  ip_csum_t sum;
104 
105  init_nat_k (&kv, ip->dst_address, 0, 0, 0);
106  if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
107  return;
108 
109  m = pool_elt_at_index (nm->static_mappings, value.value);
110 
111  old_addr = ip->dst_address.as_u32;
112  new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
113  sum = ip->checksum;
114  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
115  ip->checksum = ip_csum_fold (sum);
116 
117  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
118  vnet_buffer (b)->sw_if_index[VLIB_TX] = m->fib_index;
119 }
120 #endif
121 
122 #ifndef CLIB_MARCH_VARIANT
123 int
125  nat44_ei_main_t *nm, u32 thread_index, vlib_buffer_t *b0,
126  ip4_header_t *ip0, udp_header_t *udp0,
127  tcp_header_t *tcp0, u32 proto0, int do_trace,
128  u32 *required_thread_index)
129 {
130  nat44_ei_session_t *s0 = NULL;
131  clib_bihash_kv_8_8_t kv0, value0;
132  ip_csum_t sum0;
133  u32 new_dst_addr0 = 0, old_dst_addr0, si = ~0;
134  u16 new_dst_port0 = ~0, old_dst_port0;
135  int rv;
136  ip4_address_t sm0_addr;
137  u16 sm0_port;
138  u32 sm0_fib_index;
139  u32 old_sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
140 
141  /* Check if destination is static mappings */
143  ip0->dst_address, udp0->dst_port, nm->outside_fib_index, proto0,
144  &sm0_addr, &sm0_port, &sm0_fib_index, 1 /* by external */, 0, 0))
145  {
146  new_dst_addr0 = sm0_addr.as_u32;
147  new_dst_port0 = sm0_port;
148  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sm0_fib_index;
149  }
150  /* or active session */
151  else
152  {
153  init_nat_k (&kv0, ip0->dst_address, udp0->dst_port,
154  nm->outside_fib_index, proto0);
155  rv = clib_bihash_search_8_8 (&nm->out2in, &kv0, &value0);
156  if (rv)
157  {
158  rv = 0;
159  goto trace;
160  }
161 
162  if (thread_index != nat_value_get_thread_index (&value0))
163  {
164  *required_thread_index = nat_value_get_thread_index (&value0);
165  return 0;
166  }
167 
168  si = nat_value_get_session_index (&value0);
169  s0 = pool_elt_at_index (nm->per_thread_data[thread_index].sessions, si);
170  new_dst_addr0 = s0->in2out.addr.as_u32;
171  new_dst_port0 = s0->in2out.port;
172  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
173  }
174 
175  /* Check if anything has changed and if not, then return 0. This
176  helps avoid infinite loop, repeating the three nodes
177  nat44-hairpinning-->ip4-lookup-->ip4-local, in case nothing has
178  changed. */
179  old_dst_addr0 = ip0->dst_address.as_u32;
180  old_dst_port0 = tcp0->dst;
181  if (new_dst_addr0 == old_dst_addr0 && new_dst_port0 == old_dst_port0 &&
182  vnet_buffer (b0)->sw_if_index[VLIB_TX] == old_sw_if_index)
183  return 0;
184 
185  /* Destination is behind the same NAT, use internal address and port */
186  if (new_dst_addr0)
187  {
188  old_dst_addr0 = ip0->dst_address.as_u32;
189  ip0->dst_address.as_u32 = new_dst_addr0;
190  sum0 = ip0->checksum;
191  sum0 = ip_csum_update (sum0, old_dst_addr0, new_dst_addr0, ip4_header_t,
192  dst_address);
193  ip0->checksum = ip_csum_fold (sum0);
194 
195  old_dst_port0 = tcp0->dst;
196  if (PREDICT_TRUE (new_dst_port0 != old_dst_port0))
197  {
198  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
199  {
200  tcp0->dst = new_dst_port0;
201  sum0 = tcp0->checksum;
202  sum0 = ip_csum_update (sum0, old_dst_addr0, new_dst_addr0,
203  ip4_header_t, dst_address);
204  sum0 = ip_csum_update (sum0, old_dst_port0, new_dst_port0,
205  ip4_header_t /* cheat */, length);
206  tcp0->checksum = ip_csum_fold (sum0);
207  }
208  else
209  {
210  udp0->dst_port = new_dst_port0;
211  udp0->checksum = 0;
212  }
213  }
214  else
215  {
216  if (PREDICT_TRUE (proto0 == NAT_PROTOCOL_TCP))
217  {
218  sum0 = tcp0->checksum;
219  sum0 = ip_csum_update (sum0, old_dst_addr0, new_dst_addr0,
220  ip4_header_t, dst_address);
221  tcp0->checksum = ip_csum_fold (sum0);
222  }
223  }
224  rv = 1;
225  goto trace;
226  }
227  rv = 0;
228 trace:
229  if (do_trace && PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
230  (b0->flags & VLIB_BUFFER_IS_TRACED)))
231  {
232  nat44_ei_hairpin_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t));
233  t->addr.as_u32 = new_dst_addr0;
234  t->port = new_dst_port0;
235  t->fib_index = vnet_buffer (b0)->sw_if_index[VLIB_TX];
236  if (s0)
237  {
238  t->session_index = si;
239  }
240  else
241  {
242  t->session_index = ~0;
243  }
244  }
245  return rv;
246 }
247 #endif
248 
249 #ifndef CLIB_MARCH_VARIANT
250 u32
252  u32 thread_index, ip4_header_t *ip0,
253  icmp46_header_t *icmp0, u32 *required_thread_index)
254 {
255  clib_bihash_kv_8_8_t kv0, value0;
256  u32 old_dst_addr0, new_dst_addr0;
257  u32 old_addr0, new_addr0;
258  u16 old_port0, new_port0;
259  u16 old_checksum0, new_checksum0;
260  u32 si, ti = 0;
261  ip_csum_t sum0;
262  nat44_ei_session_t *s0;
264 
266  vnet_buffer (b0)->ip.reass.icmp_type_or_tcp_flags))
267  {
268  ip4_header_t *inner_ip0 = 0;
269  tcp_udp_header_t *l4_header = 0;
270 
271  inner_ip0 = (ip4_header_t *) ((icmp_echo_header_t *) (icmp0 + 1) + 1);
272  l4_header = ip4_next_header (inner_ip0);
274 
275  if (protocol != NAT_PROTOCOL_TCP && protocol != NAT_PROTOCOL_UDP)
276  return 1;
277 
278  init_nat_k (&kv0, ip0->dst_address, l4_header->src_port,
279  nm->outside_fib_index, protocol);
280  if (clib_bihash_search_8_8 (&nm->out2in, &kv0, &value0))
281  return 1;
282  ti = nat_value_get_thread_index (&value0);
283  if (ti != thread_index)
284  {
285  *required_thread_index = ti;
286  return 1;
287  }
288  si = nat_value_get_session_index (&value0);
289  s0 = pool_elt_at_index (nm->per_thread_data[ti].sessions, si);
290  new_dst_addr0 = s0->in2out.addr.as_u32;
291  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
292 
293  /* update inner source IP address */
294  old_addr0 = inner_ip0->src_address.as_u32;
295  inner_ip0->src_address.as_u32 = new_dst_addr0;
296  new_addr0 = inner_ip0->src_address.as_u32;
297  sum0 = icmp0->checksum;
298  sum0 =
299  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t, src_address);
300  icmp0->checksum = ip_csum_fold (sum0);
301 
302  /* update inner IP header checksum */
303  old_checksum0 = inner_ip0->checksum;
304  sum0 = inner_ip0->checksum;
305  sum0 =
306  ip_csum_update (sum0, old_addr0, new_addr0, ip4_header_t, src_address);
307  inner_ip0->checksum = ip_csum_fold (sum0);
308  new_checksum0 = inner_ip0->checksum;
309  sum0 = icmp0->checksum;
310  sum0 = ip_csum_update (sum0, old_checksum0, new_checksum0, ip4_header_t,
311  checksum);
312  icmp0->checksum = ip_csum_fold (sum0);
313 
314  /* update inner source port */
315  old_port0 = l4_header->src_port;
316  l4_header->src_port = s0->in2out.port;
317  new_port0 = l4_header->src_port;
318  sum0 = icmp0->checksum;
319  sum0 = ip_csum_update (sum0, old_port0, new_port0, tcp_udp_header_t,
320  src_port);
321  icmp0->checksum = ip_csum_fold (sum0);
322  }
323  else
324  {
325  init_nat_k (&kv0, ip0->dst_address, 0, nm->outside_fib_index, 0);
326  if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv0,
327  &value0))
328  {
329  icmp_echo_header_t *echo0 = (icmp_echo_header_t *) (icmp0 + 1);
330  u16 icmp_id0 = echo0->identifier;
331  init_nat_k (&kv0, ip0->dst_address, icmp_id0, nm->outside_fib_index,
332  NAT_PROTOCOL_ICMP);
333  int rv = clib_bihash_search_8_8 (&nm->out2in, &kv0, &value0);
334  if (!rv)
335  {
336  ti = nat_value_get_thread_index (&value0);
337  if (ti != thread_index)
338  {
339  *required_thread_index = ti;
340  return 1;
341  }
342  si = nat_value_get_session_index (&value0);
343  s0 = pool_elt_at_index (nm->per_thread_data[ti].sessions, si);
344  new_dst_addr0 = s0->in2out.addr.as_u32;
345  vnet_buffer (b0)->sw_if_index[VLIB_TX] = s0->in2out.fib_index;
346  echo0->identifier = s0->in2out.port;
347  sum0 = icmp0->checksum;
348  sum0 = ip_csum_update (sum0, icmp_id0, s0->in2out.port,
349  icmp_echo_header_t, identifier);
350  icmp0->checksum = ip_csum_fold (sum0);
351  goto change_addr;
352  }
353 
354  return 1;
355  }
356 
357  m0 = pool_elt_at_index (nm->static_mappings, value0.value);
358 
359  new_dst_addr0 = m0->local_addr.as_u32;
360  if (vnet_buffer (b0)->sw_if_index[VLIB_TX] == ~0)
361  vnet_buffer (b0)->sw_if_index[VLIB_TX] = m0->fib_index;
362  }
363 change_addr:
364  /* Destination is behind the same NAT, use internal address and port */
365  if (new_dst_addr0)
366  {
367  old_dst_addr0 = ip0->dst_address.as_u32;
368  ip0->dst_address.as_u32 = new_dst_addr0;
369  sum0 = ip0->checksum;
370  sum0 = ip_csum_update (sum0, old_dst_addr0, new_dst_addr0, ip4_header_t,
371  dst_address);
372  ip0->checksum = ip_csum_fold (sum0);
373  }
374  return 0;
375 }
376 #endif
377 
379  ip4_header_t *ip);
380 
381 #ifndef CLIB_MARCH_VARIANT
382 void
384  ip4_header_t *ip)
385 {
388  u32 old_addr, new_addr;
389  ip_csum_t sum;
390 
391  init_nat_k (&kv, ip->dst_address, 0, 0, 0);
392  if (clib_bihash_search_8_8 (&nm->static_mapping_by_external, &kv, &value))
393  return;
394 
395  m = pool_elt_at_index (nm->static_mappings, value.value);
396 
397  old_addr = ip->dst_address.as_u32;
398  new_addr = ip->dst_address.as_u32 = m->local_addr.as_u32;
399  sum = ip->checksum;
400  sum = ip_csum_update (sum, old_addr, new_addr, ip4_header_t, dst_address);
401  ip->checksum = ip_csum_fold (sum);
402 
403  if (vnet_buffer (b)->sw_if_index[VLIB_TX] == ~0)
404  vnet_buffer (b)->sw_if_index[VLIB_TX] = m->fib_index;
405 }
406 #endif
407 
408 VLIB_NODE_FN (nat44_ei_hairpin_src_node)
410 {
411  u32 n_left_from, *from, *to_next;
414 
416  n_left_from = frame->n_vectors;
417  next_index = node->cached_next_index;
418 
419  while (n_left_from > 0)
420  {
421  u32 n_left_to_next;
422 
423  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
424 
425  while (n_left_from > 0 && n_left_to_next > 0)
426  {
427  u32 bi0;
428  vlib_buffer_t *b0;
429  u32 next0;
431  u32 sw_if_index0;
432 
433  /* speculatively enqueue b0 to the current next frame */
434  bi0 = from[0];
435  to_next[0] = bi0;
436  from += 1;
437  to_next += 1;
438  n_left_from -= 1;
439  n_left_to_next -= 1;
440 
441  b0 = vlib_get_buffer (vm, bi0);
442  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
443 
445  {
446  /* Only packets from NAT inside interface */
447  if ((nat44_ei_interface_is_inside (i)) &&
448  (sw_if_index0 == i->sw_if_index))
449  {
450  if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) &
452  {
453  if (PREDICT_TRUE (nm->num_workers > 1))
454  {
456  goto skip_feature_next;
457  }
458  else
459  {
461  goto skip_feature_next;
462  }
463  }
464  break;
465  }
466  }
467 
468  vnet_feature_next (&next0, b0);
469  skip_feature_next:
470 
471  if (next0 != NAT44_EI_HAIRPIN_SRC_NEXT_DROP)
472  {
474  &nm->counters.hairpinning, vm->thread_index, sw_if_index0, 1);
475  }
476 
477  /* verify speculative enqueue, maybe switch current next frame */
478  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
479  n_left_to_next, bi0, next0);
480  }
481 
482  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
483  }
484 
485  return frame->n_vectors;
486 }
487 
490 {
491  u32 n_left_from, *from, *to_next;
492  u32 thread_index = vm->thread_index;
495 
496  from = vlib_frame_vector_args (frame);
497  n_left_from = frame->n_vectors;
498  next_index = node->cached_next_index;
499 
500  while (n_left_from > 0)
501  {
502  u32 n_left_to_next;
503 
504  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
505 
506  while (n_left_from > 0 && n_left_to_next > 0)
507  {
508  u32 bi0;
509  vlib_buffer_t *b0;
510  u32 next0;
511  ip4_header_t *ip0;
512  u32 proto0;
513  u32 sw_if_index0;
514  u32 required_thread_index = thread_index;
515 
516  /* speculatively enqueue b0 to the current next frame */
517  bi0 = from[0];
518  to_next[0] = bi0;
519  from += 1;
520  to_next += 1;
521  n_left_from -= 1;
522  n_left_to_next -= 1;
523 
524  b0 = vlib_get_buffer (vm, bi0);
526  ip0 = vlib_buffer_get_current (b0);
527  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
528 
529  proto0 = ip_proto_to_nat_proto (ip0->protocol);
530 
531  vnet_buffer (b0)->snat.flags = 0;
533  {
534  if (proto0 == NAT_PROTOCOL_TCP || proto0 == NAT_PROTOCOL_UDP)
535  {
536  udp_header_t *udp0 = ip4_next_header (ip0);
537  tcp_header_t *tcp0 = (tcp_header_t *) udp0;
538 
539  nat44_ei_hairpinning (vm, node, nm, thread_index, b0, ip0,
540  udp0, tcp0, proto0, 1 /* do_trace */,
541  &required_thread_index);
542  }
543  else if (proto0 == NAT_PROTOCOL_ICMP)
544  {
545  icmp46_header_t *icmp0 = ip4_next_header (ip0);
546 
547  nat44_ei_icmp_hairpinning (nm, b0, thread_index, ip0, icmp0,
548  &required_thread_index);
549  }
550  else
551  {
553  }
554 
555  vnet_buffer (b0)->snat.flags = NAT44_EI_FLAG_HAIRPINNING;
556  }
557 
558  if (thread_index != required_thread_index)
559  {
560  vnet_buffer (b0)->snat.required_thread_index =
561  required_thread_index;
563  }
564 
565  if (next0 != NAT44_EI_HAIRPIN_NEXT_DROP)
566  {
568  &nm->counters.hairpinning, vm->thread_index, sw_if_index0, 1);
569  }
570 
571  /* verify speculative enqueue, maybe switch current next frame */
572  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
573  n_left_to_next, bi0, next0);
574  }
575 
576  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
577  }
578 
579  return frame->n_vectors;
580 }
581 
584 {
585  u32 n_left_from, *from, *to_next;
586  u32 thread_index = vm->thread_index;
590  u8 arc_index = vnet_feat_arc_ip4_local.feature_arc_index;
592 
593  from = vlib_frame_vector_args (frame);
594  n_left_from = frame->n_vectors;
595  next_index = node->cached_next_index;
596 
597  while (n_left_from > 0)
598  {
599  u32 n_left_to_next;
600 
601  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
602 
603  while (n_left_from > 0 && n_left_to_next > 0)
604  {
605  u32 bi0;
606  vlib_buffer_t *b0;
607  u32 next0;
608  ip4_header_t *ip0;
609  u32 proto0;
610  udp_header_t *udp0;
611  tcp_header_t *tcp0;
612  u32 sw_if_index0;
613  u32 required_thread_index = thread_index;
614 
615  /* speculatively enqueue b0 to the current next frame */
616  bi0 = from[0];
617  to_next[0] = bi0;
618  from += 1;
619  to_next += 1;
620  n_left_from -= 1;
621  n_left_to_next -= 1;
622 
623  b0 = vlib_get_buffer (vm, bi0);
624  ip0 = vlib_buffer_get_current (b0);
625  udp0 = ip4_next_header (ip0);
626  tcp0 = (tcp_header_t *) udp0;
627  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
628 
629  proto0 = ip_proto_to_nat_proto (ip0->protocol);
630  int next0_resolved = 0;
631 
632  if (nat44_ei_hairpinning (vm, node, nm, thread_index, b0, ip0, udp0,
633  tcp0, proto0, 1 /* do_trace */,
634  &required_thread_index))
635  {
637  next0_resolved = 1;
638  }
639 
640  if (thread_index != required_thread_index)
641  {
642  vnet_buffer (b0)->snat.required_thread_index =
643  required_thread_index;
645  next0_resolved = 1;
646  }
647 
648  if (!next0_resolved)
650  &next0, 0);
651 
652  if (next0 != NAT44_EI_HAIRPIN_NEXT_DROP)
653  {
655  &nm->counters.hairpinning, vm->thread_index, sw_if_index0, 1);
656  }
657 
658  /* verify speculative enqueue, maybe switch current next frame */
659  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
660  n_left_to_next, bi0, next0);
661  }
662 
663  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
664  }
665 
666  return frame->n_vectors;
667 }
668 
671 {
674 }
675 
678 {
681 }
682 
684  .name = "nat44-ei-hairpin-dst-handoff",
685  .vector_size = sizeof (u32),
689 
690  .n_next_nodes = 1,
691 
692  .next_nodes = {
693  [0] = "error-drop",
694  },
695 };
696 
698  .name = "nat44-ei-hairpinning-handoff",
699  .vector_size = sizeof (u32),
703 
704  .n_next_nodes = 1,
705 
706  .next_nodes = {
707  [0] = "error-drop",
708  },
709 };
710 
712  .name = "nat44-ei-hairpin-src",
713  .vector_size = sizeof (u32),
715  .n_next_nodes = NAT44_EI_HAIRPIN_SRC_N_NEXT,
716  .next_nodes = {
717  [NAT44_EI_HAIRPIN_SRC_NEXT_DROP] = "error-drop",
718  [NAT44_EI_HAIRPIN_SRC_NEXT_SNAT_IN2OUT] = "nat44-ei-in2out-output",
719  [NAT44_EI_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT] = "interface-output",
720  [NAT44_EI_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH] = "nat44-ei-in2out-output-worker-handoff",
721  },
722 };
723 
725  .name = "nat44-ei-hairpin-dst",
726  .vector_size = sizeof (u32),
728  .format_trace = format_nat44_ei_hairpin_trace,
729  .n_next_nodes = NAT44_EI_HAIRPIN_N_NEXT,
730  .next_nodes = {
731  [NAT44_EI_HAIRPIN_NEXT_DROP] = "error-drop",
732  [NAT44_EI_HAIRPIN_NEXT_LOOKUP] = "ip4-lookup",
733  [NAT44_EI_HAIRPIN_NEXT_HANDOFF] = "nat44-ei-hairpin-dst-handoff",
734  },
735 };
736 
738  .name = "nat44-ei-hairpinning",
739  .vector_size = sizeof (u32),
741  .format_trace = format_nat44_ei_hairpin_trace,
742  .n_next_nodes = NAT44_EI_HAIRPIN_N_NEXT,
743  .next_nodes = {
744  [NAT44_EI_HAIRPIN_NEXT_DROP] = "error-drop",
745  [NAT44_EI_HAIRPIN_NEXT_LOOKUP] = "ip4-lookup",
746  [NAT44_EI_HAIRPIN_NEXT_HANDOFF] = "nat44-ei-hairpinning-handoff",
747  },
748 };
749 
750 /*
751  * fd.io coding-style-patch-verification: ON
752  *
753  * Local Variables:
754  * eval: (c-set-style "gnu")
755  * End:
756  */
vnet_config_main_t config_main
Definition: feature.h:82
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
static u8 * format_nat44_ei_hairpin_trace(u8 *s, va_list *args)
static_always_inline int nat44_ei_is_hairpinning(nat44_ei_main_t *nm, ip4_address_t *dst_addr)
ip4_address_t addr
Definition: nat44_ei.h:69
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)
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:899
vlib_node_registration_t nat44_ei_hairpin_src_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpin_src_node)
#define CLIB_UNUSED(x)
Definition: clib.h:90
ip4_address_t src_address
Definition: ip4_packet.h:125
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
u32 thread_index
#define PREDICT_TRUE(x)
Definition: clib.h:125
vl_api_ip_proto_t protocol
Definition: lb_types.api:72
vlib_main_t * vm
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)
u32 thread_index
Definition: main.h:213
void nat44_ei_hairpinning_unknown_proto(nat44_ei_main_t *nm, vlib_buffer_t *b, ip4_header_t *ip)
NAT44 endpoint independent plugin declarations.
nat44_ei_session_t * sessions
Definition: nat44_ei.h:283
uword ip_csum_t
Definition: ip_packet.h:245
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)
#define VLIB_NODE_FN(node)
Definition: node.h:202
vlib_node_registration_t nat44_ei_hairpinning_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpinning_node)
struct _tcp_header tcp_header_t
clib_bihash_8_8_t static_mapping_by_external
Definition: nat44_ei.h:333
unsigned char u8
Definition: types.h:56
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
unsigned int u32
Definition: types.h:88
format_function_t format_ip4_address
Definition: format.h:73
#define static_always_inline
Definition: clib.h:112
nat44_ei_hairpin_next_t
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:24
nat44_ei_address_t * addresses
Definition: nat44_ei.h:369
ip4_address_t dst_address
Definition: ip4_packet.h:125
description fragment has unexpected format
Definition: map.api:433
vlib_node_registration_t nat44_ei_hairpinning_dst_handoff_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpinning_dst_handoff_node)
vlib_simple_counter_main_t hairpinning
Definition: nat44_ei.h:442
static u32 nat_value_get_session_index(clib_bihash_kv_8_8_t *value)
u32 hairpin_dst_fq_index
Definition: nat44_ei.h:477
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
int __clib_unused rv
Definition: application.c:491
struct nat44_ei_main_s::@81 counters
vl_api_fib_path_type_t type
Definition: fib_types.api:123
#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
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
nat44_ei_interface_t * output_feature_interfaces
Definition: nat44_ei.h:340
unsigned short u16
Definition: types.h:57
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
static void * vnet_get_config_data(vnet_config_main_t *cm, u32 *config_index, u32 *next_index, u32 n_data_bytes)
Definition: config.h:123
#define PREDICT_FALSE(x)
Definition: clib.h:124
vl_api_address_union_t src_address
Definition: ip_types.api:122
void nat44_ei_hairpinning_sm_unknown_proto(nat44_ei_main_t *nm, vlib_buffer_t *b, ip4_header_t *ip)
#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
vlib_main_t vlib_node_runtime_t * node
#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[]
vlib_node_registration_t nat44_ei_hairpinning_handoff_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpinning_handoff_node)
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
u64 value
the value
Definition: bihash_8_8.h:44
vl_api_mac_address_t dst_addr
Definition: flow_types.api:65
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
nat44_ei_main_per_thread_data_t * per_thread_data
Definition: nat44_ei.h:366
u32 ti
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
vnet_feature_arc_registration_t vnet_feat_arc_ip4_local
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
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)
vnet_feature_main_t feature_main
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:156
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
#define ARRAY_LEN(x)
Definition: clib.h:70
u8 value
Definition: qos.api:54
vlib_node_registration_t nat44_ei_hairpin_dst_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpin_dst_node)
u32 hairpinning_fq_index
Definition: nat44_ei.h:476
clib_bihash_8_8_t out2in
Definition: nat44_ei.h:362
vnet_sw_interface_t * si
vlib_put_next_frame(vm, node, next_index, 0)
char const int length
Definition: cJSON.h:163
u8 arc_index
nat44_ei_hairpin_src_next_t next_index
Definition: defs.h:47
VLIB buffer representation.
Definition: buffer.h:111
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
nat44_ei_hairpin_src_next_t
nat44_ei_main_t nat44_ei_main
Definition: nat44_ei.c:40
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:295
struct _vnet_feature_arc_registration vnet_feature_arc_registration_t
feature registration object
#define vnet_buffer(b)
Definition: buffer.h:437
ip4_address_t local_addr
Definition: nat44_ei.h:166
#define vec_foreach(var, vec)
Vector iterator.
u16 flags
Copy of main node flags.
Definition: node.h:492
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
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:292
vnet_feature_config_main_t * feature_config_mains
feature config main objects
Definition: feature.h:100
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
#define nat44_ei_interface_is_inside(ip)
Definition: nat44_ei.h:671
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 vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:111
#define NAT44_EI_FLAG_HAIRPINNING
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
Definition: defs.h:46