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