FD.io VPP  v17.01-9-ge7dcee4
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/dpo/drop_dpo.h>
47 #include <vnet/dpo/classify_dpo.h>
48 #include <vnet/dpo/punt_dpo.h>
49 #include <vnet/dpo/receive_dpo.h>
50 #include <vnet/dpo/ip_null_dpo.h>
51 
52 /**
53  * @file
54  * @brief IPv4 and IPv6 adjacency and lookup table managment.
55  *
56  */
57 
60  u32 sw_if_index,
61  void *addr_fib,
62  u32 address_length,
63  u32 is_del, u32 * result_if_address_index)
64 {
65  vnet_main_t *vnm = vnet_get_main ();
66  ip_interface_address_t *a, *prev, *next;
67  uword *p = mhash_get (&lm->address_to_if_address_index, addr_fib);
68 
70  sw_if_index, ~0);
71  a = p ? pool_elt_at_index (lm->if_address_pool, p[0]) : 0;
72 
73  /* Verify given length. */
74  if ((a && (address_length != a->address_length)) || (address_length == 0))
75  {
76  vnm->api_errno = VNET_API_ERROR_ADDRESS_LENGTH_MISMATCH;
77  return clib_error_create
78  ("%U wrong length (expected %d) for interface %U",
79  lm->format_address_and_length, addr_fib,
80  address_length, a ? a->address_length : -1,
81  format_vnet_sw_if_index_name, vnm, sw_if_index);
82  }
83 
84  if (is_del)
85  {
86  if (!a)
87  {
88  vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
89  vnm->api_errno = VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
90  return clib_error_create ("%U not found for interface %U",
92  addr_fib, address_length,
94  }
95 
96  if (a->prev_this_sw_interface != ~0)
97  {
98  prev =
102  }
103  if (a->next_this_sw_interface != ~0)
104  {
105  next =
109 
110  if (a->prev_this_sw_interface == ~0)
111  lm->if_address_pool_index_by_sw_if_index[sw_if_index] =
113  }
114 
115  if ((a->next_this_sw_interface == ~0)
116  && (a->prev_this_sw_interface == ~0))
117  lm->if_address_pool_index_by_sw_if_index[sw_if_index] = ~0;
118 
120  /* old_value */ 0);
121  pool_put (lm->if_address_pool, a);
122 
123  if (result_if_address_index)
124  *result_if_address_index = ~0;
125  }
126 
127  else if (!a)
128  {
129  u32 pi; /* previous index */
130  u32 ai;
131  u32 hi; /* head index */
132 
133  pool_get (lm->if_address_pool, a);
134  memset (a, ~0, sizeof (a[0]));
135  ai = a - lm->if_address_pool;
136 
137  hi = pi = lm->if_address_pool_index_by_sw_if_index[sw_if_index];
138  prev = 0;
139  while (pi != (u32) ~ 0)
140  {
141  prev = pool_elt_at_index (lm->if_address_pool, pi);
142  pi = prev->next_this_sw_interface;
143  }
144  pi = prev ? prev - lm->if_address_pool : (u32) ~ 0;
145 
147  addr_fib, ai, /* old_value */ 0);
148  a->address_length = address_length;
149  a->sw_if_index = sw_if_index;
150  a->flags = 0;
151  a->prev_this_sw_interface = pi;
152  a->next_this_sw_interface = ~0;
153  if (prev)
154  prev->next_this_sw_interface = ai;
155 
156  lm->if_address_pool_index_by_sw_if_index[sw_if_index] =
157  (hi != ~0) ? hi : ai;
158  if (result_if_address_index)
159  *result_if_address_index = ai;
160  }
161  else
162  {
163  if (result_if_address_index)
164  *result_if_address_index = a - lm->if_address_pool;
165  }
166 
167 
168  return /* no error */ 0;
169 }
170 
171 void
173 {
174  /* ensure that adjacency is cacheline aligned and sized */
175  STATIC_ASSERT (STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0,
176  "Cache line marker must be 1st element in struct");
179  "Data in cache line 0 is bigger than cache line size");
180 
181  /* Preallocate three "special" adjacencies */
182  lm->adjacency_heap = adj_pool;
183 
184  if (!lm->fib_result_n_bytes)
185  lm->fib_result_n_bytes = sizeof (uword);
186 
187  lm->is_ip6 = is_ip6;
188  if (is_ip6)
189  {
192  sizeof (ip6_address_fib_t));
193  }
194  else
195  {
198  sizeof (ip4_address_fib_t));
199  }
200 
201  {
202  int i;
203 
204  /* Setup all IP protocols to be punted and builtin-unknown. */
205  for (i = 0; i < 256; i++)
206  {
209  }
210 
212  lm->local_next_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
213  IP_PROTOCOL_ICMP] = IP_LOCAL_NEXT_ICMP;
214  lm->builtin_protocol_by_ip_protocol[IP_PROTOCOL_UDP] =
216  lm->builtin_protocol_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
217  IP_PROTOCOL_ICMP] =
219  }
220 }
221 
222 u8 *
223 format_ip_flow_hash_config (u8 * s, va_list * args)
224 {
225  flow_hash_config_t flow_hash_config = va_arg (*args, u32);
226 
227 #define _(n,v) if (flow_hash_config & v) s = format (s, "%s ", #n);
229 #undef _
230 
231  return s;
232 }
233 
234 u8 *
235 format_ip_lookup_next (u8 * s, va_list * args)
236 {
237  ip_lookup_next_t n = va_arg (*args, ip_lookup_next_t);
238  char *t = 0;
239 
240  switch (n)
241  {
242  default:
243  s = format (s, "unknown %d", n);
244  return s;
245 
246  case IP_LOOKUP_NEXT_DROP:
247  t = "drop";
248  break;
249  case IP_LOOKUP_NEXT_PUNT:
250  t = "punt";
251  break;
252  case IP_LOOKUP_NEXT_ARP:
253  t = "arp";
254  break;
256  t = "midchain";
257  break;
259  t = "glean";
260  break;
262  break;
263  }
264 
265  if (t)
266  vec_add (s, t, strlen (t));
267 
268  return s;
269 }
270 
271 u8 *
272 format_ip_adjacency_packet_data (u8 * s, va_list * args)
273 {
274  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
275  u32 adj_index = va_arg (*args, u32);
276  u8 *packet_data = va_arg (*args, u8 *);
277  u32 n_packet_data_bytes = va_arg (*args, u32);
278  ip_adjacency_t *adj = adj_get (adj_index);
279 
280  switch (adj->lookup_next_index)
281  {
283  s = format (s, "%U",
285  vnm->vlib_main, &adj->rewrite_header, packet_data,
286  n_packet_data_bytes);
287  break;
288 
289  default:
290  break;
291  }
292 
293  return s;
294 }
295 
296 static uword
297 unformat_dpo (unformat_input_t * input, va_list * args)
298 {
299  dpo_id_t *dpo = va_arg (*args, dpo_id_t *);
300  fib_protocol_t fp = va_arg (*args, int);
301  dpo_proto_t proto;
302 
303  proto = fib_proto_to_dpo (fp);
304 
305  if (unformat (input, "drop"))
306  dpo_copy (dpo, drop_dpo_get (proto));
307  else if (unformat (input, "punt"))
308  dpo_copy (dpo, punt_dpo_get (proto));
309  else if (unformat (input, "local"))
310  receive_dpo_add_or_lock (proto, ~0, NULL, dpo);
311  else if (unformat (input, "null-send-unreach"))
313  else if (unformat (input, "null-send-prohibit"))
315  else if (unformat (input, "null"))
317  else if (unformat (input, "classify"))
318  {
319  u32 classify_table_index;
320 
321  if (!unformat (input, "%d", &classify_table_index))
322  {
323  clib_warning ("classify adj must specify table index");
324  return 0;
325  }
326 
327  dpo_set (dpo, DPO_CLASSIFY, proto,
328  classify_dpo_create (proto, classify_table_index));
329  }
330  else
331  return 0;
332 
333  return 1;
334 }
335 
336 const ip46_address_t zero_addr = {
337  .as_u64 = {
338  0, 0},
339 };
340 
341 u32
343 {
344  ip4_main_t *im4 = &ip4_main;
345  ip6_main_t *im6 = &ip6_main;
346  uword *p;
347 
348  switch (proto)
349  {
350  case FIB_PROTOCOL_IP4:
351  p = hash_get (im4->fib_index_by_table_id, table_id);
352  break;
353  case FIB_PROTOCOL_IP6:
354  p = hash_get (im6->fib_index_by_table_id, table_id);
355  break;
356  default:
357  p = NULL;
358  break;
359  }
360  if (NULL != p)
361  {
362  return (p[0]);
363  }
364  return (~0);
365 }
366 
367 clib_error_t *
369  unformat_input_t * main_input, vlib_cli_command_t * cmd)
370 {
371  unformat_input_t _line_input, *line_input = &_line_input;
372  fib_route_path_t *rpaths = NULL, rpath;
373  dpo_id_t dpo = DPO_INVALID, *dpos = NULL;
374  fib_prefix_t *prefixs = NULL, pfx;
375  mpls_label_t out_label, via_label;
376  clib_error_t *error = NULL;
377  u32 table_id, is_del;
378  vnet_main_t *vnm;
379  u32 fib_index;
380  f64 count;
381  int i;
382 
383  vnm = vnet_get_main ();
384  is_del = 0;
385  table_id = 0;
386  count = 1;
387  memset (&pfx, 0, sizeof (pfx));
388  out_label = via_label = MPLS_LABEL_INVALID;
389 
390  /* Get a line of input. */
391  if (!unformat_user (main_input, unformat_line_input, line_input))
392  return 0;
393 
394  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
395  {
396  memset (&rpath, 0, sizeof (rpath));
397 
398  if (unformat (line_input, "table %d", &table_id))
399  ;
400  else if (unformat (line_input, "del"))
401  is_del = 1;
402  else if (unformat (line_input, "add"))
403  is_del = 0;
404  else if (unformat (line_input, "resolve-via-host"))
405  {
406  if (vec_len (rpaths) == 0)
407  {
408  error = clib_error_return (0, "Paths then flags");
409  goto done;
410  }
411  rpaths[vec_len (rpaths) - 1].frp_flags |=
413  }
414  else if (unformat (line_input, "resolve-via-attached"))
415  {
416  if (vec_len (rpaths) == 0)
417  {
418  error = clib_error_return (0, "Paths then flags");
419  goto done;
420  }
421  rpaths[vec_len (rpaths) - 1].frp_flags |=
423  }
424  else if (unformat (line_input, "out-label %U",
425  unformat_mpls_unicast_label, &out_label))
426  {
427  if (vec_len (rpaths) == 0)
428  {
429  error = clib_error_return (0, "Paths then labels");
430  goto done;
431  }
432  vec_add1 (rpaths[vec_len (rpaths) - 1].frp_label_stack, out_label);
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_proto = FIB_PROTOCOL_MPLS;
439  rpath.frp_sw_if_index = ~0;
440  vec_add1 (rpaths, rpath);
441  }
442  else if (unformat (line_input, "count %f", &count))
443  ;
444 
445  else if (unformat (line_input, "%U/%d",
446  unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len))
447  {
448  pfx.fp_proto = FIB_PROTOCOL_IP4;
449  vec_add1 (prefixs, pfx);
450  }
451  else if (unformat (line_input, "%U/%d",
452  unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len))
453  {
454  pfx.fp_proto = FIB_PROTOCOL_IP6;
455  vec_add1 (prefixs, pfx);
456  }
457  else if (unformat (line_input, "via %U %U weight %u",
459  &rpath.frp_addr.ip4,
461  &rpath.frp_sw_if_index, &rpath.frp_weight))
462  {
463  rpath.frp_proto = FIB_PROTOCOL_IP4;
464  vec_add1 (rpaths, rpath);
465  }
466 
467  else if (unformat (line_input, "via %U %U weight %u",
469  &rpath.frp_addr.ip6,
471  &rpath.frp_sw_if_index, &rpath.frp_weight))
472  {
473  rpath.frp_proto = FIB_PROTOCOL_IP6;
474  vec_add1 (rpaths, rpath);
475  }
476 
477  else if (unformat (line_input, "via %U %U",
479  &rpath.frp_addr.ip4,
481  &rpath.frp_sw_if_index))
482  {
483  rpath.frp_weight = 1;
484  rpath.frp_proto = FIB_PROTOCOL_IP4;
485  vec_add1 (rpaths, rpath);
486  }
487 
488  else if (unformat (line_input, "via %U %U",
490  &rpath.frp_addr.ip6,
492  &rpath.frp_sw_if_index))
493  {
494  rpath.frp_weight = 1;
495  rpath.frp_proto = FIB_PROTOCOL_IP6;
496  vec_add1 (rpaths, rpath);
497  }
498  else if (unformat (line_input, "via %U next-hop-table %d",
500  &rpath.frp_addr.ip4, &rpath.frp_fib_index))
501  {
502  rpath.frp_weight = 1;
503  rpath.frp_sw_if_index = ~0;
504  rpath.frp_proto = FIB_PROTOCOL_IP4;
505  vec_add1 (rpaths, rpath);
506  }
507  else if (unformat (line_input, "via %U next-hop-table %d",
509  &rpath.frp_addr.ip6, &rpath.frp_fib_index))
510  {
511  rpath.frp_weight = 1;
512  rpath.frp_sw_if_index = ~0;
513  rpath.frp_proto = FIB_PROTOCOL_IP6;
514  vec_add1 (rpaths, rpath);
515  }
516  else if (unformat (line_input, "via %U",
517  unformat_ip4_address, &rpath.frp_addr.ip4))
518  {
519  /*
520  * the recursive next-hops are by default in the same table
521  * as the prefix
522  */
523  rpath.frp_fib_index = table_id;
524  rpath.frp_weight = 1;
525  rpath.frp_sw_if_index = ~0;
526  rpath.frp_proto = FIB_PROTOCOL_IP4;
527  vec_add1 (rpaths, rpath);
528  }
529  else if (unformat (line_input, "via %U",
530  unformat_ip6_address, &rpath.frp_addr.ip6))
531  {
532  rpath.frp_fib_index = table_id;
533  rpath.frp_weight = 1;
534  rpath.frp_sw_if_index = ~0;
535  rpath.frp_proto = FIB_PROTOCOL_IP6;
536  vec_add1 (rpaths, rpath);
537  }
538  else if (unformat (line_input,
539  "lookup in table %d", &rpath.frp_fib_index))
540  {
541  rpath.frp_proto = pfx.fp_proto;
542  rpath.frp_sw_if_index = ~0;
543  vec_add1 (rpaths, rpath);
544  }
545  else if (vec_len (prefixs) > 0 &&
546  unformat (line_input, "via %U",
548  &rpath.frp_sw_if_index))
549  {
550  rpath.frp_weight = 1;
551  rpath.frp_proto = prefixs[0].fp_proto;
552  vec_add1 (rpaths, rpath);
553  }
554  else if (vec_len (prefixs) > 0 &&
555  unformat (line_input, "via %U",
556  unformat_dpo, &dpo, prefixs[0].fp_proto))
557  {
558  vec_add1 (dpos, dpo);
559  }
560  else
561  {
562  error = unformat_parse_error (line_input);
563  goto done;
564  }
565  }
566 
567  unformat_free (line_input);
568 
569  if (vec_len (prefixs) == 0)
570  {
571  error =
572  clib_error_return (0, "expected ip4/ip6 destination address/length.");
573  goto done;
574  }
575 
576  if (!is_del && vec_len (rpaths) + vec_len (dpos) == 0)
577  {
578  error = clib_error_return (0, "expected paths.");
579  goto done;
580  }
581 
582  if (~0 == table_id)
583  {
584  /*
585  * if no table_id is passed we will manipulate the default
586  */
587  fib_index = 0;
588  }
589  else
590  {
591  fib_index = fib_table_id_find_fib_index (prefixs[0].fp_proto, table_id);
592 
593  if (~0 == fib_index)
594  {
595  error = clib_error_return (0, "Nonexistent table id %d", table_id);
596  goto done;
597  }
598  }
599 
600  for (i = 0; i < vec_len (prefixs); i++)
601  {
602  if (is_del && 0 == vec_len (rpaths))
603  {
604  fib_table_entry_delete (fib_index, &prefixs[i], FIB_SOURCE_CLI);
605  }
606  else if (!is_del && 1 == vec_len (dpos))
607  {
609  &prefixs[i],
612  &dpos[0]);
613  dpo_reset (&dpos[0]);
614  }
615  else if (vec_len (dpos) > 0)
616  {
617  error =
619  "Load-balancing over multiple special adjacencies is unsupported");
620  goto done;
621  }
622  else if (0 < vec_len (rpaths))
623  {
624  u32 k, j, n, incr;
625  ip46_address_t dst = prefixs[i].fp_addr;
626  f64 t[2];
627  n = count;
628  t[0] = vlib_time_now (vm);
629  incr = 1 << ((FIB_PROTOCOL_IP4 == prefixs[0].fp_proto ? 32 : 128) -
630  prefixs[i].fp_len);
631 
632  for (k = 0; k < n; k++)
633  {
634  for (j = 0; j < vec_len (rpaths); j++)
635  {
636  u32 fi;
637  /*
638  * the CLI parsing stored table Ids, swap to FIB indicies
639  */
640  fi = fib_table_id_find_fib_index (prefixs[i].fp_proto,
641  rpaths[i].frp_fib_index);
642 
643  if (~0 == fi)
644  {
645  error =
646  clib_error_return (0, "Via table %d does not exist",
647  rpaths[i].frp_fib_index);
648  goto done;
649  }
650  rpaths[i].frp_fib_index = fi;
651 
652  fib_prefix_t rpfx = {
653  .fp_len = prefixs[i].fp_len,
654  .fp_proto = prefixs[i].fp_proto,
655  .fp_addr = dst,
656  };
657 
658  if (is_del)
659  fib_table_entry_path_remove2 (fib_index,
660  &rpfx,
661  FIB_SOURCE_CLI, &rpaths[j]);
662  else
663  fib_table_entry_path_add2 (fib_index,
664  &rpfx,
667  &rpaths[j]);
668  }
669 
670  if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto)
671  {
672  dst.ip4.as_u32 =
673  clib_host_to_net_u32 (incr +
674  clib_net_to_host_u32 (dst.
675  ip4.as_u32));
676  }
677  else
678  {
679  int bucket = (incr < 64 ? 0 : 1);
680  dst.ip6.as_u64[bucket] =
681  clib_host_to_net_u64 (incr +
682  clib_net_to_host_u64 (dst.ip6.as_u64
683  [bucket]));
684 
685  }
686  }
687  t[1] = vlib_time_now (vm);
688  if (count > 1)
689  vlib_cli_output (vm, "%.6e routes/sec", count / (t[1] - t[0]));
690  }
691  else
692  {
693  error = clib_error_return (0, "Don't understand what you want...");
694  goto done;
695  }
696  }
697 
698 
699 done:
700  vec_free (dpos);
701  vec_free (prefixs);
702  vec_free (rpaths);
703  return error;
704 }
705 
706 /* *INDENT-OFF* */
707 VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
708  .path = "ip",
709  .short_help = "Internet protocol (IP) commands",
710 };
711 /* *INDENT-ON* */
712 
713 /* *INDENT-OFF* */
714 VLIB_CLI_COMMAND (vlib_cli_ip6_command, static) = {
715  .path = "ip6",
716  .short_help = "Internet protocol version 6 (IPv6) commands",
717 };
718 /* *INDENT-ON* */
719 
720 /* *INDENT-OFF* */
721 VLIB_CLI_COMMAND (vlib_cli_show_ip_command, static) = {
722  .path = "show ip",
723  .short_help = "Internet protocol (IP) show commands",
724 };
725 /* *INDENT-ON* */
726 
727 /* *INDENT-OFF* */
728 VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
729  .path = "show ip6",
730  .short_help = "Internet protocol version 6 (IPv6) show commands",
731 };
732 /* *INDENT-ON* */
733 
734 /*?
735  * This command is used to add or delete IPv4 or IPv6 routes. All
736  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
737  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
738  * can be IPv4 or IPv6, but all must be of the same form in a single
739  * command. To display the current set of routes, use the commands
740  * '<em>show ip fib</em>' and '<em>show ip6 fib</em>'.
741  *
742  * @cliexpar
743  * Example of how to add a straight forward static route:
744  * @cliexcmd{ip route add 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
745  * Example of how to delete a straight forward static route:
746  * @cliexcmd{ip route del 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
747  * Mainly for route add/del performance testing, one can add or delete
748  * multiple routes by adding 'count N' to the previous item:
749  * @cliexcmd{ip route add count 10 7.0.0.0/24 via 6.0.0.1 GigabitEthernet2/0/0}
750  * Add multiple routes for the same destination to create equal-cost multipath:
751  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0}
752  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0}
753  * For unequal-cost multipath, specify the desired weights. This
754  * combination of weights results in 3/4 of the traffic following the
755  * second path, 1/4 following the first path:
756  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0 weight 1}
757  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3}
758  * To add a route to a particular FIB table (VRF), use:
759  * @cliexcmd{ip route add 172.16.24.0/24 table 7 via GigabitEthernet2/0/0}
760  ?*/
761 /* *INDENT-OFF* */
762 VLIB_CLI_COMMAND (ip_route_command, static) = {
763  .path = "ip route",
764  .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>]",
765  .function = vnet_ip_route_cmd,
766  .is_mp_safe = 1,
767 };
768 /* *INDENT-ON* */
769 
770 /*
771  * The next two routines address a longstanding script hemorrhoid.
772  * Probing a v4 or v6 neighbor needs to appear to be synchronous,
773  * or dependent route-adds will simply fail.
774  */
775 static clib_error_t *
777  int retry_count)
778 {
779  vnet_main_t *vnm = vnet_get_main ();
780  clib_error_t *e;
781  int i;
782  int resolved = 0;
783  uword event_type;
784  uword *event_data = 0;
785 
787 
788  if (retry_count > 0)
790  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
791  1 /* event */ , 0 /* data */ );
792 
793  for (i = 0; i < retry_count; i++)
794  {
795  /* The interface may be down, etc. */
796  e = ip6_probe_neighbor (vm, a, sw_if_index);
797 
798  if (e)
799  return e;
800 
802  event_type = vlib_process_get_events (vm, &event_data);
803  switch (event_type)
804  {
805  case 1: /* resolved... */
806  vlib_cli_output (vm, "Resolved %U", format_ip6_address, a);
807  resolved = 1;
808  goto done;
809 
810  case ~0: /* timeout */
811  break;
812 
813  default:
814  clib_warning ("unknown event_type %d", event_type);
815  }
816  vec_reset_length (event_data);
817  }
818 
819 done:
820 
821  if (!resolved)
822  return clib_error_return (0, "Resolution failed for %U",
823  format_ip6_address, a);
824  return 0;
825 }
826 
827 static clib_error_t *
829  int retry_count)
830 {
831  vnet_main_t *vnm = vnet_get_main ();
832  clib_error_t *e;
833  int i;
834  int resolved = 0;
835  uword event_type;
836  uword *event_data = 0;
837 
839 
840  if (retry_count > 0)
842  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
843  1 /* event */ , 0 /* data */ );
844 
845  for (i = 0; i < retry_count; i++)
846  {
847  /* The interface may be down, etc. */
848  e = ip4_probe_neighbor (vm, a, sw_if_index);
849 
850  if (e)
851  return e;
852 
854  event_type = vlib_process_get_events (vm, &event_data);
855  switch (event_type)
856  {
857  case 1: /* resolved... */
858  vlib_cli_output (vm, "Resolved %U", format_ip4_address, a);
859  resolved = 1;
860  goto done;
861 
862  case ~0: /* timeout */
863  break;
864 
865  default:
866  clib_warning ("unknown event_type %d", event_type);
867  }
868  vec_reset_length (event_data);
869  }
870 
871 done:
872 
873  vec_reset_length (event_data);
874 
875  if (!resolved)
876  return clib_error_return (0, "Resolution failed for %U",
877  format_ip4_address, a);
878  return 0;
879 }
880 
881 static clib_error_t *
883  unformat_input_t * input, vlib_cli_command_t * cmd)
884 {
885  vnet_main_t *vnm = vnet_get_main ();
886  unformat_input_t _line_input, *line_input = &_line_input;
887  ip4_address_t a4;
888  ip6_address_t a6;
889  clib_error_t *error = 0;
890  u32 sw_if_index = ~0;
891  int retry_count = 3;
892  int is_ip4 = 1;
893  int address_set = 0;
894 
895  /* Get a line of input. */
896  if (!unformat_user (input, unformat_line_input, line_input))
897  return 0;
898 
899  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
900  {
901  if (unformat_user (line_input, unformat_vnet_sw_interface, vnm,
902  &sw_if_index))
903  ;
904  else if (unformat (line_input, "retry %d", &retry_count))
905  ;
906 
907  else if (unformat (line_input, "%U", unformat_ip4_address, &a4))
908  address_set++;
909  else if (unformat (line_input, "%U", unformat_ip6_address, &a6))
910  {
911  address_set++;
912  is_ip4 = 0;
913  }
914  else
915  return clib_error_return (0, "unknown input '%U'",
916  format_unformat_error, line_input);
917  }
918 
919  unformat_free (line_input);
920 
921  if (sw_if_index == ~0)
922  return clib_error_return (0, "Interface required, not set.");
923  if (address_set == 0)
924  return clib_error_return (0, "ip address required, not set.");
925  if (address_set > 1)
926  return clib_error_return (0, "Multiple ip addresses not supported.");
927 
928  if (is_ip4)
929  error = ip4_probe_neighbor_wait (vm, &a4, sw_if_index, retry_count);
930  else
931  error = ip6_probe_neighbor_wait (vm, &a6, sw_if_index, retry_count);
932 
933  return error;
934 }
935 
936 /*?
937  * The '<em>ip probe-neighbor</em>' command ARPs for IPv4 addresses or
938  * attempts IPv6 neighbor discovery depending on the supplied IP address
939  * format.
940  *
941  * @note This command will not immediately affect the indicated FIB; it
942  * is not suitable for use in establishing a FIB entry prior to adding
943  * recursive FIB entries. As in: don't use it in a script to probe a
944  * gateway prior to adding a default route. It won't work. Instead,
945  * configure a static ARP cache entry [see '<em>set ip arp</em>'], or
946  * a static IPv6 neighbor [see '<em>set ip6 neighbor</em>'].
947  *
948  * @cliexpar
949  * Example of probe for an IPv4 address:
950  * @cliexcmd{ip probe-neighbor GigabitEthernet2/0/0 172.16.1.2}
951 ?*/
952 /* *INDENT-OFF* */
953 VLIB_CLI_COMMAND (ip_probe_neighbor_command, static) = {
954  .path = "ip probe-neighbor",
955  .function = probe_neighbor_address,
956  .short_help = "ip probe-neighbor <interface> <ip4-addr> | <ip6-addr> [retry nn]",
957  .is_mp_safe = 1,
958 };
959 /* *INDENT-ON* */
960 
961 /*
962  * fd.io coding-style-patch-verification: ON
963  *
964  * Local Variables:
965  * eval: (c-set-style "gnu")
966  * End:
967  */
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:776
u32 fib_table_id_find_fib_index(fib_protocol_t proto, u32 table_id)
Definition: lookup.c:342
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:154
ip_lookup_next_t
Common (IP4/IP6) next index stored in adjacency.
Definition: lookup.h:60
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
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
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
ip_adjacency_t * adj_pool
The global adjacnecy pool.
Definition: adj.c:35
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:966
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:684
ip_adjacency_t * adjacency_heap
Definition: lookup.h:369
a
Definition: bitmap.h:516
static uword unformat_dpo(unformat_input_t *input, va_list *args)
Definition: lookup.c:297
A representation of a path as described by a route producer.
Definition: fib_types.h:285
format_function_t format_ip6_address
Definition: format.h:95
ip_interface_address_t * if_address_pool
Pool of addresses that are assigned to interfaces.
Definition: lookup.h:375
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:828
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#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:182
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:521
IP unicast adjacency.
Definition: lookup.h:188
u32 mpls_label_t
A label value only, i.e.
Definition: packet.h:24
From the CLI.
Definition: fib_entry.h:62
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:221
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
#define STRUCT_OFFSET_OF(t, f)
Definition: clib.h:62
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
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:200
format_function_t format_ip4_address
Definition: format.h:79
mhash_t address_to_if_address_index
Hash table mapping address to index in interface address pool.
Definition: lookup.h:378
format_function_t format_vnet_sw_if_index_name
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:368
unformat_function_t unformat_mpls_unicast_label
Definition: mpls.h:107
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Adjacency to drop this packet.
Definition: lookup.h:63
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:559
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:235
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:117
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:527
Recursion constraint of via a host prefix.
Definition: fib_types.h:261
Aggregrate type for a prefix.
Definition: fib_types.h:145
const dpo_id_t * punt_dpo_get(dpo_proto_t proto)
Definition: punt_dpo.c:25
Adjacency to punt this packet.
Definition: lookup.h:65
static void unformat_free(unformat_input_t *i)
Definition: format.h:161
#define clib_warning(format, args...)
Definition: error.h:59
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:977
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
u16 fp_len
The mask length.
Definition: fib_types.h:149
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: lookup.h:78
clib_error_t * ip6_probe_neighbor(vlib_main_t *vm, ip6_address_t *dst, u32 sw_if_index)
Definition: ip6_forward.c:1886
Definition: fib_entry.h:216
unformat_function_t unformat_ip4_address
Definition: format.h:76
clib_error_t * ip4_probe_neighbor(vlib_main_t *vm, ip4_address_t *dst, u32 sw_if_index)
Definition: ip4_forward.c:2170
vnet_api_error_t api_errno
Definition: vnet.h:77
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:138
#define hash_get(h, key)
Definition: hash.h:248
format_function_t format_vnet_sw_interface_name
Definition: fib_entry.h:220
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:112
vlib_main_t * vlib_main
Definition: vnet.h:79
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:168
index_t classify_dpo_create(dpo_proto_t proto, u32 classify_table_index)
Definition: classify_dpo.c:43
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define unformat_parse_error(input)
Definition: format.h:267
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:565
u8 local_next_by_ip_protocol[256]
Table mapping ip protocol to ip[46]-local node next index.
Definition: lookup.h:408
#define clib_error_create(args...)
Definition: error.h:108
Recursion constraint of via an attahced prefix.
Definition: fib_types.h:265
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
Definition: mhash.h:117
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
unformat_function_t unformat_ip6_address
Definition: format.h:94
uword * fib_index_by_table_id
Definition: ip6.h:151
void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
Definition: mhash.c:168
static vlib_process_t * vlib_get_current_process(vlib_main_t *vm)
Definition: node_funcs.h:397
#define MPLS_LABEL_INVALID
Definition: mpls_types.h:33
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
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:808
void ip_lookup_init(ip_lookup_main_t *lm, u32 is_ip6)
Definition: lookup.c:172
format_function_t format_vnet_rewrite_header
Definition: rewrite.h:293
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: lookup.h:73
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:618
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:154
u8 builtin_protocol_by_ip_protocol[256]
IP_BUILTIN_PROTOCOL_{TCP,UDP,ICMP,OTHER} by protocol in IP header.
Definition: lookup.h:411
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
#define foreach_flow_hash_bit
Definition: lookup.h:149
u32 * if_address_pool_index_by_sw_if_index
Head of doubly linked list of interface addresses for each software interface.
Definition: lookup.h:382
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:288
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
static uword * mhash_get(mhash_t *h, const void *key)
Definition: mhash.h:110
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
ip6_main_t ip6_main
Definition: ip6_forward.c:2828
IPv4 main type.
Definition: ip4.h:95
This packets follow a mid-chain adjacency.
Definition: lookup.h:89
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:324
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:220
u32 flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
Definition: lookup.h:160
u64 uword
Definition: types.h:112
void vnet_register_ip6_neighbor_resolution_event(vnet_main_t *vnm, void *address_arg, uword node_index, uword type_opaque, uword data)
format_function_t format_ip6_address_and_length
Definition: format.h:96
#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
Definition: lookup.h:199
#define STATIC_ASSERT(truth,...)
u32 is_ip6
1 for ip6; 0 for ip4.
Definition: lookup.h:399
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:165
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:59
static uword vlib_in_process_context(vlib_main_t *vm)
Definition: node_funcs.h:404
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1099
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:83
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:191
#define clib_error_return(e, args...)
Definition: error.h:111
u8 * format_ip_flow_hash_config(u8 *s, va_list *args)
Definition: lookup.c:223
struct _unformat_input_t unformat_input_t
static clib_error_t * probe_neighbor_address(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: lookup.c:882
u8 * format_ip_adjacency_packet_data(u8 *s, va_list *args)
Definition: lookup.c:272
#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:445
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
format_function_t format_ip4_address_and_length
Definition: format.h:80
unformat_function_t unformat_line_input
Definition: format.h:281
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:316
const ip46_address_t zero_addr
Definition: lookup.c:336
u32 fib_result_n_bytes
Number of bytes in a fib result.
Definition: lookup.h:394
format_function_t * format_address_and_length
Either format_ip4_address_and_length or format_ip6_address_and_length.
Definition: lookup.h:402