FD.io VPP  v21.10.1-2-g0a485f517
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
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 
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
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);
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
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,
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);
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);
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 
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 
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 rx_sw_if_index0;
432  u32 tx_sw_if_index0;
433 
434  /* speculatively enqueue b0 to the current next frame */
435  bi0 = from[0];
436  to_next[0] = bi0;
437  from += 1;
438  to_next += 1;
439  n_left_from -= 1;
440  n_left_to_next -= 1;
441 
442  b0 = vlib_get_buffer (vm, bi0);
443  rx_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
444  tx_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
445 
447  {
448  /* Only packets from NAT inside interface */
450  (rx_sw_if_index0 == i->sw_if_index))
451  {
452  if (PREDICT_FALSE ((vnet_buffer (b0)->snat.flags) &
454  {
455  if (PREDICT_TRUE (nm->num_workers > 1))
456  {
458  goto skip_feature_next;
459  }
460  else
461  {
463  goto skip_feature_next;
464  }
465  }
466  break;
467  }
468  }
469 
470  vnet_feature_next (&next0, b0);
471  skip_feature_next:
472 
473  if (next0 != NAT44_EI_HAIRPIN_SRC_NEXT_DROP)
474  {
476  vm->thread_index, tx_sw_if_index0,
477  1);
478  }
479 
480  /* verify speculative enqueue, maybe switch current next frame */
482  n_left_to_next, bi0, next0);
483  }
484 
485  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
486  }
487 
488  return frame->n_vectors;
489 }
490 
493 {
494  u32 n_left_from, *from, *to_next;
498 
500  n_left_from = frame->n_vectors;
501  next_index = node->cached_next_index;
502 
503  while (n_left_from > 0)
504  {
505  u32 n_left_to_next;
506 
507  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
508 
509  while (n_left_from > 0 && n_left_to_next > 0)
510  {
511  u32 bi0;
512  vlib_buffer_t *b0;
513  u32 next0;
514  ip4_header_t *ip0;
515  u32 proto0;
516  u32 sw_if_index0;
517  u32 required_thread_index = thread_index;
518 
519  /* speculatively enqueue b0 to the current next frame */
520  bi0 = from[0];
521  to_next[0] = bi0;
522  from += 1;
523  to_next += 1;
524  n_left_from -= 1;
525  n_left_to_next -= 1;
526 
527  b0 = vlib_get_buffer (vm, bi0);
529  ip0 = vlib_buffer_get_current (b0);
530  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
531 
532  proto0 = ip_proto_to_nat_proto (ip0->protocol);
533 
534  vnet_buffer (b0)->snat.flags = 0;
536  {
537  if (proto0 == NAT_PROTOCOL_TCP || proto0 == NAT_PROTOCOL_UDP)
538  {
539  udp_header_t *udp0 = ip4_next_header (ip0);
540  tcp_header_t *tcp0 = (tcp_header_t *) udp0;
541 
543  udp0, tcp0, proto0, 1 /* do_trace */,
544  &required_thread_index);
545  }
546  else if (proto0 == NAT_PROTOCOL_ICMP)
547  {
548  icmp46_header_t *icmp0 = ip4_next_header (ip0);
549 
550  nat44_ei_icmp_hairpinning (nm, b0, thread_index, ip0, icmp0,
551  &required_thread_index);
552  }
553  else
554  {
556  }
557 
558  vnet_buffer (b0)->snat.flags = NAT44_EI_FLAG_HAIRPINNING;
559  }
560 
561  if (thread_index != required_thread_index)
562  {
563  vnet_buffer (b0)->snat.required_thread_index =
564  required_thread_index;
566  }
567 
568  if (next0 != NAT44_EI_HAIRPIN_NEXT_DROP)
569  {
571  &nm->counters.hairpinning, vm->thread_index, sw_if_index0, 1);
572  }
573 
574  /* verify speculative enqueue, maybe switch current next frame */
576  n_left_to_next, bi0, next0);
577  }
578 
579  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
580  }
581 
582  return frame->n_vectors;
583 }
584 
587 {
588  u32 n_left_from, *from, *to_next;
593  u8 arc_index = vnet_feat_arc_ip4_local.feature_arc_index;
595 
597  n_left_from = frame->n_vectors;
598  next_index = node->cached_next_index;
599 
600  while (n_left_from > 0)
601  {
602  u32 n_left_to_next;
603 
604  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
605 
606  while (n_left_from > 0 && n_left_to_next > 0)
607  {
608  u32 bi0;
609  vlib_buffer_t *b0;
610  u32 next0;
611  ip4_header_t *ip0;
612  u32 proto0;
613  udp_header_t *udp0;
614  tcp_header_t *tcp0;
615  u32 sw_if_index0;
616  u32 required_thread_index = thread_index;
617 
618  /* speculatively enqueue b0 to the current next frame */
619  bi0 = from[0];
620  to_next[0] = bi0;
621  from += 1;
622  to_next += 1;
623  n_left_from -= 1;
624  n_left_to_next -= 1;
625 
626  b0 = vlib_get_buffer (vm, bi0);
627  ip0 = vlib_buffer_get_current (b0);
628  udp0 = ip4_next_header (ip0);
629  tcp0 = (tcp_header_t *) udp0;
630  sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
631 
632  proto0 = ip_proto_to_nat_proto (ip0->protocol);
633  int next0_resolved = 0;
634 
635  if (nat44_ei_hairpinning (vm, node, nm, thread_index, b0, ip0, udp0,
636  tcp0, proto0, 1 /* do_trace */,
637  &required_thread_index))
638  {
640  next0_resolved = 1;
641  }
642 
643  if (thread_index != required_thread_index)
644  {
645  vnet_buffer (b0)->snat.required_thread_index =
646  required_thread_index;
648  next0_resolved = 1;
649  }
650 
651  if (!next0_resolved)
653  &next0, 0);
654 
655  if (next0 != NAT44_EI_HAIRPIN_NEXT_DROP)
656  {
658  &nm->counters.hairpinning, vm->thread_index, sw_if_index0, 1);
659  }
660 
661  /* verify speculative enqueue, maybe switch current next frame */
663  n_left_to_next, bi0, next0);
664  }
665 
666  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
667  }
668 
669  return frame->n_vectors;
670 }
671 
674 {
677 }
678 
681 {
684 }
685 
687  .name = "nat44-ei-hairpin-dst-handoff",
688  .vector_size = sizeof (u32),
692 
693  .n_next_nodes = 1,
694 
695  .next_nodes = {
696  [0] = "error-drop",
697  },
698 };
699 
701  .name = "nat44-ei-hairpinning-handoff",
702  .vector_size = sizeof (u32),
706 
707  .n_next_nodes = 1,
708 
709  .next_nodes = {
710  [0] = "error-drop",
711  },
712 };
713 
715  .name = "nat44-ei-hairpin-src",
716  .vector_size = sizeof (u32),
718  .n_next_nodes = NAT44_EI_HAIRPIN_SRC_N_NEXT,
719  .next_nodes = {
720  [NAT44_EI_HAIRPIN_SRC_NEXT_DROP] = "error-drop",
721  [NAT44_EI_HAIRPIN_SRC_NEXT_SNAT_IN2OUT] = "nat44-ei-in2out-output",
722  [NAT44_EI_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT] = "interface-output",
723  [NAT44_EI_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH] = "nat44-ei-in2out-output-worker-handoff",
724  },
725 };
726 
728  .name = "nat44-ei-hairpin-dst",
729  .vector_size = sizeof (u32),
731  .format_trace = format_nat44_ei_hairpin_trace,
732  .n_next_nodes = NAT44_EI_HAIRPIN_N_NEXT,
733  .next_nodes = {
734  [NAT44_EI_HAIRPIN_NEXT_DROP] = "error-drop",
735  [NAT44_EI_HAIRPIN_NEXT_LOOKUP] = "ip4-lookup",
736  [NAT44_EI_HAIRPIN_NEXT_HANDOFF] = "nat44-ei-hairpin-dst-handoff",
737  },
738 };
739 
741  .name = "nat44-ei-hairpinning",
742  .vector_size = sizeof (u32),
744  .format_trace = format_nat44_ei_hairpin_trace,
745  .n_next_nodes = NAT44_EI_HAIRPIN_N_NEXT,
746  .next_nodes = {
747  [NAT44_EI_HAIRPIN_NEXT_DROP] = "error-drop",
748  [NAT44_EI_HAIRPIN_NEXT_LOOKUP] = "ip4-lookup",
749  [NAT44_EI_HAIRPIN_NEXT_HANDOFF] = "nat44-ei-hairpinning-handoff",
750  },
751 };
752 
753 /*
754  * fd.io coding-style-patch-verification: ON
755  *
756  * Local Variables:
757  * eval: (c-set-style "gnu")
758  * End:
759  */
vlib.h
nat44_ei_hairpinning_handoff_error_strings
static char * nat44_ei_hairpinning_handoff_error_strings[]
Definition: nat44_ei_hairpinning.h:17
nat44_ei_hairpinning_sm_unknown_proto
void nat44_ei_hairpinning_sm_unknown_proto(nat44_ei_main_t *nm, vlib_buffer_t *b, ip4_header_t *ip)
Definition: nat44_ei_hairpinning.c:97
vnet_feature_config_main_t_
Definition: feature.h:80
nat_value_get_thread_index
static u32 nat_value_get_thread_index(clib_bihash_kv_8_8_t *value)
Definition: nat44_ei_inlines.h:105
nat44_ei_is_hairpinning
static_always_inline int nat44_ei_is_hairpinning(nat44_ei_main_t *nm, ip4_address_t *dst_addr)
Definition: nat44_ei_hairpinning.c:77
trace
static vlib_cli_command_t trace
(constructor) VLIB_CLI_COMMAND (trace)
Definition: vlib_api_cli.c:870
vnet_feature_config_main_t_::config_main
vnet_config_main_t config_main
Definition: feature.h:82
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
nat44_ei_hairpin_trace_t
Definition: nat44_ei_hairpinning.c:45
nat44_ei_address_t
Definition: nat44_ei.h:68
nat44_ei_hairpinning
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)
Definition: nat44_ei_hairpinning.c:124
format_ip4_address
format_function_t format_ip4_address
Definition: format.h:73
nat44_ei_hairpin_src_node
vlib_node_registration_t nat44_ei_hairpin_src_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpin_src_node)
Definition: nat44_ei_hairpinning.c:714
next_index
nat44_ei_hairpin_src_next_t next_index
Definition: nat44_ei_hairpinning.c:412
nat44_ei_main_s::static_mappings
nat44_ei_static_mapping_t * static_mappings
Definition: nat44_ei.h:337
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei_hairpinning.c:409
vlib_get_buffer
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
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
tcp_header_t
struct _tcp_header tcp_header_t
ip_proto_to_nat_proto
static nat_protocol_t ip_proto_to_nat_proto(u8 ip_proto)
Common NAT inline functions.
Definition: inlines.h:24
VLIB_NODE_TYPE_INTERNAL
@ VLIB_NODE_TYPE_INTERNAL
Definition: node.h:72
NAT44_EI_FLAG_HAIRPINNING
#define NAT44_EI_FLAG_HAIRPINNING
Definition: nat44_ei_hairpinning.c:26
clib_bihash_kv_8_8_t::value
u64 value
the value
Definition: bihash_8_8.h:44
ip4_address_t::as_u32
u32 as_u32
Definition: ip4_packet.h:57
nat44_ei_static_mapping_t::fib_index
u32 fib_index
Definition: nat44_ei.h:176
u16
unsigned short u16
Definition: types.h:57
NAT44_EI_HAIRPIN_NEXT_DROP
@ NAT44_EI_HAIRPIN_NEXT_DROP
Definition: nat44_ei_hairpinning.c:40
nat44_ei_interface_t
Definition: nat44_ei.h:189
nat44_ei_main_s::hairpin_dst_fq_index
u32 hairpin_dst_fq_index
Definition: nat44_ei.h:478
nat44_ei_hairpin_trace_t::session_index
u32 session_index
Definition: nat44_ei_hairpinning.c:50
fm
vnet_feature_main_t * fm
Definition: nat44_ei_hairpinning.c:592
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
NAT44_EI_HAIRPIN_SRC_NEXT_DROP
@ NAT44_EI_HAIRPIN_SRC_NEXT_DROP
Definition: nat44_ei_hairpinning.c:30
nat44_ei_hairpinning_unknown_proto
void nat44_ei_hairpinning_unknown_proto(nat44_ei_main_t *nm, vlib_buffer_t *b, ip4_header_t *ip)
Definition: nat44_ei_hairpinning.c:383
nat44_ei_main_s::addresses
nat44_ei_address_t * addresses
Definition: nat44_ei.h:370
nat44_ei_main_s::counters
struct nat44_ei_main_s::@81 counters
vlib_frame_t
Definition: node.h:372
icmp_type_is_error_message
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
Definition: cnat_node.h:109
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
NAT44_EI_HAIRPIN_SRC_NEXT_SNAT_IN2OUT
@ NAT44_EI_HAIRPIN_SRC_NEXT_SNAT_IN2OUT
Definition: nat44_ei_hairpinning.c:31
nat44_ei_static_mapping_match
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
nat44_ei_main_per_thread_data_t::sessions
nat44_ei_session_t * sessions
Definition: nat44_ei.h:284
nat44_ei_main_s
Definition: nat44_ei.h:317
ti
u32 ti
Definition: interface_output.c:425
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
vlib_increment_simple_counter
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
NAT44_EI_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH
@ NAT44_EI_HAIRPIN_SRC_NEXT_SNAT_IN2OUT_WH
Definition: nat44_ei_hairpinning.c:32
VLIB_NODE_FN
#define VLIB_NODE_FN(node)
Definition: node.h:202
nat44_ei_main_s::hairpinning
vlib_simple_counter_main_t hairpinning
Definition: nat44_ei.h:443
nat_value_get_session_index
static u32 nat_value_get_session_index(clib_bihash_kv_8_8_t *value)
Definition: nat44_ei_inlines.h:111
nat44_ei_main
nat44_ei_main_t nat44_ei_main
Definition: nat44_ei.c:40
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
tcp_udp_header_t::src_port
u16 src_port
Definition: nat44_ei.h:96
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
VLIB_NODE_FLAG_TRACE
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:291
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei_hairpinning.c:410
NAT44_EI_HAIRPIN_N_NEXT
@ NAT44_EI_HAIRPIN_N_NEXT
Definition: nat44_ei_hairpinning.c:42
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
vnet_feature_next
static_always_inline void vnet_feature_next(u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:322
ARRAY_LEN
#define ARRAY_LEN(x)
Definition: clib.h:70
vlib_frame_vector_args
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:301
nat44_ei_icmp_hairpinning
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)
Definition: nat44_ei_hairpinning.c:251
static_always_inline
#define static_always_inline
Definition: clib.h:112
vm
vlib_main_t * vm
Definition: nat44_ei_hairpinning.c:409
tcp_udp_header_t
Definition: nat44_ei.h:94
nat44_ei_main_s::outside_fib_index
u32 outside_fib_index
Definition: nat44_ei.h:354
arc_index
u8 arc_index
Definition: nat44_ei_hairpinning.c:593
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
src_port
vl_api_ip_port_and_mask_t src_port
Definition: flow_types.api:91
dst_addr
vl_api_mac_address_t dst_addr
Definition: flow_types.api:65
nat44_ei_hairpinning_node
vlib_node_registration_t nat44_ei_hairpinning_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpinning_node)
Definition: nat44_ei_hairpinning.c:740
nat44_ei_main_s::per_thread_data
nat44_ei_main_per_thread_data_t * per_thread_data
Definition: nat44_ei.h:367
icmp_echo_header_t::identifier
u16 identifier
Definition: nat44_ei.h:90
format_nat44_ei_hairpinning_handoff_trace
static u8 * format_nat44_ei_hairpinning_handoff_trace(u8 *s, va_list *args)
Definition: nat44_ei_hairpinning.h:29
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:594
ip4_header_t::checksum
u16 checksum
Definition: ip4_packet.h:118
nat44_ei_static_mapping_t
Definition: nat44_ei.h:162
feature_main
vnet_feature_main_t feature_main
Definition: pnat_test_stubs.h:27
ip4_address_t
Definition: ip4_packet.h:50
nat44_ei_hairpinning_handoff_fn_inline
static uword nat44_ei_hairpinning_handoff_fn_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, u32 fq_index)
Definition: nat44_ei_hairpinning.h:43
nat44_ei_main_s::static_mapping_by_external
clib_bihash_8_8_t static_mapping_by_external
Definition: nat44_ei.h:334
nat44_ei_interface_is_inside
#define nat44_ei_interface_is_inside(ip)
Definition: nat44_ei.h:672
vlib_node_registration_t
struct _vlib_node_registration vlib_node_registration_t
ip4_header_t::dst_address
ip4_address_t dst_address
Definition: ip4_packet.h:125
nat44_ei_address_t::addr
ip4_address_t addr
Definition: nat44_ei.h:70
nat44_ei_main_s::output_feature_interfaces
nat44_ei_interface_t * output_feature_interfaces
Definition: nat44_ei.h:341
udp_header_t::checksum
u16 checksum
Definition: udp_packet.h:55
nat44_ei.h
nat44_ei_static_mapping_t::local_addr
ip4_address_t local_addr
Definition: nat44_ei.h:167
NAT44_EI_HAIRPIN_NEXT_LOOKUP
@ NAT44_EI_HAIRPIN_NEXT_LOOKUP
Definition: nat44_ei_hairpinning.c:39
vlib_buffer_t::current_config_index
u32 current_config_index
Used by feature subgraph arcs to visit enabled feature nodes.
Definition: buffer.h:156
nat44_ei_hairpinning_dst_handoff_node
vlib_node_registration_t nat44_ei_hairpinning_dst_handoff_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpinning_dst_handoff_node)
Definition: nat44_ei_hairpinning.c:686
nat44_ei_main_s::hairpinning_fq_index
u32 hairpinning_fq_index
Definition: nat44_ei.h:477
vlib_validate_buffer_enqueue_x1
#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
ip4_header_t::src_address
ip4_address_t src_address
Definition: ip4_packet.h:125
format
description fragment has unexpected format
Definition: map.api:433
NAT44_EI_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT
@ NAT44_EI_HAIRPIN_SRC_NEXT_INTERFACE_OUTPUT
Definition: nat44_ei_hairpinning.c:33
vlib_put_next_frame
vlib_put_next_frame(vm, node, next_index, 0)
u32
unsigned int u32
Definition: types.h:88
nat44_ei_hairpin_trace_t::addr
ip4_address_t addr
Definition: nat44_ei_hairpinning.c:47
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
protocol
vl_api_ip_proto_t protocol
Definition: lb_types.api:72
NAT44_EI_HAIRPIN_SRC_N_NEXT
@ NAT44_EI_HAIRPIN_SRC_N_NEXT
Definition: nat44_ei_hairpinning.c:34
si
vnet_sw_interface_t * si
Definition: interface_output.c:418
vec_foreach
#define vec_foreach(var, vec)
Vector iterator.
Definition: vec_bootstrap.h:213
clib_bihash_kv_8_8_t
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
nm
nat44_ei_main_t * nm
Definition: nat44_ei_hairpinning.c:413
value
u8 value
Definition: qos.api:54
ip4_fib.h
icmp_echo_header_t
Definition: nat44_ei.h:88
nat44_ei_hairpin_dst_node
vlib_node_registration_t nat44_ei_hairpin_dst_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpin_dst_node)
Definition: nat44_ei_hairpinning.c:727
length
char const int length
Definition: cJSON.h:163
vlib_main_t
Definition: main.h:102
ip_csum_update
#define ip_csum_update(sum, old, new, type, field)
Definition: ip_packet.h:295
vlib_node_t
Definition: node.h:247
vlib_add_trace
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
b
vlib_buffer_t ** b
Definition: nat44_ei_out2in.c:717
u8
unsigned char u8
Definition: types.h:56
nat44_ei_hairpinning.h
vlib_buffer_get_current
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:257
ip
vl_api_address_t ip
Definition: l2.api:558
ip_csum_t
uword ip_csum_t
Definition: ip_packet.h:245
vnet_get_config_data
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
nat44_ei_hairpin_next_t
nat44_ei_hairpin_next_t
Definition: nat44_ei_hairpinning.c:37
nat44_ei_hairpin_trace_t::fib_index
u32 fib_index
Definition: nat44_ei_hairpinning.c:49
nat44_ei_main_s::out2in
clib_bihash_8_8_t out2in
Definition: nat44_ei.h:363
i
int i
Definition: flowhash_template.h:376
rv
int __clib_unused rv
Definition: application.c:491
nat44_ei_inlines.h
nat44_ei_hairpin_src_next_t
nat44_ei_hairpin_src_next_t
Definition: nat44_ei_hairpinning.c:28
vnet_feature_main_t::feature_config_mains
vnet_feature_config_main_t * feature_config_mains
feature config main objects
Definition: feature.h:100
vnet.h
vlib_node_runtime_t
Definition: node.h:454
src_address
vl_api_address_union_t src_address
Definition: ip_types.api:122
from
from
Definition: nat44_ei_hairpinning.c:415
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
nat44_ei_hairpin_trace_t::port
u16 port
Definition: nat44_ei_hairpinning.c:48
NAT44_EI_HAIRPIN_NEXT_HANDOFF
@ NAT44_EI_HAIRPIN_NEXT_HANDOFF
Definition: nat44_ei_hairpinning.c:41
sw_if_index
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
vlib_get_next_frame
#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
ip_csum_fold
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:301
VLIB_TX
@ VLIB_TX
Definition: defs.h:47
init_nat_k
static void init_nat_k(clib_bihash_kv_8_8_t *kv, ip4_address_t addr, u16 port, u32 fib_index, nat_protocol_t proto)
Definition: nat44_ei_inlines.h:56
n_left_from
n_left_from
Definition: nat44_ei_hairpinning.c:416
nat44_ei_main_s::num_workers
u32 num_workers
Definition: nat44_ei.h:357
vnet_feature_arc_registration_t
struct _vnet_feature_arc_registration vnet_feature_arc_registration_t
feature registration object
nat44_ei_hairpinning_handoff_node
vlib_node_registration_t nat44_ei_hairpinning_handoff_node
(constructor) VLIB_REGISTER_NODE (nat44_ei_hairpinning_handoff_node)
Definition: nat44_ei_hairpinning.c:700
type
vl_api_fib_path_type_t type
Definition: fib_types.api:123
ip4_header_t::protocol
u8 protocol
Definition: ip4_packet.h:115
format_nat44_ei_hairpin_trace
static u8 * format_nat44_ei_hairpin_trace(u8 *s, va_list *args)
Definition: nat44_ei_hairpinning.c:54
ip4_next_header
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:196
vnet_feature_main_t
Definition: feature.h:86
vlib_buffer_t::flags
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index,...
Definition: buffer.h:133
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
VLIB_REGISTER_NODE
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:169
vnet_feat_arc_ip4_local
vnet_feature_arc_registration_t vnet_feat_arc_ip4_local