FD.io VPP  v18.10-34-gcce845e
Vector Packet Processing
ip4_forward.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/ip4_forward.c: IP v4 forwarding
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/vnet.h>
41 #include <vnet/ip/ip.h>
42 #include <vnet/ip/ip_frag.h>
43 #include <vnet/ethernet/ethernet.h> /* for ethernet_header_t */
44 #include <vnet/ethernet/arp_packet.h> /* for ethernet_arp_header_t */
45 #include <vnet/ppp/ppp.h>
46 #include <vnet/srp/srp.h> /* for srp_hw_interface_class */
47 #include <vnet/api_errno.h> /* for API error numbers */
48 #include <vnet/fib/fib_table.h> /* for FIB table and entry creation */
49 #include <vnet/fib/fib_entry.h> /* for FIB table and entry creation */
50 #include <vnet/fib/fib_urpf_list.h> /* for FIB uRPF check */
51 #include <vnet/fib/ip4_fib.h>
52 #include <vnet/dpo/load_balance.h>
54 #include <vnet/dpo/classify_dpo.h>
55 #include <vnet/mfib/mfib_table.h> /* for mFIB table and entry creation */
56 
57 #include <vnet/ip/ip4_forward.h>
58 
59 /** @brief IPv4 lookup node.
60  @node ip4-lookup
61 
62  This is the main IPv4 lookup dispatch node.
63 
64  @param vm vlib_main_t corresponding to the current thread
65  @param node vlib_node_runtime_t
66  @param frame vlib_frame_t whose contents should be dispatched
67 
68  @par Graph mechanics: buffer metadata, next index usage
69 
70  @em Uses:
71  - <code>vnet_buffer(b)->sw_if_index[VLIB_RX]</code>
72  - Indicates the @c sw_if_index value of the interface that the
73  packet was received on.
74  - <code>vnet_buffer(b)->sw_if_index[VLIB_TX]</code>
75  - When the value is @c ~0 then the node performs a longest prefix
76  match (LPM) for the packet destination address in the FIB attached
77  to the receive interface.
78  - Otherwise perform LPM for the packet destination address in the
79  indicated FIB. In this case <code>[VLIB_TX]</code> is a FIB index
80  value (0, 1, ...) and not a VRF id.
81 
82  @em Sets:
83  - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
84  - The lookup result adjacency index.
85 
86  <em>Next Index:</em>
87  - Dispatches the packet to the node index found in
88  ip_adjacency_t @c adj->lookup_next_index
89  (where @c adj is the lookup result adjacency).
90 */
92  vlib_frame_t * frame)
93 {
94  return ip4_lookup_inline (vm, node, frame,
95  /* lookup_for_responses_to_locally_received_packets */
96  0);
97 
98 }
99 
100 static u8 *format_ip4_lookup_trace (u8 * s, va_list * args);
101 
102 /* *INDENT-OFF* */
104 {
105  .name = "ip4-lookup",
106  .vector_size = sizeof (u32),
107  .format_trace = format_ip4_lookup_trace,
108  .n_next_nodes = IP_LOOKUP_N_NEXT,
109  .next_nodes = IP4_LOOKUP_NEXT_NODES,
110 };
111 /* *INDENT-ON* */
112 
114  vlib_node_runtime_t * node,
115  vlib_frame_t * frame)
116 {
118  u32 n_left_from, n_left_to_next, *from, *to_next;
119  ip_lookup_next_t next;
120  u32 thread_index = vm->thread_index;
121 
122  from = vlib_frame_vector_args (frame);
123  n_left_from = frame->n_vectors;
124  next = node->cached_next_index;
125 
126  if (node->flags & VLIB_NODE_FLAG_TRACE)
127  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
128 
129  while (n_left_from > 0)
130  {
131  vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
132 
133 
134  while (n_left_from >= 4 && n_left_to_next >= 2)
135  {
136  ip_lookup_next_t next0, next1;
137  const load_balance_t *lb0, *lb1;
138  vlib_buffer_t *p0, *p1;
139  u32 pi0, lbi0, hc0, pi1, lbi1, hc1;
140  const ip4_header_t *ip0, *ip1;
141  const dpo_id_t *dpo0, *dpo1;
142 
143  /* Prefetch next iteration. */
144  {
145  vlib_buffer_t *p2, *p3;
146 
147  p2 = vlib_get_buffer (vm, from[2]);
148  p3 = vlib_get_buffer (vm, from[3]);
149 
150  vlib_prefetch_buffer_header (p2, STORE);
151  vlib_prefetch_buffer_header (p3, STORE);
152 
153  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE);
154  CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE);
155  }
156 
157  pi0 = to_next[0] = from[0];
158  pi1 = to_next[1] = from[1];
159 
160  from += 2;
161  n_left_from -= 2;
162  to_next += 2;
163  n_left_to_next -= 2;
164 
165  p0 = vlib_get_buffer (vm, pi0);
166  p1 = vlib_get_buffer (vm, pi1);
167 
168  ip0 = vlib_buffer_get_current (p0);
169  ip1 = vlib_buffer_get_current (p1);
170  lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
171  lbi1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX];
172 
173  lb0 = load_balance_get (lbi0);
174  lb1 = load_balance_get (lbi1);
175 
176  /*
177  * this node is for via FIBs we can re-use the hash value from the
178  * to node if present.
179  * We don't want to use the same hash value at each level in the recursion
180  * graph as that would lead to polarisation
181  */
182  hc0 = hc1 = 0;
183 
184  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
185  {
186  if (PREDICT_TRUE (vnet_buffer (p0)->ip.flow_hash))
187  {
188  hc0 = vnet_buffer (p0)->ip.flow_hash =
189  vnet_buffer (p0)->ip.flow_hash >> 1;
190  }
191  else
192  {
193  hc0 = vnet_buffer (p0)->ip.flow_hash =
195  }
197  (lb0, (hc0 & (lb0->lb_n_buckets_minus_1)));
198  }
199  else
200  {
201  dpo0 = load_balance_get_bucket_i (lb0, 0);
202  }
203  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
204  {
205  if (PREDICT_TRUE (vnet_buffer (p1)->ip.flow_hash))
206  {
207  hc1 = vnet_buffer (p1)->ip.flow_hash =
208  vnet_buffer (p1)->ip.flow_hash >> 1;
209  }
210  else
211  {
212  hc1 = vnet_buffer (p1)->ip.flow_hash =
214  }
216  (lb1, (hc1 & (lb1->lb_n_buckets_minus_1)));
217  }
218  else
219  {
220  dpo1 = load_balance_get_bucket_i (lb1, 0);
221  }
222 
223  next0 = dpo0->dpoi_next_node;
224  next1 = dpo1->dpoi_next_node;
225 
226  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
227  vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
228 
230  (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0));
232  (cm, thread_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1));
233 
234  vlib_validate_buffer_enqueue_x2 (vm, node, next,
235  to_next, n_left_to_next,
236  pi0, pi1, next0, next1);
237  }
238 
239  while (n_left_from > 0 && n_left_to_next > 0)
240  {
241  ip_lookup_next_t next0;
242  const load_balance_t *lb0;
243  vlib_buffer_t *p0;
244  u32 pi0, lbi0, hc0;
245  const ip4_header_t *ip0;
246  const dpo_id_t *dpo0;
247 
248  pi0 = from[0];
249  to_next[0] = pi0;
250  from += 1;
251  to_next += 1;
252  n_left_to_next -= 1;
253  n_left_from -= 1;
254 
255  p0 = vlib_get_buffer (vm, pi0);
256 
257  ip0 = vlib_buffer_get_current (p0);
258  lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
259 
260  lb0 = load_balance_get (lbi0);
261 
262  hc0 = 0;
263  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
264  {
265  if (PREDICT_TRUE (vnet_buffer (p0)->ip.flow_hash))
266  {
267  hc0 = vnet_buffer (p0)->ip.flow_hash =
268  vnet_buffer (p0)->ip.flow_hash >> 1;
269  }
270  else
271  {
272  hc0 = vnet_buffer (p0)->ip.flow_hash =
274  }
276  (lb0, (hc0 & (lb0->lb_n_buckets_minus_1)));
277  }
278  else
279  {
280  dpo0 = load_balance_get_bucket_i (lb0, 0);
281  }
282 
283  next0 = dpo0->dpoi_next_node;
284  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
285 
287  (cm, thread_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0));
288 
289  vlib_validate_buffer_enqueue_x1 (vm, node, next,
290  to_next, n_left_to_next,
291  pi0, next0);
292  }
293 
294  vlib_put_next_frame (vm, node, next, n_left_to_next);
295  }
296 
297  return frame->n_vectors;
298 }
299 
300 /* *INDENT-OFF* */
302 {
303  .name = "ip4-load-balance",
304  .vector_size = sizeof (u32),
305  .sibling_of = "ip4-lookup",
306  .format_trace = format_ip4_lookup_trace,
307 };
308 /* *INDENT-ON* */
309 
310 #ifndef CLIB_MARCH_VARIANT
311 /* get first interface address */
314  ip_interface_address_t ** result_ia)
315 {
316  ip_lookup_main_t *lm = &im->lookup_main;
317  ip_interface_address_t *ia = 0;
318  ip4_address_t *result = 0;
319 
320  /* *INDENT-OFF* */
322  (lm, ia, sw_if_index,
323  1 /* honor unnumbered */ ,
324  ({
325  ip4_address_t * a =
327  result = a;
328  break;
329  }));
330  /* *INDENT-OFF* */
331  if (result_ia)
332  *result_ia = result ? ia : 0;
333  return result;
334 }
335 
336 static void
338  fib_prefix_t *pfx,
340 {
342 
343  iflags = vnet_sw_interface_get_flags(vnet_get_main(), sw_if_index);
344 
346  pfx,
348 
350  {
351  fib_table_entry_update_one_path (fib_index, pfx,
355  /* No next-hop address */
357  sw_if_index,
358  // invalid FIB index
359  ~0,
360  1,
361  // no out-label stack
362  NULL,
364  }
365  else
366  {
367  fib_table_entry_special_add(fib_index,
368  pfx,
372  }
373 }
374 
375 static void
377  ip4_main_t * im, u32 fib_index,
379 {
380  ip_lookup_main_t *lm = &im->lookup_main;
382  fib_prefix_t pfx = {
383  .fp_len = a->address_length,
384  .fp_proto = FIB_PROTOCOL_IP4,
385  .fp_addr.ip4 = *address,
386  };
387 
388  if (pfx.fp_len <= 30)
389  {
390  /* a /30 or shorter - add a glean for the network address */
391  fib_table_entry_update_one_path (fib_index, &pfx,
396  /* No next-hop address */
397  NULL,
398  sw_if_index,
399  // invalid FIB index
400  ~0,
401  1,
402  // no out-label stack
403  NULL,
405 
406  /* Add the two broadcast addresses as drop */
407  fib_prefix_t net_pfx = {
408  .fp_len = 32,
409  .fp_proto = FIB_PROTOCOL_IP4,
410  .fp_addr.ip4.as_u32 = address->as_u32 & im->fib_masks[pfx.fp_len],
411  };
412  if (net_pfx.fp_addr.ip4.as_u32 != pfx.fp_addr.ip4.as_u32)
413  fib_table_entry_special_add(fib_index,
414  &net_pfx,
418  net_pfx.fp_addr.ip4.as_u32 |= ~im->fib_masks[pfx.fp_len];
419  if (net_pfx.fp_addr.ip4.as_u32 != pfx.fp_addr.ip4.as_u32)
420  ip4_add_subnet_bcast_route(fib_index, &net_pfx, sw_if_index);
421  }
422  else if (pfx.fp_len == 31)
423  {
424  u32 mask = clib_host_to_net_u32(1);
425  fib_prefix_t net_pfx = pfx;
426 
427  net_pfx.fp_len = 32;
428  net_pfx.fp_addr.ip4.as_u32 ^= mask;
429 
430  /* a /31 - add the other end as an attached host */
431  fib_table_entry_update_one_path (fib_index, &net_pfx,
435  &net_pfx.fp_addr,
436  sw_if_index,
437  // invalid FIB index
438  ~0,
439  1,
440  NULL,
442  }
443  pfx.fp_len = 32;
444 
445  if (sw_if_index < vec_len (lm->classify_table_index_by_sw_if_index))
446  {
447  u32 classify_table_index =
449  if (classify_table_index != (u32) ~ 0)
450  {
451  dpo_id_t dpo = DPO_INVALID;
452 
453  dpo_set (&dpo,
454  DPO_CLASSIFY,
456  classify_dpo_create (DPO_PROTO_IP4, classify_table_index));
457 
459  &pfx,
461  FIB_ENTRY_FLAG_NONE, &dpo);
462  dpo_reset (&dpo);
463  }
464  }
465 
466  fib_table_entry_update_one_path (fib_index, &pfx,
471  &pfx.fp_addr,
472  sw_if_index,
473  // invalid FIB index
474  ~0,
475  1, NULL,
477 }
478 
479 static void
481  u32 fib_index,
483 {
484  fib_prefix_t pfx = {
486  .fp_proto = FIB_PROTOCOL_IP4,
487  .fp_addr.ip4 = *address,
488  };
489 
490  if (pfx.fp_len <= 30)
491  {
492  fib_prefix_t net_pfx = {
493  .fp_len = 32,
494  .fp_proto = FIB_PROTOCOL_IP4,
495  .fp_addr.ip4.as_u32 = address->as_u32 & im->fib_masks[pfx.fp_len],
496  };
497  if (net_pfx.fp_addr.ip4.as_u32 != pfx.fp_addr.ip4.as_u32)
499  &net_pfx,
501  net_pfx.fp_addr.ip4.as_u32 |= ~im->fib_masks[pfx.fp_len];
502  if (net_pfx.fp_addr.ip4.as_u32 != pfx.fp_addr.ip4.as_u32)
504  &net_pfx,
506  fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE);
507  }
508  else if (pfx.fp_len == 31)
509  {
510  u32 mask = clib_host_to_net_u32(1);
511  fib_prefix_t net_pfx = pfx;
512 
513  net_pfx.fp_len = 32;
514  net_pfx.fp_addr.ip4.as_u32 ^= mask;
515 
516  fib_table_entry_delete (fib_index, &net_pfx, FIB_SOURCE_INTERFACE);
517  }
518 
519  pfx.fp_len = 32;
520  fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE);
521 }
522 
523 void
525 {
526  ip4_main_t *im = &ip4_main;
527 
529 
530  /*
531  * enable/disable only on the 1<->0 transition
532  */
533  if (is_enable)
534  {
535  if (1 != ++im->ip_enabled_by_sw_if_index[sw_if_index])
536  return;
537  }
538  else
539  {
540  ASSERT (im->ip_enabled_by_sw_if_index[sw_if_index] > 0);
541  if (0 != --im->ip_enabled_by_sw_if_index[sw_if_index])
542  return;
543  }
544  vnet_feature_enable_disable ("ip4-unicast", "ip4-not-enabled", sw_if_index,
545  !is_enable, 0, 0);
546 
547 
548  vnet_feature_enable_disable ("ip4-multicast", "ip4-not-enabled",
549  sw_if_index, !is_enable, 0, 0);
550 }
551 
552 static clib_error_t *
556  u32 address_length, u32 is_del)
557 {
558  vnet_main_t *vnm = vnet_get_main ();
559  ip4_main_t *im = &ip4_main;
560  ip_lookup_main_t *lm = &im->lookup_main;
561  clib_error_t *error = 0;
562  u32 if_address_index, elts_before;
563  ip4_address_fib_t ip4_af, *addr_fib = 0;
564 
565  /* local0 interface doesn't support IP addressing */
566  if (sw_if_index == 0)
567  {
568  return
569  clib_error_create ("local0 interface doesn't support IP addressing");
570  }
571 
572  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
573  ip4_addr_fib_init (&ip4_af, address,
574  vec_elt (im->fib_index_by_sw_if_index, sw_if_index));
575  vec_add1 (addr_fib, ip4_af);
576 
577  /*
578  * there is no support for adj-fib handling in the presence of overlapping
579  * subnets on interfaces. Easy fix - disallow overlapping subnets, like
580  * most routers do.
581  */
582  /* *INDENT-OFF* */
583  if (!is_del)
584  {
585  /* When adding an address check that it does not conflict
586  with an existing address on any interface in this table. */
588  vnet_sw_interface_t *sif;
589 
591  ({
592  if (im->fib_index_by_sw_if_index[sw_if_index] ==
593  im->fib_index_by_sw_if_index[sif->sw_if_index])
594  {
595  foreach_ip_interface_address
596  (&im->lookup_main, ia, sif->sw_if_index,
597  0 /* honor unnumbered */ ,
598  ({
599  ip4_address_t * x =
600  ip_interface_address_get_address
601  (&im->lookup_main, ia);
602  if (ip4_destination_matches_route
603  (im, address, x, ia->address_length) ||
604  ip4_destination_matches_route (im,
605  x,
606  address,
607  address_length))
608  {
609  vnm->api_errno = VNET_API_ERROR_DUPLICATE_IF_ADDRESS;
610 
611  return
612  clib_error_create
613  ("failed to add %U which conflicts with %U for interface %U",
614  format_ip4_address_and_length, address,
615  address_length,
616  format_ip4_address_and_length, x,
617  ia->address_length,
618  format_vnet_sw_if_index_name, vnm,
619  sif->sw_if_index);
620  }
621  }));
622  }
623  }));
624  }
625  /* *INDENT-ON* */
626 
627  elts_before = pool_elts (lm->if_address_pool);
628 
630  (lm, sw_if_index, addr_fib, address_length, is_del, &if_address_index);
631  if (error)
632  goto done;
633 
635 
636  if (is_del)
637  ip4_del_interface_routes (im, ip4_af.fib_index, address, address_length);
638  else
640  im, ip4_af.fib_index,
642  (lm->if_address_pool, if_address_index));
643 
644  /* If pool did not grow/shrink: add duplicate address. */
645  if (elts_before != pool_elts (lm->if_address_pool))
646  {
648  vec_foreach (cb, im->add_del_interface_address_callbacks)
649  cb->function (im, cb->function_opaque, sw_if_index,
650  address, address_length, if_address_index, is_del);
651  }
652 
653 done:
654  vec_free (addr_fib);
655  return error;
656 }
657 
658 clib_error_t *
662  u32 address_length, u32 is_del)
663 {
665  (vm, sw_if_index, address, address_length, is_del);
666 }
667 
668 void
670 {
672  ip4_main_t *im;
673 
674  im = &ip4_main;
675 
676  /*
677  * when directed broadcast is enabled, the subnet braodcast route will forward
678  * packets using an adjacency with a broadcast MAC. otherwise it drops
679  */
680  /* *INDENT-OFF* */
682  sw_if_index, 0,
683  ({
684  if (ia->address_length <= 30)
685  {
686  ip4_address_t *ipa;
687 
688  ipa = ip_interface_address_get_address (&im->lookup_main, ia);
689 
690  fib_prefix_t pfx = {
691  .fp_len = 32,
692  .fp_proto = FIB_PROTOCOL_IP4,
693  .fp_addr = {
694  .ip4.as_u32 = (ipa->as_u32 | ~im->fib_masks[ia->address_length]),
695  },
696  };
697 
698  ip4_add_subnet_bcast_route
699  (fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4,
700  sw_if_index),
701  &pfx, sw_if_index);
702  }
703  }));
704  /* *INDENT-ON* */
705 }
706 #endif
707 
708 /* Built-in ip4 unicast rx feature path definition */
709 /* *INDENT-OFF* */
710 VNET_FEATURE_ARC_INIT (ip4_unicast, static) =
711 {
712  .arc_name = "ip4-unicast",
713  .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
714  .arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index,
715 };
716 
718 {
719  .arc_name = "ip4-unicast",
720  .node_name = "ip4-flow-classify",
721  .runs_before = VNET_FEATURES ("ip4-inacl"),
722 };
723 
724 VNET_FEATURE_INIT (ip4_inacl, static) =
725 {
726  .arc_name = "ip4-unicast",
727  .node_name = "ip4-inacl",
728  .runs_before = VNET_FEATURES ("ip4-source-check-via-rx"),
729 };
730 
731 VNET_FEATURE_INIT (ip4_source_check_1, static) =
732 {
733  .arc_name = "ip4-unicast",
734  .node_name = "ip4-source-check-via-rx",
735  .runs_before = VNET_FEATURES ("ip4-source-check-via-any"),
736 };
737 
738 VNET_FEATURE_INIT (ip4_source_check_2, static) =
739 {
740  .arc_name = "ip4-unicast",
741  .node_name = "ip4-source-check-via-any",
742  .runs_before = VNET_FEATURES ("ip4-policer-classify"),
743 };
744 
746 {
747  .arc_name = "ip4-unicast",
748  .node_name = "ip4-source-and-port-range-check-rx",
749  .runs_before = VNET_FEATURES ("ip4-policer-classify"),
750 };
751 
753 {
754  .arc_name = "ip4-unicast",
755  .node_name = "ip4-policer-classify",
756  .runs_before = VNET_FEATURES ("ipsec-input-ip4"),
757 };
758 
759 VNET_FEATURE_INIT (ip4_ipsec, static) =
760 {
761  .arc_name = "ip4-unicast",
762  .node_name = "ipsec-input-ip4",
763  .runs_before = VNET_FEATURES ("vpath-input-ip4"),
764 };
765 
766 VNET_FEATURE_INIT (ip4_vpath, static) =
767 {
768  .arc_name = "ip4-unicast",
769  .node_name = "vpath-input-ip4",
770  .runs_before = VNET_FEATURES ("ip4-vxlan-bypass"),
771 };
772 
773 VNET_FEATURE_INIT (ip4_vxlan_bypass, static) =
774 {
775  .arc_name = "ip4-unicast",
776  .node_name = "ip4-vxlan-bypass",
777  .runs_before = VNET_FEATURES ("ip4-lookup"),
778 };
779 
781 {
782  .arc_name = "ip4-unicast",
783  .node_name = "ip4-not-enabled",
784  .runs_before = VNET_FEATURES ("ip4-lookup"),
785 };
786 
787 VNET_FEATURE_INIT (ip4_lookup, static) =
788 {
789  .arc_name = "ip4-unicast",
790  .node_name = "ip4-lookup",
791  .runs_before = 0, /* not before any other features */
792 };
793 
794 /* Built-in ip4 multicast rx feature path definition */
795 VNET_FEATURE_ARC_INIT (ip4_multicast, static) =
796 {
797  .arc_name = "ip4-multicast",
798  .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
799  .arc_index_ptr = &ip4_main.lookup_main.mcast_feature_arc_index,
800 };
801 
802 VNET_FEATURE_INIT (ip4_vpath_mc, static) =
803 {
804  .arc_name = "ip4-multicast",
805  .node_name = "vpath-input-ip4",
806  .runs_before = VNET_FEATURES ("ip4-mfib-forward-lookup"),
807 };
808 
809 VNET_FEATURE_INIT (ip4_mc_not_enabled, static) =
810 {
811  .arc_name = "ip4-multicast",
812  .node_name = "ip4-not-enabled",
813  .runs_before = VNET_FEATURES ("ip4-mfib-forward-lookup"),
814 };
815 
816 VNET_FEATURE_INIT (ip4_lookup_mc, static) =
817 {
818  .arc_name = "ip4-multicast",
819  .node_name = "ip4-mfib-forward-lookup",
820  .runs_before = 0, /* last feature */
821 };
822 
823 /* Source and port-range check ip4 tx feature path definition */
824 VNET_FEATURE_ARC_INIT (ip4_output, static) =
825 {
826  .arc_name = "ip4-output",
827  .start_nodes = VNET_FEATURES ("ip4-rewrite", "ip4-midchain", "ip4-dvr-dpo"),
828  .arc_index_ptr = &ip4_main.lookup_main.output_feature_arc_index,
829 };
830 
832 {
833  .arc_name = "ip4-output",
834  .node_name = "ip4-source-and-port-range-check-tx",
835  .runs_before = VNET_FEATURES ("ip4-outacl"),
836 };
837 
838 VNET_FEATURE_INIT (ip4_outacl, static) =
839 {
840  .arc_name = "ip4-output",
841  .node_name = "ip4-outacl",
842  .runs_before = VNET_FEATURES ("ipsec-output-ip4"),
843 };
844 
845 VNET_FEATURE_INIT (ip4_ipsec_output, static) =
846 {
847  .arc_name = "ip4-output",
848  .node_name = "ipsec-output-ip4",
849  .runs_before = VNET_FEATURES ("interface-output"),
850 };
851 
852 /* Built-in ip4 tx feature path definition */
853 VNET_FEATURE_INIT (ip4_interface_output, static) =
854 {
855  .arc_name = "ip4-output",
856  .node_name = "interface-output",
857  .runs_before = 0, /* not before any other features */
858 };
859 /* *INDENT-ON* */
860 
861 static clib_error_t *
863 {
864  ip4_main_t *im = &ip4_main;
865 
866  /* Fill in lookup tables with default table (0). */
867  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
868  vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
869 
870  if (!is_add)
871  {
872  ip4_main_t *im4 = &ip4_main;
873  ip_lookup_main_t *lm4 = &im4->lookup_main;
874  ip_interface_address_t *ia = 0;
876  vlib_main_t *vm = vlib_get_main ();
877 
878  vnet_sw_interface_update_unnumbered (sw_if_index, ~0, 0);
879  /* *INDENT-OFF* */
880  foreach_ip_interface_address (lm4, ia, sw_if_index, 0,
881  ({
882  address = ip_interface_address_get_address (lm4, ia);
883  ip4_add_del_interface_address(vm, sw_if_index, address, ia->address_length, 1);
884  }));
885  /* *INDENT-ON* */
886  }
887 
888  vnet_feature_enable_disable ("ip4-unicast", "ip4-not-enabled", sw_if_index,
889  is_add, 0, 0);
890 
891  vnet_feature_enable_disable ("ip4-multicast", "ip4-not-enabled",
892  sw_if_index, is_add, 0, 0);
893 
894  return /* no error */ 0;
895 }
896 
898 
899 /* Global IP4 main. */
901 
902 static clib_error_t *
904 {
905  ip4_main_t *im = &ip4_main;
906  clib_error_t *error;
907  uword i;
908 
909  if ((error = vlib_call_init_function (vm, vnet_feature_init)))
910  return error;
912  return (error);
913  if ((error = vlib_call_init_function (vm, fib_module_init)))
914  return error;
915  if ((error = vlib_call_init_function (vm, mfib_module_init)))
916  return error;
917 
918  for (i = 0; i < ARRAY_LEN (im->fib_masks); i++)
919  {
920  u32 m;
921 
922  if (i < 32)
923  m = pow2_mask (i) << (32 - i);
924  else
925  m = ~0;
926  im->fib_masks[i] = clib_host_to_net_u32 (m);
927  }
928 
929  ip_lookup_init (&im->lookup_main, /* is_ip6 */ 0);
930 
931  /* Create FIB with index 0 and table id of 0. */
936 
937  {
938  pg_node_t *pn;
939  pn = pg_get_node (ip4_lookup_node.index);
941  }
942 
943  {
945 
946  memset (&h, 0, sizeof (h));
947 
948  /* Set target ethernet address to all zeros. */
949  memset (h.ip4_over_ethernet[1].ethernet, 0,
950  sizeof (h.ip4_over_ethernet[1].ethernet));
951 
952 #define _16(f,v) h.f = clib_host_to_net_u16 (v);
953 #define _8(f,v) h.f = v;
954  _16 (l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
955  _16 (l3_type, ETHERNET_TYPE_IP4);
956  _8 (n_l2_address_bytes, 6);
957  _8 (n_l3_address_bytes, 4);
958  _16 (opcode, ETHERNET_ARP_OPCODE_request);
959 #undef _16
960 #undef _8
961 
963  /* data */ &h,
964  sizeof (h),
965  /* alloc chunk size */ 8,
966  "ip4 arp");
967  }
968 
969  return error;
970 }
971 
973 
974 typedef struct
975 {
976  /* Adjacency taken. */
980 
981  /* Packet data, possibly *after* rewrite. */
982  u8 packet_data[64 - 1 * sizeof (u32)];
983 }
985 
986 #ifndef CLIB_MARCH_VARIANT
987 u8 *
988 format_ip4_forward_next_trace (u8 * s, va_list * args)
989 {
990  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
991  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
992  ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
993  u32 indent = format_get_indent (s);
994  s = format (s, "%U%U",
995  format_white_space, indent,
996  format_ip4_header, t->packet_data, sizeof (t->packet_data));
997  return s;
998 }
999 #endif
1000 
1001 static u8 *
1002 format_ip4_lookup_trace (u8 * s, va_list * args)
1003 {
1004  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1005  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1006  ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
1007  u32 indent = format_get_indent (s);
1008 
1009  s = format (s, "fib %d dpo-idx %d flow hash: 0x%08x",
1010  t->fib_index, t->dpo_index, t->flow_hash);
1011  s = format (s, "\n%U%U",
1012  format_white_space, indent,
1013  format_ip4_header, t->packet_data, sizeof (t->packet_data));
1014  return s;
1015 }
1016 
1017 static u8 *
1018 format_ip4_rewrite_trace (u8 * s, va_list * args)
1019 {
1020  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1021  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1022  ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
1023  u32 indent = format_get_indent (s);
1024 
1025  s = format (s, "tx_sw_if_index %d dpo-idx %d : %U flow hash: 0x%08x",
1028  s = format (s, "\n%U%U",
1029  format_white_space, indent,
1031  t->dpo_index, t->packet_data, sizeof (t->packet_data));
1032  return s;
1033 }
1034 
1035 #ifndef CLIB_MARCH_VARIANT
1036 /* Common trace function for all ip4-forward next nodes. */
1037 void
1039  vlib_node_runtime_t * node,
1040  vlib_frame_t * frame, vlib_rx_or_tx_t which_adj_index)
1041 {
1042  u32 *from, n_left;
1043  ip4_main_t *im = &ip4_main;
1044 
1045  n_left = frame->n_vectors;
1046  from = vlib_frame_vector_args (frame);
1047 
1048  while (n_left >= 4)
1049  {
1050  u32 bi0, bi1;
1051  vlib_buffer_t *b0, *b1;
1052  ip4_forward_next_trace_t *t0, *t1;
1053 
1054  /* Prefetch next iteration. */
1055  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
1056  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
1057 
1058  bi0 = from[0];
1059  bi1 = from[1];
1060 
1061  b0 = vlib_get_buffer (vm, bi0);
1062  b1 = vlib_get_buffer (vm, bi1);
1063 
1064  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1065  {
1066  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1067  t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
1068  t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
1069  t0->fib_index =
1070  (vnet_buffer (b0)->sw_if_index[VLIB_TX] !=
1071  (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] :
1074 
1075  clib_memcpy (t0->packet_data,
1077  sizeof (t0->packet_data));
1078  }
1079  if (b1->flags & VLIB_BUFFER_IS_TRACED)
1080  {
1081  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
1082  t1->dpo_index = vnet_buffer (b1)->ip.adj_index[which_adj_index];
1083  t1->flow_hash = vnet_buffer (b1)->ip.flow_hash;
1084  t1->fib_index =
1085  (vnet_buffer (b1)->sw_if_index[VLIB_TX] !=
1086  (u32) ~ 0) ? vnet_buffer (b1)->sw_if_index[VLIB_TX] :
1090  sizeof (t1->packet_data));
1091  }
1092  from += 2;
1093  n_left -= 2;
1094  }
1095 
1096  while (n_left >= 1)
1097  {
1098  u32 bi0;
1099  vlib_buffer_t *b0;
1101 
1102  bi0 = from[0];
1103 
1104  b0 = vlib_get_buffer (vm, bi0);
1105 
1106  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1107  {
1108  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1109  t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
1110  t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
1111  t0->fib_index =
1112  (vnet_buffer (b0)->sw_if_index[VLIB_TX] !=
1113  (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] :
1117  sizeof (t0->packet_data));
1118  }
1119  from += 1;
1120  n_left -= 1;
1121  }
1122 }
1123 
1124 /* Compute TCP/UDP/ICMP4 checksum in software. */
1125 u16
1127  ip4_header_t * ip0)
1128 {
1129  ip_csum_t sum0;
1130  u32 ip_header_length, payload_length_host_byte_order;
1131  u32 n_this_buffer, n_bytes_left, n_ip_bytes_this_buffer;
1132  u16 sum16;
1133  void *data_this_buffer;
1134 
1135  /* Initialize checksum with ip header. */
1136  ip_header_length = ip4_header_bytes (ip0);
1137  payload_length_host_byte_order =
1138  clib_net_to_host_u16 (ip0->length) - ip_header_length;
1139  sum0 =
1140  clib_host_to_net_u32 (payload_length_host_byte_order +
1141  (ip0->protocol << 16));
1142 
1143  if (BITS (uword) == 32)
1144  {
1145  sum0 =
1146  ip_csum_with_carry (sum0,
1148  sum0 =
1149  ip_csum_with_carry (sum0,
1151  }
1152  else
1153  sum0 =
1155 
1156  n_bytes_left = n_this_buffer = payload_length_host_byte_order;
1157  data_this_buffer = (void *) ip0 + ip_header_length;
1158  n_ip_bytes_this_buffer =
1159  p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
1160  if (n_this_buffer + ip_header_length > n_ip_bytes_this_buffer)
1161  {
1162  n_this_buffer = n_ip_bytes_this_buffer > ip_header_length ?
1163  n_ip_bytes_this_buffer - ip_header_length : 0;
1164  }
1165  while (1)
1166  {
1167  sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer);
1168  n_bytes_left -= n_this_buffer;
1169  if (n_bytes_left == 0)
1170  break;
1171 
1172  ASSERT (p0->flags & VLIB_BUFFER_NEXT_PRESENT);
1173  p0 = vlib_get_buffer (vm, p0->next_buffer);
1174  data_this_buffer = vlib_buffer_get_current (p0);
1175  n_this_buffer = p0->current_length;
1176  }
1177 
1178  sum16 = ~ip_csum_fold (sum0);
1179 
1180  return sum16;
1181 }
1182 
1183 u32
1185 {
1187  udp_header_t *udp0;
1188  u16 sum16;
1189 
1190  ASSERT (ip0->protocol == IP_PROTOCOL_TCP
1191  || ip0->protocol == IP_PROTOCOL_UDP);
1192 
1193  udp0 = (void *) (ip0 + 1);
1194  if (ip0->protocol == IP_PROTOCOL_UDP && udp0->checksum == 0)
1195  {
1196  p0->flags |= (VNET_BUFFER_F_L4_CHECKSUM_COMPUTED
1197  | VNET_BUFFER_F_L4_CHECKSUM_CORRECT);
1198  return p0->flags;
1199  }
1200 
1201  sum16 = ip4_tcp_udp_compute_checksum (vm, p0, ip0);
1202 
1203  p0->flags |= (VNET_BUFFER_F_L4_CHECKSUM_COMPUTED
1204  | ((sum16 == 0) << VNET_BUFFER_F_LOG2_L4_CHECKSUM_CORRECT));
1205 
1206  return p0->flags;
1207 }
1208 #endif
1209 
1210 /* *INDENT-OFF* */
1211 VNET_FEATURE_ARC_INIT (ip4_local) =
1212 {
1213  .arc_name = "ip4-local",
1214  .start_nodes = VNET_FEATURES ("ip4-local"),
1215 };
1216 /* *INDENT-ON* */
1217 
1218 static inline void
1220  ip4_header_t * ip, u8 is_udp, u8 * error,
1221  u8 * good_tcp_udp)
1222 {
1223  u32 flags0;
1224  flags0 = ip4_tcp_udp_validate_checksum (vm, p);
1225  *good_tcp_udp = (flags0 & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
1226  if (is_udp)
1227  {
1228  udp_header_t *udp;
1229  u32 ip_len, udp_len;
1230  i32 len_diff;
1231  udp = ip4_next_header (ip);
1232  /* Verify UDP length. */
1233  ip_len = clib_net_to_host_u16 (ip->length);
1234  udp_len = clib_net_to_host_u16 (udp->length);
1235 
1236  len_diff = ip_len - udp_len;
1237  *good_tcp_udp &= len_diff >= 0;
1238  *error = len_diff < 0 ? IP4_ERROR_UDP_LENGTH : *error;
1239  }
1240 }
1241 
1242 #define ip4_local_csum_is_offloaded(_b) \
1243  _b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM \
1244  || _b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM
1245 
1246 #define ip4_local_need_csum_check(is_tcp_udp, _b) \
1247  (is_tcp_udp && !(_b->flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED \
1248  || ip4_local_csum_is_offloaded (_b)))
1249 
1250 #define ip4_local_csum_is_valid(_b) \
1251  (_b->flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT \
1252  || (ip4_local_csum_is_offloaded (_b))) != 0
1253 
1254 static inline void
1256  ip4_header_t * ih, u8 * error)
1257 {
1258  u8 is_udp, is_tcp_udp, good_tcp_udp;
1259 
1260  is_udp = ih->protocol == IP_PROTOCOL_UDP;
1261  is_tcp_udp = is_udp || ih->protocol == IP_PROTOCOL_TCP;
1262 
1263  if (PREDICT_FALSE (ip4_local_need_csum_check (is_tcp_udp, b)))
1264  ip4_local_l4_csum_validate (vm, b, ih, is_udp, error, &good_tcp_udp);
1265  else
1266  good_tcp_udp = ip4_local_csum_is_valid (b);
1267 
1268  ASSERT (IP4_ERROR_TCP_CHECKSUM + 1 == IP4_ERROR_UDP_CHECKSUM);
1269  *error = (is_tcp_udp && !good_tcp_udp
1270  ? IP4_ERROR_TCP_CHECKSUM + is_udp : *error);
1271 }
1272 
1273 static inline void
1275  ip4_header_t ** ih, u8 * error)
1276 {
1277  u8 is_udp[2], is_tcp_udp[2], good_tcp_udp[2];
1278 
1279  is_udp[0] = ih[0]->protocol == IP_PROTOCOL_UDP;
1280  is_udp[1] = ih[1]->protocol == IP_PROTOCOL_UDP;
1281 
1282  is_tcp_udp[0] = is_udp[0] || ih[0]->protocol == IP_PROTOCOL_TCP;
1283  is_tcp_udp[1] = is_udp[1] || ih[1]->protocol == IP_PROTOCOL_TCP;
1284 
1285  good_tcp_udp[0] = ip4_local_csum_is_valid (b[0]);
1286  good_tcp_udp[1] = ip4_local_csum_is_valid (b[1]);
1287 
1288  if (PREDICT_FALSE (ip4_local_need_csum_check (is_tcp_udp[0], b[0])
1289  || ip4_local_need_csum_check (is_tcp_udp[1], b[1])))
1290  {
1291  if (is_tcp_udp[0])
1292  ip4_local_l4_csum_validate (vm, b[0], ih[0], is_udp[0], &error[0],
1293  &good_tcp_udp[0]);
1294  if (is_tcp_udp[1])
1295  ip4_local_l4_csum_validate (vm, b[1], ih[1], is_udp[1], &error[1],
1296  &good_tcp_udp[1]);
1297  }
1298 
1299  error[0] = (is_tcp_udp[0] && !good_tcp_udp[0] ?
1300  IP4_ERROR_TCP_CHECKSUM + is_udp[0] : error[0]);
1301  error[1] = (is_tcp_udp[1] && !good_tcp_udp[1] ?
1302  IP4_ERROR_TCP_CHECKSUM + is_udp[1] : error[1]);
1303 }
1304 
1305 static inline void
1307  vlib_buffer_t * b, u16 * next, u8 error,
1308  u8 head_of_feature_arc)
1309 {
1310  u8 arc_index = vnet_feat_arc_ip4_local.feature_arc_index;
1311  u32 next_index;
1312 
1313  *next = error != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : *next;
1314  b->error = error ? error_node->errors[error] : 0;
1315  if (head_of_feature_arc)
1316  {
1317  next_index = *next;
1318  if (PREDICT_TRUE (error == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
1319  {
1320  vnet_feature_arc_start (arc_index,
1322  &next_index, b);
1323  *next = next_index;
1324  }
1325  }
1326 }
1327 
1328 typedef struct
1329 {
1334 
1335 static inline void
1337  ip4_local_last_check_t * last_check, u8 * error0)
1338 {
1339  ip4_fib_mtrie_leaf_t leaf0;
1340  ip4_fib_mtrie_t *mtrie0;
1341  const dpo_id_t *dpo0;
1342  load_balance_t *lb0;
1343  u32 lbi0;
1344 
1345  vnet_buffer (b)->ip.fib_index =
1346  vnet_buffer (b)->sw_if_index[VLIB_TX] != ~0 ?
1347  vnet_buffer (b)->sw_if_index[VLIB_TX] : vnet_buffer (b)->ip.fib_index;
1348 
1349  if (PREDICT_FALSE (last_check->src.as_u32 != ip0->src_address.as_u32))
1350  {
1351  mtrie0 = &ip4_fib_get (vnet_buffer (b)->ip.fib_index)->mtrie;
1352  leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, &ip0->src_address);
1353  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 2);
1354  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 3);
1355  lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
1356 
1357  vnet_buffer (b)->ip.adj_index[VLIB_TX] = lbi0;
1358  vnet_buffer (b)->ip.adj_index[VLIB_RX] = lbi0;
1359 
1360  lb0 = load_balance_get (lbi0);
1361  dpo0 = load_balance_get_bucket_i (lb0, 0);
1362 
1363  /*
1364  * Must have a route to source otherwise we drop the packet.
1365  * ip4 broadcasts are accepted, e.g. to make dhcp client work
1366  *
1367  * The checks are:
1368  * - the source is a recieve => it's from us => bogus, do this
1369  * first since it sets a different error code.
1370  * - uRPF check for any route to source - accept if passes.
1371  * - allow packets destined to the broadcast address from unknown sources
1372  */
1373 
1374  *error0 = ((*error0 == IP4_ERROR_UNKNOWN_PROTOCOL
1375  && dpo0->dpoi_type == DPO_RECEIVE) ?
1376  IP4_ERROR_SPOOFED_LOCAL_PACKETS : *error0);
1377  *error0 = ((*error0 == IP4_ERROR_UNKNOWN_PROTOCOL
1378  && !fib_urpf_check_size (lb0->lb_urpf)
1379  && ip0->dst_address.as_u32 != 0xFFFFFFFF) ?
1380  IP4_ERROR_SRC_LOOKUP_MISS : *error0);
1381 
1382  last_check->src.as_u32 = ip0->src_address.as_u32;
1383  last_check->lbi = lbi0;
1384  last_check->error = *error0;
1385  }
1386  else
1387  {
1388  vnet_buffer (b)->ip.adj_index[VLIB_TX] = last_check->lbi;
1389  vnet_buffer (b)->ip.adj_index[VLIB_RX] = last_check->lbi;
1390  *error0 = last_check->error;
1391  }
1392 }
1393 
1394 static inline void
1396  ip4_local_last_check_t * last_check, u8 * error)
1397 {
1398  ip4_fib_mtrie_leaf_t leaf[2];
1399  ip4_fib_mtrie_t *mtrie[2];
1400  const dpo_id_t *dpo[2];
1401  load_balance_t *lb[2];
1402  u32 not_last_hit = 0;
1403  u32 lbi[2];
1404 
1405  not_last_hit |= ip[0]->src_address.as_u32 ^ last_check->src.as_u32;
1406  not_last_hit |= ip[1]->src_address.as_u32 ^ last_check->src.as_u32;
1407 
1408  vnet_buffer (b[0])->ip.fib_index =
1409  vnet_buffer (b[0])->sw_if_index[VLIB_TX] != ~0 ?
1410  vnet_buffer (b[0])->sw_if_index[VLIB_TX] :
1411  vnet_buffer (b[0])->ip.fib_index;
1412 
1413  vnet_buffer (b[1])->ip.fib_index =
1414  vnet_buffer (b[1])->sw_if_index[VLIB_TX] != ~0 ?
1415  vnet_buffer (b[1])->sw_if_index[VLIB_TX] :
1416  vnet_buffer (b[1])->ip.fib_index;
1417 
1418  if (PREDICT_FALSE (not_last_hit))
1419  {
1420  mtrie[0] = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie;
1421  mtrie[1] = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie;
1422 
1423  leaf[0] = ip4_fib_mtrie_lookup_step_one (mtrie[0], &ip[0]->src_address);
1424  leaf[1] = ip4_fib_mtrie_lookup_step_one (mtrie[1], &ip[1]->src_address);
1425 
1426  leaf[0] = ip4_fib_mtrie_lookup_step (mtrie[0], leaf[0],
1427  &ip[0]->src_address, 2);
1428  leaf[1] = ip4_fib_mtrie_lookup_step (mtrie[1], leaf[1],
1429  &ip[1]->src_address, 2);
1430 
1431  leaf[0] = ip4_fib_mtrie_lookup_step (mtrie[0], leaf[0],
1432  &ip[0]->src_address, 3);
1433  leaf[1] = ip4_fib_mtrie_lookup_step (mtrie[1], leaf[1],
1434  &ip[1]->src_address, 3);
1435 
1436  lbi[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf[0]);
1437  lbi[1] = ip4_fib_mtrie_leaf_get_adj_index (leaf[1]);
1438 
1439  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = lbi[0];
1440  vnet_buffer (b[0])->ip.adj_index[VLIB_RX] = lbi[0];
1441 
1442  vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = lbi[1];
1443  vnet_buffer (b[1])->ip.adj_index[VLIB_RX] = lbi[1];
1444 
1445  lb[0] = load_balance_get (lbi[0]);
1446  lb[1] = load_balance_get (lbi[1]);
1447 
1448  dpo[0] = load_balance_get_bucket_i (lb[0], 0);
1449  dpo[1] = load_balance_get_bucket_i (lb[1], 0);
1450 
1451  error[0] = ((error[0] == IP4_ERROR_UNKNOWN_PROTOCOL &&
1452  dpo[0]->dpoi_type == DPO_RECEIVE) ?
1453  IP4_ERROR_SPOOFED_LOCAL_PACKETS : error[0]);
1454  error[0] = ((error[0] == IP4_ERROR_UNKNOWN_PROTOCOL &&
1455  !fib_urpf_check_size (lb[0]->lb_urpf) &&
1456  ip[0]->dst_address.as_u32 != 0xFFFFFFFF)
1457  ? IP4_ERROR_SRC_LOOKUP_MISS : error[0]);
1458 
1459  error[1] = ((error[1] == IP4_ERROR_UNKNOWN_PROTOCOL &&
1460  dpo[1]->dpoi_type == DPO_RECEIVE) ?
1461  IP4_ERROR_SPOOFED_LOCAL_PACKETS : error[1]);
1462  error[1] = ((error[1] == IP4_ERROR_UNKNOWN_PROTOCOL &&
1463  !fib_urpf_check_size (lb[1]->lb_urpf) &&
1464  ip[1]->dst_address.as_u32 != 0xFFFFFFFF)
1465  ? IP4_ERROR_SRC_LOOKUP_MISS : error[1]);
1466 
1467  last_check->src.as_u32 = ip[1]->src_address.as_u32;
1468  last_check->lbi = lbi[1];
1469  last_check->error = error[1];
1470  }
1471  else
1472  {
1473  vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = last_check->lbi;
1474  vnet_buffer (b[0])->ip.adj_index[VLIB_RX] = last_check->lbi;
1475 
1476  vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = last_check->lbi;
1477  vnet_buffer (b[1])->ip.adj_index[VLIB_RX] = last_check->lbi;
1478 
1479  error[0] = last_check->error;
1480  error[1] = last_check->error;
1481  }
1482 }
1483 
1485 {
1489 };
1490 
1491 /**
1492  * Determine packet type and next node.
1493  *
1494  * The expectation is that all packets that are not L4 will skip
1495  * checksums and source checks.
1496  */
1499 {
1500  ip_lookup_main_t *lm = &ip4_main.lookup_main;
1501 
1502  if (PREDICT_FALSE (ip4_is_fragment (ip)))
1503  {
1504  *next = IP_LOCAL_NEXT_REASSEMBLY;
1506  }
1507  if (PREDICT_FALSE (b->flags & VNET_BUFFER_F_IS_NATED))
1508  {
1509  *next = lm->local_next_by_ip_protocol[ip->protocol];
1510  return IP_LOCAL_PACKET_TYPE_NAT;
1511  }
1512 
1513  *next = lm->local_next_by_ip_protocol[ip->protocol];
1514  return IP_LOCAL_PACKET_TYPE_L4;
1515 }
1516 
1517 static inline uword
1519  vlib_node_runtime_t * node,
1520  vlib_frame_t * frame, int head_of_feature_arc)
1521 {
1522  u32 *from, n_left_from;
1523  vlib_node_runtime_t *error_node =
1525  u16 nexts[VLIB_FRAME_SIZE], *next;
1526  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
1527  ip4_header_t *ip[2];
1528  u8 error[2], pt[2];
1529 
1530  ip4_local_last_check_t last_check = {
1531  .src = {.as_u32 = 0},
1532  .lbi = ~0,
1533  .error = IP4_ERROR_UNKNOWN_PROTOCOL
1534  };
1535 
1536  from = vlib_frame_vector_args (frame);
1537  n_left_from = frame->n_vectors;
1538 
1539  if (node->flags & VLIB_NODE_FLAG_TRACE)
1540  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
1541 
1542  vlib_get_buffers (vm, from, bufs, n_left_from);
1543  b = bufs;
1544  next = nexts;
1545 
1546  while (n_left_from >= 6)
1547  {
1548  u8 not_batch = 0;
1549 
1550  /* Prefetch next iteration. */
1551  {
1552  vlib_prefetch_buffer_header (b[4], LOAD);
1553  vlib_prefetch_buffer_header (b[5], LOAD);
1554 
1555  CLIB_PREFETCH (b[4]->data, CLIB_CACHE_LINE_BYTES, LOAD);
1556  CLIB_PREFETCH (b[5]->data, CLIB_CACHE_LINE_BYTES, LOAD);
1557  }
1558 
1559  error[0] = error[1] = IP4_ERROR_UNKNOWN_PROTOCOL;
1560 
1561  ip[0] = vlib_buffer_get_current (b[0]);
1562  ip[1] = vlib_buffer_get_current (b[1]);
1563 
1564  vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data;
1565  vnet_buffer (b[1])->l3_hdr_offset = b[1]->current_data;
1566 
1567  pt[0] = ip4_local_classify (b[0], ip[0], &next[0]);
1568  pt[1] = ip4_local_classify (b[1], ip[1], &next[1]);
1569 
1570  not_batch = pt[0] ^ pt[1];
1571 
1572  if (head_of_feature_arc == 0 || (pt[0] && not_batch == 0))
1573  goto skip_checks;
1574 
1575  if (PREDICT_TRUE (not_batch == 0))
1576  {
1577  ip4_local_check_l4_csum_x2 (vm, b, ip, error);
1578  ip4_local_check_src_x2 (b, ip, &last_check, error);
1579  }
1580  else
1581  {
1582  if (!pt[0])
1583  {
1584  ip4_local_check_l4_csum (vm, b[0], ip[0], &error[0]);
1585  ip4_local_check_src (b[0], ip[0], &last_check, &error[0]);
1586  }
1587  if (!pt[1])
1588  {
1589  ip4_local_check_l4_csum (vm, b[1], ip[1], &error[1]);
1590  ip4_local_check_src (b[1], ip[1], &last_check, &error[1]);
1591  }
1592  }
1593 
1594  skip_checks:
1595 
1596  ip4_local_set_next_and_error (error_node, b[0], &next[0], error[0],
1597  head_of_feature_arc);
1598  ip4_local_set_next_and_error (error_node, b[1], &next[1], error[1],
1599  head_of_feature_arc);
1600 
1601  b += 2;
1602  next += 2;
1603  n_left_from -= 2;
1604  }
1605 
1606  while (n_left_from > 0)
1607  {
1608  error[0] = IP4_ERROR_UNKNOWN_PROTOCOL;
1609 
1610  ip[0] = vlib_buffer_get_current (b[0]);
1611  vnet_buffer (b[0])->l3_hdr_offset = b[0]->current_data;
1612  pt[0] = ip4_local_classify (b[0], ip[0], &next[0]);
1613 
1614  if (head_of_feature_arc == 0 || pt[0])
1615  goto skip_check;
1616 
1617  ip4_local_check_l4_csum (vm, b[0], ip[0], &error[0]);
1618  ip4_local_check_src (b[0], ip[0], &last_check, &error[0]);
1619 
1620  skip_check:
1621 
1622  ip4_local_set_next_and_error (error_node, b[0], &next[0], error[0],
1623  head_of_feature_arc);
1624 
1625  b += 1;
1626  next += 1;
1627  n_left_from -= 1;
1628  }
1629 
1630  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
1631  return frame->n_vectors;
1632 }
1633 
1635  vlib_frame_t * frame)
1636 {
1637  return ip4_local_inline (vm, node, frame, 1 /* head of feature arc */ );
1638 }
1639 
1640 /* *INDENT-OFF* */
1642 {
1643  .name = "ip4-local",
1644  .vector_size = sizeof (u32),
1645  .format_trace = format_ip4_forward_next_trace,
1646  .n_next_nodes = IP_LOCAL_N_NEXT,
1647  .next_nodes =
1648  {
1649  [IP_LOCAL_NEXT_DROP] = "ip4-drop",
1650  [IP_LOCAL_NEXT_PUNT] = "ip4-punt",
1651  [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
1652  [IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",
1653  [IP_LOCAL_NEXT_REASSEMBLY] = "ip4-reassembly",
1654  },
1655 };
1656 /* *INDENT-ON* */
1657 
1658 
1660  vlib_node_runtime_t * node,
1661  vlib_frame_t * frame)
1662 {
1663  return ip4_local_inline (vm, node, frame, 0 /* head of feature arc */ );
1664 }
1665 
1666 /* *INDENT-OFF* */
1668  .name = "ip4-local-end-of-arc",
1669  .vector_size = sizeof (u32),
1670 
1671  .format_trace = format_ip4_forward_next_trace,
1672  .sibling_of = "ip4-local",
1673 };
1674 
1675 VNET_FEATURE_INIT (ip4_local_end_of_arc, static) = {
1676  .arc_name = "ip4-local",
1677  .node_name = "ip4-local-end-of-arc",
1678  .runs_before = 0, /* not before any other features */
1679 };
1680 /* *INDENT-ON* */
1681 
1682 #ifndef CLIB_MARCH_VARIANT
1683 void
1684 ip4_register_protocol (u32 protocol, u32 node_index)
1685 {
1686  vlib_main_t *vm = vlib_get_main ();
1687  ip4_main_t *im = &ip4_main;
1688  ip_lookup_main_t *lm = &im->lookup_main;
1689 
1690  ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
1691  lm->local_next_by_ip_protocol[protocol] =
1692  vlib_node_add_next (vm, ip4_local_node.index, node_index);
1693 }
1694 #endif
1695 
1696 static clib_error_t *
1698  unformat_input_t * input, vlib_cli_command_t * cmd)
1699 {
1700  ip4_main_t *im = &ip4_main;
1701  ip_lookup_main_t *lm = &im->lookup_main;
1702  int i;
1703 
1704  vlib_cli_output (vm, "Protocols handled by ip4_local");
1705  for (i = 0; i < ARRAY_LEN (lm->local_next_by_ip_protocol); i++)
1706  {
1708  {
1709  u32 node_index = vlib_get_node (vm,
1710  ip4_local_node.index)->
1711  next_nodes[lm->local_next_by_ip_protocol[i]];
1712  vlib_cli_output (vm, "%d: %U", i, format_vlib_node_name, vm,
1713  node_index);
1714  }
1715  }
1716  return 0;
1717 }
1718 
1719 
1720 
1721 /*?
1722  * Display the set of protocols handled by the local IPv4 stack.
1723  *
1724  * @cliexpar
1725  * Example of how to display local protocol table:
1726  * @cliexstart{show ip local}
1727  * Protocols handled by ip4_local
1728  * 1
1729  * 17
1730  * 47
1731  * @cliexend
1732 ?*/
1733 /* *INDENT-OFF* */
1734 VLIB_CLI_COMMAND (show_ip_local, static) =
1735 {
1736  .path = "show ip local",
1737  .function = show_ip_local_command_fn,
1738  .short_help = "show ip local",
1739 };
1740 /* *INDENT-ON* */
1741 
1744  vlib_node_runtime_t * node,
1745  vlib_frame_t * frame, int is_glean)
1746 {
1747  vnet_main_t *vnm = vnet_get_main ();
1748  ip4_main_t *im = &ip4_main;
1749  ip_lookup_main_t *lm = &im->lookup_main;
1750  u32 *from, *to_next_drop;
1751  uword n_left_from, n_left_to_next_drop, next_index;
1752  u32 thread_index = vm->thread_index;
1753  u64 seed;
1754 
1755  if (node->flags & VLIB_NODE_FLAG_TRACE)
1756  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
1757 
1758  seed = throttle_seed (&im->arp_throttle, thread_index, vlib_time_now (vm));
1759 
1760  from = vlib_frame_vector_args (frame);
1761  n_left_from = frame->n_vectors;
1762  next_index = node->cached_next_index;
1763  if (next_index == IP4_ARP_NEXT_DROP)
1764  next_index = IP4_ARP_N_NEXT; /* point to first interface */
1765 
1766  while (n_left_from > 0)
1767  {
1769  to_next_drop, n_left_to_next_drop);
1770 
1771  while (n_left_from > 0 && n_left_to_next_drop > 0)
1772  {
1773  u32 pi0, adj_index0, sw_if_index0, drop0;
1774  ip_adjacency_t *adj0;
1775  vlib_buffer_t *p0;
1776  ip4_header_t *ip0;
1777  u64 r0;
1778 
1779  pi0 = from[0];
1780 
1781  p0 = vlib_get_buffer (vm, pi0);
1782 
1783  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
1784  adj0 = adj_get (adj_index0);
1785  ip0 = vlib_buffer_get_current (p0);
1786 
1787  sw_if_index0 = adj0->rewrite_header.sw_if_index;
1788  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1789 
1790  if (PREDICT_TRUE (is_glean))
1791  {
1792  /*
1793  * this is the Glean case, so we are ARPing for the
1794  * packet's destination
1795  */
1796  r0 = ip0->dst_address.data_u32;
1797  }
1798  else
1799  {
1800  r0 = adj0->sub_type.nbr.next_hop.ip4.data_u32;
1801  }
1802  /* combine the address and interface for the hash key */
1803  r0 = r0 << 32;
1804  r0 |= sw_if_index0;
1805 
1806  drop0 = throttle_check (&im->arp_throttle, thread_index, r0, seed);
1807 
1808  from += 1;
1809  n_left_from -= 1;
1810  to_next_drop[0] = pi0;
1811  to_next_drop += 1;
1812  n_left_to_next_drop -= 1;
1813 
1814  p0->error =
1815  node->errors[drop0 ? IP4_ARP_ERROR_DROP :
1817 
1818  /*
1819  * the adj has been updated to a rewrite but the node the DPO that got
1820  * us here hasn't - yet. no big deal. we'll drop while we wait.
1821  */
1823  continue;
1824 
1825  if (drop0)
1826  continue;
1827 
1828  /*
1829  * Can happen if the control-plane is programming tables
1830  * with traffic flowing; at least that's today's lame excuse.
1831  */
1832  if ((is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_GLEAN)
1833  || (!is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP))
1834  {
1835  p0->error = node->errors[IP4_ARP_ERROR_NON_ARP_ADJ];
1836  }
1837  else
1838  /* Send ARP request. */
1839  {
1840  u32 bi0 = 0;
1841  vlib_buffer_t *b0;
1843  vnet_hw_interface_t *hw_if0;
1844 
1845  h0 =
1848  &bi0);
1849 
1850  /* Seems we're out of buffers */
1851  if (PREDICT_FALSE (!h0))
1852  continue;
1853 
1854  /* Add rewrite/encap string for ARP packet. */
1855  vnet_rewrite_one_header (adj0[0], h0,
1856  sizeof (ethernet_header_t));
1857 
1858  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1859 
1860  /* Src ethernet address in ARP header. */
1861  clib_memcpy (h0->ip4_over_ethernet[0].ethernet,
1862  hw_if0->hw_address,
1863  sizeof (h0->ip4_over_ethernet[0].ethernet));
1864 
1865  if (is_glean)
1866  {
1867  /* The interface's source address is stashed in the Glean Adj */
1868  h0->ip4_over_ethernet[0].ip4 =
1869  adj0->sub_type.glean.receive_addr.ip4;
1870 
1871  /* Copy in destination address we are requesting. This is the
1872  * glean case, so it's the packet's destination.*/
1873  h0->ip4_over_ethernet[1].ip4.data_u32 =
1874  ip0->dst_address.data_u32;
1875  }
1876  else
1877  {
1878  /* Src IP address in ARP header. */
1879  if (ip4_src_address_for_packet (lm, sw_if_index0,
1880  &h0->
1881  ip4_over_ethernet[0].ip4))
1882  {
1883  /* No source address available */
1884  p0->error =
1886  vlib_buffer_free (vm, &bi0, 1);
1887  continue;
1888  }
1889 
1890  /* Copy in destination address we are requesting from the
1891  incomplete adj */
1892  h0->ip4_over_ethernet[1].ip4.data_u32 =
1893  adj0->sub_type.nbr.next_hop.ip4.as_u32;
1894  }
1895 
1896  vlib_buffer_copy_trace_flag (vm, p0, bi0);
1897  b0 = vlib_get_buffer (vm, bi0);
1899  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
1900 
1901  vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
1902 
1903  vlib_set_next_frame_buffer (vm, node,
1904  adj0->rewrite_header.next_index,
1905  bi0);
1906  }
1907  }
1908 
1909  vlib_put_next_frame (vm, node, IP4_ARP_NEXT_DROP, n_left_to_next_drop);
1910  }
1911 
1912  return frame->n_vectors;
1913 }
1914 
1916  vlib_frame_t * frame)
1917 {
1918  return (ip4_arp_inline (vm, node, frame, 0));
1919 }
1920 
1922  vlib_frame_t * frame)
1923 {
1924  return (ip4_arp_inline (vm, node, frame, 1));
1925 }
1926 
1927 static char *ip4_arp_error_strings[] = {
1928  [IP4_ARP_ERROR_DROP] = "address overflow drops",
1929  [IP4_ARP_ERROR_REQUEST_SENT] = "ARP requests sent",
1930  [IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies",
1931  [IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed",
1932  [IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed",
1933  [IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request",
1934 };
1935 
1936 /* *INDENT-OFF* */
1938 {
1939  .name = "ip4-arp",
1940  .vector_size = sizeof (u32),
1941  .format_trace = format_ip4_forward_next_trace,
1942  .n_errors = ARRAY_LEN (ip4_arp_error_strings),
1943  .error_strings = ip4_arp_error_strings,
1944  .n_next_nodes = IP4_ARP_N_NEXT,
1945  .next_nodes =
1946  {
1947  [IP4_ARP_NEXT_DROP] = "error-drop",
1948  },
1949 };
1950 
1952 {
1953  .name = "ip4-glean",
1954  .vector_size = sizeof (u32),
1955  .format_trace = format_ip4_forward_next_trace,
1956  .n_errors = ARRAY_LEN (ip4_arp_error_strings),
1957  .error_strings = ip4_arp_error_strings,
1958  .n_next_nodes = IP4_ARP_N_NEXT,
1959  .next_nodes = {
1960  [IP4_ARP_NEXT_DROP] = "error-drop",
1961  },
1962 };
1963 /* *INDENT-ON* */
1964 
1965 #define foreach_notrace_ip4_arp_error \
1966 _(DROP) \
1967 _(REQUEST_SENT) \
1968 _(REPLICATE_DROP) \
1969 _(REPLICATE_FAIL)
1970 
1971 static clib_error_t *
1973 {
1975 
1976  /* don't trace ARP request packets */
1977 #define _(a) \
1978  vnet_pcap_drop_trace_filter_add_del \
1979  (rt->errors[IP4_ARP_ERROR_##a], \
1980  1 /* is_add */);
1982 #undef _
1983  return 0;
1984 }
1985 
1987 
1988 
1989 #ifndef CLIB_MARCH_VARIANT
1990 /* Send an ARP request to see if given destination is reachable on given interface. */
1991 clib_error_t *
1993  u8 refresh)
1994 {
1995  vnet_main_t *vnm = vnet_get_main ();
1996  ip4_main_t *im = &ip4_main;
1998  ip4_address_t *src;
2000  ip_adjacency_t *adj;
2002  vnet_sw_interface_t *si;
2003  vlib_buffer_t *b;
2004  adj_index_t ai;
2005  u32 bi = 0;
2006  u8 unicast_rewrite = 0;
2007 
2008  si = vnet_get_sw_interface (vnm, sw_if_index);
2009 
2011  {
2012  return clib_error_return (0, "%U: interface %U down",
2013  format_ip4_address, dst,
2015  sw_if_index);
2016  }
2017 
2018  src =
2019  ip4_interface_address_matching_destination (im, dst, sw_if_index, &ia);
2020  if (!src)
2021  {
2022  vnm->api_errno = VNET_API_ERROR_NO_MATCHING_INTERFACE;
2023  return clib_error_return
2024  (0,
2025  "no matching interface address for destination %U (interface %U)",
2027  sw_if_index);
2028  }
2029 
2032  &bi);
2033 
2034  if (!h)
2035  return clib_error_return (0, "ARP request packet allocation failed");
2036 
2037  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
2038  if (PREDICT_FALSE (!hi->hw_address))
2039  {
2040  return clib_error_return (0, "%U: interface %U do not support ip probe",
2041  format_ip4_address, dst,
2043  sw_if_index);
2044  }
2045 
2046  clib_memcpy (h->ip4_over_ethernet[0].ethernet, hi->hw_address,
2047  sizeof (h->ip4_over_ethernet[0].ethernet));
2048 
2049  h->ip4_over_ethernet[0].ip4 = src[0];
2050  h->ip4_over_ethernet[1].ip4 = dst[0];
2051 
2052  b = vlib_get_buffer (vm, bi);
2053  vnet_buffer (b)->sw_if_index[VLIB_RX] =
2054  vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
2055 
2056  ip46_address_t nh = {
2057  .ip4 = *dst,
2058  };
2059 
2061  VNET_LINK_IP4, &nh, sw_if_index);
2062  adj = adj_get (ai);
2063 
2064  /* Peer has been previously resolved, retrieve glean adj instead */
2066  {
2067  if (refresh)
2068  unicast_rewrite = 1;
2069  else
2070  {
2071  adj_unlock (ai);
2073  VNET_LINK_IP4, sw_if_index, &nh);
2074  adj = adj_get (ai);
2075  }
2076  }
2077 
2078  /* Add encapsulation string for software interface (e.g. ethernet header). */
2079  vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
2080  if (unicast_rewrite)
2081  {
2082  u16 *etype = vlib_buffer_get_current (b) - 2;
2083  etype[0] = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
2084  }
2085  vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
2086 
2087  {
2089  u32 *to_next = vlib_frame_vector_args (f);
2090  to_next[0] = bi;
2091  f->n_vectors = 1;
2093  }
2094 
2095  adj_unlock (ai);
2096  return /* no error */ 0;
2097 }
2098 #endif
2099 
2100 typedef enum
2101 {
2107 
2108 /**
2109  * This bits of an IPv4 address to mask to construct a multicast
2110  * MAC address
2111  */
2112 #if CLIB_ARCH_IS_BIG_ENDIAN
2113 #define IP4_MCAST_ADDR_MASK 0x007fffff
2114 #else
2115 #define IP4_MCAST_ADDR_MASK 0xffff7f00
2116 #endif
2117 
2118 always_inline void
2120  u16 adj_packet_bytes, bool df, u16 * next, u32 * error)
2121 {
2122  if (packet_len > adj_packet_bytes)
2123  {
2124  *error = IP4_ERROR_MTU_EXCEEDED;
2125  if (df)
2126  {
2128  (b, ICMP4_destination_unreachable,
2129  ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
2130  adj_packet_bytes);
2132  }
2133  else
2134  {
2135  /* IP fragmentation */
2136  ip_frag_set_vnet_buffer (b, adj_packet_bytes,
2138  *next = IP4_REWRITE_NEXT_FRAGMENT;
2139  }
2140  }
2141 }
2142 
2143 /* Decrement TTL & update checksum.
2144  Works either endian, so no need for byte swap. */
2147  u32 * error)
2148 {
2149  i32 ttl;
2150  u32 checksum;
2151  if (PREDICT_FALSE (b->flags & VNET_BUFFER_F_LOCALLY_ORIGINATED))
2152  {
2153  b->flags &= ~VNET_BUFFER_F_LOCALLY_ORIGINATED;
2154  return;
2155  }
2156 
2157  ttl = ip->ttl;
2158 
2159  /* Input node should have reject packets with ttl 0. */
2160  ASSERT (ip->ttl > 0);
2161 
2162  checksum = ip->checksum + clib_host_to_net_u16 (0x0100);
2163  checksum += checksum >= 0xffff;
2164 
2165  ip->checksum = checksum;
2166  ttl -= 1;
2167  ip->ttl = ttl;
2168 
2169  /*
2170  * If the ttl drops below 1 when forwarding, generate
2171  * an ICMP response.
2172  */
2173  if (PREDICT_FALSE (ttl <= 0))
2174  {
2175  *error = IP4_ERROR_TIME_EXPIRED;
2176  vnet_buffer (b)->sw_if_index[VLIB_TX] = (u32) ~ 0;
2177  icmp4_error_set_vnet_buffer (b, ICMP4_time_exceeded,
2178  ICMP4_time_exceeded_ttl_exceeded_in_transit,
2179  0);
2181  }
2182 
2183  /* Verify checksum. */
2184  ASSERT ((ip->checksum == ip4_header_checksum (ip)) ||
2185  (b->flags & VNET_BUFFER_F_OFFLOAD_IP_CKSUM));
2186 }
2187 
2188 
2191  vlib_node_runtime_t * node,
2192  vlib_frame_t * frame,
2193  int do_counters, int is_midchain, int is_mcast)
2194 {
2195  ip_lookup_main_t *lm = &ip4_main.lookup_main;
2196  u32 *from = vlib_frame_vector_args (frame);
2197  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
2198  u16 nexts[VLIB_FRAME_SIZE], *next;
2199  u32 n_left_from;
2200  vlib_node_runtime_t *error_node =
2202 
2203  n_left_from = frame->n_vectors;
2204  u32 thread_index = vm->thread_index;
2205 
2206  vlib_get_buffers (vm, from, bufs, n_left_from);
2207  clib_memset_u16 (nexts, IP4_REWRITE_NEXT_DROP, n_left_from);
2208 
2209  if (n_left_from >= 6)
2210  {
2211  int i;
2212  for (i = 0; i < 6; i++)
2213  vlib_prefetch_buffer_header (bufs[i], LOAD);
2214  }
2215 
2216  next = nexts;
2217  b = bufs;
2218  while (n_left_from >= 8)
2219  {
2220  ip_adjacency_t *adj0, *adj1;
2221  ip4_header_t *ip0, *ip1;
2222  u32 rw_len0, error0, adj_index0;
2223  u32 rw_len1, error1, adj_index1;
2224  u32 tx_sw_if_index0, tx_sw_if_index1;
2225  u8 *p;
2226 
2227  vlib_prefetch_buffer_header (b[6], LOAD);
2228  vlib_prefetch_buffer_header (b[7], LOAD);
2229 
2230  adj_index0 = vnet_buffer (b[0])->ip.adj_index[VLIB_TX];
2231  adj_index1 = vnet_buffer (b[1])->ip.adj_index[VLIB_TX];
2232 
2233  /*
2234  * pre-fetch the per-adjacency counters
2235  */
2236  if (do_counters)
2237  {
2239  thread_index, adj_index0);
2241  thread_index, adj_index1);
2242  }
2243 
2244  ip0 = vlib_buffer_get_current (b[0]);
2245  ip1 = vlib_buffer_get_current (b[1]);
2246 
2247  error0 = error1 = IP4_ERROR_NONE;
2248 
2249  ip4_ttl_and_checksum_check (b[0], ip0, next + 0, &error0);
2250  ip4_ttl_and_checksum_check (b[1], ip1, next + 1, &error1);
2251 
2252  /* Rewrite packet header and updates lengths. */
2253  adj0 = adj_get (adj_index0);
2254  adj1 = adj_get (adj_index1);
2255 
2256  /* Worth pipelining. No guarantee that adj0,1 are hot... */
2257  rw_len0 = adj0[0].rewrite_header.data_bytes;
2258  rw_len1 = adj1[0].rewrite_header.data_bytes;
2259  vnet_buffer (b[0])->ip.save_rewrite_length = rw_len0;
2260  vnet_buffer (b[1])->ip.save_rewrite_length = rw_len1;
2261 
2262  p = vlib_buffer_get_current (b[2]);
2265 
2266  p = vlib_buffer_get_current (b[3]);
2269 
2270  /* Check MTU of outgoing interface. */
2271  ip4_mtu_check (b[0], clib_net_to_host_u16 (ip0->length),
2272  adj0[0].rewrite_header.max_l3_packet_bytes,
2274  clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
2275  next + 0, &error0);
2276  ip4_mtu_check (b[1], clib_net_to_host_u16 (ip1->length),
2277  adj1[0].rewrite_header.max_l3_packet_bytes,
2279  clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
2280  next + 1, &error1);
2281 
2282  if (is_mcast)
2283  {
2284  error0 = ((adj0[0].rewrite_header.sw_if_index ==
2285  vnet_buffer (b[0])->sw_if_index[VLIB_RX]) ?
2286  IP4_ERROR_SAME_INTERFACE : error0);
2287  error1 = ((adj1[0].rewrite_header.sw_if_index ==
2288  vnet_buffer (b[1])->sw_if_index[VLIB_RX]) ?
2289  IP4_ERROR_SAME_INTERFACE : error1);
2290  }
2291 
2292  b[0]->error = error_node->errors[error0];
2293  b[1]->error = error_node->errors[error1];
2294  /* Don't adjust the buffer for ttl issue; icmp-error node wants
2295  * to see the IP headerr */
2296  if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
2297  {
2298  u32 next_index = adj0[0].rewrite_header.next_index;
2299  b[0]->current_data -= rw_len0;
2300  b[0]->current_length += rw_len0;
2301  tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
2302  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = tx_sw_if_index0;
2303 
2304  if (PREDICT_FALSE
2305  (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2307  tx_sw_if_index0, &next_index, b[0]);
2308  next[0] = next_index;
2309  }
2310  if (PREDICT_TRUE (error1 == IP4_ERROR_NONE))
2311  {
2312  u32 next_index = adj1[0].rewrite_header.next_index;
2313  b[1]->current_data -= rw_len1;
2314  b[1]->current_length += rw_len1;
2315 
2316  tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index;
2317  vnet_buffer (b[1])->sw_if_index[VLIB_TX] = tx_sw_if_index1;
2318 
2319  if (PREDICT_FALSE
2320  (adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2322  tx_sw_if_index1, &next_index, b[1]);
2323  next[1] = next_index;
2324  }
2325 
2326  /* Guess we are only writing on simple Ethernet header. */
2327  vnet_rewrite_two_headers (adj0[0], adj1[0],
2328  ip0, ip1, sizeof (ethernet_header_t));
2329 
2330  /*
2331  * Bump the per-adjacency counters
2332  */
2333  if (do_counters)
2334  {
2337  thread_index,
2338  adj_index0, 1, vlib_buffer_length_in_chain (vm, b[0]) + rw_len0);
2339 
2342  thread_index,
2343  adj_index1, 1, vlib_buffer_length_in_chain (vm, b[1]) + rw_len1);
2344  }
2345 
2346  if (is_midchain)
2347  {
2348  adj0->sub_type.midchain.fixup_func
2349  (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data);
2350  adj1->sub_type.midchain.fixup_func
2351  (vm, adj1, b[1], adj1->sub_type.midchain.fixup_data);
2352  }
2353 
2354  if (is_mcast)
2355  {
2356  /*
2357  * copy bytes from the IP address into the MAC rewrite
2358  */
2360  adj0->rewrite_header.dst_mcast_offset,
2361  &ip0->dst_address.as_u32, (u8 *) ip0);
2363  adj1->rewrite_header.dst_mcast_offset,
2364  &ip1->dst_address.as_u32, (u8 *) ip1);
2365  }
2366 
2367  next += 2;
2368  b += 2;
2369  n_left_from -= 2;
2370  }
2371 
2372  while (n_left_from > 0)
2373  {
2374  ip_adjacency_t *adj0;
2375  ip4_header_t *ip0;
2376  u32 rw_len0, adj_index0, error0;
2377  u32 tx_sw_if_index0;
2378 
2379  adj_index0 = vnet_buffer (b[0])->ip.adj_index[VLIB_TX];
2380 
2381  adj0 = adj_get (adj_index0);
2382 
2383  if (do_counters)
2385  thread_index, adj_index0);
2386 
2387  ip0 = vlib_buffer_get_current (b[0]);
2388 
2389  error0 = IP4_ERROR_NONE;
2390 
2391  ip4_ttl_and_checksum_check (b[0], ip0, next + 0, &error0);
2392 
2393 
2394  /* Update packet buffer attributes/set output interface. */
2395  rw_len0 = adj0[0].rewrite_header.data_bytes;
2396  vnet_buffer (b[0])->ip.save_rewrite_length = rw_len0;
2397 
2398  /* Check MTU of outgoing interface. */
2399  ip4_mtu_check (b[0], clib_net_to_host_u16 (ip0->length),
2400  adj0[0].rewrite_header.max_l3_packet_bytes,
2402  clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT),
2403  next + 0, &error0);
2404 
2405  if (is_mcast)
2406  {
2407  error0 = ((adj0[0].rewrite_header.sw_if_index ==
2408  vnet_buffer (b[0])->sw_if_index[VLIB_RX]) ?
2409  IP4_ERROR_SAME_INTERFACE : error0);
2410  }
2411  b[0]->error = error_node->errors[error0];
2412 
2413  /* Don't adjust the buffer for ttl issue; icmp-error node wants
2414  * to see the IP headerr */
2415  if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
2416  {
2417  u32 next_index = adj0[0].rewrite_header.next_index;
2418  b[0]->current_data -= rw_len0;
2419  b[0]->current_length += rw_len0;
2420  tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
2421  vnet_buffer (b[0])->sw_if_index[VLIB_TX] = tx_sw_if_index0;
2422 
2423  if (PREDICT_FALSE
2424  (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2426  tx_sw_if_index0, &next_index, b[0]);
2427  next[0] = next_index;
2428  }
2429 
2430  /* Guess we are only writing on simple Ethernet header. */
2431  vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
2432 
2433  if (do_counters)
2436  thread_index, adj_index0, 1,
2437  vlib_buffer_length_in_chain (vm, b[0]) + rw_len0);
2438 
2439  if (is_midchain)
2440  {
2441  adj0->sub_type.midchain.fixup_func
2442  (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data);
2443  }
2444 
2445  if (is_mcast)
2446  {
2447  /*
2448  * copy bytes from the IP address into the MAC rewrite
2449  */
2451  adj0->rewrite_header.dst_mcast_offset,
2452  &ip0->dst_address.as_u32, (u8 *) ip0);
2453  }
2454 
2455  next += 1;
2456  b += 1;
2457  n_left_from -= 1;
2458  }
2459 
2460 
2461  /* Need to do trace after rewrites to pick up new packet data. */
2462  if (node->flags & VLIB_NODE_FLAG_TRACE)
2463  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
2464 
2465  vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors);
2466  return frame->n_vectors;
2467 }
2468 
2469 
2470 /** @brief IPv4 rewrite node.
2471  @node ip4-rewrite
2472 
2473  This is the IPv4 transit-rewrite node: decrement TTL, fix the ipv4
2474  header checksum, fetch the ip adjacency, check the outbound mtu,
2475  apply the adjacency rewrite, and send pkts to the adjacency
2476  rewrite header's rewrite_next_index.
2477 
2478  @param vm vlib_main_t corresponding to the current thread
2479  @param node vlib_node_runtime_t
2480  @param frame vlib_frame_t whose contents should be dispatched
2481 
2482  @par Graph mechanics: buffer metadata, next index usage
2483 
2484  @em Uses:
2485  - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
2486  - the rewrite adjacency index
2487  - <code>adj->lookup_next_index</code>
2488  - Must be IP_LOOKUP_NEXT_REWRITE or IP_LOOKUP_NEXT_ARP, otherwise
2489  the packet will be dropped.
2490  - <code>adj->rewrite_header</code>
2491  - Rewrite string length, rewrite string, next_index
2492 
2493  @em Sets:
2494  - <code>b->current_data, b->current_length</code>
2495  - Updated net of applying the rewrite string
2496 
2497  <em>Next Indices:</em>
2498  - <code> adj->rewrite_header.next_index </code>
2499  or @c ip4-drop
2500 */
2501 
2503  vlib_frame_t * frame)
2504 {
2505  if (adj_are_counters_enabled ())
2506  return ip4_rewrite_inline (vm, node, frame, 1, 0, 0);
2507  else
2508  return ip4_rewrite_inline (vm, node, frame, 0, 0, 0);
2509 }
2510 
2512  vlib_node_runtime_t * node,
2513  vlib_frame_t * frame)
2514 {
2515  if (adj_are_counters_enabled ())
2516  return ip4_rewrite_inline (vm, node, frame, 1, 0, 0);
2517  else
2518  return ip4_rewrite_inline (vm, node, frame, 0, 0, 0);
2519 }
2520 
2522  vlib_node_runtime_t * node,
2523  vlib_frame_t * frame)
2524 {
2525  if (adj_are_counters_enabled ())
2526  return ip4_rewrite_inline (vm, node, frame, 1, 1, 0);
2527  else
2528  return ip4_rewrite_inline (vm, node, frame, 0, 1, 0);
2529 }
2530 
2532  vlib_node_runtime_t * node,
2533  vlib_frame_t * frame)
2534 {
2535  if (adj_are_counters_enabled ())
2536  return ip4_rewrite_inline (vm, node, frame, 1, 0, 1);
2537  else
2538  return ip4_rewrite_inline (vm, node, frame, 0, 0, 1);
2539 }
2540 
2542  vlib_node_runtime_t * node,
2543  vlib_frame_t * frame)
2544 {
2545  if (adj_are_counters_enabled ())
2546  return ip4_rewrite_inline (vm, node, frame, 1, 1, 1);
2547  else
2548  return ip4_rewrite_inline (vm, node, frame, 0, 1, 1);
2549 }
2550 
2551 /* *INDENT-OFF* */
2553  .name = "ip4-rewrite",
2554  .vector_size = sizeof (u32),
2555 
2556  .format_trace = format_ip4_rewrite_trace,
2557 
2558  .n_next_nodes = IP4_REWRITE_N_NEXT,
2559  .next_nodes = {
2560  [IP4_REWRITE_NEXT_DROP] = "ip4-drop",
2561  [IP4_REWRITE_NEXT_ICMP_ERROR] = "ip4-icmp-error",
2562  [IP4_REWRITE_NEXT_FRAGMENT] = "ip4-frag",
2563  },
2564 };
2565 
2567  .name = "ip4-rewrite-bcast",
2568  .vector_size = sizeof (u32),
2569 
2570  .format_trace = format_ip4_rewrite_trace,
2571  .sibling_of = "ip4-rewrite",
2572 };
2573 
2575  .name = "ip4-rewrite-mcast",
2576  .vector_size = sizeof (u32),
2577 
2578  .format_trace = format_ip4_rewrite_trace,
2579  .sibling_of = "ip4-rewrite",
2580 };
2581 
2583  .name = "ip4-mcast-midchain",
2584  .vector_size = sizeof (u32),
2585 
2586  .format_trace = format_ip4_rewrite_trace,
2587  .sibling_of = "ip4-rewrite",
2588 };
2589 
2591  .name = "ip4-midchain",
2592  .vector_size = sizeof (u32),
2593  .format_trace = format_ip4_forward_next_trace,
2594  .sibling_of = "ip4-rewrite",
2595 };
2596 /* *INDENT-ON */
2597 
2598 static int
2600 {
2601  ip4_fib_mtrie_t *mtrie0;
2602  ip4_fib_mtrie_leaf_t leaf0;
2603  u32 lbi0;
2604 
2605  mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
2606 
2607  leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, a);
2608  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 2);
2609  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 3);
2610 
2611  lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
2612 
2613  return lbi0 == ip4_fib_table_lookup_lb (ip4_fib_get (fib_index0), a);
2614 }
2615 
2616 static clib_error_t *
2618  unformat_input_t * input, vlib_cli_command_t * cmd)
2619 {
2620  ip4_fib_t *fib;
2621  u32 table_id = 0;
2622  f64 count = 1;
2623  u32 n;
2624  int i;
2625  ip4_address_t ip4_base_address;
2626  u64 errors = 0;
2627 
2628  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2629  {
2630  if (unformat (input, "table %d", &table_id))
2631  {
2632  /* Make sure the entry exists. */
2633  fib = ip4_fib_get (table_id);
2634  if ((fib) && (fib->index != table_id))
2635  return clib_error_return (0, "<fib-index> %d does not exist",
2636  table_id);
2637  }
2638  else if (unformat (input, "count %f", &count))
2639  ;
2640 
2641  else if (unformat (input, "%U",
2642  unformat_ip4_address, &ip4_base_address))
2643  ;
2644  else
2645  return clib_error_return (0, "unknown input `%U'",
2646  format_unformat_error, input);
2647  }
2648 
2649  n = count;
2650 
2651  for (i = 0; i < n; i++)
2652  {
2653  if (!ip4_lookup_validate (&ip4_base_address, table_id))
2654  errors++;
2655 
2656  ip4_base_address.as_u32 =
2657  clib_host_to_net_u32 (1 +
2658  clib_net_to_host_u32 (ip4_base_address.as_u32));
2659  }
2660 
2661  if (errors)
2662  vlib_cli_output (vm, "%llu errors out of %d lookups\n", errors, n);
2663  else
2664  vlib_cli_output (vm, "No errors in %d lookups\n", n);
2665 
2666  return 0;
2667 }
2668 
2669 /*?
2670  * Perform a lookup of an IPv4 Address (or range of addresses) in the
2671  * given FIB table to determine if there is a conflict with the
2672  * adjacency table. The fib-id can be determined by using the
2673  * '<em>show ip fib</em>' command. If fib-id is not entered, default value
2674  * of 0 is used.
2675  *
2676  * @todo This command uses fib-id, other commands use table-id (not
2677  * just a name, they are different indexes). Would like to change this
2678  * to table-id for consistency.
2679  *
2680  * @cliexpar
2681  * Example of how to run the test lookup command:
2682  * @cliexstart{test lookup 172.16.1.1 table 1 count 2}
2683  * No errors in 2 lookups
2684  * @cliexend
2685 ?*/
2686 /* *INDENT-OFF* */
2687 VLIB_CLI_COMMAND (lookup_test_command, static) =
2688 {
2689  .path = "test lookup",
2690  .short_help = "test lookup <ipv4-addr> [table <fib-id>] [count <nn>]",
2691  .function = test_lookup_command_fn,
2692 };
2693 /* *INDENT-ON* */
2694 
2695 #ifndef CLIB_MARCH_VARIANT
2696 int
2697 vnet_set_ip4_flow_hash (u32 table_id, u32 flow_hash_config)
2698 {
2699  u32 fib_index;
2700 
2701  fib_index = fib_table_find (FIB_PROTOCOL_IP4, table_id);
2702 
2703  if (~0 == fib_index)
2704  return VNET_API_ERROR_NO_SUCH_FIB;
2705 
2707  flow_hash_config);
2708 
2709  return 0;
2710 }
2711 #endif
2712 
2713 static clib_error_t *
2715  unformat_input_t * input,
2716  vlib_cli_command_t * cmd)
2717 {
2718  int matched = 0;
2719  u32 table_id = 0;
2720  u32 flow_hash_config = 0;
2721  int rv;
2722 
2723  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2724  {
2725  if (unformat (input, "table %d", &table_id))
2726  matched = 1;
2727 #define _(a,v) \
2728  else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;}
2730 #undef _
2731  else
2732  break;
2733  }
2734 
2735  if (matched == 0)
2736  return clib_error_return (0, "unknown input `%U'",
2737  format_unformat_error, input);
2738 
2739  rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
2740  switch (rv)
2741  {
2742  case 0:
2743  break;
2744 
2745  case VNET_API_ERROR_NO_SUCH_FIB:
2746  return clib_error_return (0, "no such FIB table %d", table_id);
2747 
2748  default:
2749  clib_warning ("BUG: illegal flow hash config 0x%x", flow_hash_config);
2750  break;
2751  }
2752 
2753  return 0;
2754 }
2755 
2756 /*?
2757  * Configure the set of IPv4 fields used by the flow hash.
2758  *
2759  * @cliexpar
2760  * Example of how to set the flow hash on a given table:
2761  * @cliexcmd{set ip flow-hash table 7 dst sport dport proto}
2762  * Example of display the configured flow hash:
2763  * @cliexstart{show ip fib}
2764  * ipv4-VRF:0, fib_index 0, flow hash: src dst sport dport proto
2765  * 0.0.0.0/0
2766  * unicast-ip4-chain
2767  * [@0]: dpo-load-balance: [index:0 buckets:1 uRPF:0 to:[0:0]]
2768  * [0] [@0]: dpo-drop ip6
2769  * 0.0.0.0/32
2770  * unicast-ip4-chain
2771  * [@0]: dpo-load-balance: [index:1 buckets:1 uRPF:1 to:[0:0]]
2772  * [0] [@0]: dpo-drop ip6
2773  * 224.0.0.0/8
2774  * unicast-ip4-chain
2775  * [@0]: dpo-load-balance: [index:3 buckets:1 uRPF:3 to:[0:0]]
2776  * [0] [@0]: dpo-drop ip6
2777  * 6.0.1.2/32
2778  * unicast-ip4-chain
2779  * [@0]: dpo-load-balance: [index:30 buckets:1 uRPF:29 to:[0:0]]
2780  * [0] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
2781  * 7.0.0.1/32
2782  * unicast-ip4-chain
2783  * [@0]: dpo-load-balance: [index:31 buckets:4 uRPF:30 to:[0:0]]
2784  * [0] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
2785  * [1] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
2786  * [2] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
2787  * [3] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
2788  * 240.0.0.0/8
2789  * unicast-ip4-chain
2790  * [@0]: dpo-load-balance: [index:2 buckets:1 uRPF:2 to:[0:0]]
2791  * [0] [@0]: dpo-drop ip6
2792  * 255.255.255.255/32
2793  * unicast-ip4-chain
2794  * [@0]: dpo-load-balance: [index:4 buckets:1 uRPF:4 to:[0:0]]
2795  * [0] [@0]: dpo-drop ip6
2796  * ipv4-VRF:7, fib_index 1, flow hash: dst sport dport proto
2797  * 0.0.0.0/0
2798  * unicast-ip4-chain
2799  * [@0]: dpo-load-balance: [index:12 buckets:1 uRPF:11 to:[0:0]]
2800  * [0] [@0]: dpo-drop ip6
2801  * 0.0.0.0/32
2802  * unicast-ip4-chain
2803  * [@0]: dpo-load-balance: [index:13 buckets:1 uRPF:12 to:[0:0]]
2804  * [0] [@0]: dpo-drop ip6
2805  * 172.16.1.0/24
2806  * unicast-ip4-chain
2807  * [@0]: dpo-load-balance: [index:17 buckets:1 uRPF:16 to:[0:0]]
2808  * [0] [@4]: ipv4-glean: af_packet0
2809  * 172.16.1.1/32
2810  * unicast-ip4-chain
2811  * [@0]: dpo-load-balance: [index:18 buckets:1 uRPF:17 to:[1:84]]
2812  * [0] [@2]: dpo-receive: 172.16.1.1 on af_packet0
2813  * 172.16.1.2/32
2814  * unicast-ip4-chain
2815  * [@0]: dpo-load-balance: [index:21 buckets:1 uRPF:20 to:[0:0]]
2816  * [0] [@5]: ipv4 via 172.16.1.2 af_packet0: IP4: 02:fe:9e:70:7a:2b -> 26:a5:f6:9c:3a:36
2817  * 172.16.2.0/24
2818  * unicast-ip4-chain
2819  * [@0]: dpo-load-balance: [index:19 buckets:1 uRPF:18 to:[0:0]]
2820  * [0] [@4]: ipv4-glean: af_packet1
2821  * 172.16.2.1/32
2822  * unicast-ip4-chain
2823  * [@0]: dpo-load-balance: [index:20 buckets:1 uRPF:19 to:[0:0]]
2824  * [0] [@2]: dpo-receive: 172.16.2.1 on af_packet1
2825  * 224.0.0.0/8
2826  * unicast-ip4-chain
2827  * [@0]: dpo-load-balance: [index:15 buckets:1 uRPF:14 to:[0:0]]
2828  * [0] [@0]: dpo-drop ip6
2829  * 240.0.0.0/8
2830  * unicast-ip4-chain
2831  * [@0]: dpo-load-balance: [index:14 buckets:1 uRPF:13 to:[0:0]]
2832  * [0] [@0]: dpo-drop ip6
2833  * 255.255.255.255/32
2834  * unicast-ip4-chain
2835  * [@0]: dpo-load-balance: [index:16 buckets:1 uRPF:15 to:[0:0]]
2836  * [0] [@0]: dpo-drop ip6
2837  * @cliexend
2838 ?*/
2839 /* *INDENT-OFF* */
2840 VLIB_CLI_COMMAND (set_ip_flow_hash_command, static) =
2841 {
2842  .path = "set ip flow-hash",
2843  .short_help =
2844  "set ip flow-hash table <table-id> [src] [dst] [sport] [dport] [proto] [reverse]",
2845  .function = set_ip_flow_hash_command_fn,
2846 };
2847 /* *INDENT-ON* */
2848 
2849 #ifndef CLIB_MARCH_VARIANT
2850 int
2852  u32 table_index)
2853 {
2854  vnet_main_t *vnm = vnet_get_main ();
2856  ip4_main_t *ipm = &ip4_main;
2857  ip_lookup_main_t *lm = &ipm->lookup_main;
2859  ip4_address_t *if_addr;
2860 
2861  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
2862  return VNET_API_ERROR_NO_MATCHING_INTERFACE;
2863 
2864  if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
2865  return VNET_API_ERROR_NO_SUCH_ENTRY;
2866 
2869 
2870  if_addr = ip4_interface_first_address (ipm, sw_if_index, NULL);
2871 
2872  if (NULL != if_addr)
2873  {
2874  fib_prefix_t pfx = {
2875  .fp_len = 32,
2876  .fp_proto = FIB_PROTOCOL_IP4,
2877  .fp_addr.ip4 = *if_addr,
2878  };
2879  u32 fib_index;
2880 
2882  sw_if_index);
2883 
2884 
2885  if (table_index != (u32) ~ 0)
2886  {
2887  dpo_id_t dpo = DPO_INVALID;
2888 
2889  dpo_set (&dpo,
2890  DPO_CLASSIFY,
2891  DPO_PROTO_IP4,
2892  classify_dpo_create (DPO_PROTO_IP4, table_index));
2893 
2895  &pfx,
2897  FIB_ENTRY_FLAG_NONE, &dpo);
2898  dpo_reset (&dpo);
2899  }
2900  else
2901  {
2902  fib_table_entry_special_remove (fib_index,
2903  &pfx, FIB_SOURCE_CLASSIFY);
2904  }
2905  }
2906 
2907  return 0;
2908 }
2909 #endif
2910 
2911 static clib_error_t *
2913  unformat_input_t * input,
2914  vlib_cli_command_t * cmd)
2915 {
2916  u32 table_index = ~0;
2917  int table_index_set = 0;
2918  u32 sw_if_index = ~0;
2919  int rv;
2920 
2921  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2922  {
2923  if (unformat (input, "table-index %d", &table_index))
2924  table_index_set = 1;
2925  else if (unformat (input, "intfc %U", unformat_vnet_sw_interface,
2926  vnet_get_main (), &sw_if_index))
2927  ;
2928  else
2929  break;
2930  }
2931 
2932  if (table_index_set == 0)
2933  return clib_error_return (0, "classify table-index must be specified");
2934 
2935  if (sw_if_index == ~0)
2936  return clib_error_return (0, "interface / subif must be specified");
2937 
2938  rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
2939 
2940  switch (rv)
2941  {
2942  case 0:
2943  break;
2944 
2945  case VNET_API_ERROR_NO_MATCHING_INTERFACE:
2946  return clib_error_return (0, "No such interface");
2947 
2948  case VNET_API_ERROR_NO_SUCH_ENTRY:
2949  return clib_error_return (0, "No such classifier table");
2950  }
2951  return 0;
2952 }
2953 
2954 /*?
2955  * Assign a classification table to an interface. The classification
2956  * table is created using the '<em>classify table</em>' and '<em>classify session</em>'
2957  * commands. Once the table is create, use this command to filter packets
2958  * on an interface.
2959  *
2960  * @cliexpar
2961  * Example of how to assign a classification table to an interface:
2962  * @cliexcmd{set ip classify intfc GigabitEthernet2/0/0 table-index 1}
2963 ?*/
2964 /* *INDENT-OFF* */
2965 VLIB_CLI_COMMAND (set_ip_classify_command, static) =
2966 {
2967  .path = "set ip classify",
2968  .short_help =
2969  "set ip classify intfc <interface> table-index <classify-idx>",
2970  .function = set_ip_classify_command_fn,
2971 };
2972 /* *INDENT-ON* */
2973 
2974 static clib_error_t *
2976 {
2977  ip4_main_t *im = &ip4_main;
2978  uword heapsize = 0;
2979 
2980  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2981  {
2982  if (unformat (input, "heap-size %U", unformat_memory_size, &heapsize))
2983  ;
2984  else
2985  return clib_error_return (0,
2986  "invalid heap-size parameter `%U'",
2987  format_unformat_error, input);
2988  }
2989 
2990  im->mtrie_heap_size = heapsize;
2991 
2992  return 0;
2993 }
2994 
2996 
2997 /*
2998  * fd.io coding-style-patch-verification: ON
2999  *
3000  * Local Variables:
3001  * eval: (c-set-style "gnu")
3002  * End:
3003  */
vlib_node_registration_t ip4_mcast_midchain_node
(constructor) VLIB_REGISTER_NODE (ip4_mcast_midchain_node)
Definition: ip4_forward.c:2582
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:180
#define vnet_rewrite_one_header(rw0, p0, most_likely_size)
Definition: rewrite.h:277
u16 lb_n_buckets
number of buckets in the load-balance.
Definition: load_balance.h:94
vmrglw vmrglh hi
u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, mfib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: mfib_table.c:467
#define ip4_local_need_csum_check(is_tcp_udp, _b)
Definition: ip4_forward.c:1246
typedef address
Definition: ip_types.api:35
clib_error_t * ip4_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 is_del)
Definition: ip4_forward.c:659
vl_api_address_t src
Definition: vxlan_gbp.api:33
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
Definition: ip4_forward.c:313
struct ip_adjacency_t_::@45::@47 midchain
IP_LOOKUP_NEXT_MIDCHAIN.
static clib_error_t * ip4_config(vlib_main_t *vm, unformat_input_t *input)
Definition: ip4_forward.c:2975
#define CLIB_UNUSED(x)
Definition: clib.h:81
static uword ip4_local_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int head_of_feature_arc)
Definition: ip4_forward.c:1518
format_function_t format_ip_adjacency_packet_data
Definition: format.h:59
int vnet_set_ip4_flow_hash(u32 table_id, u32 flow_hash_config)
Definition: ip4_forward.c:2697
static int fib_urpf_check_size(index_t ui)
Data-Plane function to check the size of an uRPF list, (i.e.
void ip_frag_set_vnet_buffer(vlib_buffer_t *b, u16 mtu, u8 next_index, u8 flags)
Definition: ip_frag.c:236
format_function_t format_vlib_node_name
Definition: node_funcs.h:1167
a
Definition: bitmap.h:538
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:204
static void vlib_buffer_free(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Free buffers Frees the entire buffer chain for each buffer.
Definition: buffer_funcs.h:547
The mutiway-TRIE.
Definition: ip4_mtrie.h:129
ip4_address_t src_address
Definition: ip4_packet.h:169
static void vlib_set_next_frame_buffer(vlib_main_t *vm, vlib_node_runtime_t *node, u32 next_index, u32 buffer_index)
Definition: node_funcs.h:397
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
static clib_error_t * ip4_lookup_init(vlib_main_t *vm)
Definition: ip4_forward.c:903
static clib_error_t * ip4_add_del_interface_address_internal(vlib_main_t *vm, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 is_del)
Definition: ip4_forward.c:553
static ip4_fib_mtrie_leaf_t ip4_fib_mtrie_lookup_step(const ip4_fib_mtrie_t *m, ip4_fib_mtrie_leaf_t current_leaf, const ip4_address_t *dst_address, u32 dst_address_byte_index)
Lookup step.
Definition: ip4_mtrie.h:202
vnet_interface_main_t interface_main
Definition: vnet.h:56
struct ip_adjacency_t_::@45::@46 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
format_function_t format_ip4_header
Definition: format.h:83
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:103
#define PREDICT_TRUE(x)
Definition: clib.h:108
static int ip4_lookup_validate(ip4_address_t *a, u32 fib_index0)
Definition: ip4_forward.c:2599
unsigned long u64
Definition: types.h:89
static void ip4_mtu_check(vlib_buffer_t *b, u16 packet_len, u16 adj_packet_bytes, bool df, u16 *next, u32 *error)
Definition: ip4_forward.c:2119
static uword ip4_not_enabled(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define NULL
Definition: clib.h:57
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip4.h:296
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
IP unicast adjacency.
Definition: adj.h:185
u32 fib_table_get_index_for_sw_if_index(fib_protocol_t proto, u32 sw_if_index)
Get the index of the FIB bound to the interface.
Definition: fib_table.c:956
union ip_adjacency_t_::@45 sub_type
flow_hash_config_t lb_hash_config
the hash config to use when selecting a bucket.
Definition: load_balance.h:134
static const dpo_id_t * load_balance_get_fwd_bucket(const load_balance_t *lb, u16 bucket)
u32 thread_index
Definition: main.h:179
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
static clib_error_t * test_lookup_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_forward.c:2617
unformat_function_t unformat_pg_ip4_header
Definition: format.h:88
ip4_rewrite_next_t
Definition: ip4_forward.c:2100
int i
static u32 format_get_indent(u8 *s)
Definition: format.h:72
ip_lookup_main_t lookup_main
Definition: ip4.h:98
uword ip_csum_t
Definition: ip_packet.h:181
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:184
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:112
static void ip4_local_set_next_and_error(vlib_node_runtime_t *error_node, vlib_buffer_t *b, u16 *next, u8 error, u8 head_of_feature_arc)
Definition: ip4_forward.c:1306
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
u16 flags_and_fragment_offset
Definition: ip4_packet.h:150
unformat_function_t unformat_vnet_sw_interface
static uword ip4_lookup_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int lookup_for_responses_to_locally_received_packets)
Definition: ip4_forward.h:55
#define VLIB_NODE_FN(node)
Definition: node.h:187
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:472
Definition: fib_entry.h:277
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
Definition: buffer_funcs.h:263
VNET_FEATURE_ARC_INIT(ip4_unicast, static)
static u32 ip4_lookup(gid_ip4_table_t *db, u32 vni, ip_prefix_t *key)
u8 mcast_feature_arc_index
Feature arc indices.
Definition: lookup.h:136
format_function_t format_vnet_sw_if_index_name
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1118
unsigned char u8
Definition: types.h:56
ip_lookup_next_t
An adjacency is a representation of an attached L3 peer.
Definition: adj.h:50
enum vnet_sw_interface_flags_t_ vnet_sw_interface_flags_t
double f64
Definition: types.h:142
static void ip4_local_check_l4_csum_x2(vlib_main_t *vm, vlib_buffer_t **b, ip4_header_t **ih, u8 *error)
Definition: ip4_forward.c:1274
static int ip4_is_fragment(const ip4_header_t *i)
Definition: ip4_packet.h:212
static pg_node_t * pg_get_node(uword node_index)
Definition: pg.h:356
static void ip4_local_check_l4_csum(vlib_main_t *vm, vlib_buffer_t *b, ip4_header_t *ih, u8 *error)
Definition: ip4_forward.c:1255
fib_node_index_t fib_table_entry_update_one_path(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, dpo_proto_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Update the entry to have just one path.
Definition: fib_table.c:772
u8 output_feature_arc_index
Definition: lookup.h:138
vlib_rx_or_tx_t
Definition: defs.h:44
Definition: fib_entry.h:283
format_function_t format_ip4_address
Definition: format.h:75
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:380
memset(h->entries, 0, sizeof(h->entries[0])*entries)
static clib_error_t * show_ip_local_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_forward.c:1697
u32 * mfib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:115
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:109
#define static_always_inline
Definition: clib.h:95
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:738
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:443
unformat_function_t unformat_ip4_address
Definition: format.h:70
#define vlib_prefetch_buffer_with_index(vm, bi, type)
Prefetch buffer metadata by buffer index The first 64 bytes of buffer contains most header informatio...
Definition: buffer_funcs.h:337
ethernet_arp_ip4_over_ethernet_address_t ip4_over_ethernet[2]
Definition: arp_packet.h:136
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:163
format_function_t format_ip_adjacency
Definition: format.h:58
ip_local_packet_type_e
Definition: ip4_forward.c:1484
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:407
u32 sw_if_index
Definition: vxlan_gbp.api:39
#define always_inline
Definition: clib.h:94
static uword pow2_mask(uword x)
Definition: clib.h:216
static void ip4_add_interface_routes(u32 sw_if_index, ip4_main_t *im, u32 fib_index, ip_interface_address_t *a)
Definition: ip4_forward.c:376
u16 lb_n_buckets_minus_1
number of buckets in the load-balance - 1.
Definition: load_balance.h:99
ip4_address_t dst_address
Definition: ip4_packet.h:169
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
u32 index
Definition: ip4_fib.h:57
#define ip4_local_csum_is_valid(_b)
Definition: ip4_forward.c:1250
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:187
u32 ip4_fib_mtrie_leaf_t
Definition: ip4_mtrie.h:52
Aggregrate type for a prefix.
Definition: fib_types.h:203
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:182
#define clib_error_return(e, args...)
Definition: error.h:99
vlib_node_registration_t ip4_arp_node
(constructor) VLIB_REGISTER_NODE (ip4_arp_node)
Definition: ip4_forward.c:1937
void adj_unlock(adj_index_t adj_index)
Release a reference counting lock on the adjacency.
Definition: adj.c:252
void ip4_sw_interface_enable_disable(u32 sw_if_index, u32 is_enable)
Definition: ip4_forward.c:524
static void ip4_local_check_src_x2(vlib_buffer_t **b, ip4_header_t **ip, ip4_local_last_check_t *last_check, u8 *error)
Definition: ip4_forward.c:1395
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:240
unsigned int u32
Definition: types.h:88
#define clib_error_create(args...)
Definition: error.h:96
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1064
u16 fp_len
The mask length.
Definition: fib_types.h:207
#define vlib_call_init_function(vm, x)
Definition: init.h:260
IPv4 Forwarding.
#define VLIB_FRAME_SIZE
Definition: node.h:382
#define foreach_notrace_ip4_arp_error
Definition: ip4_forward.c:1965
static clib_error_t * vnet_feature_init(vlib_main_t *vm)
Definition: feature.c:22
static u32 ip4_fib_mtrie_leaf_get_adj_index(ip4_fib_mtrie_leaf_t n)
From the stored slot value extract the LB index value.
Definition: ip4_mtrie.h:192
Definition: fib_entry.h:275
vlib_node_registration_t ip4_rewrite_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_node)
Definition: ip4_forward.c:2552
struct ip_adjacency_t_::@45::@48 glean
IP_LOOKUP_NEXT_GLEAN.
void ip4_directed_broadcast(u32 sw_if_index, u8 enable)
Definition: ip4_forward.c:669
vnet_api_error_t api_errno
Definition: vnet.h:78
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
Definition: fib_entry.h:280
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
vlib_node_registration_t ip4_input_node
Global ip4 input node.
Definition: ip4_input.c:317
void vlib_packet_template_init(vlib_main_t *vm, vlib_packet_template_t *t, void *packet_data, uword n_packet_data_bytes, uword min_n_buffers_each_alloc, char *fmt,...)
Definition: buffer.c:690
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:113
u32 * classify_table_index_by_sw_if_index
First table index to use for this interface, ~0 => none.
Definition: lookup.h:133
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:226
vlib_node_registration_t ip4_local_node
(constructor) VLIB_REGISTER_NODE (ip4_local_node)
Definition: ip4_forward.c:1641
index_t classify_dpo_create(dpo_proto_t proto, u32 classify_table_index)
Definition: classify_dpo.c:43
u8 address_length
Definition: ip_types.api:42
dpo_type_t dpoi_type
the type
Definition: dpo.h:172
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:209
void ip4_register_protocol(u32 protocol, u32 node_index)
Definition: ip4_forward.c:1684
struct _unformat_input_t unformat_input_t
uword mtrie_heap_size
Heapsize for the Mtries.
Definition: ip4.h:154
unsigned short u16
Definition: types.h:57
static uword ip4_arp_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_glean)
Definition: ip4_forward.c:1743
void ip4_forward_next_trace(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, vlib_rx_or_tx_t which_adj_index)
Definition: ip4_forward.c:1038
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:191
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:205
u8 * ip_enabled_by_sw_if_index
Definition: ip4.h:118
static uword ip4_rewrite_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int do_counters, int is_midchain, int is_mcast)
Definition: ip4_forward.c:2190
The FIB DPO provieds;.
Definition: load_balance.h:84
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:900
static u64 throttle_seed(throttle_t *t, u32 thread_index, f64 time_now)
Definition: throttle.h:41
#define PREDICT_FALSE(x)
Definition: clib.h:107
u8 local_next_by_ip_protocol[256]
Table mapping ip protocol to ip[46]-local node next index.
Definition: lookup.h:151
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
vnet_sw_interface_flags_t flags
Definition: interface.h:720
static uword ip4_inacl(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static void vlib_prefetch_combined_counter(const vlib_combined_counter_main_t *cm, u32 thread_index, u32 index)
Pre-fetch a per-thread combined counter for the given object index.
Definition: counter.h:219
vl_api_address_union_t src_address
Definition: ip_types.api:49
void vnet_sw_interface_update_unnumbered(u32 unnumbered_sw_if_index, u32 ip_sw_if_index, u8 enable)
Definition: interface.c:1431
load_balance_main_t load_balance_main
The one instance of load-balance main.
Definition: load_balance.c:56
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:218
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
Definition: node_funcs.h:364
vlib_combined_counter_main_t adjacency_counters
Adjacency packet counters.
Definition: adj.c:25
ip4_fib_mtrie_t mtrie
Mtrie for fast lookups.
Definition: ip4_fib.h:48
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:138
static u8 * format_ip4_lookup_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1002
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags)
Add a &#39;special&#39; entry to the FIB.
Definition: fib_table.c:388
The IPv4 FIB.
Definition: ip4_fib.h:39
#define IP4_LOOKUP_NEXT_NODES
Definition: adj.h:108
static u8 * format_ip4_rewrite_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1018
static uword ip4_policer_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:790
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
#define VLIB_EARLY_CONFIG_FUNCTION(x, n,...)
Definition: init.h:216
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:155
static void vlib_buffer_copy_trace_flag(vlib_main_t *vm, vlib_buffer_t *b, u32 bi_target)
Definition: trace_funcs.h:147
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
u16 n_vectors
Definition: node.h:401
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:79
vlib_main_t * vm
Definition: buffer.c:294
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
Definition: buffer_node.h:332
vl_api_address_t dst
Definition: vxlan_gbp.api:34
static void ip4_local_l4_csum_validate(vlib_main_t *vm, vlib_buffer_t *p, ip4_header_t *ip, u8 is_udp, u8 *error, u8 *good_tcp_udp)
Definition: ip4_forward.c:1219
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:339
vnet_feature_arc_registration_t vnet_feat_arc_ip4_local
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:853
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:431
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:73
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_fib.h:113
void fib_table_set_flow_hash_config(u32 fib_index, fib_protocol_t proto, flow_hash_config_t hash_config)
Set the flow hash configured used by the table.
Definition: fib_table.c:1022
static ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_packet.h:254
#define clib_warning(format, args...)
Definition: error.h:59
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
Definition: node_funcs.h:89
static void ip4_local_check_src(vlib_buffer_t *b, ip4_header_t *ip0, ip4_local_last_check_t *last_check, u8 *error0)
Definition: ip4_forward.c:1336
Definition: fib_entry.h:278
#define clib_memcpy(a, b, c)
Definition: string.h:75
#define IP4_MCAST_ADDR_MASK
This bits of an IPv4 address to mask to construct a multicast MAC address.
Definition: ip4_forward.c:2115
static clib_error_t * set_ip_flow_hash_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_forward.c:2714
unformat_function_t * unformat_edit
Definition: pg.h:313
u8 packet_data[64-1 *sizeof(u32)]
Definition: ip4_forward.c:982
void ip_lookup_init(ip_lookup_main_t *lm, u32 is_ip6)
Definition: lookup.c:203
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:271
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
#define ARRAY_LEN(x)
Definition: clib.h:61
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
Definition: main.c:455
clib_error_t * ip4_probe_neighbor(vlib_main_t *vm, ip4_address_t *dst, u32 sw_if_index, u8 refresh)
Definition: ip4_forward.c:1992
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:185
vlib_combined_counter_main_t lbm_via_counters
Definition: load_balance.h:47
static clib_error_t * set_ip_classify_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_forward.c:2912
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:155
static clib_error_t * ip4_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: ip4_forward.c:862
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:67
#define foreach_flow_hash_bit
Definition: lookup.h:71
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:307
vlib_packet_template_t ip4_arp_request_packet_template
Template used to generate IP4 ARP packets.
Definition: ip4.h:136
signed int i32
Definition: types.h:77
static clib_error_t * ip4_mtrie_module_init(vlib_main_t *vm)
Definition: ip4_mtrie.c:802
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:513
vlib_node_registration_t ip4_load_balance_node
(constructor) VLIB_REGISTER_NODE (ip4_load_balance_node)
Definition: ip4_forward.c:301
#define ASSERT(truth)
index_t lb_urpf
This is the index of the uRPF list for this LB.
Definition: load_balance.h:129
static ip4_fib_mtrie_leaf_t ip4_fib_mtrie_lookup_step_one(const ip4_fib_mtrie_t *m, const ip4_address_t *dst_address)
Lookup step number 1.
Definition: ip4_mtrie.h:224
u32 ip4_tcp_udp_validate_checksum(vlib_main_t *vm, vlib_buffer_t *p0)
Definition: ip4_forward.c:1184
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:200
The default route source.
Definition: fib_entry.h:137
static clib_error_t * fib_module_init(vlib_main_t *vm)
Definition: fib.c:23
IPv4 main type.
Definition: ip4.h:96
Classify.
Definition: fib_entry.h:44
throttle_t arp_throttle
ARP throttling.
Definition: ip4.h:160
vlib_node_registration_t ip4_glean_node
(constructor) VLIB_REGISTER_NODE (ip4_glean_node)
Definition: ip4_forward.c:1951
static void ip4_addr_fib_init(ip4_address_fib_t *addr_fib, const ip4_address_t *address, u32 fib_index)
Definition: ip4_packet.h:67
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:129
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1123
vlib_node_registration_t ip4_midchain_node
(constructor) VLIB_REGISTER_NODE (ip4_midchain_node)
Definition: ip4_forward.c:2590
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:218
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:22
size_t count
Definition: vapi.c:46
vlib_node_registration_t ip4_rewrite_mcast_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_mcast_node)
Definition: ip4_forward.c:2574
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
Route added as a result of interface configuration.
Definition: fib_entry.h:54
vlib_node_registration_t ip4_rewrite_bcast_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_bcast_node)
Definition: ip4_forward.c:2566
#define VNET_FEATURES(...)
Definition: feature.h:386
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
Definition: trace_funcs.h:57
static_always_inline void clib_memset_u16(void *p, u16 val, uword count)
Definition: string.h:233
#define vec_elt(v, i)
Get vector value at index i.
static_always_inline void ip4_ttl_and_checksum_check(vlib_buffer_t *b, ip4_header_t *ip, u16 *next, u32 *error)
Definition: ip4_forward.c:2146
u8 ucast_feature_arc_index
Definition: lookup.h:137
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1126
Definition: defs.h:47
static void vnet_ip_mcast_fixup_header(u32 dst_mcast_mask, u32 dst_mcast_offset, u32 *addr, u8 *packet0)
Definition: rewrite.h:289
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:184
VNET_FEATURE_INIT(ip4_flow_classify, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:200
Definition: fib_entry.h:276
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
Definition: buffer.h:547
u64 uword
Definition: types.h:112
static u8 ip4_local_classify(vlib_buffer_t *b, ip4_header_t *ip, u16 *next)
Determine packet type and next node.
Definition: ip4_forward.c:1498
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:846
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:267
u8 * format_ip4_forward_next_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:988
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:195
adj_index_t adj_glean_add_or_lock(fib_protocol_t proto, vnet_link_t linkt, u32 sw_if_index, const ip46_address_t *nh_addr)
Glean Adjacency.
Definition: adj_glean.c:50
clib_error_t * ip_interface_address_add_del(ip_lookup_main_t *lm, u32 sw_if_index, void *addr_fib, u32 address_length, u32 is_del, u32 *result_if_address_index)
Definition: lookup.c:62
A collection of combined counters.
Definition: counter.h:172
static void ip4_add_subnet_bcast_route(u32 fib_index, fib_prefix_t *pfx, u32 sw_if_index)
Definition: ip4_forward.c:337
static uword ip4_flow_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
unformat_function_t unformat_memory_size
Definition: format.h:295
static clib_error_t * mfib_module_init(vlib_main_t *vm)
Definition: mfib_table.c:641
static void ip4_del_interface_routes(ip4_main_t *im, u32 fib_index, ip4_address_t *address, u32 address_length)
Definition: ip4_forward.c:480
#define vnet_buffer(b)
Definition: buffer.h:344
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static uword ip4_source_and_port_range_check_tx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static vnet_sw_interface_flags_t vnet_sw_interface_get_flags(vnet_main_t *vnm, u32 sw_if_index)
int vnet_set_ip4_classify_intfc(vlib_main_t *vm, u32 sw_if_index, u32 table_index)
Definition: ip4_forward.c:2851
u8 data[0]
Packet data.
Definition: buffer.h:175
static vlib_node_t * vlib_get_node(vlib_main_t *vm, u32 i)
Get vlib node by index.
Definition: node_funcs.h:59
adj_index_t adj_nbr_add_or_lock(fib_protocol_t nh_proto, vnet_link_t link_type, const ip46_address_t *nh_addr, u32 sw_if_index)
Neighbour Adjacency sub-type.
Definition: adj_nbr.c:214
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:231
#define vec_foreach(var, vec)
Vector iterator.
index_t ip4_fib_table_lookup_lb(ip4_fib_t *fib, const ip4_address_t *addr)
Definition: ip4_fib.c:267
#define IP4_HEADER_FLAG_DONT_FRAGMENT
Definition: ip4_packet.h:152
u16 flags
Copy of main node flags.
Definition: node.h:507
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:180
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(ip4_sw_interface_add_del)
static int ip4_header_bytes(const ip4_header_t *i)
Definition: ip4_packet.h:234
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:173
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
Definition: buffer_funcs.h:141
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:310
static uword ip4_outacl(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#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:486
#define vnet_rewrite_two_headers(rw0, rw1, p0, p1, most_likely_size)
Definition: rewrite.h:282
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:116
This adjacency/interface has output features configured.
Definition: rewrite.h:57
static int ip4_src_address_for_packet(ip_lookup_main_t *lm, u32 sw_if_index, ip4_address_t *src)
Definition: ip4.h:198
#define BITS(x)
Definition: clib.h:60
static clib_error_t * arp_notrace_init(vlib_main_t *vm)
Definition: ip4_forward.c:1972
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:725
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:58
static uword ip4_source_and_port_range_check_rx(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:246
Definition: pg.h:310
const ip46_address_t ADJ_BCAST_ADDR
The special broadcast address (to construct a broadcast adjacency.
Definition: adj.c:41
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:237
static int adj_are_counters_enabled(void)
Get the global configuration option for enabling per-adj counters.
Definition: adj.h:389
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
static char * ip4_arp_error_strings[]
Definition: ip4_forward.c:1927
Definition: defs.h:46
int vnet_feature_enable_disable(const char *arc_name, const char *node_name, u32 sw_if_index, int enable_disable, void *feature_config, u32 n_feature_config_bytes)
Definition: feature.c:233
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170
vlib_node_registration_t ip4_local_end_of_arc_node
(constructor) VLIB_REGISTER_NODE (ip4_local_end_of_arc_node)
Definition: ip4_forward.c:1667
u32 fib_masks[33]
Definition: ip4.h:109
static int throttle_check(throttle_t *t, u32 thread_index, u64 hash, u64 seed)
Definition: throttle.h:54
static ip4_address_t * ip4_interface_address_matching_destination(ip4_main_t *im, ip4_address_t *dst, u32 sw_if_index, ip_interface_address_t **result_ia)
Definition: ip4.h:219
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:226
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128