FD.io VPP  v17.01.1-3-gc6833f8
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 static clib_error_t *
172 ip_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
173 {
175  lookup_main.if_address_pool_index_by_sw_if_index,
176  sw_if_index, ~0);
178  lookup_main.if_address_pool_index_by_sw_if_index,
179  sw_if_index, ~0);
180 
181  return (NULL);
182 }
183 
185 
186 void
188 {
189  /* ensure that adjacency is cacheline aligned and sized */
190  STATIC_ASSERT (STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0,
191  "Cache line marker must be 1st element in struct");
194  "Data in cache line 0 is bigger than cache line size");
195 
196  /* Preallocate three "special" adjacencies */
197  lm->adjacency_heap = adj_pool;
198 
199  if (!lm->fib_result_n_bytes)
200  lm->fib_result_n_bytes = sizeof (uword);
201 
202  lm->is_ip6 = is_ip6;
203  if (is_ip6)
204  {
207  sizeof (ip6_address_fib_t));
208  }
209  else
210  {
213  sizeof (ip4_address_fib_t));
214  }
215 
216  {
217  int i;
218 
219  /* Setup all IP protocols to be punted and builtin-unknown. */
220  for (i = 0; i < 256; i++)
221  {
224  }
225 
227  lm->local_next_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
228  IP_PROTOCOL_ICMP] = IP_LOCAL_NEXT_ICMP;
229  lm->builtin_protocol_by_ip_protocol[IP_PROTOCOL_UDP] =
231  lm->builtin_protocol_by_ip_protocol[is_ip6 ? IP_PROTOCOL_ICMP6 :
232  IP_PROTOCOL_ICMP] =
234  }
235 }
236 
237 u8 *
238 format_ip_flow_hash_config (u8 * s, va_list * args)
239 {
240  flow_hash_config_t flow_hash_config = va_arg (*args, u32);
241 
242 #define _(n,v) if (flow_hash_config & v) s = format (s, "%s ", #n);
244 #undef _
245 
246  return s;
247 }
248 
249 u8 *
250 format_ip_lookup_next (u8 * s, va_list * args)
251 {
252  ip_lookup_next_t n = va_arg (*args, ip_lookup_next_t);
253  char *t = 0;
254 
255  switch (n)
256  {
257  default:
258  s = format (s, "unknown %d", n);
259  return s;
260 
261  case IP_LOOKUP_NEXT_DROP:
262  t = "drop";
263  break;
264  case IP_LOOKUP_NEXT_PUNT:
265  t = "punt";
266  break;
267  case IP_LOOKUP_NEXT_ARP:
268  t = "arp";
269  break;
271  t = "midchain";
272  break;
274  t = "glean";
275  break;
277  break;
278  }
279 
280  if (t)
281  vec_add (s, t, strlen (t));
282 
283  return s;
284 }
285 
286 u8 *
287 format_ip_adjacency_packet_data (u8 * s, va_list * args)
288 {
289  vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
290  u32 adj_index = va_arg (*args, u32);
291  u8 *packet_data = va_arg (*args, u8 *);
292  u32 n_packet_data_bytes = va_arg (*args, u32);
293  ip_adjacency_t *adj = adj_get (adj_index);
294 
295  switch (adj->lookup_next_index)
296  {
298  s = format (s, "%U",
300  vnm->vlib_main, &adj->rewrite_header, packet_data,
301  n_packet_data_bytes);
302  break;
303 
304  default:
305  break;
306  }
307 
308  return s;
309 }
310 
311 static uword
312 unformat_dpo (unformat_input_t * input, va_list * args)
313 {
314  dpo_id_t *dpo = va_arg (*args, dpo_id_t *);
315  fib_protocol_t fp = va_arg (*args, int);
316  dpo_proto_t proto;
317 
318  proto = fib_proto_to_dpo (fp);
319 
320  if (unformat (input, "drop"))
321  dpo_copy (dpo, drop_dpo_get (proto));
322  else if (unformat (input, "punt"))
323  dpo_copy (dpo, punt_dpo_get (proto));
324  else if (unformat (input, "local"))
325  receive_dpo_add_or_lock (proto, ~0, NULL, dpo);
326  else if (unformat (input, "null-send-unreach"))
328  else if (unformat (input, "null-send-prohibit"))
330  else if (unformat (input, "null"))
332  else if (unformat (input, "classify"))
333  {
334  u32 classify_table_index;
335 
336  if (!unformat (input, "%d", &classify_table_index))
337  {
338  clib_warning ("classify adj must specify table index");
339  return 0;
340  }
341 
342  dpo_set (dpo, DPO_CLASSIFY, proto,
343  classify_dpo_create (proto, classify_table_index));
344  }
345  else
346  return 0;
347 
348  return 1;
349 }
350 
351 const ip46_address_t zero_addr = {
352  .as_u64 = {
353  0, 0},
354 };
355 
356 u32
358 {
359  ip4_main_t *im4 = &ip4_main;
360  ip6_main_t *im6 = &ip6_main;
361  uword *p;
362 
363  switch (proto)
364  {
365  case FIB_PROTOCOL_IP4:
366  p = hash_get (im4->fib_index_by_table_id, table_id);
367  break;
368  case FIB_PROTOCOL_IP6:
369  p = hash_get (im6->fib_index_by_table_id, table_id);
370  break;
371  default:
372  p = NULL;
373  break;
374  }
375  if (NULL != p)
376  {
377  return (p[0]);
378  }
379  return (~0);
380 }
381 
382 clib_error_t *
384  unformat_input_t * main_input, vlib_cli_command_t * cmd)
385 {
386  unformat_input_t _line_input, *line_input = &_line_input;
387  fib_route_path_t *rpaths = NULL, rpath;
388  dpo_id_t dpo = DPO_INVALID, *dpos = NULL;
389  fib_prefix_t *prefixs = NULL, pfx;
390  mpls_label_t out_label, via_label;
391  clib_error_t *error = NULL;
392  u32 table_id, is_del;
393  vnet_main_t *vnm;
394  u32 fib_index;
395  f64 count;
396  int i;
397 
398  vnm = vnet_get_main ();
399  is_del = 0;
400  table_id = 0;
401  count = 1;
402  memset (&pfx, 0, sizeof (pfx));
403  out_label = via_label = MPLS_LABEL_INVALID;
404 
405  /* Get a line of input. */
406  if (!unformat_user (main_input, unformat_line_input, line_input))
407  return 0;
408 
409  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
410  {
411  memset (&rpath, 0, sizeof (rpath));
412 
413  if (unformat (line_input, "table %d", &table_id))
414  ;
415  else if (unformat (line_input, "del"))
416  is_del = 1;
417  else if (unformat (line_input, "add"))
418  is_del = 0;
419  else if (unformat (line_input, "resolve-via-host"))
420  {
421  if (vec_len (rpaths) == 0)
422  {
423  error = clib_error_return (0, "Paths then flags");
424  goto done;
425  }
426  rpaths[vec_len (rpaths) - 1].frp_flags |=
428  }
429  else if (unformat (line_input, "resolve-via-attached"))
430  {
431  if (vec_len (rpaths) == 0)
432  {
433  error = clib_error_return (0, "Paths then flags");
434  goto done;
435  }
436  rpaths[vec_len (rpaths) - 1].frp_flags |=
438  }
439  else if (unformat (line_input, "out-label %U",
440  unformat_mpls_unicast_label, &out_label))
441  {
442  if (vec_len (rpaths) == 0)
443  {
444  error = clib_error_return (0, "Paths then labels");
445  goto done;
446  }
447  vec_add1 (rpaths[vec_len (rpaths) - 1].frp_label_stack, out_label);
448  }
449  else if (unformat (line_input, "via-label %U",
450  unformat_mpls_unicast_label, &rpath.frp_local_label))
451  {
452  rpath.frp_weight = 1;
453  rpath.frp_proto = FIB_PROTOCOL_MPLS;
454  rpath.frp_sw_if_index = ~0;
455  vec_add1 (rpaths, rpath);
456  }
457  else if (unformat (line_input, "count %f", &count))
458  ;
459 
460  else if (unformat (line_input, "%U/%d",
461  unformat_ip4_address, &pfx.fp_addr.ip4, &pfx.fp_len))
462  {
463  pfx.fp_proto = FIB_PROTOCOL_IP4;
464  vec_add1 (prefixs, pfx);
465  }
466  else if (unformat (line_input, "%U/%d",
467  unformat_ip6_address, &pfx.fp_addr.ip6, &pfx.fp_len))
468  {
469  pfx.fp_proto = FIB_PROTOCOL_IP6;
470  vec_add1 (prefixs, pfx);
471  }
472  else if (unformat (line_input, "via %U %U weight %u",
474  &rpath.frp_addr.ip4,
476  &rpath.frp_sw_if_index, &rpath.frp_weight))
477  {
478  rpath.frp_proto = FIB_PROTOCOL_IP4;
479  vec_add1 (rpaths, rpath);
480  }
481 
482  else if (unformat (line_input, "via %U %U weight %u",
484  &rpath.frp_addr.ip6,
486  &rpath.frp_sw_if_index, &rpath.frp_weight))
487  {
488  rpath.frp_proto = FIB_PROTOCOL_IP6;
489  vec_add1 (rpaths, rpath);
490  }
491 
492  else if (unformat (line_input, "via %U %U",
494  &rpath.frp_addr.ip4,
496  &rpath.frp_sw_if_index))
497  {
498  rpath.frp_weight = 1;
499  rpath.frp_proto = FIB_PROTOCOL_IP4;
500  vec_add1 (rpaths, rpath);
501  }
502 
503  else if (unformat (line_input, "via %U %U",
505  &rpath.frp_addr.ip6,
507  &rpath.frp_sw_if_index))
508  {
509  rpath.frp_weight = 1;
510  rpath.frp_proto = FIB_PROTOCOL_IP6;
511  vec_add1 (rpaths, rpath);
512  }
513  else if (unformat (line_input, "via %U next-hop-table %d",
515  &rpath.frp_addr.ip4, &rpath.frp_fib_index))
516  {
517  rpath.frp_weight = 1;
518  rpath.frp_sw_if_index = ~0;
519  rpath.frp_proto = FIB_PROTOCOL_IP4;
520  vec_add1 (rpaths, rpath);
521  }
522  else if (unformat (line_input, "via %U next-hop-table %d",
524  &rpath.frp_addr.ip6, &rpath.frp_fib_index))
525  {
526  rpath.frp_weight = 1;
527  rpath.frp_sw_if_index = ~0;
528  rpath.frp_proto = FIB_PROTOCOL_IP6;
529  vec_add1 (rpaths, rpath);
530  }
531  else if (unformat (line_input, "via %U",
532  unformat_ip4_address, &rpath.frp_addr.ip4))
533  {
534  /*
535  * the recursive next-hops are by default in the same table
536  * as the prefix
537  */
538  rpath.frp_fib_index = table_id;
539  rpath.frp_weight = 1;
540  rpath.frp_sw_if_index = ~0;
541  rpath.frp_proto = FIB_PROTOCOL_IP4;
542  vec_add1 (rpaths, rpath);
543  }
544  else if (unformat (line_input, "via %U",
545  unformat_ip6_address, &rpath.frp_addr.ip6))
546  {
547  rpath.frp_fib_index = table_id;
548  rpath.frp_weight = 1;
549  rpath.frp_sw_if_index = ~0;
550  rpath.frp_proto = FIB_PROTOCOL_IP6;
551  vec_add1 (rpaths, rpath);
552  }
553  else if (unformat (line_input,
554  "lookup in table %d", &rpath.frp_fib_index))
555  {
556  rpath.frp_proto = pfx.fp_proto;
557  rpath.frp_sw_if_index = ~0;
558  vec_add1 (rpaths, rpath);
559  }
560  else if (vec_len (prefixs) > 0 &&
561  unformat (line_input, "via %U",
563  &rpath.frp_sw_if_index))
564  {
565  rpath.frp_weight = 1;
566  rpath.frp_proto = prefixs[0].fp_proto;
567  vec_add1 (rpaths, rpath);
568  }
569  else if (vec_len (prefixs) > 0 &&
570  unformat (line_input, "via %U",
571  unformat_dpo, &dpo, prefixs[0].fp_proto))
572  {
573  vec_add1 (dpos, dpo);
574  }
575  else
576  {
577  error = unformat_parse_error (line_input);
578  goto done;
579  }
580  }
581 
582  unformat_free (line_input);
583 
584  if (vec_len (prefixs) == 0)
585  {
586  error =
587  clib_error_return (0, "expected ip4/ip6 destination address/length.");
588  goto done;
589  }
590 
591  if (!is_del && vec_len (rpaths) + vec_len (dpos) == 0)
592  {
593  error = clib_error_return (0, "expected paths.");
594  goto done;
595  }
596 
597  if (~0 == table_id)
598  {
599  /*
600  * if no table_id is passed we will manipulate the default
601  */
602  fib_index = 0;
603  }
604  else
605  {
606  fib_index = fib_table_id_find_fib_index (prefixs[0].fp_proto, table_id);
607 
608  if (~0 == fib_index)
609  {
610  error = clib_error_return (0, "Nonexistent table id %d", table_id);
611  goto done;
612  }
613  }
614 
615  for (i = 0; i < vec_len (prefixs); i++)
616  {
617  if (is_del && 0 == vec_len (rpaths))
618  {
619  fib_table_entry_delete (fib_index, &prefixs[i], FIB_SOURCE_CLI);
620  }
621  else if (!is_del && 1 == vec_len (dpos))
622  {
624  &prefixs[i],
627  &dpos[0]);
628  dpo_reset (&dpos[0]);
629  }
630  else if (vec_len (dpos) > 0)
631  {
632  error =
634  "Load-balancing over multiple special adjacencies is unsupported");
635  goto done;
636  }
637  else if (0 < vec_len (rpaths))
638  {
639  u32 k, j, n, incr;
640  ip46_address_t dst = prefixs[i].fp_addr;
641  f64 t[2];
642  n = count;
643  t[0] = vlib_time_now (vm);
644  incr = 1 << ((FIB_PROTOCOL_IP4 == prefixs[0].fp_proto ? 32 : 128) -
645  prefixs[i].fp_len);
646 
647  for (k = 0; k < n; k++)
648  {
649  for (j = 0; j < vec_len (rpaths); j++)
650  {
651  u32 fi;
652  /*
653  * the CLI parsing stored table Ids, swap to FIB indicies
654  */
655  fi = fib_table_id_find_fib_index (prefixs[i].fp_proto,
656  rpaths[i].frp_fib_index);
657 
658  if (~0 == fi)
659  {
660  error =
661  clib_error_return (0, "Via table %d does not exist",
662  rpaths[i].frp_fib_index);
663  goto done;
664  }
665  rpaths[i].frp_fib_index = fi;
666 
667  fib_prefix_t rpfx = {
668  .fp_len = prefixs[i].fp_len,
669  .fp_proto = prefixs[i].fp_proto,
670  .fp_addr = dst,
671  };
672 
673  if (is_del)
674  fib_table_entry_path_remove2 (fib_index,
675  &rpfx,
676  FIB_SOURCE_CLI, &rpaths[j]);
677  else
678  fib_table_entry_path_add2 (fib_index,
679  &rpfx,
682  &rpaths[j]);
683  }
684 
685  if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto)
686  {
687  dst.ip4.as_u32 =
688  clib_host_to_net_u32 (incr +
689  clib_net_to_host_u32 (dst.
690  ip4.as_u32));
691  }
692  else
693  {
694  int bucket = (incr < 64 ? 0 : 1);
695  dst.ip6.as_u64[bucket] =
696  clib_host_to_net_u64 (incr +
697  clib_net_to_host_u64 (dst.ip6.as_u64
698  [bucket]));
699 
700  }
701  }
702  t[1] = vlib_time_now (vm);
703  if (count > 1)
704  vlib_cli_output (vm, "%.6e routes/sec", count / (t[1] - t[0]));
705  }
706  else
707  {
708  error = clib_error_return (0, "Don't understand what you want...");
709  goto done;
710  }
711  }
712 
713 
714 done:
715  vec_free (dpos);
716  vec_free (prefixs);
717  vec_free (rpaths);
718  return error;
719 }
720 
721 /* *INDENT-OFF* */
722 VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
723  .path = "ip",
724  .short_help = "Internet protocol (IP) commands",
725 };
726 /* *INDENT-ON* */
727 
728 /* *INDENT-OFF* */
729 VLIB_CLI_COMMAND (vlib_cli_ip6_command, static) = {
730  .path = "ip6",
731  .short_help = "Internet protocol version 6 (IPv6) commands",
732 };
733 /* *INDENT-ON* */
734 
735 /* *INDENT-OFF* */
736 VLIB_CLI_COMMAND (vlib_cli_show_ip_command, static) = {
737  .path = "show ip",
738  .short_help = "Internet protocol (IP) show commands",
739 };
740 /* *INDENT-ON* */
741 
742 /* *INDENT-OFF* */
743 VLIB_CLI_COMMAND (vlib_cli_show_ip6_command, static) = {
744  .path = "show ip6",
745  .short_help = "Internet protocol version 6 (IPv6) show commands",
746 };
747 /* *INDENT-ON* */
748 
749 /*?
750  * This command is used to add or delete IPv4 or IPv6 routes. All
751  * IP Addresses ('<em><dst-ip-addr>/<width></em>',
752  * '<em><next-hop-ip-addr></em>' and '<em><adj-hop-ip-addr></em>')
753  * can be IPv4 or IPv6, but all must be of the same form in a single
754  * command. To display the current set of routes, use the commands
755  * '<em>show ip fib</em>' and '<em>show ip6 fib</em>'.
756  *
757  * @cliexpar
758  * Example of how to add a straight forward static route:
759  * @cliexcmd{ip route add 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
760  * Example of how to delete a straight forward static route:
761  * @cliexcmd{ip route del 6.0.1.2/32 via 6.0.0.1 GigabitEthernet2/0/0}
762  * Mainly for route add/del performance testing, one can add or delete
763  * multiple routes by adding 'count N' to the previous item:
764  * @cliexcmd{ip route add count 10 7.0.0.0/24 via 6.0.0.1 GigabitEthernet2/0/0}
765  * Add multiple routes for the same destination to create equal-cost multipath:
766  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0}
767  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0}
768  * For unequal-cost multipath, specify the desired weights. This
769  * combination of weights results in 3/4 of the traffic following the
770  * second path, 1/4 following the first path:
771  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.1 GigabitEthernet2/0/0 weight 1}
772  * @cliexcmd{ip route add 7.0.0.1/32 via 6.0.0.2 GigabitEthernet2/0/0 weight 3}
773  * To add a route to a particular FIB table (VRF), use:
774  * @cliexcmd{ip route add 172.16.24.0/24 table 7 via GigabitEthernet2/0/0}
775  ?*/
776 /* *INDENT-OFF* */
777 VLIB_CLI_COMMAND (ip_route_command, static) = {
778  .path = "ip route",
779  .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>]",
780  .function = vnet_ip_route_cmd,
781  .is_mp_safe = 1,
782 };
783 /* *INDENT-ON* */
784 
785 /*
786  * The next two routines address a longstanding script hemorrhoid.
787  * Probing a v4 or v6 neighbor needs to appear to be synchronous,
788  * or dependent route-adds will simply fail.
789  */
790 static clib_error_t *
792  int retry_count)
793 {
794  vnet_main_t *vnm = vnet_get_main ();
795  clib_error_t *e;
796  int i;
797  int resolved = 0;
798  uword event_type;
799  uword *event_data = 0;
800 
802 
803  if (retry_count > 0)
805  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
806  1 /* event */ , 0 /* data */ );
807 
808  for (i = 0; i < retry_count; i++)
809  {
810  /* The interface may be down, etc. */
811  e = ip6_probe_neighbor (vm, a, sw_if_index);
812 
813  if (e)
814  return e;
815 
817  event_type = vlib_process_get_events (vm, &event_data);
818  switch (event_type)
819  {
820  case 1: /* resolved... */
821  vlib_cli_output (vm, "Resolved %U", format_ip6_address, a);
822  resolved = 1;
823  goto done;
824 
825  case ~0: /* timeout */
826  break;
827 
828  default:
829  clib_warning ("unknown event_type %d", event_type);
830  }
831  vec_reset_length (event_data);
832  }
833 
834 done:
835 
836  if (!resolved)
837  return clib_error_return (0, "Resolution failed for %U",
838  format_ip6_address, a);
839  return 0;
840 }
841 
842 static clib_error_t *
844  int retry_count)
845 {
846  vnet_main_t *vnm = vnet_get_main ();
847  clib_error_t *e;
848  int i;
849  int resolved = 0;
850  uword event_type;
851  uword *event_data = 0;
852 
854 
855  if (retry_count > 0)
857  (vnm, a, vlib_get_current_process (vm)->node_runtime.node_index,
858  1 /* event */ , 0 /* data */ );
859 
860  for (i = 0; i < retry_count; i++)
861  {
862  /* The interface may be down, etc. */
863  e = ip4_probe_neighbor (vm, a, sw_if_index);
864 
865  if (e)
866  return e;
867 
869  event_type = vlib_process_get_events (vm, &event_data);
870  switch (event_type)
871  {
872  case 1: /* resolved... */
873  vlib_cli_output (vm, "Resolved %U", format_ip4_address, a);
874  resolved = 1;
875  goto done;
876 
877  case ~0: /* timeout */
878  break;
879 
880  default:
881  clib_warning ("unknown event_type %d", event_type);
882  }
883  vec_reset_length (event_data);
884  }
885 
886 done:
887 
888  vec_reset_length (event_data);
889 
890  if (!resolved)
891  return clib_error_return (0, "Resolution failed for %U",
892  format_ip4_address, a);
893  return 0;
894 }
895 
896 static clib_error_t *
898  unformat_input_t * input, vlib_cli_command_t * cmd)
899 {
900  vnet_main_t *vnm = vnet_get_main ();
901  unformat_input_t _line_input, *line_input = &_line_input;
902  ip4_address_t a4;
903  ip6_address_t a6;
904  clib_error_t *error = 0;
905  u32 sw_if_index = ~0;
906  int retry_count = 3;
907  int is_ip4 = 1;
908  int address_set = 0;
909 
910  /* Get a line of input. */
911  if (!unformat_user (input, unformat_line_input, line_input))
912  return 0;
913 
914  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
915  {
916  if (unformat_user (line_input, unformat_vnet_sw_interface, vnm,
917  &sw_if_index))
918  ;
919  else if (unformat (line_input, "retry %d", &retry_count))
920  ;
921 
922  else if (unformat (line_input, "%U", unformat_ip4_address, &a4))
923  address_set++;
924  else if (unformat (line_input, "%U", unformat_ip6_address, &a6))
925  {
926  address_set++;
927  is_ip4 = 0;
928  }
929  else
930  return clib_error_return (0, "unknown input '%U'",
931  format_unformat_error, line_input);
932  }
933 
934  unformat_free (line_input);
935 
936  if (sw_if_index == ~0)
937  return clib_error_return (0, "Interface required, not set.");
938  if (address_set == 0)
939  return clib_error_return (0, "ip address required, not set.");
940  if (address_set > 1)
941  return clib_error_return (0, "Multiple ip addresses not supported.");
942 
943  if (is_ip4)
944  error = ip4_probe_neighbor_wait (vm, &a4, sw_if_index, retry_count);
945  else
946  error = ip6_probe_neighbor_wait (vm, &a6, sw_if_index, retry_count);
947 
948  return error;
949 }
950 
951 /*?
952  * The '<em>ip probe-neighbor</em>' command ARPs for IPv4 addresses or
953  * attempts IPv6 neighbor discovery depending on the supplied IP address
954  * format.
955  *
956  * @note This command will not immediately affect the indicated FIB; it
957  * is not suitable for use in establishing a FIB entry prior to adding
958  * recursive FIB entries. As in: don't use it in a script to probe a
959  * gateway prior to adding a default route. It won't work. Instead,
960  * configure a static ARP cache entry [see '<em>set ip arp</em>'], or
961  * a static IPv6 neighbor [see '<em>set ip6 neighbor</em>'].
962  *
963  * @cliexpar
964  * Example of probe for an IPv4 address:
965  * @cliexcmd{ip probe-neighbor GigabitEthernet2/0/0 172.16.1.2}
966 ?*/
967 /* *INDENT-OFF* */
968 VLIB_CLI_COMMAND (ip_probe_neighbor_command, static) = {
969  .path = "ip probe-neighbor",
970  .function = probe_neighbor_address,
971  .short_help = "ip probe-neighbor <interface> <ip4-addr> | <ip6-addr> [retry nn]",
972  .is_mp_safe = 1,
973 };
974 /* *INDENT-ON* */
975 
976 /*
977  * fd.io coding-style-patch-verification: ON
978  *
979  * Local Variables:
980  * eval: (c-set-style "gnu")
981  * End:
982  */
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:791
u32 fib_table_id_find_fib_index(fib_protocol_t proto, u32 table_id)
Definition: lookup.c:357
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:312
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:843
#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:383
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:250
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:187
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
static clib_error_t * ip_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: lookup.c:172
#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:238
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:897
u8 * format_ip_adjacency_packet_data(u8 *s, va_list *args)
Definition: lookup.c:287
#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
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(ip_sw_interface_add_del)
const ip46_address_t zero_addr
Definition: lookup.c:351
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