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