FD.io VPP  v21.06-1-gbb7418cf9
Vector Packet Processing
cnat_translation.c
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 #include <vnet/fib/fib_source.h>
17 #include <vnet/fib/fib_table.h>
19 #include <vnet/dpo/load_balance.h>
20 #include <vnet/dpo/drop_dpo.h>
21 
22 #include <cnat/cnat_translation.h>
23 #include <cnat/cnat_session.h>
24 #include <cnat/cnat_client.h>
25 
27 clib_bihash_8_8_t cnat_translation_db;
30 
32 
33 vlib_combined_counter_main_t cnat_translation_counters = {
34  .name = "cnat-translation",
35  .stat_segment_name = "/net/cnat-translation",
36 };
37 
38 void
41 {
43 
44  if (INDEX_INVALID == ep->ce_sw_if_index)
45  return;
46 
47  pool_get (tr_resolutions, ar);
48  ar->af = ep->ce_ip.version;
49  ar->sw_if_index = ep->ce_sw_if_index;
50  ar->type = type;
51  ar->opaque = opaque;
52  ar->cti = cti;
53 }
54 
55 static void
57 {
58  cnat_resolve_ep (&path->src_ep);
59  cnat_resolve_ep (&path->dst_ep);
60 }
61 
62 void
64 {
65  /* Delete tr resolution entries matching translation index */
67  index_t *indexes = 0, *ari;
68  pool_foreach (ar, tr_resolutions)
69  {
70  if ((cti == INDEX_INVALID || ar->cti == cti) &&
71  (ar->type == type || CNAT_RESOLV_ADDR_ANY == type))
72  vec_add1 (indexes, ar - tr_resolutions);
73  }
74  vec_foreach (ari, indexes) pool_put_index (tr_resolutions, *ari);
75 
76  vec_free (indexes);
77 }
78 
79 static void
81 {
82  /* We only track fully resolved endpoints */
83  if (!(trk->ct_flags & CNAT_TRK_ACTIVE))
84  return;
85  fib_entry_untrack (trk->ct_fei, trk->ct_sibling);
86 }
87 
88 static void
90 {
91  fib_prefix_t pfx;
92  /* We only track fully resolved endpoints */
95  trk->ct_flags |= CNAT_TRK_ACTIVE;
96  else
97  {
98  trk->ct_flags &= ~CNAT_TRK_ACTIVE;
99  return;
100  }
101 
104  &pfx,
106  cti, &trk->ct_sibling);
107 
110  (pfx.fp_proto), &trk->ct_dpo);
111 }
112 
113 u8 *
114 format_cnat_lb_type (u8 *s, va_list *args)
115 {
116  cnat_lb_type_t lb_type = va_arg (*args, int);
117  if (CNAT_LB_DEFAULT == lb_type)
118  s = format (s, "default");
119  else if (CNAT_LB_MAGLEV == lb_type)
120  s = format (s, "maglev");
121  else
122  s = format (s, "unknown");
123  return (s);
124 }
125 
126 uword
128 {
129  cnat_lb_type_t *a = va_arg (*args, cnat_lb_type_t *);
130  if (unformat (input, "default"))
131  *a = CNAT_LB_DEFAULT;
132  else if (unformat (input, "maglev"))
133  *a = CNAT_LB_MAGLEV;
134  else
135  return 0;
136  return 1;
137 }
138 
139 /**
140  * Add a translation to the bihash
141  *
142  * @param cci the ID of the parent client (invalid if vip not resolved)
143  * @param vip the translation endpoint
144  * @param proto the translation proto
145  * @param cti the translation index to be used as value
146  */
147 static void
150 {
152  u64 key;
153  if (INDEX_INVALID == cci)
154  {
155  key = proto << 8 | 0x80 | vip->ce_ip.version;
156  key = key << 16 | vip->ce_port;
157  key = key << 32 | (u32) vip->ce_sw_if_index;
158  }
159  else
160  {
161  key = proto << 8;
162  key = key << 16 | vip->ce_port;
163  key = key << 32 | (u32) cci;
164  }
165 
166  bkey.key = key;
167  bkey.value = cti;
168 
169  clib_bihash_add_del_8_8 (&cnat_translation_db, &bkey, 1);
170 }
171 
172 /**
173  * Remove a translation from the bihash
174  *
175  * @param cci the ID of the parent client
176  * @param vip the translation endpoint
177  * @param proto the translation proto
178  */
179 static void
182 {
184  u64 key;
185  if (INDEX_INVALID == cci)
186  {
187  key = proto << 8 | 0x80 | vip->ce_ip.version;
188  key = key << 16 | vip->ce_port;
189  key = key << 32 | (u32) vip->ce_sw_if_index;
190  }
191  else
192  {
193  key = proto << 8;
194  key = key << 16 | vip->ce_port;
195  key = key << 32 | (u32) cci;
196  }
197 
198  bkey.key = key;
199 
200  clib_bihash_add_del_8_8 (&cnat_translation_db, &bkey, 0);
201 }
202 
203 typedef struct
204 {
210 
211 static int
212 cnat_maglev_entry_compare (void *_a, void *_b)
213 {
214  cnat_ep_trk_t *a = ((cnat_maglev_entry_t *) _a)->trk;
215  cnat_ep_trk_t *b = ((cnat_maglev_entry_t *) _b)->trk;
216  int rv = 0;
217  if ((rv =
219  return rv;
220  if ((rv = a->ct_ep[VLIB_TX].ce_port - a->ct_ep[VLIB_TX].ce_port))
221  return rv;
222  if ((rv =
224  return rv;
225  if ((rv = a->ct_ep[VLIB_RX].ce_port - a->ct_ep[VLIB_RX].ce_port))
226  return rv;
227  return 0;
228 }
229 
230 static void
232 {
233  cnat_maglev_entry_t *backends = NULL, *bk;
235  u32 done = 0;
236  cnat_ep_trk_t *trk;
237  int ep_idx = 0;
238 
239  vec_foreach (trk, ct->ct_active_paths)
240  {
242  u32 h1, h2;
243 
244  if (AF_IP4 == ip_addr_version (&trk->ct_ep[VLIB_TX].ce_ip))
245  {
246  u32 a, b, c;
247  a = ip_addr_v4 (&trk->ct_ep[VLIB_TX].ce_ip).data_u32;
248  b = (u64) trk->ct_ep[VLIB_TX].ce_port << 16 |
249  (u64) trk->ct_ep[VLIB_RX].ce_port;
250  c = ip_addr_v4 (&trk->ct_ep[VLIB_RX].ce_ip).data_u32;
251  hash_v3_mix32 (a, b, c);
252  hash_v3_finalize32 (a, b, c);
253  h1 = c;
254  h2 = b;
255  }
256  else
257  {
258  u64 a, b, c;
259  a = ip_addr_v6 (&trk->ct_ep[VLIB_TX].ce_ip).as_u64[0] ^
260  ip_addr_v6 (&trk->ct_ep[VLIB_TX].ce_ip).as_u64[1];
261  b = (u64) trk->ct_ep[VLIB_TX].ce_port << 16 |
262  (u64) trk->ct_ep[VLIB_RX].ce_port;
263  c = ip_addr_v6 (&trk->ct_ep[VLIB_RX].ce_ip).as_u64[0] ^
264  ip_addr_v6 (&trk->ct_ep[VLIB_RX].ce_ip).as_u64[1];
265  hash_mix64 (a, b, c);
266  h1 = c;
267  h2 = b;
268  }
269 
270  bk.offset = h1 % cm->maglev_len;
271  bk.skip = h2 % (cm->maglev_len - 1) + 1;
272  bk.index = ep_idx++;
273  bk.trk = trk;
274  vec_add1 (backends, bk);
275  }
276 
277  if (0 == ep_idx)
278  return;
279 
281 
282  /* Don't free if previous vector exists, just zero */
283  vec_validate (ct->lb_maglev, cm->maglev_len);
284  vec_set (ct->lb_maglev, -1);
285 
286  while (1)
287  {
288  vec_foreach (bk, backends)
289  {
290  u32 next = 0;
291  u32 c = (bk->offset + next * bk->skip) % cm->maglev_len;
292  while (ct->lb_maglev[c] != (u32) -1)
293  {
294  next++;
295  c = (bk->offset + next * bk->skip) % cm->maglev_len;
296  }
297  ct->lb_maglev[c] = bk->index;
298  done++;
299  if (done == cm->maglev_len)
300  goto finished;
301  }
302  }
303 
304 finished:
305  vec_free (backends);
306 }
307 
308 static void
310 {
311  fib_protocol_t fproto;
312  cnat_ep_trk_t *trk;
313  dpo_proto_t dproto;
314  u32 ep_idx = 0;
315  index_t lbi;
316 
318  dproto = fib_proto_to_dpo (fproto);
319 
321 
322  vec_foreach (trk, ct->ct_paths)
323  if (trk->ct_flags & CNAT_TRK_ACTIVE)
324  vec_add1 (ct->ct_active_paths, *trk);
325 
328 
329  ep_idx = 0;
330  vec_foreach (trk, ct->ct_active_paths)
331  load_balance_set_bucket (lbi, ep_idx++, &trk->ct_dpo);
332 
333  if (ep_idx > 0 && CNAT_LB_MAGLEV == ct->lb_type)
335 
336  dpo_set (&ct->ct_lb, DPO_LOAD_BALANCE, dproto, lbi);
337  dpo_stack (cnat_client_dpo, dproto, &ct->ct_lb, &ct->ct_lb);
339 }
340 
341 int
343 {
344  cnat_translation_t *ct;
345  cnat_ep_trk_t *trk;
346 
347  if (pool_is_free_index (cnat_translation_pool, id))
348  return (VNET_API_ERROR_NO_SUCH_ENTRY);
349 
350  ct = pool_elt_at_index (cnat_translation_pool, id);
351 
352  dpo_reset (&ct->ct_lb);
353 
354  vec_foreach (trk, ct->ct_active_paths)
355  cnat_tracker_release (trk);
356 
360  pool_put (cnat_translation_pool, ct);
361 
362  return (0);
363 }
364 
365 u32
369 {
371  const cnat_client_t *cc;
372  cnat_translation_t *ct;
373  cnat_ep_trk_t *trk;
374  index_t cci;
375 
376  cnat_lazy_init ();
377  if (cnat_resolve_ep (vip))
378  {
379  /* vip only contains a sw_if_index for now */
380  ct = cnat_find_translation (vip->ce_sw_if_index, vip->ce_port, proto);
381  cci = INDEX_INVALID;
382  }
383  else
384  {
385  /* do we know of this ep's vip */
386  cci = cnat_client_add (&vip->ce_ip, flags);
387  cc = cnat_client_get (cci);
388 
389  ct = cnat_find_translation (cc->parent_cci, vip->ce_port, proto);
390  }
391 
392  if (NULL == ct)
393  {
394  pool_get_zero (cnat_translation_pool, ct);
395 
396  clib_memcpy (&ct->ct_vip, vip, sizeof (*vip));
397  ct->ct_proto = proto;
398  ct->ct_cci = cci;
399  ct->index = ct - cnat_translation_pool;
400  ct->lb_type = lb_type;
401 
402  cnat_add_translation_to_db (cci, vip, proto, ct->index);
404 
405  vlib_validate_combined_counter (&cnat_translation_counters, ct->index);
406  vlib_zero_combined_counter (&cnat_translation_counters, ct->index);
407  }
408  ct->flags = flags;
409 
411  cnat_translation_watch_addr (ct->index, 0, vip,
413 
414  vec_foreach (trk, ct->ct_paths)
415  {
416  cnat_tracker_release (trk);
417  }
418 
421 
422  u64 path_idx = 0;
423  vec_foreach (path, paths)
424  {
425  cnat_resolve_ep_tuple (path);
427  path_idx << 32 | VLIB_RX, &path->src_ep,
430  path_idx << 32 | VLIB_TX, &path->dst_ep,
432  path_idx++;
433 
434  vec_add2 (ct->ct_paths, trk, 1);
435 
436  clib_memcpy (&trk->ct_ep[VLIB_TX], &path->dst_ep,
437  sizeof (trk->ct_ep[VLIB_TX]));
438  clib_memcpy (&trk->ct_ep[VLIB_RX], &path->src_ep,
439  sizeof (trk->ct_ep[VLIB_RX]));
440  trk->ct_flags = path->ep_flags;
441 
442  cnat_tracker_track (ct->index, trk);
443  }
444 
446 
447  return (ct->index);
448 }
449 
450 void
452 {
453  u32 api;
454 
455  pool_foreach_index (api, cnat_translation_pool)
456  {
457  if (!cb(api, ctx))
458  break;
459  }
460 }
461 
462 static u8 *
463 format_cnat_ep_trk (u8 * s, va_list * args)
464 {
465  cnat_ep_trk_t *ck = va_arg (*args, cnat_ep_trk_t *);
466  u32 indent = va_arg (*args, u32);
467 
468  s = format (s, "%U->%U", format_cnat_endpoint, &ck->ct_ep[VLIB_RX],
470  s = format (s, "\n%Ufib-entry:%d", format_white_space, indent, ck->ct_fei);
471  s = format (s, "\n%U%U",
472  format_white_space, indent, format_dpo_id, &ck->ct_dpo, 6);
473 
474  return (s);
475 }
476 
477 u8 *
478 format_cnat_translation (u8 * s, va_list * args)
479 {
480  cnat_translation_t *ct = va_arg (*args, cnat_translation_t *);
482  cnat_ep_trk_t *ck;
483 
484  s = format (s, "[%d] ", ct->index);
485  s = format (s, "%U %U ", format_cnat_endpoint, &ct->ct_vip,
487  s = format (s, "lb:%U ", format_cnat_lb_type, ct->lb_type);
488 
489  vec_foreach (ck, ct->ct_paths)
490  s = format (s, "\n%U", format_cnat_ep_trk, ck, 2);
491 
492  /* If printing a trace, the LB object might be deleted */
494  {
495  s = format (s, "\n via:");
496  s = format (s, "\n%U%U",
497  format_white_space, 2, format_dpo_id, &ct->ct_lb, 2);
498  }
499 
500  u32 bid = 0;
501  if (CNAT_LB_MAGLEV == ct->lb_type)
502  {
503  s = format (s, "\nmaglev backends map");
504  uword *bitmap = NULL;
505  clib_bitmap_alloc (bitmap, cm->maglev_len);
506  vec_foreach (ck, ct->ct_paths)
507  {
508  clib_bitmap_zero (bitmap);
509  for (u32 i = 0; i < vec_len (ct->lb_maglev); i++)
510  if (ct->lb_maglev[i] == bid)
511  clib_bitmap_set (bitmap, i, 1);
512  s = format (s, "\n backend#%d: %U", bid, format_bitmap_hex, bitmap);
513 
514  bid++;
515  }
516  clib_bitmap_free (bitmap);
517  }
518 
519  return (s);
520 }
521 
522 static clib_error_t *
524  unformat_input_t * input, vlib_cli_command_t * cmd)
525 {
526  index_t cti;
527  cnat_translation_t *ct;
528 
529  cti = INDEX_INVALID;
530 
532  {
533  if (unformat (input, "%d", &cti))
534  ;
535  else
536  return (clib_error_return (0, "unknown input '%U'",
537  format_unformat_error, input));
538  }
539 
540  if (INDEX_INVALID == cti)
541  {
542  pool_foreach_index (cti, cnat_translation_pool)
543  {
544  ct = pool_elt_at_index (cnat_translation_pool, cti);
546  }
547  }
548  else
549  {
550  vlib_cli_output (vm, "Invalid policy ID:%d", cti);
551  }
552 
553  return (NULL);
554 }
555 
556 int
558 {
559  /* purge all the translations */
560  index_t tri, *trp, *trs = NULL;
561 
562  pool_foreach_index (tri, cnat_translation_pool)
563  {
564  vec_add1(trs, tri);
565  }
566 
567  vec_foreach (trp, trs) cnat_translation_delete (*trp);
568 
569  ASSERT (0 == pool_elts (cnat_translation_pool));
570 
571  vec_free (trs);
572 
573  return (0);
574 }
575 
576 VLIB_CLI_COMMAND (cnat_translation_show_cmd_node, static) = {
577  .path = "show cnat translation",
578  .function = cnat_translation_show,
579  .short_help = "show cnat translation <VIP>",
580  .is_mp_safe = 1,
581 };
582 
583 static fib_node_t *
585 {
587  return (&(ct->ct_node));
588 }
589 
590 static cnat_translation_t *
592 {
593  return ((cnat_translation_t *) (((char *) node) -
595  ct_node)));
596 }
597 
598 static void
600 {
601  /**/}
602 
603 /*
604  * A back walk has reached this ABF policy
605  */
609 {
610  /*
611  * re-stack the fmask on the n-eos of the via
612  */
614 
615  /* If we have more than FIB_PATH_LIST_POPULAR paths
616  * we might get called during path tracking
617  * (cnat_tracker_track) */
618  if (!(ct->flags & CNAT_TRANSLATION_STACKED))
620 
622 
624 }
625 
626 /*
627  * The translation's graph node virtual function table
628  */
629 static const fib_node_vft_t cnat_translation_vft = {
631  .fnv_last_lock = cnat_translation_last_lock_gone,
632  .fnv_back_walk = cnat_translation_back_walk_notify,
633 };
634 
635 static clib_error_t *
637  unformat_input_t * input,
638  vlib_cli_command_t * cmd)
639 {
640  u32 del_index = INDEX_INVALID;
641  ip_protocol_t proto = IP_PROTOCOL_TCP;
642  cnat_endpoint_t vip;
644  cnat_endpoint_tuple_t tmp, *paths = NULL, *path;
645  unformat_input_t _line_input, *line_input = &_line_input;
646  clib_error_t *e = 0;
648 
649  /* Get a line of input. */
650  if (!unformat_user (input, unformat_line_input, line_input))
651  return 0;
652 
653  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
654  {
655  if (unformat (line_input, "add"))
656  del_index = INDEX_INVALID;
657  else if (unformat (line_input, "del %d", &del_index))
658  ;
659  else
660  if (unformat (line_input, "proto %U", unformat_ip_protocol, &proto))
661  ;
662  else if (unformat (line_input, "vip %U", unformat_cnat_ep, &vip))
663  flags = CNAT_FLAG_EXCLUSIVE;
664  else if (unformat (line_input, "real %U", unformat_cnat_ep, &vip))
665  flags = 0;
666  else if (unformat (line_input, "to %U", unformat_cnat_ep_tuple, &tmp))
667  {
668  vec_add2 (paths, path, 1);
669  clib_memcpy (path, &tmp, sizeof (cnat_endpoint_tuple_t));
670  }
671  else if (unformat (line_input, "%U", unformat_cnat_lb_type, &lb_type))
672  ;
673  else
674  {
675  e = clib_error_return (0, "unknown input '%U'",
676  format_unformat_error, line_input);
677  goto done;
678  }
679  }
680 
681  if (INDEX_INVALID == del_index)
682  cnat_translation_update (&vip, proto, paths, flags, lb_type);
683  else
684  cnat_translation_delete (del_index);
685 
686 done:
687  vec_free (paths);
688  unformat_free (line_input);
689  return (e);
690 }
691 
692 VLIB_CLI_COMMAND (cnat_translation_cli_add_del_command, static) =
693 {
694  .path = "cnat translation",
695  .short_help = "cnat translation [add|del] proto [TCP|UDP] [vip|real] [ip|sw_if_index [v6]] [port] [to [ip|sw_if_index [v6]] [port]->[ip|sw_if_index [v6]] [port]]",
696  .function = cnat_translation_cli_add_del,
697 };
698 
699 static void
701  ip_address_t * address, u8 is_del)
702 {
703  cnat_translation_t *ct;
704  ct = cnat_translation_get (ar->cti);
705  if (!is_del && ct->ct_vip.ce_flags & CNAT_EP_FLAG_RESOLVED)
706  return;
707 
709 
710  if (is_del)
711  {
713  ct->ct_cci = INDEX_INVALID;
715  /* Are there remaining addresses ? */
716  if (0 == cnat_resolve_addr (ar->sw_if_index, ar->af, address))
717  is_del = 0;
718  }
719 
720  if (!is_del)
721  {
722  ct->ct_cci = cnat_client_add (address, ct->flags);
724  ip_address_copy (&ct->ct_vip.ce_ip, address);
726  }
727 
729  ct->index);
730 }
731 
732 static void
734  ip_address_t * address, u8 is_del)
735 {
736  cnat_translation_t *ct;
737  cnat_ep_trk_t *trk;
738  cnat_endpoint_t *ep;
739 
740  u8 direction = ar->opaque & 0xf;
741  u32 path_idx = ar->opaque >> 32;
742 
743  ct = cnat_translation_get (ar->cti);
744 
745  trk = &ct->ct_paths[path_idx];
746  ep = &trk->ct_ep[direction];
747 
748  if (!is_del && ep->ce_flags & CNAT_EP_FLAG_RESOLVED)
749  return;
750 
751  ASSERT (ep->ce_sw_if_index == ar->sw_if_index);
752 
753  if (is_del)
754  {
756  /* Are there remaining addresses ? */
757  if (0 == cnat_resolve_addr (ar->sw_if_index, ar->af, address))
758  is_del = 0;
759  }
760 
761  if (!is_del)
762  {
763  ip_address_copy (&ep->ce_ip, address);
765  }
766 
768  cnat_tracker_track (ar->cti, trk);
769 
772 }
773 
774 static void
776  u8 is_del)
777 {
778  addr_resolution_t *ar;
779  pool_foreach (ar, tr_resolutions)
780  {
781  if (ar->sw_if_index != sw_if_index)
782  continue;
783  if (ar->af != ip_addr_version (address))
784  continue;
785  cnat_if_addr_add_cbs[ar->type](ar, address, is_del);
786  }
787 }
788 
789 static void
791  uword opaque, u32 sw_if_index,
792  ip6_address_t * address,
793  u32 address_length, u32 if_address_index,
794  u32 is_del)
795 {
797  ip_address_set (&addr, address, AF_IP6);
798  cnat_if_addr_add_del_callback (sw_if_index, &addr, is_del);
799 }
800 
801 static void
803  uword opaque, u32 sw_if_index,
805  u32 address_length, u32 if_address_index,
806  u32 is_del)
807 {
809  ip_address_set (&addr, address, AF_IP4);
810  cnat_if_addr_add_del_callback (sw_if_index, &addr, is_del);
811 }
812 
813 void
816 {
818  cnat_if_addr_add_cbs[typ] = fn;
819 }
820 
821 static clib_error_t *
823 {
824  ip4_main_t *i4m = &ip4_main;
825  ip6_main_t *i6m = &ip6_main;
828  fib_node_register_new_type (&cnat_translation_vft);
829 
830  clib_bihash_init_8_8 (&cnat_translation_db, "CNat translation DB",
833 
837 
841 
846 
847  return (NULL);
848 }
849 
851 
852 /*
853  * fd.io coding-style-patch-verification: ON
854  *
855  * Local Variables:
856  * eval: (c-set-style "gnu")
857  * End:
858  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:524
walk_rc_t(* cnat_translation_walk_cb_t)(index_t index, void *ctx)
Callback function invoked during a walk of all translations.
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:211
dpo_type_t cnat_client_dpo
Definition: cnat_client.c:26
static fib_node_back_walk_rc_t cnat_translation_back_walk_notify(fib_node_t *node, fib_node_back_walk_ctx_t *ctx)
format_function_t format_ip_protocol
Definition: format.h:45
unformat_function_t unformat_ip_protocol
Definition: format.h:46
#define ip_addr_v6(_a)
Definition: ip_types.h:92
fib_node_index_t fib_entry_track(u32 fib_index, const fib_prefix_t *prefix, fib_node_type_t child_type, index_t child_index, u32 *sibling)
Trackers are used on FIB entries by objects that which to track the changing state of the entry...
#define pool_foreach_index(i, v)
Definition: pool.h:576
void vlib_validate_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
validate a combined counter
Definition: counter.c:119
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:141
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:105
a
Definition: bitmap.h:544
static int cnat_maglev_entry_compare(void *_a, void *_b)
static_always_inline cnat_translation_t * cnat_translation_get(index_t cti)
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:258
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
unsigned long u64
Definition: types.h:89
static void cnat_if_addr_add_del_backend_cb(addr_resolution_t *ar, ip_address_t *address, u8 is_del)
vnet_feature_config_main_t * cm
static clib_error_t * cnat_translation_cli_add_del(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
enum fib_node_back_walk_rc_t_ fib_node_back_walk_rc_t
Return code from a back walk function.
void fib_entry_contribute_forwarding(fib_node_index_t fib_entry_index, fib_forward_chain_type_t fct, dpo_id_t *dpo)
Definition: fib_entry.c:437
static void cnat_tracker_release(cnat_ep_trk_t *trk)
static void cnat_translation_last_lock_gone(fib_node_t *node)
ip_protocol_t ct_proto
The ip protocol for the translation.
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:43
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:607
static void cnat_add_translation_to_db(index_t cci, cnat_endpoint_t *vip, ip_protocol_t proto, index_t cti)
Add a translation to the bihash.
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:645
A Translation represents the translation of a VEP to one of a set of real server addresses.
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
Definition: bitmap.h:167
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:73
cnat_endpoint_t src_ep
Definition: cnat_types.h:84
index_t parent_cci
Parent cnat_client index if cloned via interpose or own index if vanilla client.
Definition: cnat_client.h:74
vl_api_fib_path_t path
Definition: mfib_types.api:44
u32 maglev_len
Definition: cnat_types.h:142
static void cnat_if_addr_add_del_translation_cb(addr_resolution_t *ar, ip_address_t *address, u8 is_del)
#define ip_addr_version(_a)
Definition: ip_types.h:93
u8 ct_flags
Allows to disable if not resolved yet.
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:255
index_t cnat_client_add(const ip_address_t *ip, u8 flags)
Definition: cnat_client.c:137
vhost_vring_addr_t addr
Definition: vhost_user.h:130
cnat_if_addr_add_cb_t * cnat_if_addr_add_cbs
#define hash_v3_mix32(a, b, c)
Definition: hash.h:554
unsigned char u8
Definition: types.h:56
vlib_buffer_t ** b
u32 sw_if_index
The interface index to resolve.
#define clib_bitmap_zero(v)
Clear a bitmap.
Definition: bitmap.h:102
fib_node_type_t fib_node_register_new_type(const fib_node_vft_t *vft)
Create a new FIB node type and Register the function table for it.
Definition: fib_node.c:80
cnat_translation_t * cnat_translation_pool
uword unformat_cnat_lb_type(unformat_input_t *input, va_list *args)
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static void cnat_resolve_ep_tuple(cnat_endpoint_tuple_t *path)
unsigned int u32
Definition: types.h:88
#define clib_memcpy(d, s, n)
Definition: string.h:197
index_t load_balance_create(u32 n_buckets, dpo_proto_t lb_proto, flow_hash_config_t fhc)
Definition: load_balance.c:266
u64 opaque
Callback data.
uword unformat_cnat_ep(unformat_input_t *input, va_list *args)
Definition: cnat_types.c:73
cnat_endpoint_t dst_ep
Definition: cnat_types.h:83
void cnat_translation_watch_addr(index_t cti, u64 opaque, cnat_endpoint_t *ep, cnat_addr_resol_type_t type)
Add an address resolution request.
load_balance_t * load_balance_pool
Pool of all DPOs.
Definition: load_balance.c:54
cnat_endpoint_t ct_vip
The Virtual end point.
static_always_inline cnat_translation_t * cnat_find_translation(index_t cti, u16 port, ip_protocol_t proto)
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
description fragment has unexpected format
Definition: map.api:433
Aggregate type for a prefix.
Definition: fib_types.h:202
#define clib_error_return(e, args...)
Definition: error.h:99
void ip_address_to_fib_prefix(const ip_address_t *addr, fib_prefix_t *prefix)
convert from a IP address to a FIB prefix
Definition: ip_types.c:270
cnat_lb_type_t lb_type
Type of load balancing.
u32 skip
cnat_addr_resol_type_t
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
int __clib_unused rv
Definition: application.c:491
void cnat_translation_unwatch_addr(u32 cti, cnat_addr_resol_type_t type)
Cleanup matching addr resolution requests.
static cnat_translation_t * cnat_translation_get_from_node(fib_node_t *node)
direction
int cnat_translation_purge(void)
Purge all the trahslations.
while(n_left_from > 0)
unformat_function_t unformat_line_input
Definition: format.h:275
vl_api_fib_path_type_t type
Definition: fib_types.api:123
void ip_address_set(ip_address_t *dst, const void *src, ip_address_family_t af)
Definition: ip_types.c:207
enum ip_protocol ip_protocol_t
u16 * next
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:553
static void vlib_zero_combined_counter(vlib_combined_counter_main_t *cm, u32 index)
Clear a combined counter Clears the set of per-thread counters.
Definition: counter.h:298
vl_api_interface_index_t sw_if_index
Definition: wireguard.api:34
index_t ct_cci
The client object this translation belongs on INDEX_INVALID if vip is unresolved. ...
int cnat_translation_delete(u32 id)
Delete a translation.
vl_api_ip_proto_t proto
Definition: acl_types.api:51
u64 key
the key
Definition: bihash_8_8.h:43
long ctx[MAX_CONNS]
Definition: main.c:144
struct _unformat_input_t unformat_input_t
static clib_error_t * cnat_translation_init(vlib_main_t *vm)
load-balancing over a choice of [un]equal cost paths
Definition: dpo.h:104
u8 * format_cnat_lb_type(u8 *s, va_list *args)
static void cnat_translation_stack(cnat_translation_t *ct)
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
dpo_id_t ct_dpo
The forwarding contributed by the entry.
u32 * tmp
static void cnat_translation_init_maglev(cnat_translation_t *ct)
cnat_addr_resol_type_t type
The cnat_addr_resolution_t.
u8 * format_cnat_endpoint(u8 *s, va_list *args)
Definition: cnat_types.c:134
ip6_main_t ip6_main
Definition: ip6_forward.c:2787
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
__clib_export u8 * format_bitmap_hex(u8 *s, va_list *args)
Format a bitmap as a string of hex bytes.
Definition: bitmap.c:107
#define IP_FLOW_HASH_DEFAULT
Default: 5-tuple + flowlabel without the "reverse" bit.
Definition: ip_flow_hash.h:22
An node in the FIB graph.
Definition: fib_node.h:301
static fib_node_type_t cnat_translation_fib_node_type
u32 cnat_translation_update(cnat_endpoint_t *vip, ip_protocol_t proto, cnat_endpoint_tuple_t *paths, u8 flags, cnat_lb_type_t lb_type)
create or update a translation
ip6_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Definition: ip6.h:148
cnat_ep_trk_t * ct_paths
The vector of tracked back-ends.
static_always_inline cnat_client_t * cnat_client_get(index_t i)
Definition: cnat_client.h:91
cnat_lb_type_t
#define clib_bitmap_alloc(v, n_bits)
Allocate a bitmap with the supplied number of bits.
Definition: bitmap.h:109
fib_node_t ct_node
Linkage into the FIB graph.
u64 value
the value
Definition: bihash_8_8.h:44
void cnat_translation_register_addr_add_cb(cnat_addr_resol_type_t typ, cnat_if_addr_add_cb_t fn)
#define UNFORMAT_END_OF_INPUT
Definition: format.h:137
#define hash_mix64(a0, b0, c0)
Definition: hash.h:531
svmdb_client_t * c
static void cnat_tracker_track(index_t cti, cnat_ep_trk_t *trk)
void cnat_client_translation_added(index_t cci)
A translation that references this VIP was added.
Definition: cnat_client.c:97
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:261
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:395
u32 index
Definition: flow_types.api:221
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:75
u32 offset
addr_resolution_t * tr_resolutions
fib_node_get_t fnv_get
Definition: fib_node.h:289
vnet_interface_main_t * im
Entry used to account for a translation&#39;s backend waiting for address resolution. ...
static fib_node_t * cnat_translation_get_node(fib_node_index_t index)
static u8 * format_cnat_ep_trk(u8 *s, va_list *args)
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
cnat_endpoint_t ct_ep[VLIB_N_DIR]
The EP being tracked.
8 octet key, 8 octet key value pair
Definition: bihash_8_8.h:41
fib_protocol_t ip_address_family_to_fib_proto(ip_address_family_t af)
Definition: ip_types.c:223
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
Definition: dpo.c:188
Context passed between object during a back walk.
Definition: fib_node.h:214
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:163
static void cnat_if_addr_add_del_callback(u32 sw_if_index, ip_address_t *address, u8 is_del)
u32 index
ip6_add_del_interface_address_function_t * function
Definition: ip6.h:96
static clib_error_t * cnat_translation_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
ip_address_family_t af
ip4 or ip6 resolution
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:337
#define ASSERT(truth)
void fib_entry_untrack(fib_node_index_t fei, u32 sibling)
Stop tracking a FIB entry.
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:716
#define ip_addr_v4(_a)
Definition: ip_types.h:91
manual_print typedef address
Definition: ip_types.api:96
dpo_id_t ct_lb
The LB used to forward to the backends.
void cnat_client_translation_deleted(index_t cci)
A translation that references this VIP was deleted.
Definition: cnat_client.c:108
#define hash_v3_finalize32(a, b, c)
Definition: hash.h:564
IPv4 main type.
Definition: ip4.h:107
static void cnat_remove_translation_from_db(index_t cci, cnat_endpoint_t *vip, ip_protocol_t proto)
Remove a translation from the bihash.
u8 * format_cnat_translation(u8 *s, va_list *args)
ip_address_family_t version
Definition: ip_types.h:82
index_t cti
Translation index.
static void cnat_ip4_if_addr_add_del_callback(struct ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_del)
#define clib_bitmap_free(v)
Free a bitmap.
Definition: bitmap.h:92
u8 cnat_resolve_addr(u32 sw_if_index, ip_address_family_t af, ip_address_t *addr)
Definition: cnat_types.c:29
int ip_address_cmp(const ip_address_t *ip1, const ip_address_t *ip2)
Definition: ip_types.c:117
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:343
#define vec_set(v, val)
Set all vector elements to given value.
Definition: vec.h:1006
void load_balance_set_bucket(index_t lbi, u32 bucket, const dpo_id_t *next)
Definition: load_balance.c:283
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject.
Definition: dpo.c:150
u32 translation_hash_buckets
Definition: cnat_types.h:106
typedef key
Definition: ipsec_types.api:88
void cnat_translation_walk(cnat_translation_walk_cb_t cb, void *ctx)
Walk/visit each of the translations.
paths
Definition: map.api:460
cnat_ep_trk_t * ct_active_paths
The vector of active tracked back-ends.
Definition: defs.h:47
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:190
cnat_ep_trk_t * trk
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_main_t vlib_node_runtime_t * node
Definition: nat44_ei.c:3047
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:49
uword unformat_cnat_ep_tuple(unformat_input_t *input, va_list *args)
Definition: cnat_types.c:115
#define CNAT_FIB_TABLE
Definition: cnat_types.h:27
u64 uword
Definition: types.h:112
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:1098
static void unformat_free(unformat_input_t *i)
Definition: format.h:155
cnat_main_t cnat_main
Definition: cnat_types.c:18
clib_bihash_8_8_t cnat_translation_db
char * name
The counter collection&#39;s name.
Definition: counter.h:206
void(* cnat_if_addr_add_cb_t)(addr_resolution_t *ar, ip_address_t *address, u8 is_del)
Register a call back for endpoint->address resolution.
fib_node_index_t ct_fei
The FIB entry for the EP.
uword translation_hash_memory
Definition: cnat_types.h:103
A collection of combined counters.
Definition: counter.h:203
A FIB graph nodes virtual function table.
Definition: fib_node.h:288
enum fib_node_type_t_ fib_node_type_t
The types of nodes in a FIB graph.
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
void ip_address_copy(ip_address_t *dst, const ip_address_t *src)
Definition: ip_types.c:133
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1105
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:234
#define vec_foreach(var, vec)
Vector iterator.
ip_address_t ce_ip
Definition: cnat_types.h:75
import vnet interface_types api
Definition: sample.api:20
Data used to track an EP in the FIB.
u8 cnat_resolve_ep(cnat_endpoint_t *ep)
Resolve endpoint address.
Definition: cnat_types.c:63
static void cnat_ip6_if_addr_add_del_callback(struct ip6_main_t *im, uword opaque, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 if_address_index, u32 is_del)
index_t index
Own index (if copied for trace)
void cnat_lazy_init()
Lazy initialization when first adding a translation or using snat.
Definition: cnat_types.c:176
u8 flags
Translation flags.
fib_forward_chain_type_t fib_forw_chain_type_from_fib_proto(fib_protocol_t proto)
Convert from a fib-protocol to a chain type.
Definition: fib_types.c:449
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
Definition: defs.h:46
vl_api_cnat_lb_type_t lb_type
Definition: cnat.api:71
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:163
A client is a representation of an IP address behind the NAT.
Definition: cnat_client.h:35
void dpo_stack(dpo_type_t child_type, dpo_proto_t child_proto, dpo_id_t *dpo, const dpo_id_t *parent)
Stack one DPO object on another, and thus establish a child-parent relationship.
Definition: dpo.c:535
u32 ct_sibling
The sibling on the entry&#39;s child list.
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127