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