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