FD.io VPP  v19.04.4-rc0-5-ge88582fac
Vector Packet Processing
lookup.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 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  * ip/ip_lookup.c: ip4/6 adjacency and lookup table managment
17  *
18  * Copyright (c) 2008 Eliot Dresselhaus
19  *
20  * Permission is hereby granted, free of charge, to any person obtaining
21  * a copy of this software and associated documentation files (the
22  * "Software"), to deal in the Software without restriction, including
23  * without limitation the rights to use, copy, modify, merge, publish,
24  * distribute, sublicense, and/or sell copies of the Software, and to
25  * permit persons to whom the Software is furnished to do so, subject to
26  * the following conditions:
27  *
28  * The above copyright notice and this permission notice shall be
29  * included in all copies or substantial portions of the Software.
30  *
31  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38  */
39 
40 #include <vnet/ip/ip.h>
41 #include <vnet/adj/adj.h>
42 #include <vnet/fib/fib_table.h>
43 #include <vnet/fib/ip4_fib.h>
44 #include <vnet/fib/ip6_fib.h>
45 #include <vnet/mpls/mpls.h>
46 #include <vnet/mfib/mfib_table.h>
47 #include <vnet/dpo/drop_dpo.h>
48 #include <vnet/dpo/classify_dpo.h>
49 #include <vnet/dpo/punt_dpo.h>
50 #include <vnet/dpo/receive_dpo.h>
51 #include <vnet/dpo/ip_null_dpo.h>
52 #include <vnet/dpo/l3_proxy_dpo.h>
53 #include <vnet/ip/ip6_neighbor.h>
54 #include <vnet/ethernet/arp.h>
55 
56 /**
57  * @file
58  * @brief IPv4 and IPv6 adjacency and lookup table managment.
59  *
60  */
61 
65  void *addr_fib,
67  u32 is_del, u32 * result_if_address_index)
68 {
69  vnet_main_t *vnm = vnet_get_main ();
70  ip_interface_address_t *a, *prev, *next;
71  uword *p = mhash_get (&lm->address_to_if_address_index, addr_fib);
72 
74  sw_if_index, ~0);
75  a = p ? pool_elt_at_index (lm->if_address_pool, p[0]) : 0;
76 
77  /* Verify given length. */
78  if ((a && (address_length != a->address_length)) ||
79  (address_length == 0) ||
80  (lm->is_ip6 && address_length > 128) ||
81  (!lm->is_ip6 && address_length > 32))
82  {
83  vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
84  return clib_error_create
85  ("%U wrong length (expected %d) for interface %U",
86  lm->format_address_and_length, addr_fib,
87  address_length, a ? a->address_length : -1,
88  format_vnet_sw_if_index_name, vnm, sw_if_index);
89  }
90 
91  if (is_del)
92  {
93  if (!a)
94  {
95  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
96  vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
97  return clib_error_create ("%U not found for interface %U",
99  addr_fib, address_length,
101  }
102 
103  if (a->prev_this_sw_interface != ~0)
104  {
105  prev =
109  }
110  if (a->next_this_sw_interface != ~0)
111  {
112  next =
116 
117  if (a->prev_this_sw_interface == ~0)
120  }
121 
122  if ((a->next_this_sw_interface == ~0)
123  && (a->prev_this_sw_interface == ~0))
125 
127  /* old_value */ 0);
128  pool_put (lm->if_address_pool, a);
129 
130  if (result_if_address_index)
131  *result_if_address_index = ~0;
132  }
133 
134  else if (!a)
135  {
136  u32 pi; /* previous index */
137  u32 ai;
138  u32 hi; /* head index */
139 
140  pool_get (lm->if_address_pool, a);
141  clib_memset (a, ~0, sizeof (a[0]));
142  ai = a - lm->if_address_pool;
143 
145  prev = 0;
146  while (pi != (u32) ~ 0)
147  {
148  prev = pool_elt_at_index (lm->if_address_pool, pi);
149  pi = prev->next_this_sw_interface;
150  }
151  pi = prev ? prev - lm->if_address_pool : (u32) ~ 0;
152 
154  addr_fib, ai, /* old_value */ 0);
157  a->flags = 0;
158  a->prev_this_sw_interface = pi;
159  a->next_this_sw_interface = ~0;
160  if (prev)
161  prev->next_this_sw_interface = ai;
162 
164  (hi != ~0) ? hi : ai;
165  if (result_if_address_index)
166  *result_if_address_index = ai;
167  }
168  else
169  {
170  if (sw_if_index != a->sw_if_index)
171  {
172  if (result_if_address_index)
173  *result_if_address_index = ~0;
174  vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS;
175  return clib_error_create
176  ("Prefix %U already found on interface %U",
177  lm->format_address_and_length, addr_fib, address_length,
179  }
180 
181  if (result_if_address_index)
182  *result_if_address_index = a - lm->if_address_pool;
183  }
184 
185  return /* no error */ 0;
186 }
187 
188 static clib_error_t *
190 {
192  lookup_main.if_address_pool_index_by_sw_if_index,
193  sw_if_index, ~0);
195  lookup_main.if_address_pool_index_by_sw_if_index,
196  sw_if_index, ~0);
197 
198  return (NULL);
199 }
200 
202 
203 void
205 {
206  if (!lm->fib_result_n_bytes)
207  lm->fib_result_n_bytes = sizeof (uword);
208 
209  lm->is_ip6 = is_ip6;
210  if (is_ip6)
211  {
214  sizeof (ip6_address_fib_t));
215  }
216  else
217  {
220  sizeof (ip4_address_fib_t));
221  }
222 
223  {
224  int i;
225 
226  /* Setup all IP protocols to be punted and builtin-unknown. */
227  for (i = 0; i < 256; i++)
228  {
231  }
232 
234  lm->local_next_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
235  IP_PROTOCOL_ICMP] = IP_LOCAL_NEXT_ICMP;
236  lm->builtin_protocol_by_ip_protocol[IP_PROTOCOL_UDP] =
238  lm->builtin_protocol_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
239  IP_PROTOCOL_ICMP] =
241  }
242 }
243 
244 u8 *
245 format_ip_flow_hash_config (u8 * s, va_list * args)
246 {
247  flow_hash_config_t flow_hash_config = va_arg (*args, u32);
248 
249 #define _(n,v) if (flow_hash_config & v) s = format (s, "%s ", #n);
251 #undef _
252 
253  return s;
254 }
255 
256 u8 *
257 format_ip_adjacency_packet_data (u8 * s, va_list * args)
258 {
259  u32 adj_index = va_arg (*args, u32);
260  u8 *packet_data = va_arg (*args, u8 *);
261  u32 n_packet_data_bytes = va_arg (*args, u32);
262  ip_adjacency_t *adj = adj_get (adj_index);
263 
264  switch (adj->lookup_next_index)
265  {
268  s =
269  format (s, "%U", format_hex_bytes, packet_data, n_packet_data_bytes);
270  break;
271 
272  default:
273  break;
274  }
275 
276  return s;
277 }
278 
279 static uword
280 unformat_dpo (unformat_input_t * input, va_list * args)
281 {
282  dpo_id_t *dpo = va_arg (*args, dpo_id_t *);
283  fib_protocol_t fp = va_arg (*args, int);
284  dpo_proto_t proto;
285 
286  proto = fib_proto_to_dpo (fp);
287 
288  if (unformat (input, "drop"))
289  dpo_copy (dpo, drop_dpo_get (proto));
290  else if (unformat (input, "punt"))
291  dpo_copy (dpo, punt_dpo_get (proto));
292  else if (unformat (input, "local"))
293  receive_dpo_add_or_lock (proto, ~0, NULL, dpo);
294  else if (unformat (input, "null-send-unreach"))
296  else if (unformat (input, "null-send-prohibit"))
298  else if (unformat (input, "null"))
300  else if (unformat (input, "classify"))
301  {
302  u32 classify_table_index;
303 
304  if (!unformat (input, "%d", &classify_table_index))
305  {
306  clib_warning ("classify adj must specify table index");
307  return 0;
308  }
309 
310  dpo_set (dpo, DPO_CLASSIFY, proto,
311  classify_dpo_create (proto, classify_table_index));
312  }
313  else
314  return 0;
315 
316  return 1;
317 }
318 
319 const ip46_address_t zero_addr = {
320  .as_u64 = {
321  0, 0},
322 };
323 
324 static clib_error_t *
326  unformat_input_t * main_input, vlib_cli_command_t * cmd)
327 {
328  unformat_input_t _line_input, *line_input = &_line_input;
329  u32 table_id, is_del, fib_index, payload_proto;
330  dpo_id_t dpo = DPO_INVALID, *dpos = NULL;
331  fib_route_path_t *rpaths = NULL, rpath;
332  fib_prefix_t *prefixs = NULL, pfx;
333  clib_error_t *error = NULL;
334  f64 count;
335  int i;
336 
337  is_del = 0;
338  table_id = 0;
339  count = 1;
340  clib_memset (&pfx, 0, sizeof (pfx));
341 
342  /* Get a line of input. */
343  if (!unformat_user (main_input, unformat_line_input, line_input))
344  return 0;
345 
346  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
347  {
348  clib_memset (&rpath, 0, sizeof (rpath));
349 
350  if (unformat (line_input, "table %d", &table_id))
351  ;
352  else if (unformat (line_input, "count %f", &count))
353  ;
354 
355  else if (unformat (line_input, "%U/%d",
356  unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len))
357  {
358  payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP4;
359  vec_add1 (prefixs, pfx);
360  }
361  else if (unformat (line_input, "%U/%d",
362  unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len))
363  {
364  payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP6;
365  vec_add1 (prefixs, pfx);
366  }
367  else if (unformat (line_input, "via %U",
368  unformat_fib_route_path, &rpath, &payload_proto))
369  {
370  vec_add1 (rpaths, rpath);
371  }
372  else if (vec_len (prefixs) > 0 &&
373  unformat (line_input, "via %U",
374  unformat_dpo, &dpo, prefixs[0].fp_proto))
375  {
376  vec_add1 (dpos, dpo);
377  }
378  else if (unformat (line_input, "del"))
379  is_del = 1;
380  else if (unformat (line_input, "add"))
381  is_del = 0;
382  else
383  {
384  error = unformat_parse_error (line_input);
385  goto done;
386  }
387  }
388 
389  if (vec_len (prefixs) == 0)
390  {
391  error =
392  clib_error_return (0, "expected ip4/ip6 destination address/length.");
393  goto done;
394  }
395 
396  if (!is_del && vec_len (rpaths) + vec_len (dpos) == 0)
397  {
398  error = clib_error_return (0, "expected paths.");
399  goto done;
400  }
401 
402  if (~0 == table_id)
403  {
404  /*
405  * if no table_id is passed we will manipulate the default
406  */
407  fib_index = 0;
408  }
409  else
410  {
411  fib_index = fib_table_find (prefixs[0].fp_proto, table_id);
412 
413  if (~0 == fib_index)
414  {
415  error = clib_error_return (0, "Nonexistent table id %d", table_id);
416  goto done;
417  }
418  }
419 
420  for (i = 0; i < vec_len (prefixs); i++)
421  {
422  if (is_del && 0 == vec_len (rpaths))
423  {
424  fib_table_entry_delete (fib_index, &prefixs[i], FIB_SOURCE_CLI);
425  }
426  else if (!is_del && 1 == vec_len (dpos))
427  {
429  &prefixs[i],
432  &dpos[0]);
433  dpo_reset (&dpos[0]);
434  }
435  else if (vec_len (dpos) > 0)
436  {
437  error =
439  "Load-balancing over multiple special adjacencies is unsupported");
440  goto done;
441  }
442  else if (0 < vec_len (rpaths))
443  {
444  u32 k, j, n, incr;
445  ip46_address_t dst = prefixs[i].fp_addr;
446  f64 t[2];
447  n = count;
448  t[0] = vlib_time_now (vm);
449  incr = 1 << ((FIB_PROTOCOL_IP4 == prefixs[0].fp_proto ? 32 : 128) -
450  prefixs[i].fp_len);
451 
452  for (k = 0; k < n; k++)
453  {
454  for (j = 0; j < vec_len (rpaths); j++)
455  {
456  fib_prefix_t rpfx = {
457  .fp_len = prefixs[i].fp_len,
458  .fp_proto = prefixs[i].fp_proto,
459  .fp_addr = dst,
460  };
461 
462  if (is_del)
463  fib_table_entry_path_remove2 (fib_index,
464  &rpfx,
465  FIB_SOURCE_CLI, &rpaths[j]);
466  else
467  fib_table_entry_path_add2 (fib_index,
468  &rpfx,
471  &rpaths[j]);
472  }
473 
474  if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto)
475  {
476  dst.ip4.as_u32 =
477  clib_host_to_net_u32 (incr +
478  clib_net_to_host_u32 (dst.
479  ip4.as_u32));
480  }
481  else
482  {
483  int bucket = (incr < 64 ? 0 : 1);
484  dst.ip6.as_u64[bucket] =
485  clib_host_to_net_u64 (incr +
486  clib_net_to_host_u64 (dst.ip6.as_u64
487  [bucket]));
488 
489  }
490  }
491  t[1] = vlib_time_now (vm);
492  if (count > 1)
493  vlib_cli_output (vm, "%.6e routes/sec", count / (t[1] - t[0]));
494  }
495  else
496  {
497  error = clib_error_return (0, "Don't understand what you want...");
498  goto done;
499  }
500  }
501 
502 
503 done:
504  vec_free (dpos);
505  vec_free (prefixs);
506  vec_free (rpaths);
507  unformat_free (line_input);
508  return error;
509 }
510 
511 clib_error_t *
513  unformat_input_t * main_input,
514  vlib_cli_command_t * cmd, fib_protocol_t fproto)
515 {
516  unformat_input_t _line_input, *line_input = &_line_input;
517  clib_error_t *error = NULL;
518  u32 table_id, is_add;
519  u8 *name = NULL;
520 
521  is_add = 1;
522  table_id = ~0;
523 
524  /* Get a line of input. */
525  if (!unformat_user (main_input, unformat_line_input, line_input))
526  return 0;
527 
528  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
529  {
530  if (unformat (line_input, "%d", &table_id))
531  ;
532  else if (unformat (line_input, "del"))
533  is_add = 0;
534  else if (unformat (line_input, "add"))
535  is_add = 1;
536  else if (unformat (line_input, "name %s", &name))
537  ;
538  else
539  {
540  error = unformat_parse_error (line_input);
541  goto done;
542  }
543  }
544 
545  if (~0 == table_id)
546  {
547  error = clib_error_return (0, "No table id");
548  goto done;
549  }
550  else if (0 == table_id)
551  {
552  error = clib_error_return (0, "Can't change the default table");
553  goto done;
554  }
555  else
556  {
557  if (is_add)
558  {
559  ip_table_create (fproto, table_id, 0, name);
560  }
561  else
562  {
563  ip_table_delete (fproto, table_id, 0);
564  }
565  }
566 
567 done:
568  unformat_free (line_input);
569  return error;
570 }
571 
572 clib_error_t *
574  unformat_input_t * main_input, vlib_cli_command_t * cmd)
575 {
576  return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4));
577 }
578 
579 clib_error_t *
581  unformat_input_t * main_input, vlib_cli_command_t * cmd)
582 {
583  return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6));
584 }
585 
586 /* *INDENT-OFF* */
587 VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
588  .path = "ip",
589  .short_help = "Internet protocol (IP) commands",
590 };
591 /* *INDENT-ON* */
592 
593 /* *INDENT-OFF* */
594 VLIB_CLI_COMMAND (vlib_cli_ip6_command, static) = {
595  .path = "ip6",
596  .short_help = "Internet protocol version 6 (IPv6) commands",
597 };
598 /* *INDENT-ON* */
599 
600 /* *INDENT-OFF* */
601 VLIB_CLI_COMMAND (vlib_cli_show_ip_command, static) = {
602  .path = "show ip",
603  .short_help = "Internet protocol (IP) show commands",
604 };
605 /* *INDENT-ON* */
606 
607 /* *INDENT-OFF* */
608 VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
609  .path = "show ip6",
610  .short_help = "Internet protocol version 6 (IPv6) show commands",
611 };
612 /* *INDENT-ON* */
613 
614 /*?
615  * This command is used to add or delete IPv4 or IPv6 routes. All
616  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
617  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
618  * can be IPv4 or IPv6, but all must be of the same form in a single
619  * command. To display the current set of routes, use the commands
620  * '<em>show ip fib</em>' and '<em>show ip6 fib</em>'.
621  *
622  * @cliexpar
623  * Example of how to add a straight forward static route:
624  * @cliexcmd{ip route add 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
625  * Example of how to delete a straight forward static route:
626  * @cliexcmd{ip route del 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
627  * Mainly for route add/del performance testing, one can add or delete
628  * multiple routes by adding 'count N' to the previous item:
629  * @cliexcmd{ip route add count 10 7.0.0.0/24 via 6.0.0.1 GigabitEthernet2/0/0}
630  * Add multiple routes for the same destination to create equal-cost multipath:
631  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0}
632  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0}
633  * For unequal-cost multipath, specify the desired weights. This
634  * combination of weights results in 3/4 of the traffic following the
635  * second path, 1/4 following the first path:
636  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0 weight 1}
637  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3}
638  * To add a route to a particular FIB table (VRF), use:
639  * @cliexcmd{ip route add 172.16.24.0/24 table 7 via GigabitEthernet2/0/0}
640  ?*/
641 /* *INDENT-OFF* */
642 VLIB_CLI_COMMAND (ip_route_command, static) = {
643  .path = "ip route",
644  .short_help = "ip route [add|del] [count <n>] <dst-ip-addr>/<width> [table <table-id>] via [next-hop-address] [next-hop-interface] [next-hop-table <value>] [weight <value>] [preference <value>] [udp-encap-id <value>] [ip4-lookup-in-table <value>] [ip6-lookup-in-table <value>] [mpls-lookup-in-table <value>] [resolve-via-host] [resolve-via-connected] [rx-ip4 <interface>] [out-labels <value value value>]",
645  .function = vnet_ip_route_cmd,
646  .is_mp_safe = 1,
647 };
648 
649 /* *INDENT-ON* */
650 /*?
651  * This command is used to add or delete IPv4 Tables. All
652  * Tables must be explicitly added before that can be used. Creating a
653  * table will add both unicast and multicast FIBs
654  *
655  ?*/
656 /* *INDENT-OFF* */
657 VLIB_CLI_COMMAND (ip4_table_command, static) = {
658  .path = "ip table",
659  .short_help = "ip table [add|del] <table-id>",
660  .function = vnet_ip4_table_cmd,
661  .is_mp_safe = 1,
662 };
663 /* *INDENT-ON* */
664 
665 /* *INDENT-ON* */
666 /*?
667  * This command is used to add or delete IPv4 Tables. All
668  * Tables must be explicitly added before that can be used. Creating a
669  * table will add both unicast and multicast FIBs
670  *
671  ?*/
672 /* *INDENT-OFF* */
673 VLIB_CLI_COMMAND (ip6_table_command, static) = {
674  .path = "ip6 table",
675  .short_help = "ip6 table [add|del] <table-id>",
676  .function = vnet_ip6_table_cmd,
677  .is_mp_safe = 1,
678 };
679 
680 static clib_error_t *
682  unformat_input_t * input,
683  vlib_cli_command_t * cmd,
684  fib_protocol_t fproto)
685 {
686  vnet_main_t *vnm = vnet_get_main ();
687  clib_error_t *error = 0;
688  u32 sw_if_index, table_id;
689  int rv;
690 
691  sw_if_index = ~0;
692 
693  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
694  {
695  error = clib_error_return (0, "unknown interface `%U'",
696  format_unformat_error, input);
697  goto done;
698  }
699 
700  if (unformat (input, "%d", &table_id))
701  ;
702  else
703  {
704  error = clib_error_return (0, "expected table id `%U'",
705  format_unformat_error, input);
706  goto done;
707  }
708 
709  rv = ip_table_bind (fproto, sw_if_index, table_id, 0);
710 
711  if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv)
712  {
713  error = clib_error_return (0, "IP addresses are still present on %U",
715  vnet_get_main(),
716  sw_if_index);
717  }
718  else if (VNET_API_ERROR_NO_SUCH_FIB == rv)
719  {
720  error = clib_error_return (0, "no such table %d", table_id);
721  }
722  else if (0 != rv)
723  {
724  error = clib_error_return (0, "unknown error");
725  }
726 
727  done:
728  return error;
729 }
730 
731 static clib_error_t *
733  unformat_input_t * input,
734  vlib_cli_command_t * cmd)
735 {
736  return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP4));
737 }
738 
739 static clib_error_t *
741  unformat_input_t * input,
742  vlib_cli_command_t * cmd)
743 {
744  return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP6));
745 }
746 
747 /*?
748  * Place the indicated interface into the supplied IPv4 FIB table (also known
749  * as a VRF). The FIB table must be created using "ip table add" already. To
750  * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
751  * FIB table will only be displayed if a route has been added to the table, or
752  * an IP Address is assigned to an interface in the table (which adds a route
753  * automatically).
754  *
755  * @note IP addresses added after setting the interface IP table are added to
756  * the indicated FIB table. If an IP address is added prior to changing the
757  * table then this is an error. The control plane must remove these addresses
758  * first and then change the table. VPP will not automatically move the
759  * addresses from the old to the new table as it does not know the validity
760  * of such a change.
761  *
762  * @cliexpar
763  * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
764  * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
765  ?*/
766 /* *INDENT-OFF* */
767 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
768 {
769  .path = "set interface ip table",
770  .function = ip4_table_bind_cmd,
771  .short_help = "set interface ip table <interface> <table-id>",
772 };
773 /* *INDENT-ON* */
774 
775 /*?
776  * Place the indicated interface into the supplied IPv6 FIB table (also known
777  * as a VRF). The FIB table must be created using "ip6 table add" already. To
778  * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
779  * FIB table will only be displayed if a route has been added to the table, or
780  * an IP Address is assigned to an interface in the table (which adds a route
781  * automatically).
782  *
783  * @note IP addresses added after setting the interface IP table are added to
784  * the indicated FIB table. If an IP address is added prior to changing the
785  * table then this is an error. The control plane must remove these addresses
786  * first and then change the table. VPP will not automatically move the
787  * addresses from the old to the new table as it does not know the validity
788  * of such a change.
789  *
790  * @cliexpar
791  * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id):
792  * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
793  ?*/
794 /* *INDENT-OFF* */
795 VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
796 {
797  .path = "set interface ip6 table",
798  .function = ip6_table_bind_cmd,
799  .short_help = "set interface ip6 table <interface> <table-id>"
800 };
801 /* *INDENT-ON* */
802 
803 clib_error_t *
805  unformat_input_t * main_input, vlib_cli_command_t * cmd)
806 {
807  unformat_input_t _line_input, *line_input = &_line_input;
808  clib_error_t *error = NULL;
809  fib_route_path_t rpath;
810  u32 table_id, is_del;
811  vnet_main_t *vnm;
812  mfib_prefix_t pfx;
813  u32 fib_index;
814  mfib_itf_flags_t iflags = 0;
815  mfib_entry_flags_t eflags = 0;
816  u32 gcount, scount, ss, gg, incr;
817  f64 timet[2];
818  u32 rpf_id = MFIB_RPF_ID_NONE;
819 
820  gcount = scount = 1;
821  vnm = vnet_get_main ();
822  is_del = 0;
823  table_id = 0;
824  clib_memset (&pfx, 0, sizeof (pfx));
825  clib_memset (&rpath, 0, sizeof (rpath));
826  rpath.frp_sw_if_index = ~0;
827 
828  /* Get a line of input. */
829  if (!unformat_user (main_input, unformat_line_input, line_input))
830  return 0;
831 
832  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
833  {
834  if (unformat (line_input, "table %d", &table_id))
835  ;
836  else if (unformat (line_input, "del"))
837  is_del = 1;
838  else if (unformat (line_input, "add"))
839  is_del = 0;
840  else if (unformat (line_input, "rpf-id %d", &rpf_id))
841  ;
842  else if (unformat (line_input, "scount %d", &scount))
843  ;
844  else if (unformat (line_input, "gcount %d", &gcount))
845  ;
846  else if (unformat (line_input, "%U %U",
848  &pfx.fp_src_addr.ip4,
850  {
852  pfx.fp_len = 64;
853  }
854  else if (unformat (line_input, "%U %U",
856  &pfx.fp_src_addr.ip6,
858  {
860  pfx.fp_len = 256;
861  }
862  else if (unformat (line_input, "%U/%d",
864  &pfx.fp_grp_addr.ip4, &pfx.fp_len))
865  {
866  clib_memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
868  }
869  else if (unformat (line_input, "%U/%d",
871  &pfx.fp_grp_addr.ip6, &pfx.fp_len))
872  {
873  clib_memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
875  }
876  else if (unformat (line_input, "%U",
878  {
879  clib_memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
881  pfx.fp_len = 32;
882  }
883  else if (unformat (line_input, "%U",
885  {
886  clib_memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
888  pfx.fp_len = 128;
889  }
890  else if (unformat (line_input, "via %U %U %U",
891  unformat_ip4_address, &rpath.frp_addr.ip4,
893  &rpath.frp_sw_if_index,
894  unformat_mfib_itf_flags, &iflags))
895  {
896  rpath.frp_weight = 1;
897  }
898  else if (unformat (line_input, "via %U %U %U",
899  unformat_ip6_address, &rpath.frp_addr.ip6,
901  &rpath.frp_sw_if_index,
902  unformat_mfib_itf_flags, &iflags))
903  {
904  rpath.frp_weight = 1;
905  }
906  else if (unformat (line_input, "via %U %U",
908  &rpath.frp_sw_if_index,
909  unformat_mfib_itf_flags, &iflags))
910  {
911  clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
912  rpath.frp_weight = 1;
913  }
914  else if (unformat (line_input, "via %U %U",
915  unformat_ip4_address, &rpath.frp_addr.ip4,
917  &rpath.frp_sw_if_index))
918  {
919  rpath.frp_weight = 1;
920  }
921  else if (unformat (line_input, "via %U %U",
922  unformat_ip6_address, &rpath.frp_addr.ip6,
924  &rpath.frp_sw_if_index))
925  {
926  rpath.frp_weight = 1;
927  }
928  else if (unformat (line_input, "via %U",
930  &rpath.frp_sw_if_index))
931  {
932  clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
933  rpath.frp_weight = 1;
934  }
935  else if (unformat (line_input, "via local Forward"))
936  {
937  clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
938  rpath.frp_sw_if_index = ~0;
939  rpath.frp_weight = 1;
941  /*
942  * set the path proto appropriately for the prefix
943  */
944  rpath.frp_proto = fib_proto_to_dpo (pfx.fp_proto);
945  iflags = MFIB_ITF_FLAG_FORWARD;
946  }
947  else if (unformat (line_input, "%U",
948  unformat_mfib_entry_flags, &eflags))
949  ;
950  else
951  {
952  error = unformat_parse_error (line_input);
953  goto done;
954  }
955  }
956 
957  if (~0 == table_id)
958  {
959  /*
960  * if no table_id is passed we will manipulate the default
961  */
962  fib_index = 0;
963  }
964  else
965  {
966  fib_index = mfib_table_find (pfx.fp_proto, table_id);
967 
968  if (~0 == fib_index)
969  {
970  error = clib_error_return (0, "Nonexistent table id %d", table_id);
971  goto done;
972  }
973  }
974 
975  timet[0] = vlib_time_now (vm);
976 
977  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
978  {
979  incr = 1 << (32 - (pfx.fp_len % 32));
980  }
981  else
982  {
983  incr = 1 << (128 - (pfx.fp_len % 128));
984  }
985 
986  for (ss = 0; ss < scount; ss++)
987  {
988  for (gg = 0; gg < gcount; gg++)
989  {
990  if (is_del && 0 == rpath.frp_weight)
991  {
992  /* no path provided => route delete */
993  mfib_table_entry_delete (fib_index, &pfx, MFIB_SOURCE_CLI);
994  }
995  else if (eflags || (MFIB_RPF_ID_NONE != rpf_id))
996  {
997  mfib_table_entry_update (fib_index, &pfx, MFIB_SOURCE_CLI,
998  rpf_id, eflags);
999  }
1000  else
1001  {
1002  if (is_del)
1003  mfib_table_entry_path_remove (fib_index,
1004  &pfx, MFIB_SOURCE_CLI, &rpath);
1005  else
1006  mfib_table_entry_path_update (fib_index,
1007  &pfx, MFIB_SOURCE_CLI, &rpath,
1008  iflags);
1009  }
1010 
1011  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
1012  {
1013  pfx.fp_grp_addr.ip4.as_u32 =
1014  clib_host_to_net_u32 (incr +
1015  clib_net_to_host_u32 (pfx.
1016  fp_grp_addr.ip4.
1017  as_u32));
1018  }
1019  else
1020  {
1021  int bucket = (incr < 64 ? 0 : 1);
1022  pfx.fp_grp_addr.ip6.as_u64[bucket] =
1023  clib_host_to_net_u64 (incr +
1024  clib_net_to_host_u64 (pfx.
1025  fp_grp_addr.ip6.as_u64
1026  [bucket]));
1027 
1028  }
1029  }
1030  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
1031  {
1032  pfx.fp_src_addr.ip4.as_u32 =
1033  clib_host_to_net_u32 (1 +
1034  clib_net_to_host_u32 (pfx.fp_src_addr.
1035  ip4.as_u32));
1036  }
1037  else
1038  {
1039  pfx.fp_src_addr.ip6.as_u64[1] =
1040  clib_host_to_net_u64 (1 +
1041  clib_net_to_host_u64 (pfx.fp_src_addr.
1042  ip6.as_u64[1]));
1043  }
1044  }
1045 
1046  timet[1] = vlib_time_now (vm);
1047 
1048  if (scount > 1 || gcount > 1)
1049  vlib_cli_output (vm, "%.6e routes/sec",
1050  (scount * gcount) / (timet[1] - timet[0]));
1051 
1052 done:
1053  unformat_free (line_input);
1054 
1055  return error;
1056 }
1057 
1058 /*?
1059  * This command is used to add or delete IPv4 or IPv6 multicastroutes. All
1060  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
1061  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
1062  * can be IPv4 or IPv6, but all must be of the same form in a single
1063  * command. To display the current set of routes, use the commands
1064  * '<em>show ip mfib</em>' and '<em>show ip6 mfib</em>'.
1065  * The full set of support flags for interfaces and route is shown via;
1066  * '<em>show mfib route flags</em>' and '<em>show mfib itf flags</em>'
1067  * respectively.
1068  * @cliexpar
1069  * Example of how to add a forwarding interface to a route (and create the
1070  * route if it does not exist)
1071  * @cliexcmd{ip mroute add 232.1.1.1 via GigabitEthernet2/0/0 Forward}
1072  * Example of how to add an accepting interface to a route (and create the
1073  * route if it does not exist)
1074  * @cliexcmd{ip mroute add 232.1.1.1 via GigabitEthernet2/0/1 Accept}
1075  * Example of changing the route's flags to send signals via the API
1076  * @cliexcmd{ip mroute add 232.1.1.1 Signal}
1077 
1078  ?*/
1079 /* *INDENT-OFF* */
1080 VLIB_CLI_COMMAND (ip_mroute_command, static) =
1081 {
1082  .path = "ip mroute",
1083  .short_help = "ip mroute [add|del] <dst-ip-addr>/<width> [table <table-id>] [rpf-id <ID>] [via <next-hop-ip-addr> [<interface>],",
1084  .function = vnet_ip_mroute_cmd,
1085  .is_mp_safe = 1,
1086 };
1087 /* *INDENT-ON* */
1088 
1089 /*
1090  * The next two routines address a longstanding script hemorrhoid.
1091  * Probing a v4 or v6 neighbor needs to appear to be synchronous,
1092  * or dependent route-adds will simply fail.
1093  */
1094 static clib_error_t *
1096  int retry_count)
1097 {
1098  vnet_main_t *vnm = vnet_get_main ();
1099  clib_error_t *e;
1100  int i;
1101  int resolved = 0;
1102  uword event_type;
1103  uword *event_data = 0;
1104 
1106 
1107  if (retry_count > 0)
1109  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
1110  1 /* event */ , 0 /* data */ );
1111 
1112  for (i = 0; i < retry_count; i++)
1113  {
1114  /* The interface may be down, etc. */
1115  e = ip6_probe_neighbor (vm, a, sw_if_index, 0);
1116 
1117  if (e)
1118  return e;
1119 
1121  event_type = vlib_process_get_events (vm, &event_data);
1122  switch (event_type)
1123  {
1124  case 1: /* resolved... */
1125  vlib_cli_output (vm, "Resolved %U", format_ip6_address, a);
1126  resolved = 1;
1127  goto done;
1128 
1129  case ~0: /* timeout */
1130  break;
1131 
1132  default:
1133  clib_warning ("unknown event_type %d", event_type);
1134  }
1135  vec_reset_length (event_data);
1136  }
1137 
1138 done:
1139 
1140  if (!resolved)
1141  return clib_error_return (0, "Resolution failed for %U",
1142  format_ip6_address, a);
1143  return 0;
1144 }
1145 
1146 static clib_error_t *
1148  int retry_count)
1149 {
1150  vnet_main_t *vnm = vnet_get_main ();
1151  clib_error_t *e;
1152  int i;
1153  int resolved = 0;
1154  uword event_type;
1155  uword *event_data = 0;
1156 
1158 
1159  if (retry_count > 0)
1161  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
1162  1 /* event */ , 0 /* data */ );
1163 
1164  for (i = 0; i < retry_count; i++)
1165  {
1166  /* The interface may be down, etc. */
1167  e = ip4_probe_neighbor (vm, a, sw_if_index, 0);
1168 
1169  if (e)
1170  return e;
1171 
1173  event_type = vlib_process_get_events (vm, &event_data);
1174  switch (event_type)
1175  {
1176  case 1: /* resolved... */
1177  vlib_cli_output (vm, "Resolved %U", format_ip4_address, a);
1178  resolved = 1;
1179  goto done;
1180 
1181  case ~0: /* timeout */
1182  break;
1183 
1184  default:
1185  clib_warning ("unknown event_type %d", event_type);
1186  }
1187  vec_reset_length (event_data);
1188  }
1189 
1190 done:
1191 
1192  vec_reset_length (event_data);
1193 
1194  if (!resolved)
1195  return clib_error_return (0, "Resolution failed for %U",
1196  format_ip4_address, a);
1197  return 0;
1198 }
1199 
1200 static clib_error_t *
1202  unformat_input_t * input, vlib_cli_command_t * cmd)
1203 {
1204  vnet_main_t *vnm = vnet_get_main ();
1205  unformat_input_t _line_input, *line_input = &_line_input;
1206  ip4_address_t a4;
1207  ip6_address_t a6;
1208  clib_error_t *error = 0;
1209  u32 sw_if_index = ~0;
1210  int retry_count = 3;
1211  int is_ip4 = 1;
1212  int address_set = 0;
1213 
1214  /* Get a line of input. */
1215  if (!unformat_user (input, unformat_line_input, line_input))
1216  return 0;
1217 
1218  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1219  {
1220  if (unformat_user (line_input, unformat_vnet_sw_interface, vnm,
1221  &sw_if_index))
1222  ;
1223  else if (unformat (line_input, "retry %d", &retry_count))
1224  ;
1225 
1226  else if (unformat (line_input, "%U", unformat_ip4_address, &a4))
1227  address_set++;
1228  else if (unformat (line_input, "%U", unformat_ip6_address, &a6))
1229  {
1230  address_set++;
1231  is_ip4 = 0;
1232  }
1233  else
1234  {
1235  error = clib_error_return (0, "unknown input '%U'",
1236  format_unformat_error, line_input);
1237  goto done;
1238  }
1239  }
1240 
1241  if (sw_if_index == ~0)
1242  {
1243  error = clib_error_return (0, "Interface required, not set.");
1244  goto done;
1245  }
1246  if (address_set == 0)
1247  {
1248  error = clib_error_return (0, "ip address required, not set.");
1249  goto done;
1250  }
1251  if (address_set > 1)
1252  {
1253  error = clib_error_return (0, "Multiple ip addresses not supported.");
1254  goto done;
1255  }
1256 
1257  if (is_ip4)
1258  error = ip4_probe_neighbor_wait (vm, &a4, sw_if_index, retry_count);
1259  else
1260  error = ip6_probe_neighbor_wait (vm, &a6, sw_if_index, retry_count);
1261 
1262 done:
1263  unformat_free (line_input);
1264 
1265  return error;
1266 }
1267 
1268 /*?
1269  * The '<em>ip probe-neighbor</em>' command ARPs for IPv4 addresses or
1270  * attempts IPv6 neighbor discovery depending on the supplied IP address
1271  * format.
1272  *
1273  * @note This command will not immediately affect the indicated FIB; it
1274  * is not suitable for use in establishing a FIB entry prior to adding
1275  * recursive FIB entries. As in: don't use it in a script to probe a
1276  * gateway prior to adding a default route. It won't work. Instead,
1277  * configure a static ARP cache entry [see '<em>set ip arp</em>'], or
1278  * a static IPv6 neighbor [see '<em>set ip6 neighbor</em>'].
1279  *
1280  * @cliexpar
1281  * Example of probe for an IPv4 address:
1282  * @cliexcmd{ip probe-neighbor GigabitEthernet2/0/0 172.16.1.2}
1283 ?*/
1284 /* *INDENT-OFF* */
1285 VLIB_CLI_COMMAND (ip_probe_neighbor_command, static) = {
1286  .path = "ip probe-neighbor",
1287  .function = probe_neighbor_address,
1288  .short_help = "ip probe-neighbor <interface> <ip4-addr> | <ip6-addr> [retry nn]",
1289  .is_mp_safe = 1,
1290 };
1291 /* *INDENT-ON* */
1292 
1293 clib_error_t *
1295 {
1296  u32 fib_index;
1297 
1298  if (!vnet_sw_interface_is_api_valid (vnet_get_main (), args->sw_if_index))
1299  return clib_error_return_code (0, VNET_API_ERROR_INVALID_INTERFACE, 0,
1300  "invalid sw_if_index");
1301 
1302  fib_index = fib_table_get_table_id_for_sw_if_index (args->prefix.fp_proto,
1303  args->sw_if_index);
1304  if (args->is_add)
1305  {
1306  dpo_id_t proxy_dpo = DPO_INVALID;
1307  l3_proxy_dpo_add_or_lock (fib_proto_to_dpo (args->prefix.fp_proto),
1308  args->sw_if_index, &proxy_dpo);
1310  &args->prefix,
1312  FIB_ENTRY_FLAG_EXCLUSIVE, &proxy_dpo);
1313  dpo_reset (&proxy_dpo);
1314  }
1315  else
1316  {
1317  fib_table_entry_special_remove (fib_index, &args->prefix,
1319  }
1320  return 0;
1321 }
1322 
1323 u8
1325 {
1326  u32 fib_index;
1327  fib_node_index_t fei;
1328  const dpo_id_t *dpo;
1329  l3_proxy_dpo_t *l3p;
1330  load_balance_t *lb0;
1331 
1333  sw_if_index);
1334  if (fib_index == ~0)
1335  return 0;
1336 
1337  fei = fib_table_lookup_exact_match (fib_index, pfx);
1338  if (fei == FIB_NODE_INDEX_INVALID)
1339  return 0;
1340 
1342  lb0 = load_balance_get (dpo->dpoi_index);
1343  dpo = load_balance_get_bucket_i (lb0, 0);
1344  if (dpo->dpoi_type != DPO_L3_PROXY)
1345  return 0;
1346 
1347  l3p = l3_proxy_dpo_get (dpo->dpoi_index);
1348  return (l3p->l3p_sw_if_index == sw_if_index);
1349 }
1350 
1351 typedef struct ip_container_proxy_walk_ctx_t_
1352 {
1354  void *ctx;
1356 
1357 static fib_table_walk_rc_t
1359 {
1361  const fib_prefix_t *pfx;
1362  const dpo_id_t *dpo;
1363  load_balance_t *lb;
1364  l3_proxy_dpo_t *l3p;
1365 
1366  pfx = fib_entry_get_prefix (fei);
1368  {
1370  lb = load_balance_get (dpo->dpoi_index);
1371  dpo = load_balance_get_bucket_i (lb, 0);
1372  l3p = l3_proxy_dpo_get (dpo->dpoi_index);
1373  ctx->cb (pfx, l3p->l3p_sw_if_index, ctx->ctx);
1374  }
1375 
1376  return FIB_TABLE_WALK_CONTINUE;
1377 }
1378 
1379 void
1381 {
1382  fib_table_t *fib_table;
1384  .cb = cb,
1385  .ctx = ctx,
1386  };
1387 
1388  /* *INDENT-OFF* */
1389  pool_foreach (fib_table, ip4_main.fibs,
1390  ({
1391  fib_table_walk(fib_table->ft_index,
1392  FIB_PROTOCOL_IP4,
1393  ip_container_proxy_fib_table_walk,
1394  &wctx);
1395  }));
1396  pool_foreach (fib_table, ip6_main.fibs,
1397  ({
1398  fib_table_walk(fib_table->ft_index,
1399  FIB_PROTOCOL_IP6,
1400  ip_container_proxy_fib_table_walk,
1401  &wctx);
1402  }));
1403  /* *INDENT-ON* */
1404 }
1405 
1406 clib_error_t *
1408  unformat_input_t * main_input, vlib_cli_command_t * cmd)
1409 {
1410  unformat_input_t _line_input, *line_input = &_line_input;
1411  fib_prefix_t pfx;
1412  u32 is_del, addr_set = 0;
1413  vnet_main_t *vnm;
1414  u32 sw_if_index;
1415 
1416  vnm = vnet_get_main ();
1417  is_del = 0;
1418  sw_if_index = ~0;
1419  clib_memset (&pfx, 0, sizeof (pfx));
1420 
1421  /* Get a line of input. */
1422  if (!unformat_user (main_input, unformat_line_input, line_input))
1423  return 0;
1424 
1425  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1426  {
1427  if (unformat (line_input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4))
1428  {
1429  pfx.fp_proto = FIB_PROTOCOL_IP4;
1430  pfx.fp_len = 32;
1431  addr_set = 1;
1432  }
1433  else if (unformat (line_input, "%U",
1434  unformat_ip6_address, &pfx.fp_addr.ip6))
1435  {
1436  pfx.fp_proto = FIB_PROTOCOL_IP6;
1437  pfx.fp_len = 128;
1438  addr_set = 1;
1439  }
1440  else if (unformat (line_input, "%U",
1441  unformat_vnet_sw_interface, vnm, &sw_if_index))
1442  ;
1443  else if (unformat (line_input, "del"))
1444  is_del = 1;
1445  else
1446  {
1447  unformat_free (line_input);
1448  return (clib_error_return (0, "unknown input '%U'",
1449  format_unformat_error, line_input));
1450  }
1451  }
1452 
1453  if (~0 == sw_if_index || !addr_set)
1454  {
1455  unformat_free (line_input);
1456  vlib_cli_output (vm, "interface and address must be set");
1457  return 0;
1458  }
1459 
1461  .prefix = pfx,
1462  .sw_if_index = sw_if_index,
1463  .is_add = !is_del,
1464  };
1466  unformat_free (line_input);
1467  return (NULL);
1468 }
1469 
1470 /* *INDENT-OFF* */
1471 VLIB_CLI_COMMAND (ip_container_command_node, static) = {
1472  .path = "ip container",
1473  .function = ip_container_cmd,
1474  .short_help = "ip container <address> <interface>",
1475  .is_mp_safe = 1,
1476 };
1477 /* *INDENT-ON* */
1478 
1479 clib_error_t *
1481  vlib_cli_command_t * cmd)
1482 {
1483  unformat_input_t _line_input, *line_input = &_line_input;
1484  vnet_main_t *vnm = vnet_get_main ();
1485  fib_prefix_t pfx;
1486  u32 sw_if_index = ~0;
1487  u8 has_proxy;
1488 
1489  if (!unformat_user (main_input, unformat_line_input, line_input))
1490  return 0;
1491  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1492  {
1493  if (unformat (line_input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4))
1494  {
1495  pfx.fp_proto = FIB_PROTOCOL_IP4;
1496  pfx.fp_len = 32;
1497  }
1498  else if (unformat (line_input, "%U",
1499  unformat_ip6_address, &pfx.fp_addr.ip6))
1500  {
1501  pfx.fp_proto = FIB_PROTOCOL_IP6;
1502  pfx.fp_len = 128;
1503  }
1504  else if (unformat (line_input, "%U",
1505  unformat_vnet_sw_interface, vnm, &sw_if_index))
1506  ;
1507  else
1508  {
1509  unformat_free (line_input);
1510  return (clib_error_return (0, "unknown input '%U'",
1511  format_unformat_error, line_input));
1512  }
1513  }
1514 
1515  if (~0 == sw_if_index)
1516  {
1517  unformat_free (line_input);
1518  vlib_cli_output (vm, "no interface");
1519  return (clib_error_return (0, "no interface"));
1520  }
1521 
1522  has_proxy = ip_container_proxy_is_set (&pfx, sw_if_index);
1523  vlib_cli_output (vm, "ip container proxy is: %s", has_proxy ? "on" : "off");
1524 
1525  unformat_free (line_input);
1526  return 0;
1527 }
1528 
1529 /* *INDENT-OFF* */
1530 VLIB_CLI_COMMAND (show_ip_container_command, static) = {
1531  .path = "show ip container",
1532  .function = show_ip_container_cmd_fn,
1533  .short_help = "show ip container <address> <interface>",
1534  .is_mp_safe = 1,
1535 };
1536 /* *INDENT-ON* */
1537 
1538 /*
1539  * fd.io coding-style-patch-verification: ON
1540  *
1541  * Local Variables:
1542  * eval: (c-set-style "gnu")
1543  * End:
1544  */
static clib_error_t * ip6_probe_neighbor_wait(vlib_main_t *vm, ip6_address_t *a, u32 sw_if_index, int retry_count)
Definition: lookup.c:1095
u32 sw_if_index
Definition: ipsec_gre.api:37
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
void mfib_table_entry_delete(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source)
Delete a FIB entry.
Definition: mfib_table.c:440
clib_error_t * vnet_ip4_table_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:573
vmrglw vmrglh hi
void ip_null_dpo_add_and_lock(dpo_proto_t proto, ip_null_dpo_action_t action, dpo_id_t *dpo)
Definition: ip_null_dpo.c:78
ip46_address_t frp_addr
The next-hop address.
Definition: fib_types.h:492
Continue on to the next entry.
Definition: fib_table.h:868
void ip_table_create(fib_protocol_t fproto, u32 table_id, u8 is_api, const u8 *name)
Definition: ip_api.c:1218
ip46_address_t fp_src_addr
Definition: mfib_types.h:47
void receive_dpo_add_or_lock(dpo_proto_t proto, u32 sw_if_index, const ip46_address_t *nh_addr, dpo_id_t *dpo)
Definition: receive_dpo.c:62
fib_node_index_t fib_table_lookup_exact_match(u32 fib_index, const fib_prefix_t *prefix)
Perfom an exact match in the non-forwarding table.
Definition: fib_table.c:95
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
Definition: node_funcs.h:673
enum mfib_entry_flags_t_ mfib_entry_flags_t
a
Definition: bitmap.h:538
static uword unformat_dpo(unformat_input_t *input, va_list *args)
Definition: lookup.c:280
A representation of a path as described by a route producer.
Definition: fib_types.h:476
uword unformat_mfib_itf_flags(unformat_input_t *input, va_list *args)
Definition: mfib_types.c:198
ip_interface_address_t * if_address_pool
Pool of addresses that are assigned to interfaces.
Definition: lookup.h:125
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static clib_error_t * ip4_probe_neighbor_wait(vlib_main_t *vm, ip4_address_t *a, u32 sw_if_index, int retry_count)
Definition: lookup.c:1147
uword unformat_fib_route_path(unformat_input_t *input, va_list *args)
Unformat a fib_route_path_t from CLI input.
Definition: fib_types.c:441
Multicast Adjacency.
Definition: adj.h:82
#define NULL
Definition: clib.h:58
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:353
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:255
fib_node_index_t fib_table_entry_path_add2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_route_path_t *rpath)
Add n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:556
ip_container_proxy_cb_t cb
Definition: lookup.c:1353
IP unicast adjacency.
Definition: adj.h:221
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:516
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
From the CLI.
Definition: fib_entry.h:78
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:261
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
int i
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
const fib_prefix_t * fib_entry_get_prefix(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:1688
fib_node_index_t mfib_table_entry_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, fib_rpf_id_t rpf_id, mfib_entry_flags_t entry_flags)
Add a new (with no replication) or lock an existing entry.
Definition: mfib_table.c:235
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:481
unformat_function_t unformat_vnet_sw_interface
vl_api_ip4_address_t dst
Definition: ipsec_gre.api:39
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
The data-path object representing L3 proxy.
Definition: l3_proxy_dpo.h:27
static clib_error_t * vnet_ip_route_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:325
mhash_t address_to_if_address_index
Hash table mapping address to index in interface address pool.
Definition: lookup.h:128
format_function_t format_vnet_sw_if_index_name
unsigned char u8
Definition: types.h:56
static clib_error_t * ip_table_bind_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd, fib_protocol_t fproto)
Definition: lookup.c:681
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
int ip_table_bind(fib_protocol_t fproto, u32 sw_if_index, u32 table_id, u8 is_api)
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
format_function_t format_ip4_address
Definition: format.h:75
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:433
static clib_error_t * ip6_table_bind_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: lookup.c:740
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:493
unformat_function_t unformat_ip4_address
Definition: format.h:70
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:511
#define MFIB_RPF_ID_NONE
Definition: fib_types.h:399
format_function_t format_ip6_address_and_length
Definition: format.h:94
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
Definition: node_funcs.h:516
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:407
clib_error_t * vnet_ip_container_proxy_add_del(vnet_ip_container_proxy_args_t *args)
Definition: lookup.c:1294
struct _vnet_ip_container_proxy_args vnet_ip_container_proxy_args_t
Aggregrate type for a prefix.
Definition: fib_types.h:203
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
const dpo_id_t * punt_dpo_get(dpo_proto_t proto)
Definition: punt_dpo.c:25
#define clib_error_return(e, args...)
Definition: error.h:99
fib_node_index_t mfib_table_entry_path_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath, mfib_itf_flags_t itf_flags)
Add n paths to an entry (aka route) in the FIB.
Definition: mfib_table.c:290
unsigned int u32
Definition: types.h:88
#define clib_error_create(args...)
Definition: error.h:96
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1064
u16 fp_len
The mask length.
Definition: fib_types.h:207
clib_error_t * ip6_probe_neighbor(vlib_main_t *vm, ip6_address_t *dst, u32 sw_if_index, u8 refresh)
Definition: ip6_forward.c:1486
Definition: fib_entry.h:275
unformat_function_t unformat_line_input
Definition: format.h:282
u32 l3p_sw_if_index
The Software interface index on which traffic is l3_proxyd.
Definition: l3_proxy_dpo.h:38
vnet_api_error_t api_errno
Definition: vnet.h:78
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
int(* ip_container_proxy_cb_t)(const fib_prefix_t *pfx, u32 sw_if_index, void *ctx)
Definition: lookup.h:241
format_function_t format_vnet_sw_interface_name
Definition: fib_entry.h:279
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
void vnet_register_ip6_neighbor_resolution_event(vnet_main_t *vnm, void *address_arg, uword node_index, uword type_opaque, uword data)
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
index_t classify_dpo_create(dpo_proto_t proto, u32 classify_table_index)
Definition: classify_dpo.c:43
u8 address_length
Definition: ip_types.api:37
dpo_type_t dpoi_type
the type
Definition: dpo.h:172
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:228
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:286
The FIB DPO provieds;.
Definition: load_balance.h:106
void fib_table_entry_path_remove2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_route_path_t *rpath)
Remove n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:600
u8 local_next_by_ip_protocol[256]
Table mapping ip protocol to ip[46]-local node next index.
Definition: lookup.h:153
clib_error_t * ip_container_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:1407
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
u8 name[64]
Definition: memclnt.api:152
clib_error_t * ip4_probe_neighbor(vlib_main_t *vm, ip4_address_t *dst, u32 sw_if_index, u8 refresh)
Definition: ip4_forward.c:1996
clib_error_t * vnet_ip_table_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd, fib_protocol_t fproto)
Definition: lookup.c:512
clib_error_t * vnet_ip_mroute_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:804
unformat_function_t unformat_ip6_address
Definition: format.h:91
int fib_entry_is_sourced(fib_node_index_t fib_entry_index, fib_source_t source)
uword unformat_mfib_entry_flags(unformat_input_t *input, va_list *args)
Definition: mfib_types.c:218
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
format_function_t format_ip6_address
Definition: format.h:93
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
Definition: node_funcs.h:391
vlib_main_t * vm
Definition: buffer.c:312
enum fib_table_walk_rc_t_ fib_table_walk_rc_t
return code controlling how a table walk proceeds
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:341
struct ip_container_proxy_walk_ctx_t_ ip_container_proxy_walk_ctx_t
void fib_table_entry_delete(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Delete a FIB entry.
Definition: fib_table.c:853
void ip_table_delete(fib_protocol_t fproto, u32 table_id, u8 is_api)
Definition: ip_api.c:738
#define clib_warning(format, args...)
Definition: error.h:59
static fib_table_walk_rc_t ip_container_proxy_fib_table_walk(fib_node_index_t fei, void *arg)
Definition: lookup.c:1358
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
void ip_lookup_init(ip_lookup_main_t *lm, u32 is_ip6)
Definition: lookup.c:204
void ip_container_proxy_walk(ip_container_proxy_cb_t cb, void *ctx)
Definition: lookup.c:1380
void vnet_register_ip4_arp_resolution_event(vnet_main_t *vnm, void *address_arg, uword node_index, uword type_opaque, uword data)
Definition: arp.c:770
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:185
Aggregrate type for a prefix.
Definition: mfib_types.h:24
u8 builtin_protocol_by_ip_protocol[256]
IP_BUILTIN_PROTOCOL_{TCP,UDP,ICMP,OTHER} by protocol in IP header.
Definition: lookup.h:156
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
#define foreach_flow_hash_bit
Definition: lookup.h:72
u32 * if_address_pool_index_by_sw_if_index
Head of doubly linked list of interface addresses for each software interface.
Definition: lookup.h:132
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:307
u32 fib_table_get_table_id_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the Table-ID of the FIB bound to the interface.
Definition: fib_table.c:1040
#define ASSERT(truth)
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
ip6_main_t ip6_main
Definition: ip6_forward.c:2688
u8 is_add
Definition: ipsec_gre.api:36
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:219
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:577
size_t count
Definition: vapi.c:47
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:244
u32 flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
Definition: lookup.h:84
static l3_proxy_dpo_t * l3_proxy_dpo_get(index_t index)
Definition: l3_proxy_dpo.h:58
#define unformat_parse_error(input)
Definition: format.h:268
static clib_error_t * ip4_table_bind_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: lookup.c:732
fib_protocol_t fp_proto
protocol type
Definition: mfib_types.h:33
static uword vnet_sw_interface_is_api_valid(vnet_main_t *vnm, u32 sw_if_index)
clib_error_t * vnet_ip6_table_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:580
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:184
static clib_error_t * ip_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: lookup.c:189
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
A for-us/local path.
Definition: fib_types.h:338
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:236
u32 mfib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: mfib_table.c:504
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
A route the is being &#39;proxied&#39; on behalf of another device.
Definition: fib_entry.h:48
u32 is_ip6
1 for ip6; 0 for ip4.
Definition: lookup.h:147
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
clib_error_t * ip_interface_address_add_del(ip_lookup_main_t *lm, u32 sw_if_index, void *addr_fib, u32 address_length, u32 is_del, u32 *result_if_address_index)
Definition: lookup.c:63
enum mfib_itf_flags_t_ mfib_itf_flags_t
clib_error_t * show_ip_container_cmd_fn(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:1480
static uword vlib_in_process_context(vlib_main_t *vm)
Definition: node_funcs.h:385
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:905
#define clib_error_return_code(e, code, flags, args...)
Definition: error.h:93
u8 ip_container_proxy_is_set(fib_prefix_t *pfx, u32 sw_if_index)
Definition: lookup.c:1324
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:101
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:231
u8 * format_ip_flow_hash_config(u8 *s, va_list *args)
Definition: lookup.c:245
static clib_error_t * probe_neighbor_address(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: lookup.c:1201
u8 * format_ip_adjacency_packet_data(u8 *s, va_list *args)
Definition: lookup.c:257
u16 fp_len
The mask length.
Definition: mfib_types.h:28
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
Definition: vec.h:486
void mfib_table_entry_path_remove(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath)
Remove n paths to an entry (aka route) in the FIB.
Definition: mfib_table.c:329
u8 frp_weight
[un]equal cost path weight
Definition: fib_types.h:567
struct fib_table_t_ * fibs
Definition: ip6.h:182
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:762
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(ip_sw_interface_add_del)
void l3_proxy_dpo_add_or_lock(dpo_proto_t proto, u32 sw_if_index, dpo_id_t *dpo)
Definition: l3_proxy_dpo.c:56
const ip46_address_t zero_addr
Definition: lookup.c:319
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
u32 fib_result_n_bytes
Number of bytes in a fib result.
Definition: lookup.h:144
ip46_address_t fp_grp_addr
The address type is not deriveable from the fp_addr member.
Definition: mfib_types.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
A protocol Independent FIB table.
Definition: fib_table.h:69
format_function_t * format_address_and_length
Either format_ip4_address_and_length or format_ip6_address_and_length.
Definition: lookup.h:150
format_function_t format_ip4_address_and_length
Definition: format.h:76