FD.io VPP  v19.01.3-6-g70449b9b9
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 
55 /**
56  * @file
57  * @brief IPv4 and IPv6 adjacency and lookup table managment.
58  *
59  */
60 
64  void *addr_fib,
66  u32 is_del, u32 * result_if_address_index)
67 {
68  vnet_main_t *vnm = vnet_get_main ();
69  ip_interface_address_t *a, *prev, *next;
70  uword *p = mhash_get (&lm->address_to_if_address_index, addr_fib);
71 
73  sw_if_index, ~0);
74  a = p ? pool_elt_at_index (lm->if_address_pool, p[0]) : 0;
75 
76  /* Verify given length. */
77  if ((a && (address_length != a->address_length)) ||
78  (address_length == 0) ||
79  (lm->is_ip6 && address_length > 128) ||
80  (!lm->is_ip6 && address_length > 32))
81  {
82  vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
83  return clib_error_create
84  ("%U wrong length (expected %d) for interface %U",
85  lm->format_address_and_length, addr_fib,
86  address_length, a ? a->address_length : -1,
87  format_vnet_sw_if_index_name, vnm, sw_if_index);
88  }
89 
90  if (is_del)
91  {
92  if (!a)
93  {
94  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
95  vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
96  return clib_error_create ("%U not found for interface %U",
98  addr_fib, address_length,
100  }
101 
102  if (a->prev_this_sw_interface != ~0)
103  {
104  prev =
108  }
109  if (a->next_this_sw_interface != ~0)
110  {
111  next =
115 
116  if (a->prev_this_sw_interface == ~0)
119  }
120 
121  if ((a->next_this_sw_interface == ~0)
122  && (a->prev_this_sw_interface == ~0))
124 
126  /* old_value */ 0);
127  pool_put (lm->if_address_pool, a);
128 
129  if (result_if_address_index)
130  *result_if_address_index = ~0;
131  }
132 
133  else if (!a)
134  {
135  u32 pi; /* previous index */
136  u32 ai;
137  u32 hi; /* head index */
138 
139  pool_get (lm->if_address_pool, a);
140  clib_memset (a, ~0, sizeof (a[0]));
141  ai = a - lm->if_address_pool;
142 
144  prev = 0;
145  while (pi != (u32) ~ 0)
146  {
147  prev = pool_elt_at_index (lm->if_address_pool, pi);
148  pi = prev->next_this_sw_interface;
149  }
150  pi = prev ? prev - lm->if_address_pool : (u32) ~ 0;
151 
153  addr_fib, ai, /* old_value */ 0);
156  a->flags = 0;
157  a->prev_this_sw_interface = pi;
158  a->next_this_sw_interface = ~0;
159  if (prev)
160  prev->next_this_sw_interface = ai;
161 
163  (hi != ~0) ? hi : ai;
164  if (result_if_address_index)
165  *result_if_address_index = ai;
166  }
167  else
168  {
169  if (sw_if_index != a->sw_if_index)
170  {
171  if (result_if_address_index)
172  *result_if_address_index = ~0;
173  vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS;
174  return clib_error_create
175  ("Prefix %U already found on interface %U",
176  lm->format_address_and_length, addr_fib, address_length,
178  }
179 
180  if (result_if_address_index)
181  *result_if_address_index = a - lm->if_address_pool;
182  }
183 
184  return /* no error */ 0;
185 }
186 
187 static clib_error_t *
189 {
191  lookup_main.if_address_pool_index_by_sw_if_index,
192  sw_if_index, ~0);
194  lookup_main.if_address_pool_index_by_sw_if_index,
195  sw_if_index, ~0);
196 
197  return (NULL);
198 }
199 
201 
202 void
204 {
205  if (!lm->fib_result_n_bytes)
206  lm->fib_result_n_bytes = sizeof (uword);
207 
208  lm->is_ip6 = is_ip6;
209  if (is_ip6)
210  {
213  sizeof (ip6_address_fib_t));
214  }
215  else
216  {
219  sizeof (ip4_address_fib_t));
220  }
221 
222  {
223  int i;
224 
225  /* Setup all IP protocols to be punted and builtin-unknown. */
226  for (i = 0; i < 256; i++)
227  {
230  }
231 
233  lm->local_next_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
234  IP_PROTOCOL_ICMP] = IP_LOCAL_NEXT_ICMP;
235  lm->builtin_protocol_by_ip_protocol[IP_PROTOCOL_UDP] =
237  lm->builtin_protocol_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
238  IP_PROTOCOL_ICMP] =
240  }
241 }
242 
243 u8 *
244 format_ip_flow_hash_config (u8 * s, va_list * args)
245 {
246  flow_hash_config_t flow_hash_config = va_arg (*args, u32);
247 
248 #define _(n,v) if (flow_hash_config & v) s = format (s, "%s ", #n);
250 #undef _
251 
252  return s;
253 }
254 
255 u8 *
256 format_ip_adjacency_packet_data (u8 * s, va_list * args)
257 {
258  u32 adj_index = va_arg (*args, u32);
259  u8 *packet_data = va_arg (*args, u8 *);
260  u32 n_packet_data_bytes = va_arg (*args, u32);
261  ip_adjacency_t *adj = adj_get (adj_index);
262 
263  switch (adj->lookup_next_index)
264  {
267  s =
268  format (s, "%U", format_hex_bytes, packet_data, n_packet_data_bytes);
269  break;
270 
271  default:
272  break;
273  }
274 
275  return s;
276 }
277 
278 static uword
279 unformat_dpo (unformat_input_t * input, va_list * args)
280 {
281  dpo_id_t *dpo = va_arg (*args, dpo_id_t *);
282  fib_protocol_t fp = va_arg (*args, int);
283  dpo_proto_t proto;
284 
285  proto = fib_proto_to_dpo (fp);
286 
287  if (unformat (input, "drop"))
288  dpo_copy (dpo, drop_dpo_get (proto));
289  else if (unformat (input, "punt"))
290  dpo_copy (dpo, punt_dpo_get (proto));
291  else if (unformat (input, "local"))
292  receive_dpo_add_or_lock (proto, ~0, NULL, dpo);
293  else if (unformat (input, "null-send-unreach"))
295  else if (unformat (input, "null-send-prohibit"))
297  else if (unformat (input, "null"))
299  else if (unformat (input, "classify"))
300  {
301  u32 classify_table_index;
302 
303  if (!unformat (input, "%d", &classify_table_index))
304  {
305  clib_warning ("classify adj must specify table index");
306  return 0;
307  }
308 
309  dpo_set (dpo, DPO_CLASSIFY, proto,
310  classify_dpo_create (proto, classify_table_index));
311  }
312  else
313  return 0;
314 
315  return 1;
316 }
317 
318 const ip46_address_t zero_addr = {
319  .as_u64 = {
320  0, 0},
321 };
322 
323 static clib_error_t *
325  unformat_input_t * main_input, vlib_cli_command_t * cmd)
326 {
327  unformat_input_t _line_input, *line_input = &_line_input;
328  u32 table_id, is_del, fib_index, payload_proto;
329  dpo_id_t dpo = DPO_INVALID, *dpos = NULL;
330  fib_route_path_t *rpaths = NULL, rpath;
331  fib_prefix_t *prefixs = NULL, pfx;
332  clib_error_t *error = NULL;
333  f64 count;
334  int i;
335 
336  is_del = 0;
337  table_id = 0;
338  count = 1;
339  clib_memset (&pfx, 0, sizeof (pfx));
340 
341  /* Get a line of input. */
342  if (!unformat_user (main_input, unformat_line_input, line_input))
343  return 0;
344 
345  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
346  {
347  clib_memset (&rpath, 0, sizeof (rpath));
348 
349  if (unformat (line_input, "table %d", &table_id))
350  ;
351  else if (unformat (line_input, "count %f", &count))
352  ;
353 
354  else if (unformat (line_input, "%U/%d",
355  unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len))
356  {
357  payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP4;
358  vec_add1 (prefixs, pfx);
359  }
360  else if (unformat (line_input, "%U/%d",
361  unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len))
362  {
363  payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP6;
364  vec_add1 (prefixs, pfx);
365  }
366  else if (unformat (line_input, "via %U",
367  unformat_fib_route_path, &rpath, &payload_proto))
368  {
369  vec_add1 (rpaths, rpath);
370  }
371  else if (vec_len (prefixs) > 0 &&
372  unformat (line_input, "via %U",
373  unformat_dpo, &dpo, prefixs[0].fp_proto))
374  {
375  vec_add1 (dpos, dpo);
376  }
377  else if (unformat (line_input, "del"))
378  is_del = 1;
379  else if (unformat (line_input, "add"))
380  is_del = 0;
381  else
382  {
383  error = unformat_parse_error (line_input);
384  goto done;
385  }
386  }
387 
388  if (vec_len (prefixs) == 0)
389  {
390  error =
391  clib_error_return (0, "expected ip4/ip6 destination address/length.");
392  goto done;
393  }
394 
395  if (!is_del && vec_len (rpaths) + vec_len (dpos) == 0)
396  {
397  error = clib_error_return (0, "expected paths.");
398  goto done;
399  }
400 
401  if (~0 == table_id)
402  {
403  /*
404  * if no table_id is passed we will manipulate the default
405  */
406  fib_index = 0;
407  }
408  else
409  {
410  fib_index = fib_table_find (prefixs[0].fp_proto, table_id);
411 
412  if (~0 == fib_index)
413  {
414  error = clib_error_return (0, "Nonexistent table id %d", table_id);
415  goto done;
416  }
417  }
418 
419  for (i = 0; i < vec_len (prefixs); i++)
420  {
421  if (is_del && 0 == vec_len (rpaths))
422  {
423  fib_table_entry_delete (fib_index, &prefixs[i], FIB_SOURCE_CLI);
424  }
425  else if (!is_del && 1 == vec_len (dpos))
426  {
428  &prefixs[i],
431  &dpos[0]);
432  dpo_reset (&dpos[0]);
433  }
434  else if (vec_len (dpos) > 0)
435  {
436  error =
438  "Load-balancing over multiple special adjacencies is unsupported");
439  goto done;
440  }
441  else if (0 < vec_len (rpaths))
442  {
443  u32 k, j, n, incr;
444  ip46_address_t dst = prefixs[i].fp_addr;
445  f64 t[2];
446  n = count;
447  t[0] = vlib_time_now (vm);
448  incr = 1 << ((FIB_PROTOCOL_IP4 == prefixs[0].fp_proto ? 32 : 128) -
449  prefixs[i].fp_len);
450 
451  for (k = 0; k < n; k++)
452  {
453  for (j = 0; j < vec_len (rpaths); j++)
454  {
455  fib_prefix_t rpfx = {
456  .fp_len = prefixs[i].fp_len,
457  .fp_proto = prefixs[i].fp_proto,
458  .fp_addr = dst,
459  };
460 
461  if (is_del)
462  fib_table_entry_path_remove2 (fib_index,
463  &rpfx,
464  FIB_SOURCE_CLI, &rpaths[j]);
465  else
466  fib_table_entry_path_add2 (fib_index,
467  &rpfx,
470  &rpaths[j]);
471  }
472 
473  if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto)
474  {
475  dst.ip4.as_u32 =
476  clib_host_to_net_u32 (incr +
477  clib_net_to_host_u32 (dst.
478  ip4.as_u32));
479  }
480  else
481  {
482  int bucket = (incr < 64 ? 0 : 1);
483  dst.ip6.as_u64[bucket] =
484  clib_host_to_net_u64 (incr +
485  clib_net_to_host_u64 (dst.ip6.as_u64
486  [bucket]));
487 
488  }
489  }
490  t[1] = vlib_time_now (vm);
491  if (count > 1)
492  vlib_cli_output (vm, "%.6e routes/sec", count / (t[1] - t[0]));
493  }
494  else
495  {
496  error = clib_error_return (0, "Don't understand what you want...");
497  goto done;
498  }
499  }
500 
501 
502 done:
503  vec_free (dpos);
504  vec_free (prefixs);
505  vec_free (rpaths);
506  unformat_free (line_input);
507  return error;
508 }
509 
510 clib_error_t *
512  unformat_input_t * main_input,
513  vlib_cli_command_t * cmd, fib_protocol_t fproto)
514 {
515  unformat_input_t _line_input, *line_input = &_line_input;
516  clib_error_t *error = NULL;
517  u32 table_id, is_add;
518  u8 *name = NULL;
519 
520  is_add = 1;
521  table_id = ~0;
522 
523  /* Get a line of input. */
524  if (!unformat_user (main_input, unformat_line_input, line_input))
525  return 0;
526 
527  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
528  {
529  if (unformat (line_input, "%d", &table_id))
530  ;
531  else if (unformat (line_input, "del"))
532  is_add = 0;
533  else if (unformat (line_input, "add"))
534  is_add = 1;
535  else if (unformat (line_input, "name %s", &name))
536  ;
537  else
538  {
539  error = unformat_parse_error (line_input);
540  goto done;
541  }
542  }
543 
544  if (~0 == table_id)
545  {
546  error = clib_error_return (0, "No table id");
547  goto done;
548  }
549  else if (0 == table_id)
550  {
551  error = clib_error_return (0, "Can't change the default table");
552  goto done;
553  }
554  else
555  {
556  if (is_add)
557  {
558  ip_table_create (fproto, table_id, 0, name);
559  }
560  else
561  {
562  ip_table_delete (fproto, table_id, 0);
563  }
564  }
565 
566 done:
567  unformat_free (line_input);
568  return error;
569 }
570 
571 clib_error_t *
573  unformat_input_t * main_input, vlib_cli_command_t * cmd)
574 {
575  return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4));
576 }
577 
578 clib_error_t *
580  unformat_input_t * main_input, vlib_cli_command_t * cmd)
581 {
582  return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6));
583 }
584 
585 /* *INDENT-OFF* */
586 VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
587  .path = "ip",
588  .short_help = "Internet protocol (IP) commands",
589 };
590 /* *INDENT-ON* */
591 
592 /* *INDENT-OFF* */
593 VLIB_CLI_COMMAND (vlib_cli_ip6_command, static) = {
594  .path = "ip6",
595  .short_help = "Internet protocol version 6 (IPv6) commands",
596 };
597 /* *INDENT-ON* */
598 
599 /* *INDENT-OFF* */
600 VLIB_CLI_COMMAND (vlib_cli_show_ip_command, static) = {
601  .path = "show ip",
602  .short_help = "Internet protocol (IP) show commands",
603 };
604 /* *INDENT-ON* */
605 
606 /* *INDENT-OFF* */
607 VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
608  .path = "show ip6",
609  .short_help = "Internet protocol version 6 (IPv6) show commands",
610 };
611 /* *INDENT-ON* */
612 
613 /*?
614  * This command is used to add or delete IPv4 or IPv6 routes. All
615  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
616  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
617  * can be IPv4 or IPv6, but all must be of the same form in a single
618  * command. To display the current set of routes, use the commands
619  * '<em>show ip fib</em>' and '<em>show ip6 fib</em>'.
620  *
621  * @cliexpar
622  * Example of how to add a straight forward static route:
623  * @cliexcmd{ip route add 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
624  * Example of how to delete a straight forward static route:
625  * @cliexcmd{ip route del 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
626  * Mainly for route add/del performance testing, one can add or delete
627  * multiple routes by adding 'count N' to the previous item:
628  * @cliexcmd{ip route add count 10 7.0.0.0/24 via 6.0.0.1 GigabitEthernet2/0/0}
629  * Add multiple routes for the same destination to create equal-cost multipath:
630  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0}
631  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0}
632  * For unequal-cost multipath, specify the desired weights. This
633  * combination of weights results in 3/4 of the traffic following the
634  * second path, 1/4 following the first path:
635  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0 weight 1}
636  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3}
637  * To add a route to a particular FIB table (VRF), use:
638  * @cliexcmd{ip route add 172.16.24.0/24 table 7 via GigabitEthernet2/0/0}
639  ?*/
640 /* *INDENT-OFF* */
641 VLIB_CLI_COMMAND (ip_route_command, static) = {
642  .path = "ip route",
643  .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>]",
644  .function = vnet_ip_route_cmd,
645  .is_mp_safe = 1,
646 };
647 
648 /* *INDENT-ON* */
649 /*?
650  * This command is used to add or delete IPv4 Tables. All
651  * Tables must be explicitly added before that can be used. Creating a
652  * table will add both unicast and multicast FIBs
653  *
654  ?*/
655 /* *INDENT-OFF* */
656 VLIB_CLI_COMMAND (ip4_table_command, static) = {
657  .path = "ip table",
658  .short_help = "ip table [add|del] <table-id>",
659  .function = vnet_ip4_table_cmd,
660  .is_mp_safe = 1,
661 };
662 /* *INDENT-ON* */
663 
664 /* *INDENT-ON* */
665 /*?
666  * This command is used to add or delete IPv4 Tables. All
667  * Tables must be explicitly added before that can be used. Creating a
668  * table will add both unicast and multicast FIBs
669  *
670  ?*/
671 /* *INDENT-OFF* */
672 VLIB_CLI_COMMAND (ip6_table_command, static) = {
673  .path = "ip6 table",
674  .short_help = "ip6 table [add|del] <table-id>",
675  .function = vnet_ip6_table_cmd,
676  .is_mp_safe = 1,
677 };
678 
679 static clib_error_t *
681  unformat_input_t * input,
682  vlib_cli_command_t * cmd,
683  fib_protocol_t fproto)
684 {
685  vnet_main_t *vnm = vnet_get_main ();
686  clib_error_t *error = 0;
687  u32 sw_if_index, table_id;
688  int rv;
689 
690  sw_if_index = ~0;
691 
692  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
693  {
694  error = clib_error_return (0, "unknown interface `%U'",
695  format_unformat_error, input);
696  goto done;
697  }
698 
699  if (unformat (input, "%d", &table_id))
700  ;
701  else
702  {
703  error = clib_error_return (0, "expected table id `%U'",
704  format_unformat_error, input);
705  goto done;
706  }
707 
708  rv = ip_table_bind (fproto, sw_if_index, table_id, 0);
709 
710  if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv)
711  {
712  error = clib_error_return (0, "IP addresses are still present on %U",
714  vnet_get_main(),
715  sw_if_index);
716  }
717  else if (VNET_API_ERROR_NO_SUCH_FIB == rv)
718  {
719  error = clib_error_return (0, "no such table %d", table_id);
720  }
721  else if (0 != rv)
722  {
723  error = clib_error_return (0, "unknown error");
724  }
725 
726  done:
727  return error;
728 }
729 
730 static clib_error_t *
732  unformat_input_t * input,
733  vlib_cli_command_t * cmd)
734 {
735  return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP4));
736 }
737 
738 static clib_error_t *
740  unformat_input_t * input,
741  vlib_cli_command_t * cmd)
742 {
743  return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP6));
744 }
745 
746 /*?
747  * Place the indicated interface into the supplied IPv4 FIB table (also known
748  * as a VRF). The FIB table must be created using "ip table add" already. To
749  * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
750  * FIB table will only be displayed if a route has been added to the table, or
751  * an IP Address is assigned to an interface in the table (which adds a route
752  * automatically).
753  *
754  * @note IP addresses added after setting the interface IP table are added to
755  * the indicated FIB table. If an IP address is added prior to changing the
756  * table then this is an error. The control plane must remove these addresses
757  * first and then change the table. VPP will not automatically move the
758  * addresses from the old to the new table as it does not know the validity
759  * of such a change.
760  *
761  * @cliexpar
762  * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
763  * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
764  ?*/
765 /* *INDENT-OFF* */
766 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
767 {
768  .path = "set interface ip table",
769  .function = ip4_table_bind_cmd,
770  .short_help = "set interface ip table <interface> <table-id>",
771 };
772 /* *INDENT-ON* */
773 
774 /*?
775  * Place the indicated interface into the supplied IPv6 FIB table (also known
776  * as a VRF). The FIB table must be created using "ip6 table add" already. To
777  * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
778  * FIB table will only be displayed if a route has been added to the table, or
779  * an IP Address is assigned to an interface in the table (which adds a route
780  * automatically).
781  *
782  * @note IP addresses added after setting the interface IP table are added to
783  * the indicated FIB table. If an IP address is added prior to changing the
784  * table then this is an error. The control plane must remove these addresses
785  * first and then change the table. VPP will not automatically move the
786  * addresses from the old to the new table as it does not know the validity
787  * of such a change.
788  *
789  * @cliexpar
790  * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id):
791  * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
792  ?*/
793 /* *INDENT-OFF* */
794 VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
795 {
796  .path = "set interface ip6 table",
797  .function = ip6_table_bind_cmd,
798  .short_help = "set interface ip6 table <interface> <table-id>"
799 };
800 /* *INDENT-ON* */
801 
802 clib_error_t *
804  unformat_input_t * main_input, vlib_cli_command_t * cmd)
805 {
806  unformat_input_t _line_input, *line_input = &_line_input;
807  clib_error_t *error = NULL;
808  fib_route_path_t rpath;
809  u32 table_id, is_del;
810  vnet_main_t *vnm;
811  mfib_prefix_t pfx;
812  u32 fib_index;
813  mfib_itf_flags_t iflags = 0;
814  mfib_entry_flags_t eflags = 0;
815  u32 gcount, scount, ss, gg, incr;
816  f64 timet[2];
817  u32 rpf_id = MFIB_RPF_ID_NONE;
818 
819  gcount = scount = 1;
820  vnm = vnet_get_main ();
821  is_del = 0;
822  table_id = 0;
823  clib_memset (&pfx, 0, sizeof (pfx));
824  clib_memset (&rpath, 0, sizeof (rpath));
825  rpath.frp_sw_if_index = ~0;
826 
827  /* Get a line of input. */
828  if (!unformat_user (main_input, unformat_line_input, line_input))
829  return 0;
830 
831  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
832  {
833  if (unformat (line_input, "table %d", &table_id))
834  ;
835  else if (unformat (line_input, "del"))
836  is_del = 1;
837  else if (unformat (line_input, "add"))
838  is_del = 0;
839  else if (unformat (line_input, "rpf-id %d", &rpf_id))
840  ;
841  else if (unformat (line_input, "scount %d", &scount))
842  ;
843  else if (unformat (line_input, "gcount %d", &gcount))
844  ;
845  else if (unformat (line_input, "%U %U",
847  &pfx.fp_src_addr.ip4,
849  {
851  pfx.fp_len = 64;
852  }
853  else if (unformat (line_input, "%U %U",
855  &pfx.fp_src_addr.ip6,
857  {
859  pfx.fp_len = 256;
860  }
861  else if (unformat (line_input, "%U/%d",
863  &pfx.fp_grp_addr.ip4, &pfx.fp_len))
864  {
865  clib_memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
867  }
868  else if (unformat (line_input, "%U/%d",
870  &pfx.fp_grp_addr.ip6, &pfx.fp_len))
871  {
872  clib_memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
874  }
875  else if (unformat (line_input, "%U",
877  {
878  clib_memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
880  pfx.fp_len = 32;
881  }
882  else if (unformat (line_input, "%U",
884  {
885  clib_memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
887  pfx.fp_len = 128;
888  }
889  else if (unformat (line_input, "via %U %U %U",
890  unformat_ip4_address, &rpath.frp_addr.ip4,
892  &rpath.frp_sw_if_index,
893  unformat_mfib_itf_flags, &iflags))
894  {
895  rpath.frp_weight = 1;
896  }
897  else if (unformat (line_input, "via %U %U %U",
898  unformat_ip6_address, &rpath.frp_addr.ip6,
900  &rpath.frp_sw_if_index,
901  unformat_mfib_itf_flags, &iflags))
902  {
903  rpath.frp_weight = 1;
904  }
905  else if (unformat (line_input, "via %U %U",
907  &rpath.frp_sw_if_index,
908  unformat_mfib_itf_flags, &iflags))
909  {
910  clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
911  rpath.frp_weight = 1;
912  }
913  else if (unformat (line_input, "via %U %U",
914  unformat_ip4_address, &rpath.frp_addr.ip4,
916  &rpath.frp_sw_if_index))
917  {
918  rpath.frp_weight = 1;
919  }
920  else if (unformat (line_input, "via %U %U",
921  unformat_ip6_address, &rpath.frp_addr.ip6,
923  &rpath.frp_sw_if_index))
924  {
925  rpath.frp_weight = 1;
926  }
927  else if (unformat (line_input, "via %U",
929  &rpath.frp_sw_if_index))
930  {
931  clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
932  rpath.frp_weight = 1;
933  }
934  else if (unformat (line_input, "via local Forward"))
935  {
936  clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr));
937  rpath.frp_sw_if_index = ~0;
938  rpath.frp_weight = 1;
940  /*
941  * set the path proto appropriately for the prefix
942  */
943  rpath.frp_proto = fib_proto_to_dpo (pfx.fp_proto);
944  iflags = MFIB_ITF_FLAG_FORWARD;
945  }
946  else if (unformat (line_input, "%U",
947  unformat_mfib_entry_flags, &eflags))
948  ;
949  else
950  {
951  error = unformat_parse_error (line_input);
952  goto done;
953  }
954  }
955 
956  if (~0 == table_id)
957  {
958  /*
959  * if no table_id is passed we will manipulate the default
960  */
961  fib_index = 0;
962  }
963  else
964  {
965  fib_index = mfib_table_find (pfx.fp_proto, table_id);
966 
967  if (~0 == fib_index)
968  {
969  error = clib_error_return (0, "Nonexistent table id %d", table_id);
970  goto done;
971  }
972  }
973 
974  timet[0] = vlib_time_now (vm);
975 
976  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
977  {
978  incr = 1 << (32 - (pfx.fp_len % 32));
979  }
980  else
981  {
982  incr = 1 << (128 - (pfx.fp_len % 128));
983  }
984 
985  for (ss = 0; ss < scount; ss++)
986  {
987  for (gg = 0; gg < gcount; gg++)
988  {
989  if (is_del && 0 == rpath.frp_weight)
990  {
991  /* no path provided => route delete */
992  mfib_table_entry_delete (fib_index, &pfx, MFIB_SOURCE_CLI);
993  }
994  else if (eflags || (MFIB_RPF_ID_NONE != rpf_id))
995  {
996  mfib_table_entry_update (fib_index, &pfx, MFIB_SOURCE_CLI,
997  rpf_id, eflags);
998  }
999  else
1000  {
1001  if (is_del)
1002  mfib_table_entry_path_remove (fib_index,
1003  &pfx, MFIB_SOURCE_CLI, &rpath);
1004  else
1005  mfib_table_entry_path_update (fib_index,
1006  &pfx, MFIB_SOURCE_CLI, &rpath,
1007  iflags);
1008  }
1009 
1010  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
1011  {
1012  pfx.fp_grp_addr.ip4.as_u32 =
1013  clib_host_to_net_u32 (incr +
1014  clib_net_to_host_u32 (pfx.
1015  fp_grp_addr.ip4.
1016  as_u32));
1017  }
1018  else
1019  {
1020  int bucket = (incr < 64 ? 0 : 1);
1021  pfx.fp_grp_addr.ip6.as_u64[bucket] =
1022  clib_host_to_net_u64 (incr +
1023  clib_net_to_host_u64 (pfx.
1024  fp_grp_addr.ip6.as_u64
1025  [bucket]));
1026 
1027  }
1028  }
1029  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
1030  {
1031  pfx.fp_src_addr.ip4.as_u32 =
1032  clib_host_to_net_u32 (1 +
1033  clib_net_to_host_u32 (pfx.fp_src_addr.
1034  ip4.as_u32));
1035  }
1036  else
1037  {
1038  pfx.fp_src_addr.ip6.as_u64[1] =
1039  clib_host_to_net_u64 (1 +
1040  clib_net_to_host_u64 (pfx.fp_src_addr.
1041  ip6.as_u64[1]));
1042  }
1043  }
1044 
1045  timet[1] = vlib_time_now (vm);
1046 
1047  if (scount > 1 || gcount > 1)
1048  vlib_cli_output (vm, "%.6e routes/sec",
1049  (scount * gcount) / (timet[1] - timet[0]));
1050 
1051 done:
1052  unformat_free (line_input);
1053 
1054  return error;
1055 }
1056 
1057 /*?
1058  * This command is used to add or delete IPv4 or IPv6 multicastroutes. All
1059  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
1060  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
1061  * can be IPv4 or IPv6, but all must be of the same form in a single
1062  * command. To display the current set of routes, use the commands
1063  * '<em>show ip mfib</em>' and '<em>show ip6 mfib</em>'.
1064  * The full set of support flags for interfaces and route is shown via;
1065  * '<em>show mfib route flags</em>' and '<em>show mfib itf flags</em>'
1066  * respectively.
1067  * @cliexpar
1068  * Example of how to add a forwarding interface to a route (and create the
1069  * route if it does not exist)
1070  * @cliexcmd{ip mroute add 232.1.1.1 via GigabitEthernet2/0/0 Forward}
1071  * Example of how to add an accepting interface to a route (and create the
1072  * route if it does not exist)
1073  * @cliexcmd{ip mroute add 232.1.1.1 via GigabitEthernet2/0/1 Accept}
1074  * Example of changing the route's flags to send signals via the API
1075  * @cliexcmd{ip mroute add 232.1.1.1 Signal}
1076 
1077  ?*/
1078 /* *INDENT-OFF* */
1079 VLIB_CLI_COMMAND (ip_mroute_command, static) =
1080 {
1081  .path = "ip mroute",
1082  .short_help = "ip mroute [add|del] <dst-ip-addr>/<width> [table <table-id>] [rpf-id <ID>] [via <next-hop-ip-addr> [<interface>],",
1083  .function = vnet_ip_mroute_cmd,
1084  .is_mp_safe = 1,
1085 };
1086 /* *INDENT-ON* */
1087 
1088 /*
1089  * The next two routines address a longstanding script hemorrhoid.
1090  * Probing a v4 or v6 neighbor needs to appear to be synchronous,
1091  * or dependent route-adds will simply fail.
1092  */
1093 static clib_error_t *
1095  int retry_count)
1096 {
1097  vnet_main_t *vnm = vnet_get_main ();
1098  clib_error_t *e;
1099  int i;
1100  int resolved = 0;
1101  uword event_type;
1102  uword *event_data = 0;
1103 
1105 
1106  if (retry_count > 0)
1108  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
1109  1 /* event */ , 0 /* data */ );
1110 
1111  for (i = 0; i < retry_count; i++)
1112  {
1113  /* The interface may be down, etc. */
1114  e = ip6_probe_neighbor (vm, a, sw_if_index, 0);
1115 
1116  if (e)
1117  return e;
1118 
1120  event_type = vlib_process_get_events (vm, &event_data);
1121  switch (event_type)
1122  {
1123  case 1: /* resolved... */
1124  vlib_cli_output (vm, "Resolved %U", format_ip6_address, a);
1125  resolved = 1;
1126  goto done;
1127 
1128  case ~0: /* timeout */
1129  break;
1130 
1131  default:
1132  clib_warning ("unknown event_type %d", event_type);
1133  }
1134  vec_reset_length (event_data);
1135  }
1136 
1137 done:
1138 
1139  if (!resolved)
1140  return clib_error_return (0, "Resolution failed for %U",
1141  format_ip6_address, a);
1142  return 0;
1143 }
1144 
1145 static clib_error_t *
1147  int retry_count)
1148 {
1149  vnet_main_t *vnm = vnet_get_main ();
1150  clib_error_t *e;
1151  int i;
1152  int resolved = 0;
1153  uword event_type;
1154  uword *event_data = 0;
1155 
1157 
1158  if (retry_count > 0)
1160  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
1161  1 /* event */ , 0 /* data */ );
1162 
1163  for (i = 0; i < retry_count; i++)
1164  {
1165  /* The interface may be down, etc. */
1166  e = ip4_probe_neighbor (vm, a, sw_if_index, 0);
1167 
1168  if (e)
1169  return e;
1170 
1172  event_type = vlib_process_get_events (vm, &event_data);
1173  switch (event_type)
1174  {
1175  case 1: /* resolved... */
1176  vlib_cli_output (vm, "Resolved %U", format_ip4_address, a);
1177  resolved = 1;
1178  goto done;
1179 
1180  case ~0: /* timeout */
1181  break;
1182 
1183  default:
1184  clib_warning ("unknown event_type %d", event_type);
1185  }
1186  vec_reset_length (event_data);
1187  }
1188 
1189 done:
1190 
1191  vec_reset_length (event_data);
1192 
1193  if (!resolved)
1194  return clib_error_return (0, "Resolution failed for %U",
1195  format_ip4_address, a);
1196  return 0;
1197 }
1198 
1199 static clib_error_t *
1201  unformat_input_t * input, vlib_cli_command_t * cmd)
1202 {
1203  vnet_main_t *vnm = vnet_get_main ();
1204  unformat_input_t _line_input, *line_input = &_line_input;
1205  ip4_address_t a4;
1206  ip6_address_t a6;
1207  clib_error_t *error = 0;
1208  u32 sw_if_index = ~0;
1209  int retry_count = 3;
1210  int is_ip4 = 1;
1211  int address_set = 0;
1212 
1213  /* Get a line of input. */
1214  if (!unformat_user (input, unformat_line_input, line_input))
1215  return 0;
1216 
1217  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1218  {
1219  if (unformat_user (line_input, unformat_vnet_sw_interface, vnm,
1220  &sw_if_index))
1221  ;
1222  else if (unformat (line_input, "retry %d", &retry_count))
1223  ;
1224 
1225  else if (unformat (line_input, "%U", unformat_ip4_address, &a4))
1226  address_set++;
1227  else if (unformat (line_input, "%U", unformat_ip6_address, &a6))
1228  {
1229  address_set++;
1230  is_ip4 = 0;
1231  }
1232  else
1233  {
1234  error = clib_error_return (0, "unknown input '%U'",
1235  format_unformat_error, line_input);
1236  goto done;
1237  }
1238  }
1239 
1240  if (sw_if_index == ~0)
1241  {
1242  error = clib_error_return (0, "Interface required, not set.");
1243  goto done;
1244  }
1245  if (address_set == 0)
1246  {
1247  error = clib_error_return (0, "ip address required, not set.");
1248  goto done;
1249  }
1250  if (address_set > 1)
1251  {
1252  error = clib_error_return (0, "Multiple ip addresses not supported.");
1253  goto done;
1254  }
1255 
1256  if (is_ip4)
1257  error = ip4_probe_neighbor_wait (vm, &a4, sw_if_index, retry_count);
1258  else
1259  error = ip6_probe_neighbor_wait (vm, &a6, sw_if_index, retry_count);
1260 
1261 done:
1262  unformat_free (line_input);
1263 
1264  return error;
1265 }
1266 
1267 /*?
1268  * The '<em>ip probe-neighbor</em>' command ARPs for IPv4 addresses or
1269  * attempts IPv6 neighbor discovery depending on the supplied IP address
1270  * format.
1271  *
1272  * @note This command will not immediately affect the indicated FIB; it
1273  * is not suitable for use in establishing a FIB entry prior to adding
1274  * recursive FIB entries. As in: don't use it in a script to probe a
1275  * gateway prior to adding a default route. It won't work. Instead,
1276  * configure a static ARP cache entry [see '<em>set ip arp</em>'], or
1277  * a static IPv6 neighbor [see '<em>set ip6 neighbor</em>'].
1278  *
1279  * @cliexpar
1280  * Example of probe for an IPv4 address:
1281  * @cliexcmd{ip probe-neighbor GigabitEthernet2/0/0 172.16.1.2}
1282 ?*/
1283 /* *INDENT-OFF* */
1284 VLIB_CLI_COMMAND (ip_probe_neighbor_command, static) = {
1285  .path = "ip probe-neighbor",
1286  .function = probe_neighbor_address,
1287  .short_help = "ip probe-neighbor <interface> <ip4-addr> | <ip6-addr> [retry nn]",
1288  .is_mp_safe = 1,
1289 };
1290 /* *INDENT-ON* */
1291 
1292 clib_error_t *
1294 {
1295  u32 fib_index;
1296 
1297  if (!vnet_sw_interface_is_api_valid (vnet_get_main (), args->sw_if_index))
1298  return clib_error_return_code (0, VNET_API_ERROR_INVALID_INTERFACE, 0,
1299  "invalid sw_if_index");
1300 
1301  fib_index = fib_table_get_table_id_for_sw_if_index (args->prefix.fp_proto,
1302  args->sw_if_index);
1303  if (args->is_add)
1304  {
1305  dpo_id_t proxy_dpo = DPO_INVALID;
1306  l3_proxy_dpo_add_or_lock (fib_proto_to_dpo (args->prefix.fp_proto),
1307  args->sw_if_index, &proxy_dpo);
1309  &args->prefix,
1311  FIB_ENTRY_FLAG_EXCLUSIVE, &proxy_dpo);
1312  dpo_reset (&proxy_dpo);
1313  }
1314  else
1315  {
1316  fib_table_entry_special_remove (fib_index, &args->prefix,
1318  }
1319  return 0;
1320 }
1321 
1322 u8
1324 {
1325  u32 fib_index;
1326  fib_node_index_t fei;
1327  const dpo_id_t *dpo;
1328  l3_proxy_dpo_t *l3p;
1329  load_balance_t *lb0;
1330 
1332  sw_if_index);
1333  if (fib_index == ~0)
1334  return 0;
1335 
1336  fei = fib_table_lookup_exact_match (fib_index, pfx);
1337  if (fei == FIB_NODE_INDEX_INVALID)
1338  return 0;
1339 
1341  lb0 = load_balance_get (dpo->dpoi_index);
1342  dpo = load_balance_get_bucket_i (lb0, 0);
1343  if (dpo->dpoi_type != DPO_L3_PROXY)
1344  return 0;
1345 
1346  l3p = l3_proxy_dpo_get (dpo->dpoi_index);
1347  return (l3p->l3p_sw_if_index == sw_if_index);
1348 }
1349 
1350 typedef struct ip_container_proxy_walk_ctx_t_
1351 {
1353  void *ctx;
1355 
1356 static fib_table_walk_rc_t
1358 {
1360  const fib_prefix_t *pfx;
1361  const dpo_id_t *dpo;
1362  load_balance_t *lb;
1363  l3_proxy_dpo_t *l3p;
1364 
1365  pfx = fib_entry_get_prefix (fei);
1367  {
1369  lb = load_balance_get (dpo->dpoi_index);
1370  dpo = load_balance_get_bucket_i (lb, 0);
1371  l3p = l3_proxy_dpo_get (dpo->dpoi_index);
1372  ctx->cb (pfx, l3p->l3p_sw_if_index, ctx->ctx);
1373  }
1374 
1375  return FIB_TABLE_WALK_CONTINUE;
1376 }
1377 
1378 void
1380 {
1381  fib_table_t *fib_table;
1383  .cb = cb,
1384  .ctx = ctx,
1385  };
1386 
1387  /* *INDENT-OFF* */
1388  pool_foreach (fib_table, ip4_main.fibs,
1389  ({
1390  fib_table_walk(fib_table->ft_index,
1391  FIB_PROTOCOL_IP4,
1392  ip_container_proxy_fib_table_walk,
1393  &wctx);
1394  }));
1395  pool_foreach (fib_table, ip6_main.fibs,
1396  ({
1397  fib_table_walk(fib_table->ft_index,
1398  FIB_PROTOCOL_IP6,
1399  ip_container_proxy_fib_table_walk,
1400  &wctx);
1401  }));
1402  /* *INDENT-ON* */
1403 }
1404 
1405 clib_error_t *
1407  unformat_input_t * main_input, vlib_cli_command_t * cmd)
1408 {
1409  unformat_input_t _line_input, *line_input = &_line_input;
1410  fib_prefix_t pfx;
1411  u32 is_del, addr_set = 0;
1412  vnet_main_t *vnm;
1413  u32 sw_if_index;
1414 
1415  vnm = vnet_get_main ();
1416  is_del = 0;
1417  sw_if_index = ~0;
1418  clib_memset (&pfx, 0, sizeof (pfx));
1419 
1420  /* Get a line of input. */
1421  if (!unformat_user (main_input, unformat_line_input, line_input))
1422  return 0;
1423 
1424  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1425  {
1426  if (unformat (line_input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4))
1427  {
1428  pfx.fp_proto = FIB_PROTOCOL_IP4;
1429  pfx.fp_len = 32;
1430  addr_set = 1;
1431  }
1432  else if (unformat (line_input, "%U",
1433  unformat_ip6_address, &pfx.fp_addr.ip6))
1434  {
1435  pfx.fp_proto = FIB_PROTOCOL_IP6;
1436  pfx.fp_len = 128;
1437  addr_set = 1;
1438  }
1439  else if (unformat (line_input, "%U",
1440  unformat_vnet_sw_interface, vnm, &sw_if_index))
1441  ;
1442  else if (unformat (line_input, "del"))
1443  is_del = 1;
1444  else
1445  {
1446  unformat_free (line_input);
1447  return (clib_error_return (0, "unknown input '%U'",
1448  format_unformat_error, line_input));
1449  }
1450  }
1451 
1452  if (~0 == sw_if_index || !addr_set)
1453  {
1454  unformat_free (line_input);
1455  vlib_cli_output (vm, "interface and address must be set");
1456  return 0;
1457  }
1458 
1460  .prefix = pfx,
1461  .sw_if_index = sw_if_index,
1462  .is_add = !is_del,
1463  };
1465  unformat_free (line_input);
1466  return (NULL);
1467 }
1468 
1469 /* *INDENT-OFF* */
1470 VLIB_CLI_COMMAND (ip_container_command_node, static) = {
1471  .path = "ip container",
1472  .function = ip_container_cmd,
1473  .short_help = "ip container <address> <interface>",
1474  .is_mp_safe = 1,
1475 };
1476 /* *INDENT-ON* */
1477 
1478 clib_error_t *
1480  vlib_cli_command_t * cmd)
1481 {
1482  unformat_input_t _line_input, *line_input = &_line_input;
1483  vnet_main_t *vnm = vnet_get_main ();
1484  fib_prefix_t pfx;
1485  u32 sw_if_index = ~0;
1486  u8 has_proxy;
1487 
1488  if (!unformat_user (main_input, unformat_line_input, line_input))
1489  return 0;
1490  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1491  {
1492  if (unformat (line_input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4))
1493  {
1494  pfx.fp_proto = FIB_PROTOCOL_IP4;
1495  pfx.fp_len = 32;
1496  }
1497  else if (unformat (line_input, "%U",
1498  unformat_ip6_address, &pfx.fp_addr.ip6))
1499  {
1500  pfx.fp_proto = FIB_PROTOCOL_IP6;
1501  pfx.fp_len = 128;
1502  }
1503  else if (unformat (line_input, "%U",
1504  unformat_vnet_sw_interface, vnm, &sw_if_index))
1505  ;
1506  else
1507  {
1508  unformat_free (line_input);
1509  return (clib_error_return (0, "unknown input '%U'",
1510  format_unformat_error, line_input));
1511  }
1512  }
1513 
1514  if (~0 == sw_if_index)
1515  {
1516  unformat_free (line_input);
1517  vlib_cli_output (vm, "no interface");
1518  return (clib_error_return (0, "no interface"));
1519  }
1520 
1521  has_proxy = ip_container_proxy_is_set (&pfx, sw_if_index);
1522  vlib_cli_output (vm, "ip container proxy is: %s", has_proxy ? "on" : "off");
1523 
1524  unformat_free (line_input);
1525  return 0;
1526 }
1527 
1528 /* *INDENT-OFF* */
1529 VLIB_CLI_COMMAND (show_ip_container_command, static) = {
1530  .path = "show ip container",
1531  .function = show_ip_container_cmd_fn,
1532  .short_help = "show ip container <address> <interface>",
1533  .is_mp_safe = 1,
1534 };
1535 /* *INDENT-ON* */
1536 
1537 /*
1538  * fd.io coding-style-patch-verification: ON
1539  *
1540  * Local Variables:
1541  * eval: (c-set-style "gnu")
1542  * End:
1543  */
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:1094
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:572
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:486
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:1159
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:279
A representation of a path as described by a route producer.
Definition: fib_types.h:470
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:1146
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:434
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:232
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:1352
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:506
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:525
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:1678
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:419
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:475
unformat_function_t unformat_vnet_sw_interface
#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:324
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:680
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:739
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:490
unformat_function_t unformat_ip4_address
Definition: format.h:70
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:505
#define MFIB_RPF_ID_NONE
Definition: fib_types.h:393
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
u32 sw_if_index
Definition: vxlan_gbp.api:37
clib_error_t * vnet_ip_container_proxy_add_del(vnet_ip_container_proxy_args_t *args)
Definition: lookup.c:1293
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:1473
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:511
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:1406
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:1995
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:511
clib_error_t * vnet_ip_mroute_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:803
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:301
vl_api_address_t dst
Definition: vxlan_gbp.api:33
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:701
#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:1357
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:203
void ip_container_proxy_walk(ip_container_proxy_cb_t cb, void *ctx)
Definition: lookup.c:1379
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:778
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:2624
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:571
size_t count
Definition: vapi.c:47
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:237
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:731
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:579
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:188
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
A for-us/local path.
Definition: fib_types.h:332
#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:62
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:1479
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:903
#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:1323
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:244
static clib_error_t * probe_neighbor_address(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: lookup.c:1200
u8 * format_ip_adjacency_packet_data(u8 *s, va_list *args)
Definition: lookup.c:256
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:488
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:561
struct fib_table_t_ * fibs
Definition: ip6.h:181
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:318
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