FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
cnat_node.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020 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 #ifndef __CNAT_NODE_H__
17 #define __CNAT_NODE_H__
18 
19 #include <vlibmemory/api.h>
20 #include <vnet/dpo/load_balance.h>
22 
23 #include <cnat/cnat_session.h>
24 #include <cnat/cnat_client.h>
25 #include <cnat/cnat_inline.h>
26 #include <cnat/cnat_translation.h>
27 
28 #include <vnet/ip/ip4_inlines.h>
29 #include <vnet/ip/ip6_inlines.h>
30 
33  vlib_buffer_t * b,
34  cnat_node_ctx_t * ctx, int rv,
35  cnat_session_t * session);
36 
37 typedef struct cnat_trace_element_t_
38 {
45 
47 {
51  CNAT_TRACE_NO_NAT = (1 << 3),
53 
56  cnat_session_t *session, const cnat_translation_t *ct,
57  u8 flags)
58 {
60  if (NULL != ct)
62 
63  t = vlib_add_trace (vm, node, b, sizeof (*t));
64  t->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_RX];
65  t->sw_if_index[VLIB_TX] = vnet_buffer (b)->sw_if_index[VLIB_TX];
66 
68  clib_memcpy (&t->session, session, sizeof (t->session));
70  clib_memcpy (&t->tr, ct, sizeof (cnat_translation_t));
71  t->flags = flags;
72 }
73 
74 static u8 *
75 format_cnat_trace (u8 *s, va_list *args)
76 {
77  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
78  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
79  cnat_trace_element_t *t = va_arg (*args, cnat_trace_element_t *);
80  u32 indent = format_get_indent (s);
81  vnet_main_t *vnm = vnet_get_main ();
82 
84  s = format (s, "created session");
85  else if (t->flags & CNAT_TRACE_SESSION_FOUND)
86  s = format (s, "found session");
87  else
88  s = format (s, "session not found");
89 
90  if (t->flags & (CNAT_TRACE_NO_NAT))
91  s = format (s, " [policy:skip]");
92 
93  s = format (s, "\n%Uin:%U out:%U ", format_white_space, indent,
96 
98  s = format (s, "\n%U%U", format_white_space, indent, format_cnat_session,
99  &t->session, 1);
100 
102  s = format (s, "\n%Utranslation: %U", format_white_space, indent,
103  format_cnat_translation, &t->tr, 0);
104 
105  return s;
106 }
107 
110 {
111  switch (icmp_type)
112  {
113  case ICMP4_destination_unreachable:
114  case ICMP4_time_exceeded:
115  case ICMP4_parameter_problem:
116  case ICMP4_source_quench:
117  case ICMP4_redirect:
118  case ICMP4_alternate_host_address:
119  return 1;
120  }
121  return 0;
122 }
123 
126 {
127  switch (icmp_type)
128  {
129  case ICMP4_echo_request:
130  case ICMP4_echo_reply:
131  return 1;
132  }
133  return 0;
134 }
135 
138 {
139  switch (icmp_type)
140  {
141  case ICMP6_echo_request:
142  case ICMP6_echo_reply:
143  return 1;
144  }
145  return 0;
146 }
147 
150 {
151  switch (icmp_type)
152  {
153  case ICMP6_destination_unreachable:
154  case ICMP6_time_exceeded:
155  case ICMP6_parameter_problem:
156  return 1;
157  }
158  return 0;
159 }
160 
162 cmp_ip6_address (const ip6_address_t * a1, const ip6_address_t * a2)
163 {
164  return ((a1->as_u64[0] == a2->as_u64[0])
165  && (a1->as_u64[1] == a2->as_u64[1]));
166 }
167 
168 /**
169  * Inline translation functions
170  */
171 
173 has_ip6_address (ip6_address_t * a)
174 {
175  return ((0 != a->as_u64[0]) || (0 != a->as_u64[1]));
176 }
177 
180  ip_csum_t * sum,
181  ip4_address_t new_addr[VLIB_N_DIR],
182  u16 new_port[VLIB_N_DIR])
183 {
184  u16 old_port[VLIB_N_DIR];
185  ip4_address_t old_addr[VLIB_N_DIR];
186 
187  /* Fastpath no checksum */
188  if (PREDICT_TRUE (0 == *sum))
189  {
190  udp->dst_port = new_port[VLIB_TX];
191  udp->src_port = new_port[VLIB_RX];
192  return;
193  }
194 
195  old_port[VLIB_TX] = udp->dst_port;
196  old_port[VLIB_RX] = udp->src_port;
197  old_addr[VLIB_TX] = ip4->dst_address;
198  old_addr[VLIB_RX] = ip4->src_address;
199 
200  if (new_addr[VLIB_TX].as_u32)
201  {
202  *sum =
203  ip_csum_update (*sum, old_addr[VLIB_TX].as_u32,
204  new_addr[VLIB_TX].as_u32, ip4_header_t, dst_address);
205  }
206  if (new_port[VLIB_TX])
207  {
208  udp->dst_port = new_port[VLIB_TX];
209  *sum = ip_csum_update (*sum, old_port[VLIB_TX], new_port[VLIB_TX],
210  ip4_header_t /* cheat */ ,
211  length /* changed member */ );
212  }
213  if (new_addr[VLIB_RX].as_u32)
214  {
215  *sum =
216  ip_csum_update (*sum, old_addr[VLIB_RX].as_u32,
217  new_addr[VLIB_RX].as_u32, ip4_header_t, src_address);
218  }
219  if (new_port[VLIB_RX])
220  {
221  udp->src_port = new_port[VLIB_RX];
222  *sum = ip_csum_update (*sum, old_port[VLIB_RX], new_port[VLIB_RX],
223  ip4_header_t /* cheat */ ,
224  length /* changed member */ );
225  }
226 }
227 
230 {
231  ip4_address_t old_addr[VLIB_N_DIR];
232  ip_csum_t sum;
233 
234  old_addr[VLIB_TX] = ip4->dst_address;
235  old_addr[VLIB_RX] = ip4->src_address;
236 
237  sum = ip4->checksum;
238  if (new_addr[VLIB_TX].as_u32)
239  {
240  ip4->dst_address = new_addr[VLIB_TX];
241  sum =
242  ip_csum_update (sum, old_addr[VLIB_TX].as_u32,
243  new_addr[VLIB_TX].as_u32, ip4_header_t, dst_address);
244  }
245  if (new_addr[VLIB_RX].as_u32)
246  {
247  ip4->src_address = new_addr[VLIB_RX];
248  sum =
249  ip_csum_update (sum, old_addr[VLIB_RX].as_u32,
250  new_addr[VLIB_RX].as_u32, ip4_header_t, src_address);
251  }
252  ip4->checksum = ip_csum_fold (sum);
253 }
254 
257 {
259  if (PREDICT_FALSE (tcp_fin (tcp)))
260  {
262  }
263 
264  if (PREDICT_FALSE (tcp_rst (tcp)))
265  {
267  }
268 
269  if (PREDICT_FALSE (tcp_syn (tcp) && tcp_ack (tcp)))
270  {
271  cnat_timestamp_set_lifetime (index, cm->tcp_max_age);
272  }
273 }
274 
277  ip4_address_t new_addr[VLIB_N_DIR],
278  u16 new_port[VLIB_N_DIR])
279 {
280  ip_csum_t sum;
281  u16 old_port;
282  cnat_echo_header_t *echo = (cnat_echo_header_t *) (icmp + 1);
283 
284  cnat_ip4_translate_l3 (ip4, new_addr);
285  old_port = echo->identifier;
286  echo->identifier = new_port[VLIB_RX];
287 
288  sum = icmp->checksum;
289  sum = ip_csum_update (sum, old_port, new_port[VLIB_RX],
290  ip4_header_t /* cheat */ ,
291  length /* changed member */ );
292 
293  icmp->checksum = ip_csum_fold (sum);
294 }
295 
298  icmp46_header_t * icmp,
299  ip4_address_t outer_new_addr[VLIB_N_DIR],
300  u16 outer_new_port[VLIB_N_DIR],
301  u8 snat_outer_ip)
302 {
303  ip4_address_t new_addr[VLIB_N_DIR];
304  ip4_address_t old_addr[VLIB_N_DIR];
305  u16 new_port[VLIB_N_DIR];
306  u16 old_port[VLIB_N_DIR];
307  ip_csum_t sum, old_ip_sum, inner_l4_sum, inner_l4_old_sum;
308 
309  ip4_header_t *ip4 = (ip4_header_t *) (icmp + 2);
310  udp_header_t *udp = (udp_header_t *) (ip4 + 1);
311  tcp_header_t *tcp = (tcp_header_t *) udp;
312 
313  /* Swap inner ports */
314  new_addr[VLIB_TX] = outer_new_addr[VLIB_RX];
315  new_addr[VLIB_RX] = outer_new_addr[VLIB_TX];
316  new_port[VLIB_TX] = outer_new_port[VLIB_RX];
317  new_port[VLIB_RX] = outer_new_port[VLIB_TX];
318 
319  old_addr[VLIB_TX] = ip4->dst_address;
320  old_addr[VLIB_RX] = ip4->src_address;
321  old_port[VLIB_RX] = udp->src_port;
322  old_port[VLIB_TX] = udp->dst_port;
323 
324  sum = icmp->checksum;
325  old_ip_sum = ip4->checksum;
326 
327  /* translate outer ip. */
328  if (!snat_outer_ip)
329  outer_new_addr[VLIB_RX] = outer_ip4->src_address;
330  cnat_ip4_translate_l3 (outer_ip4, outer_new_addr);
331 
332  if (ip4->protocol == IP_PROTOCOL_TCP)
333  {
334  inner_l4_old_sum = inner_l4_sum = tcp->checksum;
335  cnat_ip4_translate_l4 (ip4, udp, &inner_l4_sum, new_addr, new_port);
336  tcp->checksum = ip_csum_fold (inner_l4_sum);
337  }
338  else if (ip4->protocol == IP_PROTOCOL_UDP)
339  {
340  inner_l4_old_sum = inner_l4_sum = udp->checksum;
341  cnat_ip4_translate_l4 (ip4, udp, &inner_l4_sum, new_addr, new_port);
342  udp->checksum = ip_csum_fold (inner_l4_sum);
343  }
344  else
345  return;
346 
347  /* UDP/TCP checksum changed */
348  sum = ip_csum_update (sum, inner_l4_old_sum, inner_l4_sum,
349  ip4_header_t, checksum);
350 
351  /* UDP/TCP Ports changed */
352  if (old_port[VLIB_TX] && new_port[VLIB_TX])
353  sum = ip_csum_update (sum, old_port[VLIB_TX], new_port[VLIB_TX],
354  ip4_header_t /* cheat */ ,
355  length /* changed member */ );
356 
357  if (old_port[VLIB_RX] && new_port[VLIB_RX])
358  sum = ip_csum_update (sum, old_port[VLIB_RX], new_port[VLIB_RX],
359  ip4_header_t /* cheat */ ,
360  length /* changed member */ );
361 
362 
363  cnat_ip4_translate_l3 (ip4, new_addr);
364  ip_csum_t new_ip_sum = ip4->checksum;
365  /* IP checksum changed */
366  sum = ip_csum_update (sum, old_ip_sum, new_ip_sum, ip4_header_t, checksum);
367 
368  /* IP src/dst addr changed */
369  if (new_addr[VLIB_TX].as_u32)
370  sum =
371  ip_csum_update (sum, old_addr[VLIB_TX].as_u32, new_addr[VLIB_TX].as_u32,
372  ip4_header_t, dst_address);
373 
374  if (new_addr[VLIB_RX].as_u32)
375  sum =
376  ip_csum_update (sum, old_addr[VLIB_RX].as_u32, new_addr[VLIB_RX].as_u32,
378 
379  icmp->checksum = ip_csum_fold (sum);
380 }
381 
384  ip4_header_t * ip4, udp_header_t * udp)
385 {
386  tcp_header_t *tcp = (tcp_header_t *) udp;
387  ip4_address_t new_addr[VLIB_N_DIR];
388  u16 new_port[VLIB_N_DIR];
389 
390  new_addr[VLIB_TX] = session->value.cs_ip[VLIB_TX].ip4;
391  new_addr[VLIB_RX] = session->value.cs_ip[VLIB_RX].ip4;
392  new_port[VLIB_TX] = session->value.cs_port[VLIB_TX];
393  new_port[VLIB_RX] = session->value.cs_port[VLIB_RX];
394 
395  if (ip4->protocol == IP_PROTOCOL_TCP)
396  {
397  ip_csum_t sum = tcp->checksum;
398  cnat_ip4_translate_l4 (ip4, udp, &sum, new_addr, new_port);
399  tcp->checksum = ip_csum_fold (sum);
400  cnat_ip4_translate_l3 (ip4, new_addr);
402  }
403  else if (ip4->protocol == IP_PROTOCOL_UDP)
404  {
405  ip_csum_t sum = udp->checksum;
406  cnat_ip4_translate_l4 (ip4, udp, &sum, new_addr, new_port);
407  udp->checksum = ip_csum_fold (sum);
408  cnat_ip4_translate_l3 (ip4, new_addr);
409  }
410  else if (ip4->protocol == IP_PROTOCOL_ICMP)
411  {
412  icmp46_header_t *icmp = (icmp46_header_t *) udp;
413  if (icmp_type_is_error_message (icmp->type))
414  {
415  /* SNAT only if src_addr was translated */
416  u8 snat_outer_ip =
417  (ip4->src_address.as_u32 ==
418  session->key.cs_ip[VLIB_RX].ip4.as_u32);
419  cnat_translation_icmp4_error (ip4, icmp, new_addr, new_port,
420  snat_outer_ip);
421  }
422  else if (icmp_type_is_echo (icmp->type))
423  cnat_translation_icmp4_echo (ip4, icmp, new_addr, new_port);
424  }
425 }
426 
428 cnat_ip6_translate_l3 (ip6_header_t * ip6, ip6_address_t new_addr[VLIB_N_DIR])
429 {
430  if (has_ip6_address (&new_addr[VLIB_TX]))
431  ip6_address_copy (&ip6->dst_address, &new_addr[VLIB_TX]);
432  if (has_ip6_address (&new_addr[VLIB_RX]))
433  ip6_address_copy (&ip6->src_address, &new_addr[VLIB_RX]);
434 }
435 
438  ip_csum_t * sum,
439  ip6_address_t new_addr[VLIB_N_DIR],
440  u16 new_port[VLIB_N_DIR])
441 {
442  u16 old_port[VLIB_N_DIR];
443  ip6_address_t old_addr[VLIB_N_DIR];
444 
445  /* Fastpath no checksum */
446  if (PREDICT_TRUE (0 == *sum))
447  {
448  udp->dst_port = new_port[VLIB_TX];
449  udp->src_port = new_port[VLIB_RX];
450  return;
451  }
452 
453  old_port[VLIB_TX] = udp->dst_port;
454  old_port[VLIB_RX] = udp->src_port;
455  ip6_address_copy (&old_addr[VLIB_TX], &ip6->dst_address);
456  ip6_address_copy (&old_addr[VLIB_RX], &ip6->src_address);
457 
458  if (has_ip6_address (&new_addr[VLIB_TX]))
459  {
460  *sum = ip_csum_add_even (*sum, new_addr[VLIB_TX].as_u64[0]);
461  *sum = ip_csum_add_even (*sum, new_addr[VLIB_TX].as_u64[1]);
462  *sum = ip_csum_sub_even (*sum, old_addr[VLIB_TX].as_u64[0]);
463  *sum = ip_csum_sub_even (*sum, old_addr[VLIB_TX].as_u64[1]);
464  }
465 
466  if (new_port[VLIB_TX])
467  {
468  udp->dst_port = new_port[VLIB_TX];
469  *sum = ip_csum_update (*sum, old_port[VLIB_TX], new_port[VLIB_TX],
470  ip4_header_t /* cheat */ ,
471  length /* changed member */ );
472  }
473  if (has_ip6_address (&new_addr[VLIB_RX]))
474  {
475  *sum = ip_csum_add_even (*sum, new_addr[VLIB_RX].as_u64[0]);
476  *sum = ip_csum_add_even (*sum, new_addr[VLIB_RX].as_u64[1]);
477  *sum = ip_csum_sub_even (*sum, old_addr[VLIB_RX].as_u64[0]);
478  *sum = ip_csum_sub_even (*sum, old_addr[VLIB_RX].as_u64[1]);
479  }
480 
481  if (new_port[VLIB_RX])
482  {
483  udp->src_port = new_port[VLIB_RX];
484  *sum = ip_csum_update (*sum, old_port[VLIB_RX], new_port[VLIB_RX],
485  ip4_header_t /* cheat */ ,
486  length /* changed member */ );
487  }
488 }
489 
492  ip6_address_t new_addr[VLIB_N_DIR],
493  u16 new_port[VLIB_N_DIR])
494 {
495  cnat_echo_header_t *echo = (cnat_echo_header_t *) (icmp + 1);
496  ip6_address_t old_addr[VLIB_N_DIR];
497  ip_csum_t sum;
498  u16 old_port;
499  old_port = echo->identifier;
500  ip6_address_copy (&old_addr[VLIB_TX], &ip6->dst_address);
501  ip6_address_copy (&old_addr[VLIB_RX], &ip6->src_address);
502 
503  sum = icmp->checksum;
504 
505  cnat_ip6_translate_l3 (ip6, new_addr);
506  if (has_ip6_address (&new_addr[VLIB_TX]))
507  {
508  sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[0]);
509  sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[1]);
510  sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[0]);
511  sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[1]);
512  }
513 
514  if (has_ip6_address (&new_addr[VLIB_RX]))
515  {
516  sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[0]);
517  sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[1]);
518  sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[0]);
519  sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[1]);
520  }
521 
522  echo->identifier = new_port[VLIB_RX];
523  sum = ip_csum_update (sum, old_port, new_port[VLIB_RX],
524  ip4_header_t /* cheat */ ,
525  length /* changed member */ );
526 
527  icmp->checksum = ip_csum_fold (sum);
528 }
529 
532  icmp46_header_t * icmp,
533  ip6_address_t outer_new_addr[VLIB_N_DIR],
534  u16 outer_new_port[VLIB_N_DIR],
535  u8 snat_outer_ip)
536 {
537  ip6_address_t new_addr[VLIB_N_DIR];
538  ip6_address_t old_addr[VLIB_N_DIR];
539  ip6_address_t outer_old_addr[VLIB_N_DIR];
540  u16 new_port[VLIB_N_DIR];
541  u16 old_port[VLIB_N_DIR];
542  ip_csum_t sum, inner_l4_sum, inner_l4_old_sum;
543 
544  if (!icmp6_type_is_error_message (icmp->type))
545  return;
546 
547  ip6_header_t *ip6 = (ip6_header_t *) (icmp + 2);
548  udp_header_t *udp = (udp_header_t *) (ip6 + 1);
549  tcp_header_t *tcp = (tcp_header_t *) udp;
550 
551  /* Swap inner ports */
552  ip6_address_copy (&new_addr[VLIB_RX], &outer_new_addr[VLIB_TX]);
553  ip6_address_copy (&new_addr[VLIB_TX], &outer_new_addr[VLIB_RX]);
554  new_port[VLIB_TX] = outer_new_port[VLIB_RX];
555  new_port[VLIB_RX] = outer_new_port[VLIB_TX];
556 
557  ip6_address_copy (&old_addr[VLIB_TX], &ip6->dst_address);
558  ip6_address_copy (&old_addr[VLIB_RX], &ip6->src_address);
559  old_port[VLIB_RX] = udp->src_port;
560  old_port[VLIB_TX] = udp->dst_port;
561 
562  sum = icmp->checksum;
563  /* Translate outer ip */
564  ip6_address_copy (&outer_old_addr[VLIB_TX], &outer_ip6->dst_address);
565  ip6_address_copy (&outer_old_addr[VLIB_RX], &outer_ip6->src_address);
566  if (!snat_outer_ip)
567  ip6_address_copy (&outer_new_addr[VLIB_RX], &outer_ip6->src_address);
568  cnat_ip6_translate_l3 (outer_ip6, outer_new_addr);
569  if (has_ip6_address (&outer_new_addr[VLIB_TX]))
570  {
571  sum = ip_csum_add_even (sum, outer_new_addr[VLIB_TX].as_u64[0]);
572  sum = ip_csum_add_even (sum, outer_new_addr[VLIB_TX].as_u64[1]);
573  sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_TX].as_u64[0]);
574  sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_TX].as_u64[1]);
575  }
576 
577  if (has_ip6_address (&outer_new_addr[VLIB_RX]))
578  {
579  sum = ip_csum_add_even (sum, outer_new_addr[VLIB_RX].as_u64[0]);
580  sum = ip_csum_add_even (sum, outer_new_addr[VLIB_RX].as_u64[1]);
581  sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_RX].as_u64[0]);
582  sum = ip_csum_sub_even (sum, outer_old_addr[VLIB_RX].as_u64[1]);
583  }
584 
585  /* Translate inner TCP / UDP */
586  if (ip6->protocol == IP_PROTOCOL_TCP)
587  {
588  inner_l4_old_sum = inner_l4_sum = tcp->checksum;
589  cnat_ip6_translate_l4 (ip6, udp, &inner_l4_sum, new_addr, new_port);
590  tcp->checksum = ip_csum_fold (inner_l4_sum);
591  }
592  else if (ip6->protocol == IP_PROTOCOL_UDP)
593  {
594  inner_l4_old_sum = inner_l4_sum = udp->checksum;
595  cnat_ip6_translate_l4 (ip6, udp, &inner_l4_sum, new_addr, new_port);
596  udp->checksum = ip_csum_fold (inner_l4_sum);
597  }
598  else
599  return;
600 
601  /* UDP/TCP checksum changed */
602  sum = ip_csum_update (sum, inner_l4_old_sum, inner_l4_sum,
603  ip4_header_t /* cheat */ ,
604  checksum);
605 
606  /* UDP/TCP Ports changed */
607  if (old_port[VLIB_TX] && new_port[VLIB_TX])
608  sum = ip_csum_update (sum, old_port[VLIB_TX], new_port[VLIB_TX],
609  ip4_header_t /* cheat */ ,
610  length /* changed member */ );
611 
612  if (old_port[VLIB_RX] && new_port[VLIB_RX])
613  sum = ip_csum_update (sum, old_port[VLIB_RX], new_port[VLIB_RX],
614  ip4_header_t /* cheat */ ,
615  length /* changed member */ );
616 
617 
618  cnat_ip6_translate_l3 (ip6, new_addr);
619  /* IP src/dst addr changed */
620  if (has_ip6_address (&new_addr[VLIB_TX]))
621  {
622  sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[0]);
623  sum = ip_csum_add_even (sum, new_addr[VLIB_TX].as_u64[1]);
624  sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[0]);
625  sum = ip_csum_sub_even (sum, old_addr[VLIB_TX].as_u64[1]);
626  }
627 
628  if (has_ip6_address (&new_addr[VLIB_RX]))
629  {
630  sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[0]);
631  sum = ip_csum_add_even (sum, new_addr[VLIB_RX].as_u64[1]);
632  sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[0]);
633  sum = ip_csum_sub_even (sum, old_addr[VLIB_RX].as_u64[1]);
634  }
635 
636  icmp->checksum = ip_csum_fold (sum);
637 }
638 
641  ip6_header_t * ip6, udp_header_t * udp)
642 {
643  tcp_header_t *tcp = (tcp_header_t *) udp;
644  ip6_address_t new_addr[VLIB_N_DIR];
645  u16 new_port[VLIB_N_DIR];
646 
647  ip6_address_copy (&new_addr[VLIB_TX], &session->value.cs_ip[VLIB_TX].ip6);
648  ip6_address_copy (&new_addr[VLIB_RX], &session->value.cs_ip[VLIB_RX].ip6);
649  new_port[VLIB_TX] = session->value.cs_port[VLIB_TX];
650  new_port[VLIB_RX] = session->value.cs_port[VLIB_RX];
651 
652  if (ip6->protocol == IP_PROTOCOL_TCP)
653  {
654  ip_csum_t sum = tcp->checksum;
655  cnat_ip6_translate_l4 (ip6, udp, &sum, new_addr, new_port);
656  tcp->checksum = ip_csum_fold (sum);
657  cnat_ip6_translate_l3 (ip6, new_addr);
659  }
660  else if (ip6->protocol == IP_PROTOCOL_UDP)
661  {
662  ip_csum_t sum = udp->checksum;
663  cnat_ip6_translate_l4 (ip6, udp, &sum, new_addr, new_port);
664  udp->checksum = ip_csum_fold (sum);
665  cnat_ip6_translate_l3 (ip6, new_addr);
666  }
667  else if (ip6->protocol == IP_PROTOCOL_ICMP6)
668  {
669  icmp46_header_t *icmp = (icmp46_header_t *) udp;
670  if (icmp6_type_is_error_message (icmp->type))
671  {
672  /* SNAT only if src_addr was translated */
673  u8 snat_outer_ip = cmp_ip6_address (&ip6->src_address,
674  &session->key.
675  cs_ip[VLIB_RX].ip6);
676  cnat_translation_icmp6_error (ip6, icmp, new_addr, new_port,
677  snat_outer_ip);
678  }
679  else if (icmp6_type_is_echo (icmp->type))
680  cnat_translation_icmp6_echo (ip6, icmp, new_addr, new_port);
681  }
682 }
683 
687 {
688  udp_header_t *udp;
689  cnat_session_t *session = (cnat_session_t *) bkey;
690  u32 iph_offset = 0;
691  session->key.cs_af = af;
692 
693  session->key.cs_loc = cs_loc;
694  session->key.__cs_pad = 0;
695  if (cs_loc == CNAT_LOCATION_OUTPUT)
696  /* rewind buffer */
697  iph_offset = vnet_buffer (b)->ip.save_rewrite_length;
698 
699  if (AF_IP4 == af)
700  {
701  ip4_header_t *ip4;
702  ip4 = (ip4_header_t *) ((u8 *) vlib_buffer_get_current (b) + iph_offset);
703 
704  if (PREDICT_FALSE (ip4->protocol == IP_PROTOCOL_ICMP))
705  {
706  icmp46_header_t *icmp = (icmp46_header_t *) (ip4 + 1);
707  if (icmp_type_is_error_message (icmp->type))
708  {
709  ip4 = (ip4_header_t *) (icmp + 2); /* Use inner packet */
710  udp = (udp_header_t *) (ip4 + 1);
711  /* Swap dst & src for search as ICMP payload is reversed */
713  &ip4->dst_address);
715  &ip4->src_address);
716  session->key.cs_proto = ip4->protocol;
717  session->key.cs_port[VLIB_TX] = udp->src_port;
718  session->key.cs_port[VLIB_RX] = udp->dst_port;
719  }
720  else if (icmp_type_is_echo (icmp->type))
721  {
722  cnat_echo_header_t *echo = (cnat_echo_header_t *) (icmp + 1);
724  &ip4->dst_address);
726  &ip4->src_address);
727  session->key.cs_proto = ip4->protocol;
728  session->key.cs_port[VLIB_TX] = echo->identifier;
729  session->key.cs_port[VLIB_RX] = echo->identifier;
730  }
731  else
732  goto error;
733  }
734  else if (ip4->protocol == IP_PROTOCOL_UDP ||
735  ip4->protocol == IP_PROTOCOL_TCP)
736  {
737  udp = (udp_header_t *) (ip4 + 1);
739  &ip4->dst_address);
741  &ip4->src_address);
742  session->key.cs_proto = ip4->protocol;
743  session->key.cs_port[VLIB_RX] = udp->src_port;
744  session->key.cs_port[VLIB_TX] = udp->dst_port;
745  }
746  else
747  goto error;
748  }
749  else
750  {
751  ip6_header_t *ip6;
752  ip6 = (ip6_header_t *) ((u8 *) vlib_buffer_get_current (b) + iph_offset);
753  if (PREDICT_FALSE (ip6->protocol == IP_PROTOCOL_ICMP6))
754  {
755  icmp46_header_t *icmp = (icmp46_header_t *) (ip6 + 1);
756  if (icmp6_type_is_error_message (icmp->type))
757  {
758  ip6 = (ip6_header_t *) (icmp + 2); /* Use inner packet */
759  udp = (udp_header_t *) (ip6 + 1);
760  /* Swap dst & src for search as ICMP payload is reversed */
762  &ip6->dst_address);
764  &ip6->src_address);
765  session->key.cs_proto = ip6->protocol;
766  session->key.cs_port[VLIB_TX] = udp->src_port;
767  session->key.cs_port[VLIB_RX] = udp->dst_port;
768  }
769  else if (icmp6_type_is_echo (icmp->type))
770  {
771  cnat_echo_header_t *echo = (cnat_echo_header_t *) (icmp + 1);
773  &ip6->dst_address);
775  &ip6->src_address);
776  session->key.cs_proto = ip6->protocol;
777  session->key.cs_port[VLIB_TX] = echo->identifier;
778  session->key.cs_port[VLIB_RX] = echo->identifier;
779  }
780  else
781  goto error;
782  }
783  else if (ip6->protocol == IP_PROTOCOL_UDP ||
784  ip6->protocol == IP_PROTOCOL_TCP)
785  {
786  udp = (udp_header_t *) (ip6 + 1);
788  &ip6->dst_address);
790  &ip6->src_address);
791  session->key.cs_port[VLIB_RX] = udp->src_port;
792  session->key.cs_port[VLIB_TX] = udp->dst_port;
793  session->key.cs_proto = ip6->protocol;
794  }
795  else
796  goto error;
797  }
798  return;
799 
800 error:
801  /* Ensure we dont find anything */
802  session->key.cs_proto = 0;
803  return;
804 }
805 
808  ip4_header_t *ip4, ip6_header_t *ip6, u32 *dpoi_index)
809 {
811  const load_balance_t *lb0;
812  const dpo_id_t *dpo0;
813  u32 hash_c0, bucket0;
814 
815  lb0 = load_balance_get (ct->ct_lb.dpoi_index);
816  if (PREDICT_FALSE (!lb0->lb_n_buckets))
817  return (NULL);
818 
819  /* session table miss */
820  hash_c0 = (AF_IP4 == af ? ip4_compute_flow_hash (ip4, lb0->lb_hash_config) :
822 
823  if (PREDICT_FALSE (ct->lb_type == CNAT_LB_MAGLEV))
824  bucket0 = ct->lb_maglev[hash_c0 % cm->maglev_len];
825  else
826  bucket0 = hash_c0 % lb0->lb_n_buckets;
827 
828  dpo0 = load_balance_get_fwd_bucket (lb0, bucket0);
829 
830  *dpoi_index = dpo0->dpoi_index;
831 
832  return &ct->ct_active_paths[bucket0];
833 }
834 
835 /**
836  * Create NAT sessions
837  * rsession_location is the location the (return) session will be
838  * matched at
839  */
842  cnat_session_location_t rsession_location,
843  u8 rsession_flags)
844 {
845  cnat_client_t *cc;
846  cnat_bihash_kv_t rkey;
847  cnat_session_t *rsession = (cnat_session_t *) & rkey;
848  cnat_bihash_kv_t *bkey = (cnat_bihash_kv_t *) session;
849  cnat_bihash_kv_t rvalue;
850  int rv;
851 
852  session->value.cs_ts_index = cnat_timestamp_new (ctx->now);
854 
855  if (!(rsession_flags & CNAT_SESSION_FLAG_NO_CLIENT))
856  {
857  /* is this the first time we've seen this source address */
858  cc = (AF_IP4 == ctx->af ?
859  cnat_client_ip4_find (&session->value.cs_ip[VLIB_RX].ip4) :
860  cnat_client_ip6_find (&session->value.cs_ip[VLIB_RX].ip6));
861 
862  if (NULL == cc)
863  {
865  uword *p;
866  u32 refcnt;
867 
868  addr.version = ctx->af;
869  ip46_address_copy (&addr.ip, &session->value.cs_ip[VLIB_RX]);
870 
871  /* Throttle */
873 
875  if (p)
876  {
877  refcnt = p[0] + 1;
879  }
880  else
882 
884 
885  /* fire client create to the main thread */
886  if (!p)
888  sizeof (addr));
889  }
890  else
891  {
892  /* Refcount reverse session */
894  }
895  }
896 
897  /* create the reverse flow key */
898  ip46_address_copy (&rsession->key.cs_ip[VLIB_RX],
899  &session->value.cs_ip[VLIB_TX]);
900  ip46_address_copy (&rsession->key.cs_ip[VLIB_TX],
901  &session->value.cs_ip[VLIB_RX]);
902  rsession->key.cs_proto = session->key.cs_proto;
903  rsession->key.cs_loc = rsession_location;
904  rsession->key.__cs_pad = 0;
905  rsession->key.cs_af = ctx->af;
906  rsession->key.cs_port[VLIB_RX] = session->value.cs_port[VLIB_TX];
907  rsession->key.cs_port[VLIB_TX] = session->value.cs_port[VLIB_RX];
908 
909  /* First search for existing reverse session */
910  rv = cnat_bihash_search_i2 (&cnat_session_db, &rkey, &rvalue);
911  if (!rv)
912  {
913  /* Reverse session already exists
914  cleanup before creating for refcnts */
915  cnat_session_t *found_rsession = (cnat_session_t *) & rvalue;
916  cnat_session_free (found_rsession);
917  }
918  /* add the reverse flow */
919  ip46_address_copy (&rsession->value.cs_ip[VLIB_RX],
920  &session->key.cs_ip[VLIB_TX]);
921  ip46_address_copy (&rsession->value.cs_ip[VLIB_TX],
922  &session->key.cs_ip[VLIB_RX]);
923  rsession->value.cs_ts_index = session->value.cs_ts_index;
924  rsession->value.cs_lbi = INDEX_INVALID;
925  rsession->value.flags = rsession_flags | CNAT_SESSION_IS_RETURN;
926  rsession->value.cs_port[VLIB_TX] = session->key.cs_port[VLIB_RX];
927  rsession->value.cs_port[VLIB_RX] = session->key.cs_port[VLIB_TX];
928 
930 }
931 
936  u8 do_trace)
937 {
940  vlib_buffer_t **b = bufs;
942  f64 now;
943 
946  n_left = frame->n_vectors;
947  next = nexts;
949  now = vlib_time_now (vm);
950  cnat_session_t *session[4];
951  cnat_bihash_kv_t bkey[4], bvalue[4];
952  u64 hash[4];
953  int rv[4];
954 
955  cnat_node_ctx_t ctx = { now, thread_index, af, do_trace };
956 
957  if (n_left >= 8)
958  {
959  /* Kickstart our state */
960  cnat_session_make_key (b[3], af, cs_loc, &bkey[3]);
961  cnat_session_make_key (b[2], af, cs_loc, &bkey[2]);
962  cnat_session_make_key (b[1], af, cs_loc, &bkey[1]);
963  cnat_session_make_key (b[0], af, cs_loc, &bkey[0]);
964 
965  hash[3] = cnat_bihash_hash (&bkey[3]);
966  hash[2] = cnat_bihash_hash (&bkey[2]);
967  hash[1] = cnat_bihash_hash (&bkey[1]);
968  hash[0] = cnat_bihash_hash (&bkey[0]);
969  }
970 
971  while (n_left >= 8)
972  {
973  if (n_left >= 12)
974  {
975  vlib_prefetch_buffer_header (b[11], LOAD);
976  vlib_prefetch_buffer_header (b[10], LOAD);
977  vlib_prefetch_buffer_header (b[9], LOAD);
978  vlib_prefetch_buffer_header (b[8], LOAD);
979  }
980 
981  rv[3] = cnat_bihash_search_i2_hash (&cnat_session_db, hash[3], &bkey[3],
982  &bvalue[3]);
983  session[3] = (cnat_session_t *) (rv[3] ? &bkey[3] : &bvalue[3]);
984  next[3] = cnat_sub (vm, node, b[3], &ctx, rv[3], session[3]);
985 
986  rv[2] = cnat_bihash_search_i2_hash (&cnat_session_db, hash[2], &bkey[2],
987  &bvalue[2]);
988  session[2] = (cnat_session_t *) (rv[2] ? &bkey[2] : &bvalue[2]);
989  next[2] = cnat_sub (vm, node, b[2], &ctx, rv[2], session[2]);
990 
991  rv[1] = cnat_bihash_search_i2_hash (&cnat_session_db, hash[1], &bkey[1],
992  &bvalue[1]);
993  session[1] = (cnat_session_t *) (rv[1] ? &bkey[1] : &bvalue[1]);
994  next[1] = cnat_sub (vm, node, b[1], &ctx, rv[1], session[1]);
995 
996  rv[0] = cnat_bihash_search_i2_hash (&cnat_session_db, hash[0], &bkey[0],
997  &bvalue[0]);
998  session[0] = (cnat_session_t *) (rv[0] ? &bkey[0] : &bvalue[0]);
999  next[0] = cnat_sub (vm, node, b[0], &ctx, rv[0], session[0]);
1000 
1001  cnat_session_make_key (b[7], af, cs_loc, &bkey[3]);
1002  cnat_session_make_key (b[6], af, cs_loc, &bkey[2]);
1003  cnat_session_make_key (b[5], af, cs_loc, &bkey[1]);
1004  cnat_session_make_key (b[4], af, cs_loc, &bkey[0]);
1005 
1006  hash[3] = cnat_bihash_hash (&bkey[3]);
1007  hash[2] = cnat_bihash_hash (&bkey[2]);
1008  hash[1] = cnat_bihash_hash (&bkey[1]);
1009  hash[0] = cnat_bihash_hash (&bkey[0]);
1010 
1015 
1020 
1021  b += 4;
1022  next += 4;
1023  n_left -= 4;
1024  }
1025 
1026  while (n_left > 0)
1027  {
1028  cnat_session_make_key (b[0], af, cs_loc, &bkey[0]);
1029  rv[0] = cnat_bihash_search_i2 (&cnat_session_db, &bkey[0], &bvalue[0]);
1030 
1031  session[0] = (cnat_session_t *) (rv[0] ? &bkey[0] : &bvalue[0]);
1032  next[0] = cnat_sub (vm, node, b[0], &ctx, rv[0], session[0]);
1033 
1034  b++;
1035  next++;
1036  n_left--;
1037  }
1038 
1040 
1041  return frame->n_vectors;
1042 }
1043 
1044 /*
1045  * fd.io coding-style-patch-verification: ON
1046  *
1047  * Local Variables:
1048  * eval: (c-set-style "gnu")
1049  * End:
1050  */
1051 
1052 #endif
load_balance.h
ip_address
Definition: ip_types.h:79
cnat_client_ip6_find
static_always_inline cnat_client_t * cnat_client_ip6_find(const ip6_address_t *ip)
Find a client from an IP6 address.
Definition: cnat_client.h:179
cnat_bihash_search_i2_hash
#define cnat_bihash_search_i2_hash
Definition: cnat_bihash.h:109
udp_header_t::src_port
u16 src_port
Definition: udp_packet.h:48
cnat_translation.h
cnat_translation_icmp6_error
static_always_inline void cnat_translation_icmp6_error(ip6_header_t *outer_ip6, icmp46_header_t *icmp, ip6_address_t outer_new_addr[VLIB_N_DIR], u16 outer_new_port[VLIB_N_DIR], u8 snat_outer_ip)
Definition: cnat_node.h:531
tcp_rst
#define tcp_rst(_th)
Definition: tcp_packet.h:81
load_balance_t_::lb_n_buckets
u16 lb_n_buckets
number of buckets in the load-balance.
Definition: load_balance.h:116
api.h
cnat_add_trace
static_always_inline void cnat_add_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, cnat_session_t *session, const cnat_translation_t *ct, u8 flags)
Definition: cnat_node.h:55
dpo_id_t_::dpoi_index
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:190
cnat_load_balance
static_always_inline cnat_ep_trk_t * cnat_load_balance(const cnat_translation_t *ct, ip_address_family_t af, ip4_header_t *ip4, ip6_header_t *ip6, u32 *dpoi_index)
Definition: cnat_node.h:807
cnat_session_t_::cs_ip
ip46_address_t cs_ip[VLIB_N_DIR]
IP 4/6 address in the rx/tx direction.
Definition: cnat_session.h:47
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
bufs
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
Definition: nat44_ei_out2in.c:717
cnat_session_free
void cnat_session_free(cnat_session_t *session)
Free a session & update refcounts.
Definition: cnat_session.c:144
vlib_prefetch_buffer_header
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:231
frame
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
Definition: nat44_ei.c:3048
clib_memcpy
#define clib_memcpy(d, s, n)
Definition: string.h:197
ip4
vl_api_ip4_address_t ip4
Definition: one.api:376
tcp_ack
#define tcp_ack(_th)
Definition: tcp_packet.h:83
load_balance_map.h
cnat_node_sub_t
uword(* cnat_node_sub_t)(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, cnat_node_ctx_t *ctx, int rv, cnat_session_t *session)
Definition: cnat_node.h:31
ip46_address_set_ip4
static void ip46_address_set_ip4(ip46_address_t *ip46, const ip4_address_t *ip)
Definition: ip46_address.h:67
cnat_session_t_::cs_lbi
index_t cs_lbi
The load balance object to use to forward.
Definition: cnat_session.h:89
cnat_session_make_key
static_always_inline void cnat_session_make_key(vlib_buffer_t *b, ip_address_family_t af, cnat_session_location_t cs_loc, cnat_bihash_kv_t *bkey)
Definition: cnat_node.h:685
CNAT_TRACE_NO_NAT
@ CNAT_TRACE_NO_NAT
Definition: cnat_node.h:51
ip4_inlines.h
cnat_main
cnat_main_t cnat_main
Definition: cnat_types.c:18
tcp_header_t
struct _tcp_header tcp_header_t
cnat_client_cnt_session
static_always_inline u32 cnat_client_cnt_session(cnat_client_t *cc)
Add a session refcnt to this client.
Definition: cnat_client.h:195
cnat_session.h
CNAT_SESSION_FLAG_NO_CLIENT
@ CNAT_SESSION_FLAG_NO_CLIENT
This session doesn't have a client, do not attempt to free it.
Definition: cnat_session.h:124
vlib_get_buffers
vlib_get_buffers(vm, from, b, n_left_from)
next
u16 * next
Definition: nat44_ei_out2in.c:718
cnat_client_learn
void cnat_client_learn(const ip_address_t *addr)
Called in the main thread by RPC from the workers to learn a new client.
Definition: cnat_client.c:188
ip46_address_set_ip6
static_always_inline void ip46_address_set_ip6(ip46_address_t *dst, const ip6_address_t *src)
Definition: ip46_address.h:130
VLIB_FRAME_SIZE
#define VLIB_FRAME_SIZE
Definition: node.h:368
clib_bihash_kv_40_56_t
Definition: cnat_bihash.h:41
node
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
load_balance_t_::lb_hash_config
flow_hash_config_t lb_hash_config
the hash config to use when selecting a bucket.
Definition: load_balance.h:161
cnat_translation_icmp4_error
static_always_inline void cnat_translation_icmp4_error(ip4_header_t *outer_ip4, icmp46_header_t *icmp, ip4_address_t outer_new_addr[VLIB_N_DIR], u16 outer_new_port[VLIB_N_DIR], u8 snat_outer_ip)
Definition: cnat_node.h:297
cnat_node_ctx_
Definition: cnat_types.h:155
u16
unsigned short u16
Definition: types.h:57
hash_set_mem
#define hash_set_mem(h, key, value)
Definition: hash.h:275
cnat_trace_element_t
struct cnat_trace_element_t_ cnat_trace_element_t
format_cnat_session
u8 * format_cnat_session(u8 *s, va_list *args)
Definition: cnat_session.c:92
cnat_client_ip4_find
static_always_inline cnat_client_t * cnat_client_ip4_find(const ip4_address_t *ip)
Find a client from an IP4 address.
Definition: cnat_client.h:150
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
AF_IP4
@ AF_IP4
Definition: ip_types.h:23
cnat_session_create
static_always_inline void cnat_session_create(cnat_session_t *session, cnat_node_ctx_t *ctx, cnat_session_location_t rsession_location, u8 rsession_flags)
Create NAT sessions rsession_location is the location the (return) session will be matched at.
Definition: cnat_node.h:841
VLIB_RX
@ VLIB_RX
Definition: defs.h:46
has_ip6_address
static_always_inline u8 has_ip6_address(ip6_address_t *a)
Inline translation functions.
Definition: cnat_node.h:173
vlib_buffer_enqueue_to_next
vlib_buffer_enqueue_to_next(vm, node, from,(u16 *) nexts, frame->n_vectors)
cnat_session_t_
A session represents the memory of a translation.
Definition: cnat_session.h:37
tcp_fin
#define tcp_fin(_th)
Definition: tcp_packet.h:79
cnat_ip4_translate_l4
static_always_inline void cnat_ip4_translate_l4(ip4_header_t *ip4, udp_header_t *udp, ip_csum_t *sum, ip4_address_t new_addr[VLIB_N_DIR], u16 new_port[VLIB_N_DIR])
Definition: cnat_node.h:179
cnat_ip6_translate_l4
static_always_inline void cnat_ip6_translate_l4(ip6_header_t *ip6, udp_header_t *udp, ip_csum_t *sum, ip6_address_t new_addr[VLIB_N_DIR], u16 new_port[VLIB_N_DIR])
Definition: cnat_node.h:437
cmp_ip6_address
static_always_inline u8 cmp_ip6_address(const ip6_address_t *a1, const ip6_address_t *a2)
Definition: cnat_node.h:162
cnat_session_t_::key
struct cnat_session_t_::@645 key
this key sits in the same memory location a 'key' in the bihash kvp
addr
vhost_vring_addr_t addr
Definition: vhost_user.h:130
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
cnat_session_t_::cs_af
u8 cs_af
The address family describing the IP addresses.
Definition: cnat_session.h:62
udp_header_t
Definition: udp_packet.h:45
ip4_header_t
Definition: ip4_packet.h:87
error
Definition: cJSON.c:88
tcp_syn
#define tcp_syn(_th)
Definition: tcp_packet.h:80
cnat_trace_element_t_::flags
u8 flags
Definition: cnat_node.h:43
hash_set_mem_alloc
static void hash_set_mem_alloc(uword **h, const void *key, uword v)
Definition: hash.h:279
cnat_ip4_translate_l3
static_always_inline void cnat_ip4_translate_l3(ip4_header_t *ip4, ip4_address_t new_addr[VLIB_N_DIR])
Definition: cnat_node.h:229
CNAT_TRACE_SESSION_FOUND
@ CNAT_TRACE_SESSION_FOUND
Definition: cnat_node.h:48
icmp6_type_is_error_message
static_always_inline u8 icmp6_type_is_error_message(u8 icmp_type)
Definition: cnat_node.h:149
load_balance_get_fwd_bucket
static const dpo_id_t * load_balance_get_fwd_bucket(const load_balance_t *lb, u16 bucket)
Definition: load_balance_map.h:94
CNAT_DEFAULT_TCP_RST_TIMEOUT
#define CNAT_DEFAULT_TCP_RST_TIMEOUT
Definition: cnat_types.h:34
cnat_translation_t_::lb_type
cnat_lb_type_t lb_type
Type of load balancing.
Definition: cnat_translation.h:168
ip6_compute_flow_hash
static u32 ip6_compute_flow_hash(const ip6_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip6_inlines.h:49
format_cnat_translation
u8 * format_cnat_translation(u8 *s, va_list *args)
Definition: cnat_translation.c:478
CLIB_UNUSED
#define CLIB_UNUSED(x)
Definition: clib.h:90
vnet_buffer
#define vnet_buffer(b)
Definition: buffer.h:441
vnet_get_main
vnet_main_t * vnet_get_main(void)
Definition: pnat_test_stubs.h:56
cnat_bihash_search_i2
#define cnat_bihash_search_i2
Definition: cnat_bihash.h:110
format_cnat_trace
static u8 * format_cnat_trace(u8 *s, va_list *args)
Definition: cnat_node.h:75
cnat_echo_header_t::identifier
u16 identifier
Definition: cnat_types.h:90
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
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
clib_spinlock_lock
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:82
cnat_ip6_translate_l3
static_always_inline void cnat_ip6_translate_l3(ip6_header_t *ip6, ip6_address_t new_addr[VLIB_N_DIR])
Definition: cnat_node.h:428
static_always_inline
#define static_always_inline
Definition: clib.h:112
uword
u64 uword
Definition: types.h:112
cnat_tcp_update_session_lifetime
static_always_inline void cnat_tcp_update_session_lifetime(tcp_header_t *tcp, u32 index)
Definition: cnat_node.h:256
cnat_translation_ip6
static_always_inline void cnat_translation_ip6(const cnat_session_t *session, ip6_header_t *ip6, udp_header_t *udp)
Definition: cnat_node.h:640
vlib_main_t::thread_index
u32 thread_index
Definition: main.h:215
cnat_trace_element_t_::session
cnat_session_t session
Definition: cnat_node.h:39
f64
double f64
Definition: types.h:142
ip6_header_t::dst_address
ip6_address_t dst_address
Definition: ip6_packet.h:310
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:594
cnat_inline.h
cnat_timestamp_set_lifetime
static void cnat_timestamp_set_lifetime(u32 index, u16 lifetime)
Definition: cnat_inline.h:56
cnat_translation_ip4
static_always_inline void cnat_translation_ip4(const cnat_session_t *session, ip4_header_t *ip4, udp_header_t *udp)
Definition: cnat_node.h:383
ip4_address_t
Definition: ip4_packet.h:50
ip6_address_copy
static void ip6_address_copy(ip6_address_t *dst, const ip6_address_t *src)
Definition: ip6_packet.h:127
cnat_translation_t_::lb_maglev
u32 * lb_maglev
Definition: cnat_translation.h:172
cnat_trace_element_t_
Definition: cnat_node.h:37
cnat_client_db_t_::throttle_mem
uword * throttle_mem
Definition: cnat_client.h:141
cnat_bihash_prefetch_data
#define cnat_bihash_prefetch_data
Definition: cnat_bihash.h:114
ip6_inlines.h
cnat_client_db
cnat_client_db_t cnat_client_db
Definition: cnat_client.c:24
ip46_address_copy
static_always_inline void ip46_address_copy(ip46_address_t *dst, const ip46_address_t *src)
Definition: ip46_address.h:123
cnat_session_t_::cs_ts_index
u32 cs_ts_index
Timestamp index this session was last used.
Definition: cnat_session.h:99
cnat_session_t_::cs_proto
ip_protocol_t cs_proto
The IP protocol TCP or UDP only supported.
Definition: cnat_session.h:57
VLIB_N_RX_TX
@ VLIB_N_RX_TX
Definition: defs.h:48
udp_header_t::checksum
u16 checksum
Definition: udp_packet.h:55
cnat_translation_icmp4_echo
static_always_inline void cnat_translation_icmp4_echo(ip4_header_t *ip4, icmp46_header_t *icmp, ip4_address_t new_addr[VLIB_N_DIR], u16 new_port[VLIB_N_DIR])
Definition: cnat_node.h:276
hash_get_mem
#define hash_get_mem(h, key)
Definition: hash.h:269
ip_csum_sub_even
static ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:273
vnet_main_t
Definition: vnet.h:76
index
u32 index
Definition: flow_types.api:221
cnat_session_location_t
enum cnat_session_location_t_ cnat_session_location_t
always_inline
#define always_inline
Definition: rdma_mlx5dv.h:23
ip4_header_t::src_address
ip4_address_t src_address
Definition: ip4_packet.h:125
icmp
icmp
Definition: map.api:387
icmp6_type_is_echo
static_always_inline u8 icmp6_type_is_echo(u8 icmp_type)
Definition: cnat_node.h:137
cnat_session_t_::cs_loc
u8 cs_loc
input / output / fib session
Definition: cnat_session.h:67
cnat_session_t_::flags
u32 flags
session flags
Definition: cnat_session.h:104
u64
unsigned long u64
Definition: types.h:89
format_vnet_sw_if_index_name
format_function_t format_vnet_sw_if_index_name
Definition: interface_funcs.h:458
format
description fragment has unexpected format
Definition: map.api:433
format_get_indent
static u32 format_get_indent(u8 *s)
Definition: format.h:72
u32
unsigned int u32
Definition: types.h:88
af
vl_api_address_family_t af
Definition: ip.api:619
CNAT_SESSION_IS_RETURN
@ CNAT_SESSION_IS_RETURN
Definition: cnat_session.h:131
udp_header_t::dst_port
u16 dst_port
Definition: udp_packet.h:48
ip6
vl_api_ip6_address_t ip6
Definition: one.api:424
cnat_node_inline
static uword cnat_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, cnat_node_sub_t cnat_sub, ip_address_family_t af, cnat_session_location_t cs_loc, u8 do_trace)
Definition: cnat_node.h:933
ctx
long ctx[MAX_CONNS]
Definition: main.c:144
cnat_client.h
cnat_translation_t_::ct_active_paths
cnat_ep_trk_t * ct_active_paths
The vector of active tracked back-ends.
Definition: cnat_translation.h:142
CNAT_LB_MAGLEV
@ CNAT_LB_MAGLEV
Definition: cnat_translation.h:82
load_balance_get
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:220
vl_api_rpc_call_main_thread
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: vlib_api.c:620
n_left
u32 n_left
Definition: interface_output.c:1096
as_u64
u64 as_u64
Definition: bihash_doc.h:63
cnat_trace_element_flag_t
enum cnat_trace_element_flag_t_ cnat_trace_element_flag_t
cnat_echo_header_t
Definition: cnat_types.h:88
cnat_translation_icmp6_echo
static_always_inline void cnat_translation_icmp6_echo(ip6_header_t *ip6, icmp46_header_t *icmp, ip6_address_t new_addr[VLIB_N_DIR], u16 new_port[VLIB_N_DIR])
Definition: cnat_node.h:491
clib_spinlock_unlock
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:121
ip4_compute_flow_hash
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip4_inlines.h:51
ip6_header_t
Definition: ip6_packet.h:294
VLIB_N_DIR
#define VLIB_N_DIR
Definition: defs.h:57
cnat_session_db
cnat_bihash_t cnat_session_db
The DB of sessions.
Definition: cnat_session.c:23
now
f64 now
Definition: nat44_ei_out2in.c:710
length
char const int length
Definition: cJSON.h:163
ip6_header_t::src_address
ip6_address_t src_address
Definition: ip6_packet.h:310
cnat_bihash_hash
#define cnat_bihash_hash
Definition: cnat_bihash.h:112
vlib_main_t
Definition: main.h:102
CNAT_LOCATION_OUTPUT
@ CNAT_LOCATION_OUTPUT
Definition: cnat_session.h:137
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
a
a
Definition: bitmap.h:525
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_csum_t
uword ip_csum_t
Definition: ip_packet.h:245
cnat_trace_element_flag_t_
cnat_trace_element_flag_t_
Definition: cnat_node.h:46
cnat_translation_t_::ct_lb
dpo_id_t ct_lb
The LB used to forward to the backends.
Definition: cnat_translation.h:127
cnat_timestamp_new
static u32 cnat_timestamp_new(f64 t)
Definition: cnat_inline.h:23
CNAT_TRACE_TRANSLATION_FOUND
@ CNAT_TRACE_TRANSLATION_FOUND
Definition: cnat_node.h:50
dpo_id_t_
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:172
nexts
u16 nexts[VLIB_FRAME_SIZE]
Definition: nat44_ei_out2in.c:718
rv
int __clib_unused rv
Definition: application.c:491
cnat_session_t_::value
struct cnat_session_t_::@646 value
this value sits in the same memory location a 'value' in the bihash kvp
cnat_trace_element_t_::tr
cnat_translation_t tr
Definition: cnat_node.h:40
vlib_time_now
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:327
load_balance_t_
The FIB DPO provieds;.
Definition: load_balance.h:106
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
INDEX_INVALID
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:49
PREDICT_TRUE
#define PREDICT_TRUE(x)
Definition: clib.h:125
cnat_bihash_add_del
#define cnat_bihash_add_del
Definition: cnat_bihash.h:111
ip_csum_add_even
static ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)
Definition: ip_packet.h:256
cnat_trace_element_t_::snat_policy_result
u32 snat_policy_result
Definition: cnat_node.h:42
cnat_client_t_
A client is a representation of an IP address behind the NAT.
Definition: cnat_client.h:35
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
format_white_space
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
CNAT_TRACE_SESSION_CREATED
@ CNAT_TRACE_SESSION_CREATED
Definition: cnat_node.h:49
cnat_translation_t_
A Translation represents the translation of a VEP to one of a set of real server addresses.
Definition: cnat_translation.h:117
cnat_bihash_prefetch_bucket
#define cnat_bihash_prefetch_bucket
Definition: cnat_bihash.h:113
cnat_ep_trk_t_
Data used to track an EP in the FIB.
Definition: cnat_translation.h:32
ip_address_family_t
enum ip_address_family_t_ ip_address_family_t
vlib_buffer_t
VLIB buffer representation.
Definition: buffer.h:111
cnat_main_
Definition: cnat_types.h:94
cnat_session_t_::cs_port
u16 cs_port[VLIB_N_DIR]
ports in rx/tx
Definition: cnat_session.h:52
cnat_trace_element_t_::sw_if_index
u32 sw_if_index[VLIB_N_RX_TX]
Definition: cnat_node.h:41
icmp_type_is_echo
static_always_inline u8 icmp_type_is_echo(u8 icmp_type)
Definition: cnat_node.h:125
cnat_client_db_t_::throttle_lock
clib_spinlock_t throttle_lock
Definition: cnat_client.h:140
flags
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105