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