FD.io VPP  v18.01-8-g0eacf49
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 
63  u32 sw_if_index,
64  void *addr_fib,
65  u32 address_length,
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)
117  lm->if_address_pool_index_by_sw_if_index[sw_if_index] =
119  }
120 
121  if ((a->next_this_sw_interface == ~0)
122  && (a->prev_this_sw_interface == ~0))
123  lm->if_address_pool_index_by_sw_if_index[sw_if_index] = ~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  memset (a, ~0, sizeof (a[0]));
141  ai = a - lm->if_address_pool;
142 
143  hi = pi = lm->if_address_pool_index_by_sw_if_index[sw_if_index];
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);
154  a->address_length = address_length;
155  a->sw_if_index = sw_if_index;
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 
162  lm->if_address_pool_index_by_sw_if_index[sw_if_index] =
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 *
188 ip_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
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_lookup_next (u8 * s, va_list * args)
257 {
258  /* int promotion of ip_lookup_next_t */
259  ip_lookup_next_t n = va_arg (*args, int);
260  char *t = 0;
261 
262  switch (n)
263  {
264  default:
265  s = format (s, "unknown %d", n);
266  return s;
267 
268  case IP_LOOKUP_NEXT_DROP:
269  t = "drop";
270  break;
271  case IP_LOOKUP_NEXT_PUNT:
272  t = "punt";
273  break;
274  case IP_LOOKUP_NEXT_ARP:
275  t = "arp";
276  break;
278  t = "midchain";
279  break;
281  t = "glean";
282  break;
284  t = "mcast";
285  break;
287  break;
288  }
289 
290  if (t)
291  vec_add (s, t, strlen (t));
292 
293  return s;
294 }
295 
296 u8 *
297 format_ip_adjacency_packet_data (u8 * s, va_list * args)
298 {
299  u32 adj_index = va_arg (*args, u32);
300  u8 *packet_data = va_arg (*args, u8 *);
301  u32 n_packet_data_bytes = va_arg (*args, u32);
302  ip_adjacency_t *adj = adj_get (adj_index);
303 
304  switch (adj->lookup_next_index)
305  {
308  s =
309  format (s, "%U", format_hex_bytes, packet_data, n_packet_data_bytes);
310  break;
311 
312  default:
313  break;
314  }
315 
316  return s;
317 }
318 
319 static uword
320 unformat_dpo (unformat_input_t * input, va_list * args)
321 {
322  dpo_id_t *dpo = va_arg (*args, dpo_id_t *);
323  fib_protocol_t fp = va_arg (*args, int);
324  dpo_proto_t proto;
325 
326  proto = fib_proto_to_dpo (fp);
327 
328  if (unformat (input, "drop"))
329  dpo_copy (dpo, drop_dpo_get (proto));
330  else if (unformat (input, "punt"))
331  dpo_copy (dpo, punt_dpo_get (proto));
332  else if (unformat (input, "local"))
333  receive_dpo_add_or_lock (proto, ~0, NULL, dpo);
334  else if (unformat (input, "null-send-unreach"))
336  else if (unformat (input, "null-send-prohibit"))
338  else if (unformat (input, "null"))
340  else if (unformat (input, "classify"))
341  {
342  u32 classify_table_index;
343 
344  if (!unformat (input, "%d", &classify_table_index))
345  {
346  clib_warning ("classify adj must specify table index");
347  return 0;
348  }
349 
350  dpo_set (dpo, DPO_CLASSIFY, proto,
351  classify_dpo_create (proto, classify_table_index));
352  }
353  else
354  return 0;
355 
356  return 1;
357 }
358 
359 const ip46_address_t zero_addr = {
360  .as_u64 = {
361  0, 0},
362 };
363 
364 clib_error_t *
366  unformat_input_t * main_input, vlib_cli_command_t * cmd)
367 {
368  unformat_input_t _line_input, *line_input = &_line_input;
369  u32 table_id, is_del, fib_index, payload_proto;
370  dpo_id_t dpo = DPO_INVALID, *dpos = NULL;
371  fib_route_path_t *rpaths = NULL, rpath;
372  fib_prefix_t *prefixs = NULL, pfx;
373  clib_error_t *error = NULL;
374  f64 count;
375  int i;
376 
377  is_del = 0;
378  table_id = 0;
379  count = 1;
380  memset (&pfx, 0, sizeof (pfx));
381 
382  /* Get a line of input. */
383  if (!unformat_user (main_input, unformat_line_input, line_input))
384  return 0;
385 
386  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
387  {
388  memset (&rpath, 0, sizeof (rpath));
389 
390  if (unformat (line_input, "table %d", &table_id))
391  ;
392  else if (unformat (line_input, "count %f", &count))
393  ;
394 
395  else if (unformat (line_input, "%U/%d",
396  unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len))
397  {
398  payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP4;
399  vec_add1 (prefixs, pfx);
400  }
401  else if (unformat (line_input, "%U/%d",
402  unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len))
403  {
404  payload_proto = pfx.fp_proto = FIB_PROTOCOL_IP6;
405  vec_add1 (prefixs, pfx);
406  }
407  else if (unformat (line_input, "via %U",
408  unformat_fib_route_path, &rpath, &payload_proto))
409  {
410  vec_add1 (rpaths, rpath);
411  }
412  else if (vec_len (prefixs) > 0 &&
413  unformat (line_input, "via %U",
414  unformat_dpo, &dpo, prefixs[0].fp_proto))
415  {
416  vec_add1 (dpos, dpo);
417  }
418  else if (unformat (line_input, "del"))
419  is_del = 1;
420  else if (unformat (line_input, "add"))
421  is_del = 0;
422  else
423  {
424  error = unformat_parse_error (line_input);
425  goto done;
426  }
427  }
428 
429  if (vec_len (prefixs) == 0)
430  {
431  error =
432  clib_error_return (0, "expected ip4/ip6 destination address/length.");
433  goto done;
434  }
435 
436  if (!is_del && vec_len (rpaths) + vec_len (dpos) == 0)
437  {
438  error = clib_error_return (0, "expected paths.");
439  goto done;
440  }
441 
442  if (~0 == table_id)
443  {
444  /*
445  * if no table_id is passed we will manipulate the default
446  */
447  fib_index = 0;
448  }
449  else
450  {
451  fib_index = fib_table_find (prefixs[0].fp_proto, table_id);
452 
453  if (~0 == fib_index)
454  {
455  error = clib_error_return (0, "Nonexistent table id %d", table_id);
456  goto done;
457  }
458  }
459 
460  for (i = 0; i < vec_len (prefixs); i++)
461  {
462  if (is_del && 0 == vec_len (rpaths))
463  {
464  fib_table_entry_delete (fib_index, &prefixs[i], FIB_SOURCE_CLI);
465  }
466  else if (!is_del && 1 == vec_len (dpos))
467  {
469  &prefixs[i],
472  &dpos[0]);
473  dpo_reset (&dpos[0]);
474  }
475  else if (vec_len (dpos) > 0)
476  {
477  error =
479  "Load-balancing over multiple special adjacencies is unsupported");
480  goto done;
481  }
482  else if (0 < vec_len (rpaths))
483  {
484  u32 k, j, n, incr;
485  ip46_address_t dst = prefixs[i].fp_addr;
486  f64 t[2];
487  n = count;
488  t[0] = vlib_time_now (vm);
489  incr = 1 << ((FIB_PROTOCOL_IP4 == prefixs[0].fp_proto ? 32 : 128) -
490  prefixs[i].fp_len);
491 
492  for (k = 0; k < n; k++)
493  {
494  for (j = 0; j < vec_len (rpaths); j++)
495  {
496  u32 fi;
497  /*
498  * the CLI parsing stored table Ids, swap to FIB indicies
499  */
500  fi = fib_table_find (prefixs[i].fp_proto,
501  rpaths[i].frp_fib_index);
502 
503  if (~0 == fi)
504  {
505  error =
506  clib_error_return (0, "Via table %d does not exist",
507  rpaths[i].frp_fib_index);
508  goto done;
509  }
510  rpaths[i].frp_fib_index = fi;
511 
512  fib_prefix_t rpfx = {
513  .fp_len = prefixs[i].fp_len,
514  .fp_proto = prefixs[i].fp_proto,
515  .fp_addr = dst,
516  };
517 
518  if (is_del)
519  fib_table_entry_path_remove2 (fib_index,
520  &rpfx,
521  FIB_SOURCE_CLI, &rpaths[j]);
522  else
523  fib_table_entry_path_add2 (fib_index,
524  &rpfx,
527  &rpaths[j]);
528  }
529 
530  if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto)
531  {
532  dst.ip4.as_u32 =
533  clib_host_to_net_u32 (incr +
534  clib_net_to_host_u32 (dst.
535  ip4.as_u32));
536  }
537  else
538  {
539  int bucket = (incr < 64 ? 0 : 1);
540  dst.ip6.as_u64[bucket] =
541  clib_host_to_net_u64 (incr +
542  clib_net_to_host_u64 (dst.ip6.as_u64
543  [bucket]));
544 
545  }
546  }
547  t[1] = vlib_time_now (vm);
548  if (count > 1)
549  vlib_cli_output (vm, "%.6e routes/sec", count / (t[1] - t[0]));
550  }
551  else
552  {
553  error = clib_error_return (0, "Don't understand what you want...");
554  goto done;
555  }
556  }
557 
558 
559 done:
560  vec_free (dpos);
561  vec_free (prefixs);
562  vec_free (rpaths);
563  unformat_free (line_input);
564  return error;
565 }
566 
567 clib_error_t *
569  unformat_input_t * main_input,
570  vlib_cli_command_t * cmd, fib_protocol_t fproto)
571 {
572  unformat_input_t _line_input, *line_input = &_line_input;
573  clib_error_t *error = NULL;
574  u32 table_id, is_add;
575  u8 *name = NULL;
576 
577  is_add = 1;
578  table_id = ~0;
579 
580  /* Get a line of input. */
581  if (!unformat_user (main_input, unformat_line_input, line_input))
582  return 0;
583 
584  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
585  {
586  if (unformat (line_input, "%d", &table_id))
587  ;
588  else if (unformat (line_input, "del"))
589  is_add = 0;
590  else if (unformat (line_input, "add"))
591  is_add = 1;
592  else if (unformat (line_input, "name %s", &name))
593  ;
594  else
595  {
596  error = unformat_parse_error (line_input);
597  goto done;
598  }
599  }
600 
601  if (~0 == table_id)
602  {
603  error = clib_error_return (0, "No table id");
604  goto done;
605  }
606  else if (0 == table_id)
607  {
608  error = clib_error_return (0, "Can't change the default table");
609  goto done;
610  }
611  else
612  {
613  if (is_add)
614  {
615  ip_table_create (fproto, table_id, 0, name);
616  }
617  else
618  {
619  ip_table_delete (fproto, table_id, 0);
620  }
621  }
622 
623 done:
624  unformat_free (line_input);
625  return error;
626 }
627 
628 clib_error_t *
630  unformat_input_t * main_input, vlib_cli_command_t * cmd)
631 {
632  return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4));
633 }
634 
635 clib_error_t *
637  unformat_input_t * main_input, vlib_cli_command_t * cmd)
638 {
639  return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6));
640 }
641 
642 /* *INDENT-OFF* */
643 VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
644  .path = "ip",
645  .short_help = "Internet protocol (IP) commands",
646 };
647 /* *INDENT-ON* */
648 
649 /* *INDENT-OFF* */
650 VLIB_CLI_COMMAND (vlib_cli_ip6_command, static) = {
651  .path = "ip6",
652  .short_help = "Internet protocol version 6 (IPv6) commands",
653 };
654 /* *INDENT-ON* */
655 
656 /* *INDENT-OFF* */
657 VLIB_CLI_COMMAND (vlib_cli_show_ip_command, static) = {
658  .path = "show ip",
659  .short_help = "Internet protocol (IP) show commands",
660 };
661 /* *INDENT-ON* */
662 
663 /* *INDENT-OFF* */
664 VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
665  .path = "show ip6",
666  .short_help = "Internet protocol version 6 (IPv6) show commands",
667 };
668 /* *INDENT-ON* */
669 
670 /*?
671  * This command is used to add or delete IPv4 or IPv6 routes. All
672  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
673  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
674  * can be IPv4 or IPv6, but all must be of the same form in a single
675  * command. To display the current set of routes, use the commands
676  * '<em>show ip fib</em>' and '<em>show ip6 fib</em>'.
677  *
678  * @cliexpar
679  * Example of how to add a straight forward static route:
680  * @cliexcmd{ip route add 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
681  * Example of how to delete a straight forward static route:
682  * @cliexcmd{ip route del 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
683  * Mainly for route add/del performance testing, one can add or delete
684  * multiple routes by adding 'count N' to the previous item:
685  * @cliexcmd{ip route add count 10 7.0.0.0/24 via 6.0.0.1 GigabitEthernet2/0/0}
686  * Add multiple routes for the same destination to create equal-cost multipath:
687  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0}
688  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0}
689  * For unequal-cost multipath, specify the desired weights. This
690  * combination of weights results in 3/4 of the traffic following the
691  * second path, 1/4 following the first path:
692  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0 weight 1}
693  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3}
694  * To add a route to a particular FIB table (VRF), use:
695  * @cliexcmd{ip route add 172.16.24.0/24 table 7 via GigabitEthernet2/0/0}
696  ?*/
697 /* *INDENT-OFF* */
698 VLIB_CLI_COMMAND (ip_route_command, static) = {
699  .path = "ip route",
700  .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>]",
701  .function = vnet_ip_route_cmd,
702  .is_mp_safe = 1,
703 };
704 
705 /* *INDENT-ON* */
706 /*?
707  * This command is used to add or delete IPv4 Tables. All
708  * Tables must be explicitly added before that can be used. Creating a
709  * table will add both unicast and multicast FIBs
710  *
711  ?*/
712 /* *INDENT-OFF* */
713 VLIB_CLI_COMMAND (ip4_table_command, static) = {
714  .path = "ip table",
715  .short_help = "ip table [add|del] <table-id>",
716  .function = vnet_ip4_table_cmd,
717  .is_mp_safe = 1,
718 };
719 /* *INDENT-ON* */
720 
721 /* *INDENT-ON* */
722 /*?
723  * This command is used to add or delete IPv4 Tables. All
724  * Tables must be explicitly added before that can be used. Creating a
725  * table will add both unicast and multicast FIBs
726  *
727  ?*/
728 /* *INDENT-OFF* */
729 VLIB_CLI_COMMAND (ip6_table_command, static) = {
730  .path = "ip6 table",
731  .short_help = "ip6 table [add|del] <table-id>",
732  .function = vnet_ip6_table_cmd,
733  .is_mp_safe = 1,
734 };
735 
736 static clib_error_t *
738  unformat_input_t * input,
739  vlib_cli_command_t * cmd,
740  fib_protocol_t fproto)
741 {
742  vnet_main_t *vnm = vnet_get_main ();
743  clib_error_t *error = 0;
744  u32 sw_if_index, table_id;
745  int rv;
746 
747  sw_if_index = ~0;
748 
749  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
750  {
751  error = clib_error_return (0, "unknown interface `%U'",
752  format_unformat_error, input);
753  goto done;
754  }
755 
756  if (unformat (input, "%d", &table_id))
757  ;
758  else
759  {
760  error = clib_error_return (0, "expected table id `%U'",
761  format_unformat_error, input);
762  goto done;
763  }
764 
765  rv = ip_table_bind (fproto, sw_if_index, table_id, 0);
766 
767  if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv)
768  {
769  error = clib_error_return (0, "IP addresses are still present on %U",
771  vnet_get_main(),
772  sw_if_index);
773  }
774  else if (VNET_API_ERROR_NO_SUCH_FIB == rv)
775  {
776  error = clib_error_return (0, "no such table %d", table_id);
777  }
778  else if (0 != rv)
779  {
780  error = clib_error_return (0, "unknown error");
781  }
782 
783  done:
784  return error;
785 }
786 
787 static clib_error_t *
789  unformat_input_t * input,
790  vlib_cli_command_t * cmd)
791 {
792  return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP4));
793 }
794 
795 static clib_error_t *
797  unformat_input_t * input,
798  vlib_cli_command_t * cmd)
799 {
800  return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP6));
801 }
802 
803 /*?
804  * Place the indicated interface into the supplied IPv4 FIB table (also known
805  * as a VRF). If the FIB table does not exist, this command creates it. To
806  * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
807  * FIB table will only be displayed if a route has been added to the table, or
808  * an IP Address is assigned to an interface in the table (which adds a route
809  * automatically).
810  *
811  * @note IP addresses added after setting the interface IP table are added to
812  * the indicated FIB table. If an IP address is added prior to changing the
813  * table then this is an error. The control plane must remove these addresses
814  * first and then change the table. VPP will not automatically move the
815  * addresses from the old to the new table as it does not know the validity
816  * of such a change.
817  *
818  * @cliexpar
819  * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
820  * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
821  ?*/
822 /* *INDENT-OFF* */
823 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
824 {
825  .path = "set interface ip table",
826  .function = ip4_table_bind_cmd,
827  .short_help = "set interface ip table <interface> <table-id>",
828 };
829 /* *INDENT-ON* */
830 
831 /*?
832  * Place the indicated interface into the supplied IPv6 FIB table (also known
833  * as a VRF). If the FIB table does not exist, this command creates it. To
834  * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
835  * FIB table will only be displayed if a route has been added to the table, or
836  * an IP Address is assigned to an interface in the table (which adds a route
837  * automatically).
838  *
839  * @note IP addresses added after setting the interface IP table are added to
840  * the indicated FIB table. If an IP address is added prior to changing the
841  * table then this is an error. The control plane must remove these addresses
842  * first and then change the table. VPP will not automatically move the
843  * addresses from the old to the new table as it does not know the validity
844  * of such a change.
845  *
846  * @cliexpar
847  * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id):
848  * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
849  ?*/
850 /* *INDENT-OFF* */
851 VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
852 {
853  .path = "set interface ip6 table",
854  .function = ip6_table_bind_cmd,
855  .short_help = "set interface ip6 table <interface> <table-id>"
856 };
857 /* *INDENT-ON* */
858 
859 clib_error_t *
861  unformat_input_t * main_input, vlib_cli_command_t * cmd)
862 {
863  unformat_input_t _line_input, *line_input = &_line_input;
864  clib_error_t *error = NULL;
865  fib_route_path_t rpath;
866  u32 table_id, is_del;
867  vnet_main_t *vnm;
868  mfib_prefix_t pfx;
869  u32 fib_index;
870  mfib_itf_flags_t iflags = 0;
871  mfib_entry_flags_t eflags = 0;
872  u32 gcount, scount, ss, gg, incr;
873  f64 timet[2];
874 
875  gcount = scount = 1;
876  vnm = vnet_get_main ();
877  is_del = 0;
878  table_id = 0;
879  memset (&pfx, 0, sizeof (pfx));
880  memset (&rpath, 0, sizeof (rpath));
881  rpath.frp_sw_if_index = ~0;
882 
883  /* Get a line of input. */
884  if (!unformat_user (main_input, unformat_line_input, line_input))
885  return 0;
886 
887  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
888  {
889  if (unformat (line_input, "table %d", &table_id))
890  ;
891  else if (unformat (line_input, "del"))
892  is_del = 1;
893  else if (unformat (line_input, "add"))
894  is_del = 0;
895  else if (unformat (line_input, "scount %d", &scount))
896  ;
897  else if (unformat (line_input, "gcount %d", &gcount))
898  ;
899  else if (unformat (line_input, "%U %U",
901  &pfx.fp_src_addr.ip4,
903  {
905  pfx.fp_len = 64;
906  }
907  else if (unformat (line_input, "%U %U",
909  &pfx.fp_src_addr.ip6,
911  {
913  pfx.fp_len = 256;
914  }
915  else if (unformat (line_input, "%U/%d",
917  &pfx.fp_grp_addr.ip4, &pfx.fp_len))
918  {
919  memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
921  }
922  else if (unformat (line_input, "%U/%d",
924  &pfx.fp_grp_addr.ip6, &pfx.fp_len))
925  {
926  memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
928  }
929  else if (unformat (line_input, "%U",
931  {
932  memset (&pfx.fp_src_addr.ip4, 0, sizeof (pfx.fp_src_addr.ip4));
934  pfx.fp_len = 32;
935  }
936  else if (unformat (line_input, "%U",
938  {
939  memset (&pfx.fp_src_addr.ip6, 0, sizeof (pfx.fp_src_addr.ip6));
941  pfx.fp_len = 128;
942  }
943  else if (unformat (line_input, "via %U",
945  &rpath.frp_sw_if_index))
946  {
947  rpath.frp_weight = 1;
948  }
949  else if (unformat (line_input, "via local"))
950  {
951  rpath.frp_sw_if_index = ~0;
952  rpath.frp_weight = 1;
954  }
955  else if (unformat (line_input, "%U", unformat_mfib_itf_flags, &iflags))
956  ;
957  else if (unformat (line_input, "%U",
958  unformat_mfib_entry_flags, &eflags))
959  ;
960  else
961  {
962  error = unformat_parse_error (line_input);
963  goto done;
964  }
965  }
966 
967  if (~0 == table_id)
968  {
969  /*
970  * if no table_id is passed we will manipulate the default
971  */
972  fib_index = 0;
973  }
974  else
975  {
976  fib_index = mfib_table_find (pfx.fp_proto, table_id);
977 
978  if (~0 == fib_index)
979  {
980  error = clib_error_return (0, "Nonexistent table id %d", table_id);
981  goto done;
982  }
983  }
984 
985  timet[0] = vlib_time_now (vm);
986 
987  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
988  {
989  incr = 1 << (32 - (pfx.fp_len % 32));
990  }
991  else
992  {
993  incr = 1 << (128 - (pfx.fp_len % 128));
994  }
995 
996  for (ss = 0; ss < scount; ss++)
997  {
998  for (gg = 0; gg < gcount; gg++)
999  {
1000  if (is_del && 0 == rpath.frp_weight)
1001  {
1002  /* no path provided => route delete */
1003  mfib_table_entry_delete (fib_index, &pfx, MFIB_SOURCE_CLI);
1004  }
1005  else if (eflags)
1006  {
1007  mfib_table_entry_update (fib_index, &pfx, MFIB_SOURCE_CLI,
1008  MFIB_RPF_ID_NONE, eflags);
1009  }
1010  else
1011  {
1012  if (is_del)
1013  mfib_table_entry_path_remove (fib_index,
1014  &pfx, MFIB_SOURCE_CLI, &rpath);
1015  else
1016  mfib_table_entry_path_update (fib_index,
1017  &pfx, MFIB_SOURCE_CLI, &rpath,
1018  iflags);
1019  }
1020 
1021  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
1022  {
1023  pfx.fp_grp_addr.ip4.as_u32 =
1024  clib_host_to_net_u32 (incr +
1025  clib_net_to_host_u32 (pfx.
1026  fp_grp_addr.ip4.
1027  as_u32));
1028  }
1029  else
1030  {
1031  int bucket = (incr < 64 ? 0 : 1);
1032  pfx.fp_grp_addr.ip6.as_u64[bucket] =
1033  clib_host_to_net_u64 (incr +
1034  clib_net_to_host_u64 (pfx.
1035  fp_grp_addr.ip6.as_u64
1036  [bucket]));
1037 
1038  }
1039  }
1040  if (FIB_PROTOCOL_IP4 == pfx.fp_proto)
1041  {
1042  pfx.fp_src_addr.ip4.as_u32 =
1043  clib_host_to_net_u32 (1 +
1044  clib_net_to_host_u32 (pfx.fp_src_addr.
1045  ip4.as_u32));
1046  }
1047  else
1048  {
1049  pfx.fp_src_addr.ip6.as_u64[1] =
1050  clib_host_to_net_u64 (1 +
1051  clib_net_to_host_u64 (pfx.fp_src_addr.
1052  ip6.as_u64[1]));
1053  }
1054  }
1055 
1056  timet[1] = vlib_time_now (vm);
1057 
1058  if (scount > 1 || gcount > 1)
1059  vlib_cli_output (vm, "%.6e routes/sec",
1060  (scount * gcount) / (timet[1] - timet[0]));
1061 
1062 done:
1063  unformat_free (line_input);
1064 
1065  return error;
1066 }
1067 
1068 /*?
1069  * This command is used to add or delete IPv4 or IPv6 multicastroutes. All
1070  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
1071  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
1072  * can be IPv4 or IPv6, but all must be of the same form in a single
1073  * command. To display the current set of routes, use the commands
1074  * '<em>show ip mfib</em>' and '<em>show ip6 mfib</em>'.
1075  * The full set of support flags for interfaces and route is shown via;
1076  * '<em>show mfib route flags</em>' and '<em>show mfib itf flags</em>'
1077  * respectively.
1078  * @cliexpar
1079  * Example of how to add a forwarding interface to a route (and create the
1080  * route if it does not exist)
1081  * @cliexcmd{ip mroute add 232.1.1.1 via GigabitEthernet2/0/0 Forward}
1082  * Example of how to add an accepting interface to a route (and create the
1083  * route if it does not exist)
1084  * @cliexcmd{ip mroute add 232.1.1.1 via GigabitEthernet2/0/1 Accept}
1085  * Example of changing the route's flags to send signals via the API
1086  * @cliexcmd{ip mroute add 232.1.1.1 Signal}
1087 
1088  ?*/
1089 /* *INDENT-OFF* */
1090 VLIB_CLI_COMMAND (ip_mroute_command, static) =
1091 {
1092  .path = "ip mroute",
1093  .short_help = "ip mroute [add|del] <dst-ip-addr>/<width> [table <table-id>] [via <next-hop-ip-addr> [<interface>],",
1094  .function = vnet_ip_mroute_cmd,
1095  .is_mp_safe = 1,
1096 };
1097 /* *INDENT-ON* */
1098 
1099 /*
1100  * The next two routines address a longstanding script hemorrhoid.
1101  * Probing a v4 or v6 neighbor needs to appear to be synchronous,
1102  * or dependent route-adds will simply fail.
1103  */
1104 static clib_error_t *
1106  int retry_count)
1107 {
1108  vnet_main_t *vnm = vnet_get_main ();
1109  clib_error_t *e;
1110  int i;
1111  int resolved = 0;
1112  uword event_type;
1113  uword *event_data = 0;
1114 
1116 
1117  if (retry_count > 0)
1119  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
1120  1 /* event */ , 0 /* data */ );
1121 
1122  for (i = 0; i < retry_count; i++)
1123  {
1124  /* The interface may be down, etc. */
1125  e = ip6_probe_neighbor (vm, a, sw_if_index);
1126 
1127  if (e)
1128  return e;
1129 
1131  event_type = vlib_process_get_events (vm, &event_data);
1132  switch (event_type)
1133  {
1134  case 1: /* resolved... */
1135  vlib_cli_output (vm, "Resolved %U", format_ip6_address, a);
1136  resolved = 1;
1137  goto done;
1138 
1139  case ~0: /* timeout */
1140  break;
1141 
1142  default:
1143  clib_warning ("unknown event_type %d", event_type);
1144  }
1145  vec_reset_length (event_data);
1146  }
1147 
1148 done:
1149 
1150  if (!resolved)
1151  return clib_error_return (0, "Resolution failed for %U",
1152  format_ip6_address, a);
1153  return 0;
1154 }
1155 
1156 static clib_error_t *
1158  int retry_count)
1159 {
1160  vnet_main_t *vnm = vnet_get_main ();
1161  clib_error_t *e;
1162  int i;
1163  int resolved = 0;
1164  uword event_type;
1165  uword *event_data = 0;
1166 
1168 
1169  if (retry_count > 0)
1171  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
1172  1 /* event */ , 0 /* data */ );
1173 
1174  for (i = 0; i < retry_count; i++)
1175  {
1176  /* The interface may be down, etc. */
1177  e = ip4_probe_neighbor (vm, a, sw_if_index);
1178 
1179  if (e)
1180  return e;
1181 
1183  event_type = vlib_process_get_events (vm, &event_data);
1184  switch (event_type)
1185  {
1186  case 1: /* resolved... */
1187  vlib_cli_output (vm, "Resolved %U", format_ip4_address, a);
1188  resolved = 1;
1189  goto done;
1190 
1191  case ~0: /* timeout */
1192  break;
1193 
1194  default:
1195  clib_warning ("unknown event_type %d", event_type);
1196  }
1197  vec_reset_length (event_data);
1198  }
1199 
1200 done:
1201 
1202  vec_reset_length (event_data);
1203 
1204  if (!resolved)
1205  return clib_error_return (0, "Resolution failed for %U",
1206  format_ip4_address, a);
1207  return 0;
1208 }
1209 
1210 static clib_error_t *
1212  unformat_input_t * input, vlib_cli_command_t * cmd)
1213 {
1214  vnet_main_t *vnm = vnet_get_main ();
1215  unformat_input_t _line_input, *line_input = &_line_input;
1216  ip4_address_t a4;
1217  ip6_address_t a6;
1218  clib_error_t *error = 0;
1219  u32 sw_if_index = ~0;
1220  int retry_count = 3;
1221  int is_ip4 = 1;
1222  int address_set = 0;
1223 
1224  /* Get a line of input. */
1225  if (!unformat_user (input, unformat_line_input, line_input))
1226  return 0;
1227 
1228  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1229  {
1230  if (unformat_user (line_input, unformat_vnet_sw_interface, vnm,
1231  &sw_if_index))
1232  ;
1233  else if (unformat (line_input, "retry %d", &retry_count))
1234  ;
1235 
1236  else if (unformat (line_input, "%U", unformat_ip4_address, &a4))
1237  address_set++;
1238  else if (unformat (line_input, "%U", unformat_ip6_address, &a6))
1239  {
1240  address_set++;
1241  is_ip4 = 0;
1242  }
1243  else
1244  {
1245  error = clib_error_return (0, "unknown input '%U'",
1246  format_unformat_error, line_input);
1247  goto done;
1248  }
1249  }
1250 
1251  if (sw_if_index == ~0)
1252  {
1253  error = clib_error_return (0, "Interface required, not set.");
1254  goto done;
1255  }
1256  if (address_set == 0)
1257  {
1258  error = clib_error_return (0, "ip address required, not set.");
1259  goto done;
1260  }
1261  if (address_set > 1)
1262  {
1263  error = clib_error_return (0, "Multiple ip addresses not supported.");
1264  goto done;
1265  }
1266 
1267  if (is_ip4)
1268  error = ip4_probe_neighbor_wait (vm, &a4, sw_if_index, retry_count);
1269  else
1270  error = ip6_probe_neighbor_wait (vm, &a6, sw_if_index, retry_count);
1271 
1272 done:
1273  unformat_free (line_input);
1274 
1275  return error;
1276 }
1277 
1278 /*?
1279  * The '<em>ip probe-neighbor</em>' command ARPs for IPv4 addresses or
1280  * attempts IPv6 neighbor discovery depending on the supplied IP address
1281  * format.
1282  *
1283  * @note This command will not immediately affect the indicated FIB; it
1284  * is not suitable for use in establishing a FIB entry prior to adding
1285  * recursive FIB entries. As in: don't use it in a script to probe a
1286  * gateway prior to adding a default route. It won't work. Instead,
1287  * configure a static ARP cache entry [see '<em>set ip arp</em>'], or
1288  * a static IPv6 neighbor [see '<em>set ip6 neighbor</em>'].
1289  *
1290  * @cliexpar
1291  * Example of probe for an IPv4 address:
1292  * @cliexcmd{ip probe-neighbor GigabitEthernet2/0/0 172.16.1.2}
1293 ?*/
1294 /* *INDENT-OFF* */
1295 VLIB_CLI_COMMAND (ip_probe_neighbor_command, static) = {
1296  .path = "ip probe-neighbor",
1297  .function = probe_neighbor_address,
1298  .short_help = "ip probe-neighbor <interface> <ip4-addr> | <ip6-addr> [retry nn]",
1299  .is_mp_safe = 1,
1300 };
1301 /* *INDENT-ON* */
1302 
1303 clib_error_t *
1305 {
1306  u32 fib_index;
1307 
1308  if (!vnet_sw_interface_is_api_valid (vnet_get_main (), args->sw_if_index))
1309  return clib_error_return_code (0, VNET_API_ERROR_INVALID_INTERFACE, 0,
1310  "invalid sw_if_index");
1311 
1312  fib_index = fib_table_get_table_id_for_sw_if_index (args->prefix.fp_proto,
1313  args->sw_if_index);
1314  if (args->is_add)
1315  {
1316  dpo_id_t proxy_dpo = DPO_INVALID;
1317  l3_proxy_dpo_add_or_lock (fib_proto_to_dpo (args->prefix.fp_proto),
1318  args->sw_if_index, &proxy_dpo);
1320  &args->prefix,
1322  FIB_ENTRY_FLAG_EXCLUSIVE, &proxy_dpo);
1323  dpo_reset (&proxy_dpo);
1324  }
1325  else
1326  {
1327  fib_table_entry_special_remove (fib_index, &args->prefix,
1329  }
1330  return 0;
1331 }
1332 
1333 u8
1335 {
1336  u32 fib_index;
1337  fib_node_index_t fei;
1338  const dpo_id_t *dpo;
1339  l3_proxy_dpo_t *l3p;
1340  load_balance_t *lb0;
1341 
1343  sw_if_index);
1344  if (fib_index == ~0)
1345  return 0;
1346 
1347  fei = fib_table_lookup_exact_match (fib_index, pfx);
1348  if (fei == FIB_NODE_INDEX_INVALID)
1349  return 0;
1350 
1352  lb0 = load_balance_get (dpo->dpoi_index);
1353  dpo = load_balance_get_bucket_i (lb0, 0);
1354  if (dpo->dpoi_type != DPO_L3_PROXY)
1355  return 0;
1356 
1357  l3p = l3_proxy_dpo_get (dpo->dpoi_index);
1358  return (l3p->l3p_sw_if_index == sw_if_index);
1359 }
1360 
1361 clib_error_t *
1363  unformat_input_t * main_input, vlib_cli_command_t * cmd)
1364 {
1365  unformat_input_t _line_input, *line_input = &_line_input;
1366  fib_prefix_t pfx;
1367  u32 is_del, addr_set = 0;
1368  vnet_main_t *vnm;
1369  u32 sw_if_index;
1370 
1371  vnm = vnet_get_main ();
1372  is_del = 0;
1373  sw_if_index = ~0;
1374  memset (&pfx, 0, sizeof (pfx));
1375 
1376  /* Get a line of input. */
1377  if (!unformat_user (main_input, unformat_line_input, line_input))
1378  return 0;
1379 
1380  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1381  {
1382  if (unformat (line_input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4))
1383  {
1384  pfx.fp_proto = FIB_PROTOCOL_IP4;
1385  pfx.fp_len = 32;
1386  addr_set = 1;
1387  }
1388  else if (unformat (line_input, "%U",
1389  unformat_ip6_address, &pfx.fp_addr.ip6))
1390  {
1391  pfx.fp_proto = FIB_PROTOCOL_IP6;
1392  pfx.fp_len = 128;
1393  addr_set = 1;
1394  }
1395  else if (unformat (line_input, "%U",
1396  unformat_vnet_sw_interface, vnm, &sw_if_index))
1397  ;
1398  else if (unformat (line_input, "del"))
1399  is_del = 1;
1400  else
1401  {
1402  unformat_free (line_input);
1403  return (clib_error_return (0, "unknown input '%U'",
1404  format_unformat_error, line_input));
1405  }
1406  }
1407 
1408  if (~0 == sw_if_index || !addr_set)
1409  {
1410  unformat_free (line_input);
1411  vlib_cli_output (vm, "interface and address must be set");
1412  return 0;
1413  }
1414 
1416  .prefix = pfx,
1417  .sw_if_index = sw_if_index,
1418  .is_add = !is_del,
1419  };
1421  unformat_free (line_input);
1422  return (NULL);
1423 }
1424 
1425 /* *INDENT-OFF* */
1426 VLIB_CLI_COMMAND (ip_container_command_node, static) = {
1427  .path = "ip container",
1428  .function = ip_container_cmd,
1429  .short_help = "ip container <address> <interface>",
1430  .is_mp_safe = 1,
1431 };
1432 /* *INDENT-ON* */
1433 
1434 clib_error_t *
1436  vlib_cli_command_t * cmd)
1437 {
1438  unformat_input_t _line_input, *line_input = &_line_input;
1439  vnet_main_t *vnm = vnet_get_main ();
1440  fib_prefix_t pfx;
1441  u32 sw_if_index = ~0;
1442  u8 has_proxy;
1443 
1444  if (!unformat_user (main_input, unformat_line_input, line_input))
1445  return 0;
1446  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1447  {
1448  if (unformat (line_input, "%U", unformat_ip4_address, &pfx.fp_addr.ip4))
1449  {
1450  pfx.fp_proto = FIB_PROTOCOL_IP4;
1451  pfx.fp_len = 32;
1452  }
1453  else if (unformat (line_input, "%U",
1454  unformat_ip6_address, &pfx.fp_addr.ip6))
1455  {
1456  pfx.fp_proto = FIB_PROTOCOL_IP6;
1457  pfx.fp_len = 128;
1458  }
1459  else if (unformat (line_input, "%U",
1460  unformat_vnet_sw_interface, vnm, &sw_if_index))
1461  ;
1462  else
1463  {
1464  unformat_free (line_input);
1465  return (clib_error_return (0, "unknown input '%U'",
1466  format_unformat_error, line_input));
1467  }
1468  }
1469 
1470  if (~0 == sw_if_index)
1471  {
1472  unformat_free (line_input);
1473  vlib_cli_output (vm, "no interface");
1474  return (clib_error_return (0, "no interface"));
1475  }
1476 
1477  has_proxy = ip_container_proxy_is_set (&pfx, sw_if_index);
1478  vlib_cli_output (vm, "ip container proxy is: %s", has_proxy ? "on" : "off");
1479 
1480  unformat_free (line_input);
1481  return 0;
1482 }
1483 
1484 /* *INDENT-OFF* */
1485 VLIB_CLI_COMMAND (show_ip_container_command, static) = {
1486  .path = "show ip container",
1487  .function = show_ip_container_cmd_fn,
1488  .short_help = "show ip container <address> <interface>",
1489  .is_mp_safe = 1,
1490 };
1491 /* *INDENT-ON* */
1492 
1493 /*
1494  * fd.io coding-style-patch-verification: ON
1495  *
1496  * Local Variables:
1497  * eval: (c-set-style "gnu")
1498  * End:
1499  */
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:1105
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:181
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:356
clib_error_t * vnet_ip4_table_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:629
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
void ip_table_create(fib_protocol_t fproto, u32 table_id, u8 is_api, const u8 *name)
Definition: ip_api.c:1242
ip46_address_t fp_src_addr
Definition: mfib_types.h:47
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
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:56
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:699
enum mfib_entry_flags_t_ mfib_entry_flags_t
a
Definition: bitmap.h:516
static uword unformat_dpo(unformat_input_t *input, va_list *args)
Definition: lookup.c:320
A representation of a path as described by a route producer.
Definition: fib_types.h:377
uword unformat_mfib_itf_flags(unformat_input_t *input, va_list *args)
Definition: mfib_types.c:122
ip_interface_address_t * if_address_pool
Pool of addresses that are assigned to interfaces.
Definition: lookup.h:122
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:1157
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:335
Multicast Adjacency.
Definition: adj.h:82
#define NULL
Definition: clib.h:55
uword mhash_unset(mhash_t *h, void *key, uword *old_value)
Definition: mhash.c:353
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:224
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:539
IP unicast adjacency.
Definition: adj.h:174
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:459
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
From the CLI.
Definition: fib_entry.h:74
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:258
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:518
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)
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:165
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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:225
The data-path object representing L3 proxy.
Definition: l3_proxy_dpo.h:27
mhash_t address_to_if_address_index
Hash table mapping address to index in interface address pool.
Definition: lookup.h:125
format_function_t format_vnet_sw_if_index_name
ip_lookup_next_t
An adjacency is a representation of an attached L3 peer.
Definition: adj.h:50
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:737
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
clib_error_t * vnet_ip_route_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:365
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:595
int ip_table_bind(fib_protocol_t fproto, u32 sw_if_index, u32 table_id, u8 is_api)
Adjacency to punt this packet.
Definition: adj.h:55
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
u8 * format_ip_lookup_next(u8 *s, va_list *args)
Definition: lookup.c:256
format_function_t format_ip4_address
Definition: format.h:79
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:365
static clib_error_t * ip6_table_bind_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: lookup.c:796
unformat_function_t unformat_ip4_address
Definition: format.h:76
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:412
#define MFIB_RPF_ID_NONE
Definition: fib_types.h:358
format_function_t format_ip6_address_and_length
Definition: format.h:96
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:542
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:390
clib_error_t * vnet_ip_container_proxy_add_del(vnet_ip_container_proxy_args_t *args)
Definition: lookup.c:1304
struct _vnet_ip_container_proxy_args vnet_ip_container_proxy_args_t
Aggregrate type for a prefix.
Definition: fib_types.h:172
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:219
#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:1028
u16 fp_len
The mask length.
Definition: fib_types.h:176
clib_error_t * ip6_probe_neighbor(vlib_main_t *vm, ip6_address_t *dst, u32 sw_if_index)
Definition: ip6_forward.c:1930
Definition: fib_entry.h:238
unformat_function_t unformat_line_input
Definition: format.h:281
u32 l3p_sw_if_index
The Software interface index on which traffic is l3_proxyd.
Definition: l3_proxy_dpo.h:32
clib_error_t * ip4_probe_neighbor(vlib_main_t *vm, ip4_address_t *dst, u32 sw_if_index)
Definition: ip4_forward.c:2212
vnet_api_error_t api_errno
Definition: vnet.h:76
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:166
format_function_t format_vnet_sw_interface_name
Definition: fib_entry.h:242
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:459
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:195
index_t classify_dpo_create(dpo_proto_t proto, u32 classify_table_index)
Definition: classify_dpo.c:43
dpo_type_t dpoi_type
the type
Definition: dpo.h:170
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:203
struct _unformat_input_t unformat_input_t
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:271
The FIB DPO provieds;.
Definition: load_balance.h:84
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:583
u8 local_next_by_ip_protocol[256]
Table mapping ip protocol to ip[46]-local node next index.
Definition: lookup.h:150
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
clib_error_t * ip_container_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:1362
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
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:568
clib_error_t * vnet_ip_mroute_cmd(vlib_main_t *vm, unformat_input_t *main_input, vlib_cli_command_t *cmd)
Definition: lookup.c:860
unformat_function_t unformat_ip6_address
Definition: format.h:94
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
uword unformat_mfib_entry_flags(unformat_input_t *input, va_list *args)
Definition: mfib_types.c:142
Adjacency to drop this packet.
Definition: adj.h:53
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
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:95
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
Definition: node_funcs.h:417
vlib_main_t * vm
Definition: buffer.c:283
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
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:836
void ip_table_delete(fib_protocol_t fproto, u32 table_id, u8 is_api)
Definition: ip_api.c:786
#define clib_warning(format, args...)
Definition: error.h:59
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:29
void ip_lookup_init(ip_lookup_main_t *lm, u32 is_ip6)
Definition: lookup.c:203
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:686
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:182
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:153
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define foreach_flow_hash_bit
Definition: lookup.h:71
This packets follow a mid-chain adjacency.
Definition: adj.h:76
u32 * if_address_pool_index_by_sw_if_index
Head of doubly linked list of interface addresses for each software interface.
Definition: lookup.h:129
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:290
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:1015
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
ip6_main_t ip6_main
Definition: ip6_forward.c:3009
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:194
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:469
size_t count
Definition: vapi.c:42
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:211
u32 flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
Definition: lookup.h:82
u64 uword
Definition: types.h:112
static l3_proxy_dpo_t * l3_proxy_dpo_get(index_t index)
Definition: l3_proxy_dpo.h:52
#define unformat_parse_error(input)
Definition: format.h:267
static clib_error_t * ip4_table_bind_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: lookup.c:788
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:636
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:182
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:30
A for-us/local path.
Definition: fib_types.h:301
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:189
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:409
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
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:144
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:193
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:1435
static uword vlib_in_process_context(vlib_main_t *vm)
Definition: node_funcs.h:411
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:1181
#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:1334
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:228
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:1211
u8 * format_ip_adjacency_packet_data(u8 *s, va_list *args)
Definition: lookup.c:297
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:481
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:251
u8 frp_weight
[un]equal cost path weight
Definition: fib_types.h:459
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:423
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
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:359
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:141
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:169
format_function_t * format_address_and_length
Either format_ip4_address_and_length or format_ip6_address_and_length.
Definition: lookup.h:147
format_function_t format_ip4_address_and_length
Definition: format.h:80