FD.io VPP  v17.04-9-g99c0734
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/ethernet/ethernet.h> /* for ethernet_header_t */
43 #include <vnet/ethernet/arp_packet.h> /* for ethernet_arp_header_t */
44 #include <vnet/ppp/ppp.h>
45 #include <vnet/srp/srp.h> /* for srp_hw_interface_class */
46 #include <vnet/api_errno.h> /* for API error numbers */
47 #include <vnet/fib/fib_table.h> /* for FIB table and entry creation */
48 #include <vnet/fib/fib_entry.h> /* for FIB table and entry creation */
49 #include <vnet/fib/fib_urpf_list.h> /* for FIB uRPF check */
50 #include <vnet/fib/ip4_fib.h>
51 #include <vnet/dpo/load_balance.h>
52 #include <vnet/dpo/classify_dpo.h>
53 #include <vnet/mfib/mfib_table.h> /* for mFIB table and entry creation */
54 
55 /**
56  * @file
57  * @brief IPv4 Forwarding.
58  *
59  * This file contains the source code for IPv4 forwarding.
60  */
61 
62 void
64  vlib_node_runtime_t * node,
65  vlib_frame_t * frame,
66  vlib_rx_or_tx_t which_adj_index);
67 
70  vlib_node_runtime_t * node,
71  vlib_frame_t * frame,
72  int lookup_for_responses_to_locally_received_packets)
73 {
74  ip4_main_t *im = &ip4_main;
76  u32 n_left_from, n_left_to_next, *from, *to_next;
77  ip_lookup_next_t next;
78  u32 cpu_index = os_get_cpu_number ();
79 
80  from = vlib_frame_vector_args (frame);
81  n_left_from = frame->n_vectors;
82  next = node->cached_next_index;
83 
84  while (n_left_from > 0)
85  {
86  vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
87 
88  while (n_left_from >= 8 && n_left_to_next >= 4)
89  {
90  vlib_buffer_t *p0, *p1, *p2, *p3;
91  ip4_header_t *ip0, *ip1, *ip2, *ip3;
92  __attribute__ ((unused)) tcp_header_t *tcp0, *tcp1, *tcp2, *tcp3;
93  ip_lookup_next_t next0, next1, next2, next3;
94  const load_balance_t *lb0, *lb1, *lb2, *lb3;
95  ip4_fib_mtrie_t *mtrie0, *mtrie1, *mtrie2, *mtrie3;
96  ip4_fib_mtrie_leaf_t leaf0, leaf1, leaf2, leaf3;
97  ip4_address_t *dst_addr0, *dst_addr1, *dst_addr2, *dst_addr3;
98  __attribute__ ((unused)) u32 pi0, fib_index0, lb_index0,
99  is_tcp_udp0;
100  __attribute__ ((unused)) u32 pi1, fib_index1, lb_index1,
101  is_tcp_udp1;
102  __attribute__ ((unused)) u32 pi2, fib_index2, lb_index2,
103  is_tcp_udp2;
104  __attribute__ ((unused)) u32 pi3, fib_index3, lb_index3,
105  is_tcp_udp3;
106  flow_hash_config_t flow_hash_config0, flow_hash_config1;
107  flow_hash_config_t flow_hash_config2, flow_hash_config3;
108  u32 hash_c0, hash_c1, hash_c2, hash_c3;
109  const dpo_id_t *dpo0, *dpo1, *dpo2, *dpo3;
110 
111  /* Prefetch next iteration. */
112  {
113  vlib_buffer_t *p4, *p5, *p6, *p7;
114 
115  p4 = vlib_get_buffer (vm, from[4]);
116  p5 = vlib_get_buffer (vm, from[5]);
117  p6 = vlib_get_buffer (vm, from[6]);
118  p7 = vlib_get_buffer (vm, from[7]);
119 
120  vlib_prefetch_buffer_header (p4, LOAD);
121  vlib_prefetch_buffer_header (p5, LOAD);
122  vlib_prefetch_buffer_header (p6, LOAD);
123  vlib_prefetch_buffer_header (p7, LOAD);
124 
125  CLIB_PREFETCH (p4->data, sizeof (ip0[0]), LOAD);
126  CLIB_PREFETCH (p5->data, sizeof (ip0[0]), LOAD);
127  CLIB_PREFETCH (p6->data, sizeof (ip0[0]), LOAD);
128  CLIB_PREFETCH (p7->data, sizeof (ip0[0]), LOAD);
129  }
130 
131  pi0 = to_next[0] = from[0];
132  pi1 = to_next[1] = from[1];
133  pi2 = to_next[2] = from[2];
134  pi3 = to_next[3] = from[3];
135 
136  from += 4;
137  to_next += 4;
138  n_left_to_next -= 4;
139  n_left_from -= 4;
140 
141  p0 = vlib_get_buffer (vm, pi0);
142  p1 = vlib_get_buffer (vm, pi1);
143  p2 = vlib_get_buffer (vm, pi2);
144  p3 = vlib_get_buffer (vm, pi3);
145 
146  ip0 = vlib_buffer_get_current (p0);
147  ip1 = vlib_buffer_get_current (p1);
148  ip2 = vlib_buffer_get_current (p2);
149  ip3 = vlib_buffer_get_current (p3);
150 
151  dst_addr0 = &ip0->dst_address;
152  dst_addr1 = &ip1->dst_address;
153  dst_addr2 = &ip2->dst_address;
154  dst_addr3 = &ip3->dst_address;
155 
156  fib_index0 =
158  vnet_buffer (p0)->sw_if_index[VLIB_RX]);
159  fib_index1 =
161  vnet_buffer (p1)->sw_if_index[VLIB_RX]);
162  fib_index2 =
164  vnet_buffer (p2)->sw_if_index[VLIB_RX]);
165  fib_index3 =
167  vnet_buffer (p3)->sw_if_index[VLIB_RX]);
168  fib_index0 =
169  (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
170  (u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
171  fib_index1 =
172  (vnet_buffer (p1)->sw_if_index[VLIB_TX] ==
173  (u32) ~ 0) ? fib_index1 : vnet_buffer (p1)->sw_if_index[VLIB_TX];
174  fib_index2 =
175  (vnet_buffer (p2)->sw_if_index[VLIB_TX] ==
176  (u32) ~ 0) ? fib_index2 : vnet_buffer (p2)->sw_if_index[VLIB_TX];
177  fib_index3 =
178  (vnet_buffer (p3)->sw_if_index[VLIB_TX] ==
179  (u32) ~ 0) ? fib_index3 : vnet_buffer (p3)->sw_if_index[VLIB_TX];
180 
181 
182  if (!lookup_for_responses_to_locally_received_packets)
183  {
184  mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
185  mtrie1 = &ip4_fib_get (fib_index1)->mtrie;
186  mtrie2 = &ip4_fib_get (fib_index2)->mtrie;
187  mtrie3 = &ip4_fib_get (fib_index3)->mtrie;
188 
189  leaf0 = leaf1 = leaf2 = leaf3 = IP4_FIB_MTRIE_LEAF_ROOT;
190 
191  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 0);
192  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, dst_addr1, 0);
193  leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, dst_addr2, 0);
194  leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, dst_addr3, 0);
195  }
196 
197  tcp0 = (void *) (ip0 + 1);
198  tcp1 = (void *) (ip1 + 1);
199  tcp2 = (void *) (ip2 + 1);
200  tcp3 = (void *) (ip3 + 1);
201 
202  is_tcp_udp0 = (ip0->protocol == IP_PROTOCOL_TCP
203  || ip0->protocol == IP_PROTOCOL_UDP);
204  is_tcp_udp1 = (ip1->protocol == IP_PROTOCOL_TCP
205  || ip1->protocol == IP_PROTOCOL_UDP);
206  is_tcp_udp2 = (ip2->protocol == IP_PROTOCOL_TCP
207  || ip2->protocol == IP_PROTOCOL_UDP);
208  is_tcp_udp3 = (ip1->protocol == IP_PROTOCOL_TCP
209  || ip1->protocol == IP_PROTOCOL_UDP);
210 
211  if (!lookup_for_responses_to_locally_received_packets)
212  {
213  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 1);
214  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, dst_addr1, 1);
215  leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, dst_addr2, 1);
216  leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, dst_addr3, 1);
217  }
218 
219  if (!lookup_for_responses_to_locally_received_packets)
220  {
221  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 2);
222  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, dst_addr1, 2);
223  leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, dst_addr2, 2);
224  leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, dst_addr3, 2);
225  }
226 
227  if (!lookup_for_responses_to_locally_received_packets)
228  {
229  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 3);
230  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, dst_addr1, 3);
231  leaf2 = ip4_fib_mtrie_lookup_step (mtrie2, leaf2, dst_addr2, 3);
232  leaf3 = ip4_fib_mtrie_lookup_step (mtrie3, leaf3, dst_addr3, 3);
233  }
234 
235  if (lookup_for_responses_to_locally_received_packets)
236  {
237  lb_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_RX];
238  lb_index1 = vnet_buffer (p1)->ip.adj_index[VLIB_RX];
239  lb_index2 = vnet_buffer (p2)->ip.adj_index[VLIB_RX];
240  lb_index3 = vnet_buffer (p3)->ip.adj_index[VLIB_RX];
241  }
242  else
243  {
244  /* Handle default route. */
245  leaf0 =
246  (leaf0 ==
247  IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
248  leaf1 =
249  (leaf1 ==
250  IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie1->default_leaf : leaf1);
251  leaf2 =
252  (leaf2 ==
253  IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie2->default_leaf : leaf2);
254  leaf3 =
255  (leaf3 ==
256  IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie3->default_leaf : leaf3);
257  lb_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
258  lb_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
259  lb_index2 = ip4_fib_mtrie_leaf_get_adj_index (leaf2);
260  lb_index3 = ip4_fib_mtrie_leaf_get_adj_index (leaf3);
261  }
262 
263  lb0 = load_balance_get (lb_index0);
264  lb1 = load_balance_get (lb_index1);
265  lb2 = load_balance_get (lb_index2);
266  lb3 = load_balance_get (lb_index3);
267 
268  /* Use flow hash to compute multipath adjacency. */
269  hash_c0 = vnet_buffer (p0)->ip.flow_hash = 0;
270  hash_c1 = vnet_buffer (p1)->ip.flow_hash = 0;
271  hash_c2 = vnet_buffer (p2)->ip.flow_hash = 0;
272  hash_c3 = vnet_buffer (p3)->ip.flow_hash = 0;
273  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
274  {
275  flow_hash_config0 = lb0->lb_hash_config;
276  hash_c0 = vnet_buffer (p0)->ip.flow_hash =
277  ip4_compute_flow_hash (ip0, flow_hash_config0);
278  }
279  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
280  {
281  flow_hash_config1 = lb1->lb_hash_config;
282  hash_c1 = vnet_buffer (p1)->ip.flow_hash =
283  ip4_compute_flow_hash (ip1, flow_hash_config1);
284  }
285  if (PREDICT_FALSE (lb2->lb_n_buckets > 1))
286  {
287  flow_hash_config2 = lb2->lb_hash_config;
288  hash_c2 = vnet_buffer (p2)->ip.flow_hash =
289  ip4_compute_flow_hash (ip2, flow_hash_config2);
290  }
291  if (PREDICT_FALSE (lb3->lb_n_buckets > 1))
292  {
293  flow_hash_config3 = lb3->lb_hash_config;
294  hash_c3 = vnet_buffer (p3)->ip.flow_hash =
295  ip4_compute_flow_hash (ip3, flow_hash_config3);
296  }
297 
298  ASSERT (lb0->lb_n_buckets > 0);
299  ASSERT (is_pow2 (lb0->lb_n_buckets));
300  ASSERT (lb1->lb_n_buckets > 0);
301  ASSERT (is_pow2 (lb1->lb_n_buckets));
302  ASSERT (lb2->lb_n_buckets > 0);
303  ASSERT (is_pow2 (lb2->lb_n_buckets));
304  ASSERT (lb3->lb_n_buckets > 0);
305  ASSERT (is_pow2 (lb3->lb_n_buckets));
306 
307  dpo0 = load_balance_get_bucket_i (lb0,
308  (hash_c0 &
309  (lb0->lb_n_buckets_minus_1)));
310  dpo1 = load_balance_get_bucket_i (lb1,
311  (hash_c1 &
312  (lb1->lb_n_buckets_minus_1)));
313  dpo2 = load_balance_get_bucket_i (lb2,
314  (hash_c2 &
315  (lb2->lb_n_buckets_minus_1)));
316  dpo3 = load_balance_get_bucket_i (lb3,
317  (hash_c3 &
318  (lb3->lb_n_buckets_minus_1)));
319 
320  next0 = dpo0->dpoi_next_node;
321  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
322  next1 = dpo1->dpoi_next_node;
323  vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
324  next2 = dpo2->dpoi_next_node;
325  vnet_buffer (p2)->ip.adj_index[VLIB_TX] = dpo2->dpoi_index;
326  next3 = dpo3->dpoi_next_node;
327  vnet_buffer (p3)->ip.adj_index[VLIB_TX] = dpo3->dpoi_index;
328 
330  (cm, cpu_index, lb_index0, 1,
332  + sizeof (ethernet_header_t));
334  (cm, cpu_index, lb_index1, 1,
336  + sizeof (ethernet_header_t));
338  (cm, cpu_index, lb_index2, 1,
340  + sizeof (ethernet_header_t));
342  (cm, cpu_index, lb_index3, 1,
344  + sizeof (ethernet_header_t));
345 
346  vlib_validate_buffer_enqueue_x4 (vm, node, next,
347  to_next, n_left_to_next,
348  pi0, pi1, pi2, pi3,
349  next0, next1, next2, next3);
350  }
351 
352  while (n_left_from > 0 && n_left_to_next > 0)
353  {
354  vlib_buffer_t *p0;
355  ip4_header_t *ip0;
356  __attribute__ ((unused)) tcp_header_t *tcp0;
357  ip_lookup_next_t next0;
358  const load_balance_t *lb0;
359  ip4_fib_mtrie_t *mtrie0;
360  ip4_fib_mtrie_leaf_t leaf0;
361  ip4_address_t *dst_addr0;
362  __attribute__ ((unused)) u32 pi0, fib_index0, is_tcp_udp0, lbi0;
363  flow_hash_config_t flow_hash_config0;
364  const dpo_id_t *dpo0;
365  u32 hash_c0;
366 
367  pi0 = from[0];
368  to_next[0] = pi0;
369 
370  p0 = vlib_get_buffer (vm, pi0);
371 
372  ip0 = vlib_buffer_get_current (p0);
373 
374  dst_addr0 = &ip0->dst_address;
375 
376  fib_index0 =
378  vnet_buffer (p0)->sw_if_index[VLIB_RX]);
379  fib_index0 =
380  (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
381  (u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
382 
383  if (!lookup_for_responses_to_locally_received_packets)
384  {
385  mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
386 
387  leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
388 
389  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 0);
390  }
391 
392  tcp0 = (void *) (ip0 + 1);
393 
394  is_tcp_udp0 = (ip0->protocol == IP_PROTOCOL_TCP
395  || ip0->protocol == IP_PROTOCOL_UDP);
396 
397  if (!lookup_for_responses_to_locally_received_packets)
398  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 1);
399 
400  if (!lookup_for_responses_to_locally_received_packets)
401  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 2);
402 
403  if (!lookup_for_responses_to_locally_received_packets)
404  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 3);
405 
406  if (lookup_for_responses_to_locally_received_packets)
407  lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_RX];
408  else
409  {
410  /* Handle default route. */
411  leaf0 =
412  (leaf0 ==
413  IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
414  lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
415  }
416 
417  lb0 = load_balance_get (lbi0);
418 
419  /* Use flow hash to compute multipath adjacency. */
420  hash_c0 = vnet_buffer (p0)->ip.flow_hash = 0;
421  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
422  {
423  flow_hash_config0 = lb0->lb_hash_config;
424 
425  hash_c0 = vnet_buffer (p0)->ip.flow_hash =
426  ip4_compute_flow_hash (ip0, flow_hash_config0);
427  }
428 
429  ASSERT (lb0->lb_n_buckets > 0);
430  ASSERT (is_pow2 (lb0->lb_n_buckets));
431 
432  dpo0 = load_balance_get_bucket_i (lb0,
433  (hash_c0 &
434  (lb0->lb_n_buckets_minus_1)));
435 
436  next0 = dpo0->dpoi_next_node;
437  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
438 
440  (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0));
441 
442  from += 1;
443  to_next += 1;
444  n_left_to_next -= 1;
445  n_left_from -= 1;
446 
447  if (PREDICT_FALSE (next0 != next))
448  {
449  n_left_to_next += 1;
450  vlib_put_next_frame (vm, node, next, n_left_to_next);
451  next = next0;
452  vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
453  to_next[0] = pi0;
454  to_next += 1;
455  n_left_to_next -= 1;
456  }
457  }
458 
459  vlib_put_next_frame (vm, node, next, n_left_to_next);
460  }
461 
462  if (node->flags & VLIB_NODE_FLAG_TRACE)
463  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
464 
465  return frame->n_vectors;
466 }
467 
468 /** @brief IPv4 lookup node.
469  @node ip4-lookup
470 
471  This is the main IPv4 lookup dispatch node.
472 
473  @param vm vlib_main_t corresponding to the current thread
474  @param node vlib_node_runtime_t
475  @param frame vlib_frame_t whose contents should be dispatched
476 
477  @par Graph mechanics: buffer metadata, next index usage
478 
479  @em Uses:
480  - <code>vnet_buffer(b)->sw_if_index[VLIB_RX]</code>
481  - Indicates the @c sw_if_index value of the interface that the
482  packet was received on.
483  - <code>vnet_buffer(b)->sw_if_index[VLIB_TX]</code>
484  - When the value is @c ~0 then the node performs a longest prefix
485  match (LPM) for the packet destination address in the FIB attached
486  to the receive interface.
487  - Otherwise perform LPM for the packet destination address in the
488  indicated FIB. In this case <code>[VLIB_TX]</code> is a FIB index
489  value (0, 1, ...) and not a VRF id.
490 
491  @em Sets:
492  - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
493  - The lookup result adjacency index.
494 
495  <em>Next Index:</em>
496  - Dispatches the packet to the node index found in
497  ip_adjacency_t @c adj->lookup_next_index
498  (where @c adj is the lookup result adjacency).
499 */
500 static uword
502  vlib_node_runtime_t * node, vlib_frame_t * frame)
503 {
504  return ip4_lookup_inline (vm, node, frame,
505  /* lookup_for_responses_to_locally_received_packets */
506  0);
507 
508 }
509 
510 static u8 *format_ip4_lookup_trace (u8 * s, va_list * args);
511 
513 {
514 .function = ip4_lookup,.name = "ip4-lookup",.vector_size =
515  sizeof (u32),.format_trace = format_ip4_lookup_trace,.n_next_nodes =
516  IP_LOOKUP_N_NEXT,.next_nodes = IP4_LOOKUP_NEXT_NODES,};
517 
519 
522  vlib_node_runtime_t * node, vlib_frame_t * frame)
523 {
525  u32 n_left_from, n_left_to_next, *from, *to_next;
526  ip_lookup_next_t next;
527  u32 cpu_index = os_get_cpu_number ();
528 
529  from = vlib_frame_vector_args (frame);
530  n_left_from = frame->n_vectors;
531  next = node->cached_next_index;
532 
533  if (node->flags & VLIB_NODE_FLAG_TRACE)
534  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
535 
536  while (n_left_from > 0)
537  {
538  vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
539 
540 
541  while (n_left_from >= 4 && n_left_to_next >= 2)
542  {
543  ip_lookup_next_t next0, next1;
544  const load_balance_t *lb0, *lb1;
545  vlib_buffer_t *p0, *p1;
546  u32 pi0, lbi0, hc0, pi1, lbi1, hc1;
547  const ip4_header_t *ip0, *ip1;
548  const dpo_id_t *dpo0, *dpo1;
549 
550  /* Prefetch next iteration. */
551  {
552  vlib_buffer_t *p2, *p3;
553 
554  p2 = vlib_get_buffer (vm, from[2]);
555  p3 = vlib_get_buffer (vm, from[3]);
556 
557  vlib_prefetch_buffer_header (p2, STORE);
558  vlib_prefetch_buffer_header (p3, STORE);
559 
560  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE);
561  CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE);
562  }
563 
564  pi0 = to_next[0] = from[0];
565  pi1 = to_next[1] = from[1];
566 
567  from += 2;
568  n_left_from -= 2;
569  to_next += 2;
570  n_left_to_next -= 2;
571 
572  p0 = vlib_get_buffer (vm, pi0);
573  p1 = vlib_get_buffer (vm, pi1);
574 
575  ip0 = vlib_buffer_get_current (p0);
576  ip1 = vlib_buffer_get_current (p1);
577  lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
578  lbi1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX];
579 
580  lb0 = load_balance_get (lbi0);
581  lb1 = load_balance_get (lbi1);
582 
583  /*
584  * this node is for via FIBs we can re-use the hash value from the
585  * to node if present.
586  * We don't want to use the same hash value at each level in the recursion
587  * graph as that would lead to polarisation
588  */
589  hc0 = hc1 = 0;
590 
591  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
592  {
593  if (PREDICT_TRUE (vnet_buffer (p0)->ip.flow_hash))
594  {
595  hc0 = vnet_buffer (p0)->ip.flow_hash =
596  vnet_buffer (p0)->ip.flow_hash >> 1;
597  }
598  else
599  {
600  hc0 = vnet_buffer (p0)->ip.flow_hash =
602  }
603  }
604  if (PREDICT_FALSE (lb1->lb_n_buckets > 1))
605  {
606  if (PREDICT_TRUE (vnet_buffer (p1)->ip.flow_hash))
607  {
608  hc1 = vnet_buffer (p1)->ip.flow_hash =
609  vnet_buffer (p1)->ip.flow_hash >> 1;
610  }
611  else
612  {
613  hc1 = vnet_buffer (p1)->ip.flow_hash =
615  }
616  }
617 
618  dpo0 =
620  hc0 & (lb0->lb_n_buckets_minus_1));
621  dpo1 =
623  hc1 & (lb1->lb_n_buckets_minus_1));
624 
625  next0 = dpo0->dpoi_next_node;
626  next1 = dpo1->dpoi_next_node;
627 
628  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
629  vnet_buffer (p1)->ip.adj_index[VLIB_TX] = dpo1->dpoi_index;
630 
632  (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0));
634  (cm, cpu_index, lbi1, 1, vlib_buffer_length_in_chain (vm, p1));
635 
636  vlib_validate_buffer_enqueue_x2 (vm, node, next,
637  to_next, n_left_to_next,
638  pi0, pi1, next0, next1);
639  }
640 
641  while (n_left_from > 0 && n_left_to_next > 0)
642  {
643  ip_lookup_next_t next0;
644  const load_balance_t *lb0;
645  vlib_buffer_t *p0;
646  u32 pi0, lbi0, hc0;
647  const ip4_header_t *ip0;
648  const dpo_id_t *dpo0;
649 
650  pi0 = from[0];
651  to_next[0] = pi0;
652  from += 1;
653  to_next += 1;
654  n_left_to_next -= 1;
655  n_left_from -= 1;
656 
657  p0 = vlib_get_buffer (vm, pi0);
658 
659  ip0 = vlib_buffer_get_current (p0);
660  lbi0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
661 
662  lb0 = load_balance_get (lbi0);
663 
664  hc0 = 0;
665  if (PREDICT_FALSE (lb0->lb_n_buckets > 1))
666  {
667  if (PREDICT_TRUE (vnet_buffer (p0)->ip.flow_hash))
668  {
669  hc0 = vnet_buffer (p0)->ip.flow_hash =
670  vnet_buffer (p0)->ip.flow_hash >> 1;
671  }
672  else
673  {
674  hc0 = vnet_buffer (p0)->ip.flow_hash =
676  }
677  }
678 
679  dpo0 =
681  hc0 & (lb0->lb_n_buckets_minus_1));
682 
683  next0 = dpo0->dpoi_next_node;
684  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index;
685 
687  (cm, cpu_index, lbi0, 1, vlib_buffer_length_in_chain (vm, p0));
688 
689  vlib_validate_buffer_enqueue_x1 (vm, node, next,
690  to_next, n_left_to_next,
691  pi0, next0);
692  }
693 
694  vlib_put_next_frame (vm, node, next, n_left_to_next);
695  }
696 
697  return frame->n_vectors;
698 }
699 
701 {
702 .function = ip4_load_balance,.name = "ip4-load-balance",.vector_size =
703  sizeof (u32),.sibling_of = "ip4-lookup",.format_trace =
705 
707 
708 /* get first interface address */
711  ip_interface_address_t ** result_ia)
712 {
713  ip_lookup_main_t *lm = &im->lookup_main;
714  ip_interface_address_t *ia = 0;
715  ip4_address_t *result = 0;
716 
717  /* *INDENT-OFF* */
719  (lm, ia, sw_if_index,
720  1 /* honor unnumbered */ ,
721  ({
722  ip4_address_t * a =
724  result = a;
725  break;
726  }));
727  /* *INDENT-OFF* */
728  if (result_ia)
729  *result_ia = result ? ia : 0;
730  return result;
731 }
732 
733 static void
735  ip4_main_t * im, u32 fib_index,
737 {
738  ip_lookup_main_t *lm = &im->lookup_main;
740  fib_prefix_t pfx = {
741  .fp_len = a->address_length,
742  .fp_proto = FIB_PROTOCOL_IP4,
743  .fp_addr.ip4 = *address,
744  };
745 
746  a->neighbor_probe_adj_index = ~0;
747 
748  if (pfx.fp_len < 32)
749  {
750  fib_node_index_t fei;
751 
752  fei = fib_table_entry_update_one_path (fib_index, &pfx,
757  /* No next-hop address */
758  NULL,
759  sw_if_index,
760  // invalid FIB index
761  ~0,
762  1,
763  // no out-label stack
764  NULL,
767  }
768 
769  pfx.fp_len = 32;
770 
771  if (sw_if_index < vec_len (lm->classify_table_index_by_sw_if_index))
772  {
773  u32 classify_table_index =
774  lm->classify_table_index_by_sw_if_index[sw_if_index];
775  if (classify_table_index != (u32) ~ 0)
776  {
777  dpo_id_t dpo = DPO_INVALID;
778 
779  dpo_set (&dpo,
780  DPO_CLASSIFY,
782  classify_dpo_create (DPO_PROTO_IP4, classify_table_index));
783 
785  &pfx,
787  FIB_ENTRY_FLAG_NONE, &dpo);
788  dpo_reset (&dpo);
789  }
790  }
791 
792  fib_table_entry_update_one_path (fib_index, &pfx,
797  &pfx.fp_addr,
798  sw_if_index,
799  // invalid FIB index
800  ~0,
801  1, NULL,
803 }
804 
805 static void
807  u32 fib_index,
808  ip4_address_t * address, u32 address_length)
809 {
810  fib_prefix_t pfx = {
811  .fp_len = address_length,
812  .fp_proto = FIB_PROTOCOL_IP4,
813  .fp_addr.ip4 = *address,
814  };
815 
816  if (pfx.fp_len < 32)
817  {
818  fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE);
819  }
820 
821  pfx.fp_len = 32;
822  fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE);
823 }
824 
825 void
826 ip4_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable)
827 {
828  ip4_main_t *im = &ip4_main;
829 
831 
832  /*
833  * enable/disable only on the 1<->0 transition
834  */
835  if (is_enable)
836  {
837  if (1 != ++im->ip_enabled_by_sw_if_index[sw_if_index])
838  return;
839  }
840  else
841  {
842  ASSERT (im->ip_enabled_by_sw_if_index[sw_if_index] > 0);
843  if (0 != --im->ip_enabled_by_sw_if_index[sw_if_index])
844  return;
845  }
846  vnet_feature_enable_disable ("ip4-unicast", "ip4-drop", sw_if_index,
847  !is_enable, 0, 0);
848 
849 
850  vnet_feature_enable_disable ("ip4-multicast", "ip4-drop",
851  sw_if_index, !is_enable, 0, 0);
852 }
853 
854 static clib_error_t *
856  u32 sw_if_index,
857  ip4_address_t * address,
858  u32 address_length, u32 is_del)
859 {
860  vnet_main_t *vnm = vnet_get_main ();
861  ip4_main_t *im = &ip4_main;
862  ip_lookup_main_t *lm = &im->lookup_main;
863  clib_error_t *error = 0;
864  u32 if_address_index, elts_before;
865  ip4_address_fib_t ip4_af, *addr_fib = 0;
866 
867  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
868  ip4_addr_fib_init (&ip4_af, address,
869  vec_elt (im->fib_index_by_sw_if_index, sw_if_index));
870  vec_add1 (addr_fib, ip4_af);
871 
872  /* FIXME-LATER
873  * there is no support for adj-fib handling in the presence of overlapping
874  * subnets on interfaces. Easy fix - disallow overlapping subnets, like
875  * most routers do.
876  */
877  /* *INDENT-OFF* */
878  if (!is_del)
879  {
880  /* When adding an address check that it does not conflict
881  with an existing address. */
884  (&im->lookup_main, ia, sw_if_index,
885  0 /* honor unnumbered */ ,
886  ({
887  ip4_address_t * x =
888  ip_interface_address_get_address
889  (&im->lookup_main, ia);
890  if (ip4_destination_matches_route
891  (im, address, x, ia->address_length) ||
892  ip4_destination_matches_route (im,
893  x,
894  address,
895  address_length))
896  return
897  clib_error_create
898  ("failed to add %U which conflicts with %U for interface %U",
899  format_ip4_address_and_length, address,
900  address_length,
901  format_ip4_address_and_length, x,
902  ia->address_length,
903  format_vnet_sw_if_index_name, vnm,
904  sw_if_index);
905  }));
906  }
907  /* *INDENT-ON* */
908 
909  elts_before = pool_elts (lm->if_address_pool);
910 
912  (lm, sw_if_index, addr_fib, address_length, is_del, &if_address_index);
913  if (error)
914  goto done;
915 
916  ip4_sw_interface_enable_disable (sw_if_index, !is_del);
917 
918  if (is_del)
919  ip4_del_interface_routes (im, ip4_af.fib_index, address, address_length);
920  else
921  ip4_add_interface_routes (sw_if_index,
922  im, ip4_af.fib_index,
924  (lm->if_address_pool, if_address_index));
925 
926  /* If pool did not grow/shrink: add duplicate address. */
927  if (elts_before != pool_elts (lm->if_address_pool))
928  {
931  cb->function (im, cb->function_opaque, sw_if_index,
932  address, address_length, if_address_index, is_del);
933  }
934 
935 done:
936  vec_free (addr_fib);
937  return error;
938 }
939 
940 clib_error_t *
942  u32 sw_if_index,
943  ip4_address_t * address,
944  u32 address_length, u32 is_del)
945 {
947  (vm, sw_if_index, address, address_length, is_del);
948 }
949 
950 /* Built-in ip4 unicast rx feature path definition */
951 /* *INDENT-OFF* */
952 VNET_FEATURE_ARC_INIT (ip4_unicast, static) =
953 {
954  .arc_name = "ip4-unicast",
955  .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
956  .arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index,
957 };
958 
960 {
961  .arc_name = "ip4-unicast",
962  .node_name = "ip4-flow-classify",
963  .runs_before = VNET_FEATURES ("ip4-inacl"),
964 };
965 
966 VNET_FEATURE_INIT (ip4_inacl, static) =
967 {
968  .arc_name = "ip4-unicast",
969  .node_name = "ip4-inacl",
970  .runs_before = VNET_FEATURES ("ip4-source-check-via-rx"),
971 };
972 
973 VNET_FEATURE_INIT (ip4_source_check_1, static) =
974 {
975  .arc_name = "ip4-unicast",
976  .node_name = "ip4-source-check-via-rx",
977  .runs_before = VNET_FEATURES ("ip4-source-check-via-any"),
978 };
979 
980 VNET_FEATURE_INIT (ip4_source_check_2, static) =
981 {
982  .arc_name = "ip4-unicast",
983  .node_name = "ip4-source-check-via-any",
984  .runs_before = VNET_FEATURES ("ip4-policer-classify"),
985 };
986 
988 {
989  .arc_name = "ip4-unicast",
990  .node_name = "ip4-source-and-port-range-check-rx",
991  .runs_before = VNET_FEATURES ("ip4-policer-classify"),
992 };
993 
995 {
996  .arc_name = "ip4-unicast",
997  .node_name = "ip4-policer-classify",
998  .runs_before = VNET_FEATURES ("ipsec-input-ip4"),
999 };
1000 
1001 VNET_FEATURE_INIT (ip4_ipsec, static) =
1002 {
1003  .arc_name = "ip4-unicast",
1004  .node_name = "ipsec-input-ip4",
1005  .runs_before = VNET_FEATURES ("vpath-input-ip4"),
1006 };
1007 
1008 VNET_FEATURE_INIT (ip4_vpath, static) =
1009 {
1010  .arc_name = "ip4-unicast",
1011  .node_name = "vpath-input-ip4",
1012  .runs_before = VNET_FEATURES ("ip4-vxlan-bypass"),
1013 };
1014 
1016 {
1017  .arc_name = "ip4-unicast",
1018  .node_name = "ip4-vxlan-bypass",
1019  .runs_before = VNET_FEATURES ("ip4-lookup"),
1020 };
1021 
1022 VNET_FEATURE_INIT (ip4_drop, static) =
1023 {
1024  .arc_name = "ip4-unicast",
1025  .node_name = "ip4-drop",
1026  .runs_before = VNET_FEATURES ("ip4-lookup"),
1027 };
1028 
1029 VNET_FEATURE_INIT (ip4_lookup, static) =
1030 {
1031  .arc_name = "ip4-unicast",
1032  .node_name = "ip4-lookup",
1033  .runs_before = 0, /* not before any other features */
1034 };
1035 
1036 /* Built-in ip4 multicast rx feature path definition */
1037 VNET_FEATURE_ARC_INIT (ip4_multicast, static) =
1038 {
1039  .arc_name = "ip4-multicast",
1040  .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
1041  .arc_index_ptr = &ip4_main.lookup_main.mcast_feature_arc_index,
1042 };
1043 
1044 VNET_FEATURE_INIT (ip4_vpath_mc, static) =
1045 {
1046  .arc_name = "ip4-multicast",
1047  .node_name = "vpath-input-ip4",
1048  .runs_before = VNET_FEATURES ("ip4-mfib-forward-lookup"),
1049 };
1050 
1051 VNET_FEATURE_INIT (ip4_mc_drop, static) =
1052 {
1053  .arc_name = "ip4-multicast",
1054  .node_name = "ip4-drop",
1055  .runs_before = VNET_FEATURES ("ip4-mfib-forward-lookup"),
1056 };
1057 
1058 VNET_FEATURE_INIT (ip4_lookup_mc, static) =
1059 {
1060  .arc_name = "ip4-multicast",
1061  .node_name = "ip4-mfib-forward-lookup",
1062  .runs_before = 0, /* last feature */
1063 };
1064 
1065 /* Source and port-range check ip4 tx feature path definition */
1066 VNET_FEATURE_ARC_INIT (ip4_output, static) =
1067 {
1068  .arc_name = "ip4-output",
1069  .start_nodes = VNET_FEATURES ("ip4-rewrite", "ip4-midchain"),
1070  .arc_index_ptr = &ip4_main.lookup_main.output_feature_arc_index,
1071 };
1072 
1074 {
1075  .arc_name = "ip4-output",
1076  .node_name = "ip4-source-and-port-range-check-tx",
1077  .runs_before = VNET_FEATURES ("ipsec-output-ip4"),
1078 };
1079 
1080 VNET_FEATURE_INIT (ip4_ipsec_output, static) =
1081 {
1082  .arc_name = "ip4-output",
1083  .node_name = "ipsec-output-ip4",
1084  .runs_before = VNET_FEATURES ("interface-output"),
1085 };
1086 
1087 /* Built-in ip4 tx feature path definition */
1088 VNET_FEATURE_INIT (ip4_interface_output, static) =
1089 {
1090  .arc_name = "ip4-output",
1091  .node_name = "interface-output",
1092  .runs_before = 0, /* not before any other features */
1093 };
1094 /* *INDENT-ON* */
1095 
1096 static clib_error_t *
1097 ip4_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
1098 {
1099  ip4_main_t *im = &ip4_main;
1100 
1101  /* Fill in lookup tables with default table (0). */
1102  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1103  vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
1104 
1105  vnet_feature_enable_disable ("ip4-unicast", "ip4-drop", sw_if_index,
1106  is_add, 0, 0);
1107 
1108  vnet_feature_enable_disable ("ip4-multicast", "ip4-drop", sw_if_index,
1109  is_add, 0, 0);
1110 
1111  return /* no error */ 0;
1112 }
1113 
1115 
1116 /* Global IP4 main. */
1118 
1119 clib_error_t *
1121 {
1122  ip4_main_t *im = &ip4_main;
1123  clib_error_t *error;
1124  uword i;
1125 
1126  if ((error = vlib_call_init_function (vm, vnet_feature_init)))
1127  return error;
1128 
1129  for (i = 0; i < ARRAY_LEN (im->fib_masks); i++)
1130  {
1131  u32 m;
1132 
1133  if (i < 32)
1134  m = pow2_mask (i) << (32 - i);
1135  else
1136  m = ~0;
1137  im->fib_masks[i] = clib_host_to_net_u32 (m);
1138  }
1139 
1140  ip_lookup_init (&im->lookup_main, /* is_ip6 */ 0);
1141 
1142  /* Create FIB with index 0 and table id of 0. */
1145 
1146  {
1147  pg_node_t *pn;
1148  pn = pg_get_node (ip4_lookup_node.index);
1150  }
1151 
1152  {
1154 
1155  memset (&h, 0, sizeof (h));
1156 
1157  /* Set target ethernet address to all zeros. */
1158  memset (h.ip4_over_ethernet[1].ethernet, 0,
1159  sizeof (h.ip4_over_ethernet[1].ethernet));
1160 
1161 #define _16(f,v) h.f = clib_host_to_net_u16 (v);
1162 #define _8(f,v) h.f = v;
1163  _16 (l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1164  _16 (l3_type, ETHERNET_TYPE_IP4);
1165  _8 (n_l2_address_bytes, 6);
1166  _8 (n_l3_address_bytes, 4);
1167  _16 (opcode, ETHERNET_ARP_OPCODE_request);
1168 #undef _16
1169 #undef _8
1170 
1172  /* data */ &h,
1173  sizeof (h),
1174  /* alloc chunk size */ 8,
1175  "ip4 arp");
1176  }
1177 
1178  return error;
1179 }
1180 
1182 
1183 typedef struct
1184 {
1185  /* Adjacency taken. */
1189 
1190  /* Packet data, possibly *after* rewrite. */
1191  u8 packet_data[64 - 1 * sizeof (u32)];
1192 }
1194 
1195 u8 *
1196 format_ip4_forward_next_trace (u8 * s, va_list * args)
1197 {
1198  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1199  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1200  ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
1201  uword indent = format_get_indent (s);
1202  s = format (s, "%U%U",
1203  format_white_space, indent,
1204  format_ip4_header, t->packet_data, sizeof (t->packet_data));
1205  return s;
1206 }
1207 
1208 static u8 *
1209 format_ip4_lookup_trace (u8 * s, va_list * args)
1210 {
1211  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1212  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1213  ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
1214  uword indent = format_get_indent (s);
1215 
1216  s = format (s, "fib %d dpo-idx %d flow hash: 0x%08x",
1217  t->fib_index, t->dpo_index, t->flow_hash);
1218  s = format (s, "\n%U%U",
1219  format_white_space, indent,
1220  format_ip4_header, t->packet_data, sizeof (t->packet_data));
1221  return s;
1222 }
1223 
1224 static u8 *
1225 format_ip4_rewrite_trace (u8 * s, va_list * args)
1226 {
1227  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1228  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1229  ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
1230  uword indent = format_get_indent (s);
1231 
1232  s = format (s, "tx_sw_if_index %d dpo-idx %d : %U flow hash: 0x%08x",
1235  s = format (s, "\n%U%U",
1236  format_white_space, indent,
1238  t->dpo_index, t->packet_data, sizeof (t->packet_data));
1239  return s;
1240 }
1241 
1242 /* Common trace function for all ip4-forward next nodes. */
1243 void
1245  vlib_node_runtime_t * node,
1246  vlib_frame_t * frame, vlib_rx_or_tx_t which_adj_index)
1247 {
1248  u32 *from, n_left;
1249  ip4_main_t *im = &ip4_main;
1250 
1251  n_left = frame->n_vectors;
1252  from = vlib_frame_vector_args (frame);
1253 
1254  while (n_left >= 4)
1255  {
1256  u32 bi0, bi1;
1257  vlib_buffer_t *b0, *b1;
1258  ip4_forward_next_trace_t *t0, *t1;
1259 
1260  /* Prefetch next iteration. */
1261  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
1262  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
1263 
1264  bi0 = from[0];
1265  bi1 = from[1];
1266 
1267  b0 = vlib_get_buffer (vm, bi0);
1268  b1 = vlib_get_buffer (vm, bi1);
1269 
1270  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1271  {
1272  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1273  t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
1274  t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
1275  t0->fib_index =
1276  (vnet_buffer (b0)->sw_if_index[VLIB_TX] !=
1277  (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] :
1279  vnet_buffer (b0)->sw_if_index[VLIB_RX]);
1280 
1281  clib_memcpy (t0->packet_data,
1283  sizeof (t0->packet_data));
1284  }
1285  if (b1->flags & VLIB_BUFFER_IS_TRACED)
1286  {
1287  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
1288  t1->dpo_index = vnet_buffer (b1)->ip.adj_index[which_adj_index];
1289  t1->flow_hash = vnet_buffer (b1)->ip.flow_hash;
1290  t1->fib_index =
1291  (vnet_buffer (b1)->sw_if_index[VLIB_TX] !=
1292  (u32) ~ 0) ? vnet_buffer (b1)->sw_if_index[VLIB_TX] :
1294  vnet_buffer (b1)->sw_if_index[VLIB_RX]);
1296  sizeof (t1->packet_data));
1297  }
1298  from += 2;
1299  n_left -= 2;
1300  }
1301 
1302  while (n_left >= 1)
1303  {
1304  u32 bi0;
1305  vlib_buffer_t *b0;
1307 
1308  bi0 = from[0];
1309 
1310  b0 = vlib_get_buffer (vm, bi0);
1311 
1312  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1313  {
1314  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1315  t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
1316  t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
1317  t0->fib_index =
1318  (vnet_buffer (b0)->sw_if_index[VLIB_TX] !=
1319  (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] :
1321  vnet_buffer (b0)->sw_if_index[VLIB_RX]);
1323  sizeof (t0->packet_data));
1324  }
1325  from += 1;
1326  n_left -= 1;
1327  }
1328 }
1329 
1330 static uword
1332  vlib_node_runtime_t * node,
1333  vlib_frame_t * frame, ip4_error_t error_code)
1334 {
1335  u32 *buffers = vlib_frame_vector_args (frame);
1336  uword n_packets = frame->n_vectors;
1337 
1338  vlib_error_drop_buffers (vm, node, buffers,
1339  /* stride */ 1,
1340  n_packets,
1341  /* next */ 0,
1342  ip4_input_node.index, error_code);
1343 
1344  if (node->flags & VLIB_NODE_FLAG_TRACE)
1345  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
1346 
1347  return n_packets;
1348 }
1349 
1350 static uword
1352 {
1353  return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_ADJACENCY_DROP);
1354 }
1355 
1356 static uword
1358 {
1359  return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_ADJACENCY_PUNT);
1360 }
1361 
1362 /* *INDENT-OFF* */
1364 {
1365  .function = ip4_drop,.
1366  name = "ip4-drop",
1367  .vector_size = sizeof (u32),
1368  .format_trace = format_ip4_forward_next_trace,
1369  .n_next_nodes = 1,
1370  .next_nodes = {
1371  [0] = "error-drop",
1372  },
1373 };
1374 
1376 
1378 {
1379  .function = ip4_punt,
1380  .name = "ip4-punt",
1381  .vector_size = sizeof (u32),
1382  .format_trace = format_ip4_forward_next_trace,
1383  .n_next_nodes = 1,
1384  .next_nodes = {
1385  [0] = "error-punt",
1386  },
1387 };
1388 
1390 /* *INDENT-ON */
1391 
1392 /* Compute TCP/UDP/ICMP4 checksum in software. */
1393 u16
1395  ip4_header_t * ip0)
1396 {
1397  ip_csum_t sum0;
1398  u32 ip_header_length, payload_length_host_byte_order;
1399  u32 n_this_buffer, n_bytes_left;
1400  u16 sum16;
1401  void *data_this_buffer;
1402 
1403  /* Initialize checksum with ip header. */
1404  ip_header_length = ip4_header_bytes (ip0);
1405  payload_length_host_byte_order =
1406  clib_net_to_host_u16 (ip0->length) - ip_header_length;
1407  sum0 =
1408  clib_host_to_net_u32 (payload_length_host_byte_order +
1409  (ip0->protocol << 16));
1410 
1411  if (BITS (uword) == 32)
1412  {
1413  sum0 =
1414  ip_csum_with_carry (sum0,
1416  sum0 =
1417  ip_csum_with_carry (sum0,
1419  }
1420  else
1421  sum0 =
1423 
1424  n_bytes_left = n_this_buffer = payload_length_host_byte_order;
1425  data_this_buffer = (void *) ip0 + ip_header_length;
1426  if (n_this_buffer + ip_header_length > p0->current_length)
1427  n_this_buffer =
1428  p0->current_length >
1429  ip_header_length ? p0->current_length - ip_header_length : 0;
1430  while (1)
1431  {
1432  sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer);
1433  n_bytes_left -= n_this_buffer;
1434  if (n_bytes_left == 0)
1435  break;
1436 
1438  p0 = vlib_get_buffer (vm, p0->next_buffer);
1439  data_this_buffer = vlib_buffer_get_current (p0);
1440  n_this_buffer = p0->current_length;
1441  }
1442 
1443  sum16 = ~ip_csum_fold (sum0);
1444 
1445  return sum16;
1446 }
1447 
1448 u32
1450 {
1452  udp_header_t *udp0;
1453  u16 sum16;
1454 
1455  ASSERT (ip0->protocol == IP_PROTOCOL_TCP
1456  || ip0->protocol == IP_PROTOCOL_UDP);
1457 
1458  udp0 = (void *) (ip0 + 1);
1459  if (ip0->protocol == IP_PROTOCOL_UDP && udp0->checksum == 0)
1460  {
1463  return p0->flags;
1464  }
1465 
1466  sum16 = ip4_tcp_udp_compute_checksum (vm, p0, ip0);
1467 
1469  | ((sum16 == 0) << LOG2_IP_BUFFER_L4_CHECKSUM_CORRECT));
1470 
1471  return p0->flags;
1472 }
1473 
1474 /* *INDENT-OFF* */
1476 {
1477  .arc_name = "ip4-local",
1478  .start_nodes = VNET_FEATURES ("ip4-local"),
1479 };
1480 /* *INDENT-ON* */
1481 
1482 static inline uword
1484  vlib_node_runtime_t * node,
1485  vlib_frame_t * frame, int head_of_feature_arc)
1486 {
1487  ip4_main_t *im = &ip4_main;
1488  ip_lookup_main_t *lm = &im->lookup_main;
1489  ip_local_next_t next_index;
1490  u32 *from, *to_next, n_left_from, n_left_to_next;
1491  vlib_node_runtime_t *error_node =
1493  u8 arc_index = vnet_feat_arc_ip4_local.feature_arc_index;
1494 
1495  from = vlib_frame_vector_args (frame);
1496  n_left_from = frame->n_vectors;
1497  next_index = node->cached_next_index;
1498 
1499  if (node->flags & VLIB_NODE_FLAG_TRACE)
1500  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
1501 
1502  while (n_left_from > 0)
1503  {
1504  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1505 
1506  while (n_left_from >= 4 && n_left_to_next >= 2)
1507  {
1508  vlib_buffer_t *p0, *p1;
1509  ip4_header_t *ip0, *ip1;
1510  udp_header_t *udp0, *udp1;
1511  ip4_fib_mtrie_t *mtrie0, *mtrie1;
1512  ip4_fib_mtrie_leaf_t leaf0, leaf1;
1513  const dpo_id_t *dpo0, *dpo1;
1514  const load_balance_t *lb0, *lb1;
1515  u32 pi0, ip_len0, udp_len0, flags0, next0, fib_index0, lbi0;
1516  u32 pi1, ip_len1, udp_len1, flags1, next1, fib_index1, lbi1;
1517  i32 len_diff0, len_diff1;
1518  u8 error0, is_udp0, is_tcp_udp0, good_tcp_udp0, proto0;
1519  u8 error1, is_udp1, is_tcp_udp1, good_tcp_udp1, proto1;
1520  u32 sw_if_index0, sw_if_index1;
1521 
1522  pi0 = to_next[0] = from[0];
1523  pi1 = to_next[1] = from[1];
1524  from += 2;
1525  n_left_from -= 2;
1526  to_next += 2;
1527  n_left_to_next -= 2;
1528 
1529  next0 = next1 = IP_LOCAL_NEXT_DROP;
1530 
1531  p0 = vlib_get_buffer (vm, pi0);
1532  p1 = vlib_get_buffer (vm, pi1);
1533 
1534  ip0 = vlib_buffer_get_current (p0);
1535  ip1 = vlib_buffer_get_current (p1);
1536 
1537  vnet_buffer (p0)->ip.start_of_ip_header = p0->current_data;
1538  vnet_buffer (p1)->ip.start_of_ip_header = p1->current_data;
1539 
1540  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1541  sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX];
1542 
1543  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
1544  fib_index1 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index1);
1545 
1546  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
1547  fib_index0 =
1548  (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
1549  (u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
1550 
1551  fib_index1 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index1);
1552  fib_index1 =
1553  (vnet_buffer (p1)->sw_if_index[VLIB_TX] ==
1554  (u32) ~ 0) ? fib_index1 : vnet_buffer (p1)->sw_if_index[VLIB_TX];
1555 
1556  mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
1557  mtrie1 = &ip4_fib_get (fib_index1)->mtrie;
1558 
1559  leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
1560 
1561  leaf0 =
1562  ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 0);
1563  leaf1 =
1564  ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 0);
1565 
1566  /* Treat IP frag packets as "experimental" protocol for now
1567  until support of IP frag reassembly is implemented */
1568  proto0 = ip4_is_fragment (ip0) ? 0xfe : ip0->protocol;
1569  proto1 = ip4_is_fragment (ip1) ? 0xfe : ip1->protocol;
1570 
1571  if (head_of_feature_arc == 0)
1572  {
1573  error0 = error1 = IP4_ERROR_UNKNOWN_PROTOCOL;
1574  goto skip_checks;
1575  }
1576 
1577  is_udp0 = proto0 == IP_PROTOCOL_UDP;
1578  is_udp1 = proto1 == IP_PROTOCOL_UDP;
1579  is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
1580  is_tcp_udp1 = is_udp1 || proto1 == IP_PROTOCOL_TCP;
1581 
1582  flags0 = p0->flags;
1583  flags1 = p1->flags;
1584 
1585  good_tcp_udp0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1586  good_tcp_udp1 = (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1587 
1588  udp0 = ip4_next_header (ip0);
1589  udp1 = ip4_next_header (ip1);
1590 
1591  /* Don't verify UDP checksum for packets with explicit zero checksum. */
1592  good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1593  good_tcp_udp1 |= is_udp1 && udp1->checksum == 0;
1594 
1595  leaf0 =
1596  ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 1);
1597  leaf1 =
1598  ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 1);
1599 
1600  /* Verify UDP length. */
1601  ip_len0 = clib_net_to_host_u16 (ip0->length);
1602  ip_len1 = clib_net_to_host_u16 (ip1->length);
1603  udp_len0 = clib_net_to_host_u16 (udp0->length);
1604  udp_len1 = clib_net_to_host_u16 (udp1->length);
1605 
1606  len_diff0 = ip_len0 - udp_len0;
1607  len_diff1 = ip_len1 - udp_len1;
1608 
1609  len_diff0 = is_udp0 ? len_diff0 : 0;
1610  len_diff1 = is_udp1 ? len_diff1 : 0;
1611 
1612  if (PREDICT_FALSE (!(is_tcp_udp0 & is_tcp_udp1
1613  & good_tcp_udp0 & good_tcp_udp1)))
1614  {
1615  if (is_tcp_udp0)
1616  {
1617  if (is_tcp_udp0
1618  && !(flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
1619  flags0 = ip4_tcp_udp_validate_checksum (vm, p0);
1620  good_tcp_udp0 =
1621  (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1622  good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1623  }
1624  if (is_tcp_udp1)
1625  {
1626  if (is_tcp_udp1
1627  && !(flags1 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
1628  flags1 = ip4_tcp_udp_validate_checksum (vm, p1);
1629  good_tcp_udp1 =
1630  (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1631  good_tcp_udp1 |= is_udp1 && udp1->checksum == 0;
1632  }
1633  }
1634 
1635  good_tcp_udp0 &= len_diff0 >= 0;
1636  good_tcp_udp1 &= len_diff1 >= 0;
1637 
1638  leaf0 =
1639  ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 2);
1640  leaf1 =
1641  ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 2);
1642 
1643  error0 = error1 = IP4_ERROR_UNKNOWN_PROTOCOL;
1644 
1645  error0 = len_diff0 < 0 ? IP4_ERROR_UDP_LENGTH : error0;
1646  error1 = len_diff1 < 0 ? IP4_ERROR_UDP_LENGTH : error1;
1647 
1648  ASSERT (IP4_ERROR_TCP_CHECKSUM + 1 == IP4_ERROR_UDP_CHECKSUM);
1649  error0 = (is_tcp_udp0 && !good_tcp_udp0
1650  ? IP4_ERROR_TCP_CHECKSUM + is_udp0 : error0);
1651  error1 = (is_tcp_udp1 && !good_tcp_udp1
1652  ? IP4_ERROR_TCP_CHECKSUM + is_udp1 : error1);
1653 
1654  leaf0 =
1655  ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 3);
1656  leaf1 =
1657  ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 3);
1658  leaf0 =
1659  (leaf0 ==
1660  IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
1661  leaf1 =
1662  (leaf1 ==
1663  IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie1->default_leaf : leaf1);
1664 
1665  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = lbi0 =
1667  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = lbi0;
1668 
1669  vnet_buffer (p1)->ip.adj_index[VLIB_RX] = lbi1 =
1671  vnet_buffer (p1)->ip.adj_index[VLIB_TX] = lbi1;
1672 
1673  lb0 = load_balance_get (lbi0);
1674  lb1 = load_balance_get (lbi1);
1675  dpo0 = load_balance_get_bucket_i (lb0, 0);
1676  dpo1 = load_balance_get_bucket_i (lb1, 0);
1677 
1678  /*
1679  * Must have a route to source otherwise we drop the packet.
1680  * ip4 broadcasts are accepted, e.g. to make dhcp client work
1681  *
1682  * The checks are:
1683  * - the source is a recieve => it's from us => bogus, do this
1684  * first since it sets a different error code.
1685  * - uRPF check for any route to source - accept if passes.
1686  * - allow packets destined to the broadcast address from unknown sources
1687  */
1688  error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1689  dpo0->dpoi_type == DPO_RECEIVE) ?
1690  IP4_ERROR_SPOOFED_LOCAL_PACKETS : error0);
1691  error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1692  !fib_urpf_check_size (lb0->lb_urpf) &&
1693  ip0->dst_address.as_u32 != 0xFFFFFFFF)
1694  ? IP4_ERROR_SRC_LOOKUP_MISS : error0);
1695  error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1696  dpo1->dpoi_type == DPO_RECEIVE) ?
1697  IP4_ERROR_SPOOFED_LOCAL_PACKETS : error1);
1698  error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1699  !fib_urpf_check_size (lb1->lb_urpf) &&
1700  ip1->dst_address.as_u32 != 0xFFFFFFFF)
1701  ? IP4_ERROR_SRC_LOOKUP_MISS : error1);
1702 
1703  skip_checks:
1704 
1705  next0 = lm->local_next_by_ip_protocol[proto0];
1706  next1 = lm->local_next_by_ip_protocol[proto1];
1707 
1708  next0 =
1709  error0 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0;
1710  next1 =
1711  error1 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next1;
1712 
1713  p0->error = error0 ? error_node->errors[error0] : 0;
1714  p1->error = error1 ? error_node->errors[error1] : 0;
1715 
1716  if (head_of_feature_arc)
1717  {
1718  if (PREDICT_TRUE (error0 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
1719  vnet_feature_arc_start (arc_index, sw_if_index0, &next0, p0);
1720  if (PREDICT_TRUE (error1 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
1721  vnet_feature_arc_start (arc_index, sw_if_index1, &next1, p1);
1722  }
1723 
1724  vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1725  n_left_to_next, pi0, pi1,
1726  next0, next1);
1727  }
1728 
1729  while (n_left_from > 0 && n_left_to_next > 0)
1730  {
1731  vlib_buffer_t *p0;
1732  ip4_header_t *ip0;
1733  udp_header_t *udp0;
1734  ip4_fib_mtrie_t *mtrie0;
1735  ip4_fib_mtrie_leaf_t leaf0;
1736  u32 pi0, next0, ip_len0, udp_len0, flags0, fib_index0, lbi0;
1737  i32 len_diff0;
1738  u8 error0, is_udp0, is_tcp_udp0, good_tcp_udp0, proto0;
1739  load_balance_t *lb0;
1740  const dpo_id_t *dpo0;
1741  u32 sw_if_index0;
1742 
1743  pi0 = to_next[0] = from[0];
1744  from += 1;
1745  n_left_from -= 1;
1746  to_next += 1;
1747  n_left_to_next -= 1;
1748 
1749  next0 = IP_LOCAL_NEXT_DROP;
1750 
1751  p0 = vlib_get_buffer (vm, pi0);
1752 
1753  ip0 = vlib_buffer_get_current (p0);
1754 
1755  vnet_buffer (p0)->ip.start_of_ip_header = p0->current_data;
1756 
1757  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1758 
1759  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
1760 
1761  fib_index0 =
1762  (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
1763  (u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
1764 
1765  mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
1766 
1767  leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
1768 
1769  leaf0 =
1770  ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 0);
1771 
1772  /* Treat IP frag packets as "experimental" protocol for now
1773  until support of IP frag reassembly is implemented */
1774  proto0 = ip4_is_fragment (ip0) ? 0xfe : ip0->protocol;
1775 
1776  if (head_of_feature_arc == 0)
1777  {
1778  error0 = IP4_ERROR_UNKNOWN_PROTOCOL;
1779  goto skip_check;
1780  }
1781 
1782  is_udp0 = proto0 == IP_PROTOCOL_UDP;
1783  is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
1784 
1785  flags0 = p0->flags;
1786 
1787  good_tcp_udp0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1788 
1789  udp0 = ip4_next_header (ip0);
1790 
1791  /* Don't verify UDP checksum for packets with explicit zero checksum. */
1792  good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1793 
1794  leaf0 =
1795  ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 1);
1796 
1797  /* Verify UDP length. */
1798  ip_len0 = clib_net_to_host_u16 (ip0->length);
1799  udp_len0 = clib_net_to_host_u16 (udp0->length);
1800 
1801  len_diff0 = ip_len0 - udp_len0;
1802 
1803  len_diff0 = is_udp0 ? len_diff0 : 0;
1804 
1805  if (PREDICT_FALSE (!(is_tcp_udp0 & good_tcp_udp0)))
1806  {
1807  if (is_tcp_udp0)
1808  {
1809  if (is_tcp_udp0
1810  && !(flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
1811  flags0 = ip4_tcp_udp_validate_checksum (vm, p0);
1812  good_tcp_udp0 =
1813  (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1814  good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1815  }
1816  }
1817 
1818  good_tcp_udp0 &= len_diff0 >= 0;
1819 
1820  leaf0 =
1821  ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 2);
1822 
1823  error0 = IP4_ERROR_UNKNOWN_PROTOCOL;
1824 
1825  error0 = len_diff0 < 0 ? IP4_ERROR_UDP_LENGTH : error0;
1826 
1827  ASSERT (IP4_ERROR_TCP_CHECKSUM + 1 == IP4_ERROR_UDP_CHECKSUM);
1828  error0 = (is_tcp_udp0 && !good_tcp_udp0
1829  ? IP4_ERROR_TCP_CHECKSUM + is_udp0 : error0);
1830 
1831  leaf0 =
1832  ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 3);
1833  leaf0 =
1834  (leaf0 ==
1835  IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
1836 
1837  lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
1838  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = lbi0;
1839 
1840  lb0 = load_balance_get (lbi0);
1841  dpo0 = load_balance_get_bucket_i (lb0, 0);
1842 
1843  vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
1844  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = lbi0;
1845 
1846  error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1847  dpo0->dpoi_type == DPO_RECEIVE) ?
1848  IP4_ERROR_SPOOFED_LOCAL_PACKETS : error0);
1849  error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1850  !fib_urpf_check_size (lb0->lb_urpf) &&
1851  ip0->dst_address.as_u32 != 0xFFFFFFFF)
1852  ? IP4_ERROR_SRC_LOOKUP_MISS : error0);
1853 
1854  skip_check:
1855 
1856  next0 = lm->local_next_by_ip_protocol[proto0];
1857 
1858  next0 =
1859  error0 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0;
1860 
1861  p0->error = error0 ? error_node->errors[error0] : 0;
1862 
1863  if (head_of_feature_arc)
1864  {
1865  if (PREDICT_TRUE (error0 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
1866  vnet_feature_arc_start (arc_index, sw_if_index0, &next0, p0);
1867  }
1868 
1869  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1870  n_left_to_next, pi0, next0);
1871 
1872  }
1873 
1874  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1875  }
1876 
1877  return frame->n_vectors;
1878 }
1879 
1880 static uword
1882 {
1883  return ip4_local_inline (vm, node, frame, 1 /* head of feature arc */ );
1884 }
1885 
1886 /* *INDENT-OFF* */
1888 {
1889  .function = ip4_local,
1890  .name = "ip4-local",
1891  .vector_size = sizeof (u32),
1892  .format_trace = format_ip4_forward_next_trace,
1893  .n_next_nodes = IP_LOCAL_N_NEXT,
1894  .next_nodes =
1895  {
1896  [IP_LOCAL_NEXT_DROP] = "error-drop",
1897  [IP_LOCAL_NEXT_PUNT] = "error-punt",
1898  [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
1899  [IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",},
1900 };
1901 /* *INDENT-ON* */
1902 
1904 
1905 static uword
1907  vlib_node_runtime_t * node, vlib_frame_t * frame)
1908 {
1909  return ip4_local_inline (vm, node, frame, 0 /* head of feature arc */ );
1910 }
1911 
1912 /* *INDENT-OFF* */
1914  .function = ip4_local_end_of_arc,
1915  .name = "ip4-local-end-of-arc",
1916  .vector_size = sizeof (u32),
1917 
1918  .format_trace = format_ip4_forward_next_trace,
1919  .sibling_of = "ip4-local",
1920 };
1921 
1923 
1925  .arc_name = "ip4-local",
1926  .node_name = "ip4-local-end-of-arc",
1927  .runs_before = 0, /* not before any other features */
1928 };
1929 /* *INDENT-ON* */
1930 
1931 void
1932 ip4_register_protocol (u32 protocol, u32 node_index)
1933 {
1935  ip4_main_t *im = &ip4_main;
1936  ip_lookup_main_t *lm = &im->lookup_main;
1937 
1938  ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
1939  lm->local_next_by_ip_protocol[protocol] =
1940  vlib_node_add_next (vm, ip4_local_node.index, node_index);
1941 }
1942 
1943 static clib_error_t *
1945  unformat_input_t * input, vlib_cli_command_t * cmd)
1946 {
1947  ip4_main_t *im = &ip4_main;
1948  ip_lookup_main_t *lm = &im->lookup_main;
1949  int i;
1950 
1951  vlib_cli_output (vm, "Protocols handled by ip4_local");
1952  for (i = 0; i < ARRAY_LEN (lm->local_next_by_ip_protocol); i++)
1953  {
1955  vlib_cli_output (vm, "%d", i);
1956  }
1957  return 0;
1958 }
1959 
1960 
1961 
1962 /*?
1963  * Display the set of protocols handled by the local IPv4 stack.
1964  *
1965  * @cliexpar
1966  * Example of how to display local protocol table:
1967  * @cliexstart{show ip local}
1968  * Protocols handled by ip4_local
1969  * 1
1970  * 17
1971  * 47
1972  * @cliexend
1973 ?*/
1974 /* *INDENT-OFF* */
1975 VLIB_CLI_COMMAND (show_ip_local, static) =
1976 {
1977  .path = "show ip local",
1978  .function = show_ip_local_command_fn,
1979  .short_help = "show ip local",
1980 };
1981 /* *INDENT-ON* */
1982 
1985  vlib_node_runtime_t * node,
1986  vlib_frame_t * frame, int is_glean)
1987 {
1988  vnet_main_t *vnm = vnet_get_main ();
1989  ip4_main_t *im = &ip4_main;
1990  ip_lookup_main_t *lm = &im->lookup_main;
1991  u32 *from, *to_next_drop;
1992  uword n_left_from, n_left_to_next_drop, next_index;
1993  static f64 time_last_seed_change = -1e100;
1994  static u32 hash_seeds[3];
1995  static uword hash_bitmap[256 / BITS (uword)];
1996  f64 time_now;
1997 
1998  if (node->flags & VLIB_NODE_FLAG_TRACE)
1999  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
2000 
2001  time_now = vlib_time_now (vm);
2002  if (time_now - time_last_seed_change > 1e-3)
2003  {
2004  uword i;
2006  sizeof (hash_seeds));
2007  for (i = 0; i < ARRAY_LEN (hash_seeds); i++)
2008  hash_seeds[i] = r[i];
2009 
2010  /* Mark all hash keys as been no-seen before. */
2011  for (i = 0; i < ARRAY_LEN (hash_bitmap); i++)
2012  hash_bitmap[i] = 0;
2013 
2014  time_last_seed_change = time_now;
2015  }
2016 
2017  from = vlib_frame_vector_args (frame);
2018  n_left_from = frame->n_vectors;
2019  next_index = node->cached_next_index;
2020  if (next_index == IP4_ARP_NEXT_DROP)
2021  next_index = IP4_ARP_N_NEXT; /* point to first interface */
2022 
2023  while (n_left_from > 0)
2024  {
2026  to_next_drop, n_left_to_next_drop);
2027 
2028  while (n_left_from > 0 && n_left_to_next_drop > 0)
2029  {
2030  u32 pi0, adj_index0, a0, b0, c0, m0, sw_if_index0, drop0;
2031  ip_adjacency_t *adj0;
2032  vlib_buffer_t *p0;
2033  ip4_header_t *ip0;
2034  uword bm0;
2035 
2036  pi0 = from[0];
2037 
2038  p0 = vlib_get_buffer (vm, pi0);
2039 
2040  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
2041  adj0 = ip_get_adjacency (lm, adj_index0);
2042  ip0 = vlib_buffer_get_current (p0);
2043 
2044  a0 = hash_seeds[0];
2045  b0 = hash_seeds[1];
2046  c0 = hash_seeds[2];
2047 
2048  sw_if_index0 = adj0->rewrite_header.sw_if_index;
2049  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2050 
2051  if (is_glean)
2052  {
2053  /*
2054  * this is the Glean case, so we are ARPing for the
2055  * packet's destination
2056  */
2057  a0 ^= ip0->dst_address.data_u32;
2058  }
2059  else
2060  {
2061  a0 ^= adj0->sub_type.nbr.next_hop.ip4.data_u32;
2062  }
2063  b0 ^= sw_if_index0;
2064 
2065  hash_v3_finalize32 (a0, b0, c0);
2066 
2067  c0 &= BITS (hash_bitmap) - 1;
2068  c0 = c0 / BITS (uword);
2069  m0 = (uword) 1 << (c0 % BITS (uword));
2070 
2071  bm0 = hash_bitmap[c0];
2072  drop0 = (bm0 & m0) != 0;
2073 
2074  /* Mark it as seen. */
2075  hash_bitmap[c0] = bm0 | m0;
2076 
2077  from += 1;
2078  n_left_from -= 1;
2079  to_next_drop[0] = pi0;
2080  to_next_drop += 1;
2081  n_left_to_next_drop -= 1;
2082 
2083  p0->error =
2084  node->errors[drop0 ? IP4_ARP_ERROR_DROP :
2086 
2087  /*
2088  * the adj has been updated to a rewrite but the node the DPO that got
2089  * us here hasn't - yet. no big deal. we'll drop while we wait.
2090  */
2092  continue;
2093 
2094  if (drop0)
2095  continue;
2096 
2097  /*
2098  * Can happen if the control-plane is programming tables
2099  * with traffic flowing; at least that's today's lame excuse.
2100  */
2101  if ((is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_GLEAN)
2102  || (!is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP))
2103  {
2104  p0->error = node->errors[IP4_ARP_ERROR_NON_ARP_ADJ];
2105  }
2106  else
2107  /* Send ARP request. */
2108  {
2109  u32 bi0 = 0;
2110  vlib_buffer_t *b0;
2112  vnet_hw_interface_t *hw_if0;
2113 
2114  h0 =
2117  &bi0);
2118 
2119  /* Add rewrite/encap string for ARP packet. */
2120  vnet_rewrite_one_header (adj0[0], h0,
2121  sizeof (ethernet_header_t));
2122 
2123  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
2124 
2125  /* Src ethernet address in ARP header. */
2126  clib_memcpy (h0->ip4_over_ethernet[0].ethernet,
2127  hw_if0->hw_address,
2128  sizeof (h0->ip4_over_ethernet[0].ethernet));
2129 
2130  if (is_glean)
2131  {
2132  /* The interface's source address is stashed in the Glean Adj */
2133  h0->ip4_over_ethernet[0].ip4 =
2134  adj0->sub_type.glean.receive_addr.ip4;
2135 
2136  /* Copy in destination address we are requesting. This is the
2137  * glean case, so it's the packet's destination.*/
2138  h0->ip4_over_ethernet[1].ip4.data_u32 =
2139  ip0->dst_address.data_u32;
2140  }
2141  else
2142  {
2143  /* Src IP address in ARP header. */
2144  if (ip4_src_address_for_packet (lm, sw_if_index0,
2145  &h0->
2146  ip4_over_ethernet[0].ip4))
2147  {
2148  /* No source address available */
2149  p0->error =
2151  vlib_buffer_free (vm, &bi0, 1);
2152  continue;
2153  }
2154 
2155  /* Copy in destination address we are requesting from the
2156  incomplete adj */
2157  h0->ip4_over_ethernet[1].ip4.data_u32 =
2158  adj0->sub_type.nbr.next_hop.ip4.as_u32;
2159  }
2160 
2161  vlib_buffer_copy_trace_flag (vm, p0, bi0);
2162  b0 = vlib_get_buffer (vm, bi0);
2163  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
2164 
2165  vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
2166 
2167  vlib_set_next_frame_buffer (vm, node,
2168  adj0->rewrite_header.next_index,
2169  bi0);
2170  }
2171  }
2172 
2173  vlib_put_next_frame (vm, node, IP4_ARP_NEXT_DROP, n_left_to_next_drop);
2174  }
2175 
2176  return frame->n_vectors;
2177 }
2178 
2179 static uword
2181 {
2182  return (ip4_arp_inline (vm, node, frame, 0));
2183 }
2184 
2185 static uword
2187 {
2188  return (ip4_arp_inline (vm, node, frame, 1));
2189 }
2190 
2191 static char *ip4_arp_error_strings[] = {
2192  [IP4_ARP_ERROR_DROP] = "address overflow drops",
2193  [IP4_ARP_ERROR_REQUEST_SENT] = "ARP requests sent",
2194  [IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies",
2195  [IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed",
2196  [IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed",
2197  [IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request",
2198 };
2199 
2201 {
2202  .function = ip4_arp,.name = "ip4-arp",.vector_size =
2203  sizeof (u32),.format_trace = format_ip4_forward_next_trace,.n_errors =
2204  ARRAY_LEN (ip4_arp_error_strings),.error_strings =
2205  ip4_arp_error_strings,.n_next_nodes = IP4_ARP_N_NEXT,.next_nodes =
2206  {
2207  [IP4_ARP_NEXT_DROP] = "error-drop",}
2208 ,};
2209 
2211 {
2212  .function = ip4_glean,.name = "ip4-glean",.vector_size =
2213  sizeof (u32),.format_trace = format_ip4_forward_next_trace,.n_errors =
2214  ARRAY_LEN (ip4_arp_error_strings),.error_strings =
2215  ip4_arp_error_strings,.n_next_nodes = IP4_ARP_N_NEXT,.next_nodes =
2216  {
2217  [IP4_ARP_NEXT_DROP] = "error-drop",}
2218 ,};
2219 
2220 #define foreach_notrace_ip4_arp_error \
2221 _(DROP) \
2222 _(REQUEST_SENT) \
2223 _(REPLICATE_DROP) \
2224 _(REPLICATE_FAIL)
2225 
2226 clib_error_t *
2228 {
2230 
2231  /* don't trace ARP request packets */
2232 #define _(a) \
2233  vnet_pcap_drop_trace_filter_add_del \
2234  (rt->errors[IP4_ARP_ERROR_##a], \
2235  1 /* is_add */);
2237 #undef _
2238  return 0;
2239 }
2240 
2242 
2243 
2244 /* Send an ARP request to see if given destination is reachable on given interface. */
2245 clib_error_t *
2247 {
2248  vnet_main_t *vnm = vnet_get_main ();
2249  ip4_main_t *im = &ip4_main;
2251  ip4_address_t *src;
2253  ip_adjacency_t *adj;
2255  vnet_sw_interface_t *si;
2256  vlib_buffer_t *b;
2257  u32 bi = 0;
2258 
2259  si = vnet_get_sw_interface (vnm, sw_if_index);
2260 
2262  {
2263  return clib_error_return (0, "%U: interface %U down",
2264  format_ip4_address, dst,
2266  sw_if_index);
2267  }
2268 
2269  src =
2270  ip4_interface_address_matching_destination (im, dst, sw_if_index, &ia);
2271  if (!src)
2272  {
2273  vnm->api_errno = VNET_API_ERROR_NO_MATCHING_INTERFACE;
2274  return clib_error_return
2275  (0,
2276  "no matching interface address for destination %U (interface %U)",
2278  sw_if_index);
2279  }
2280 
2282 
2283  h =
2286  &bi);
2287 
2288  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
2289 
2290  clib_memcpy (h->ip4_over_ethernet[0].ethernet, hi->hw_address,
2291  sizeof (h->ip4_over_ethernet[0].ethernet));
2292 
2293  h->ip4_over_ethernet[0].ip4 = src[0];
2294  h->ip4_over_ethernet[1].ip4 = dst[0];
2295 
2296  b = vlib_get_buffer (vm, bi);
2297  vnet_buffer (b)->sw_if_index[VLIB_RX] =
2298  vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
2299 
2300  /* Add encapsulation string for software interface (e.g. ethernet header). */
2301  vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
2302  vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
2303 
2304  {
2306  u32 *to_next = vlib_frame_vector_args (f);
2307  to_next[0] = bi;
2308  f->n_vectors = 1;
2310  }
2311 
2312  return /* no error */ 0;
2313 }
2314 
2315 typedef enum
2316 {
2320 
2323  vlib_node_runtime_t * node,
2324  vlib_frame_t * frame,
2325  int do_counters, int is_midchain, int is_mcast)
2326 {
2327  ip_lookup_main_t *lm = &ip4_main.lookup_main;
2328  u32 *from = vlib_frame_vector_args (frame);
2329  u32 n_left_from, n_left_to_next, *to_next, next_index;
2330  vlib_node_runtime_t *error_node =
2332 
2333  n_left_from = frame->n_vectors;
2334  next_index = node->cached_next_index;
2335  u32 cpu_index = os_get_cpu_number ();
2336 
2337  while (n_left_from > 0)
2338  {
2339  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2340 
2341  while (n_left_from >= 4 && n_left_to_next >= 2)
2342  {
2343  ip_adjacency_t *adj0, *adj1;
2344  vlib_buffer_t *p0, *p1;
2345  ip4_header_t *ip0, *ip1;
2346  u32 pi0, rw_len0, next0, error0, checksum0, adj_index0;
2347  u32 pi1, rw_len1, next1, error1, checksum1, adj_index1;
2348  u32 tx_sw_if_index0, tx_sw_if_index1;
2349 
2350  /* Prefetch next iteration. */
2351  {
2352  vlib_buffer_t *p2, *p3;
2353 
2354  p2 = vlib_get_buffer (vm, from[2]);
2355  p3 = vlib_get_buffer (vm, from[3]);
2356 
2357  vlib_prefetch_buffer_header (p2, STORE);
2358  vlib_prefetch_buffer_header (p3, STORE);
2359 
2360  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE);
2361  CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE);
2362  }
2363 
2364  pi0 = to_next[0] = from[0];
2365  pi1 = to_next[1] = from[1];
2366 
2367  from += 2;
2368  n_left_from -= 2;
2369  to_next += 2;
2370  n_left_to_next -= 2;
2371 
2372  p0 = vlib_get_buffer (vm, pi0);
2373  p1 = vlib_get_buffer (vm, pi1);
2374 
2375  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
2376  adj_index1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX];
2377 
2378  /*
2379  * pre-fetch the per-adjacency counters
2380  */
2381  if (do_counters)
2382  {
2384  cpu_index, adj_index0);
2386  cpu_index, adj_index1);
2387  }
2388 
2389  /* We should never rewrite a pkt using the MISS adjacency */
2390  ASSERT (adj_index0 && adj_index1);
2391 
2392  ip0 = vlib_buffer_get_current (p0);
2393  ip1 = vlib_buffer_get_current (p1);
2394 
2395  error0 = error1 = IP4_ERROR_NONE;
2396  next0 = next1 = IP4_REWRITE_NEXT_DROP;
2397 
2398  /* Decrement TTL & update checksum.
2399  Works either endian, so no need for byte swap. */
2401  {
2402  i32 ttl0 = ip0->ttl;
2403 
2404  /* Input node should have reject packets with ttl 0. */
2405  ASSERT (ip0->ttl > 0);
2406 
2407  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
2408  checksum0 += checksum0 >= 0xffff;
2409 
2410  ip0->checksum = checksum0;
2411  ttl0 -= 1;
2412  ip0->ttl = ttl0;
2413 
2414  /*
2415  * If the ttl drops below 1 when forwarding, generate
2416  * an ICMP response.
2417  */
2418  if (PREDICT_FALSE (ttl0 <= 0))
2419  {
2420  error0 = IP4_ERROR_TIME_EXPIRED;
2421  vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
2422  icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
2423  ICMP4_time_exceeded_ttl_exceeded_in_transit,
2424  0);
2426  }
2427 
2428  /* Verify checksum. */
2429  ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2430  }
2431  else
2432  {
2434  }
2436  {
2437  i32 ttl1 = ip1->ttl;
2438 
2439  /* Input node should have reject packets with ttl 0. */
2440  ASSERT (ip1->ttl > 0);
2441 
2442  checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
2443  checksum1 += checksum1 >= 0xffff;
2444 
2445  ip1->checksum = checksum1;
2446  ttl1 -= 1;
2447  ip1->ttl = ttl1;
2448 
2449  /*
2450  * If the ttl drops below 1 when forwarding, generate
2451  * an ICMP response.
2452  */
2453  if (PREDICT_FALSE (ttl1 <= 0))
2454  {
2455  error1 = IP4_ERROR_TIME_EXPIRED;
2456  vnet_buffer (p1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
2457  icmp4_error_set_vnet_buffer (p1, ICMP4_time_exceeded,
2458  ICMP4_time_exceeded_ttl_exceeded_in_transit,
2459  0);
2461  }
2462 
2463  /* Verify checksum. */
2464  ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2465  ASSERT (ip1->checksum == ip4_header_checksum (ip1));
2466  }
2467  else
2468  {
2470  }
2471 
2472  /* Rewrite packet header and updates lengths. */
2473  adj0 = ip_get_adjacency (lm, adj_index0);
2474  adj1 = ip_get_adjacency (lm, adj_index1);
2475 
2476  /* Worth pipelining. No guarantee that adj0,1 are hot... */
2477  rw_len0 = adj0[0].rewrite_header.data_bytes;
2478  rw_len1 = adj1[0].rewrite_header.data_bytes;
2479  vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
2480  vnet_buffer (p1)->ip.save_rewrite_length = rw_len1;
2481 
2482  /* Check MTU of outgoing interface. */
2483  error0 =
2484  (vlib_buffer_length_in_chain (vm, p0) >
2485  adj0[0].
2486  rewrite_header.max_l3_packet_bytes ? IP4_ERROR_MTU_EXCEEDED :
2487  error0);
2488  error1 =
2489  (vlib_buffer_length_in_chain (vm, p1) >
2490  adj1[0].
2491  rewrite_header.max_l3_packet_bytes ? IP4_ERROR_MTU_EXCEEDED :
2492  error1);
2493 
2494  /* Don't adjust the buffer for ttl issue; icmp-error node wants
2495  * to see the IP headerr */
2496  if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
2497  {
2498  next0 = adj0[0].rewrite_header.next_index;
2499  p0->current_data -= rw_len0;
2500  p0->current_length += rw_len0;
2501  tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
2502  vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
2503 
2504  if (PREDICT_FALSE
2505  (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2507  tx_sw_if_index0, &next0, p0);
2508  }
2509  if (PREDICT_TRUE (error1 == IP4_ERROR_NONE))
2510  {
2511  next1 = adj1[0].rewrite_header.next_index;
2512  p1->current_data -= rw_len1;
2513  p1->current_length += rw_len1;
2514 
2515  tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index;
2516  vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1;
2517 
2518  if (PREDICT_FALSE
2519  (adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2521  tx_sw_if_index1, &next1, p1);
2522  }
2523 
2524  /* Guess we are only writing on simple Ethernet header. */
2525  vnet_rewrite_two_headers (adj0[0], adj1[0],
2526  ip0, ip1, sizeof (ethernet_header_t));
2527 
2528  /*
2529  * Bump the per-adjacency counters
2530  */
2531  if (do_counters)
2532  {
2535  cpu_index,
2536  adj_index0, 1,
2537  vlib_buffer_length_in_chain (vm, p0) + rw_len0);
2538 
2541  cpu_index,
2542  adj_index1, 1,
2543  vlib_buffer_length_in_chain (vm, p1) + rw_len1);
2544  }
2545 
2546  if (is_midchain)
2547  {
2548  adj0->sub_type.midchain.fixup_func (vm, adj0, p0);
2549  adj1->sub_type.midchain.fixup_func (vm, adj1, p1);
2550  }
2551  if (is_mcast)
2552  {
2553  /*
2554  * copy bytes from the IP address into the MAC rewrite
2555  */
2556  vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 1);
2557  vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1, 1);
2558  }
2559 
2560  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
2561  to_next, n_left_to_next,
2562  pi0, pi1, next0, next1);
2563  }
2564 
2565  while (n_left_from > 0 && n_left_to_next > 0)
2566  {
2567  ip_adjacency_t *adj0;
2568  vlib_buffer_t *p0;
2569  ip4_header_t *ip0;
2570  u32 pi0, rw_len0, adj_index0, next0, error0, checksum0;
2571  u32 tx_sw_if_index0;
2572 
2573  pi0 = to_next[0] = from[0];
2574 
2575  p0 = vlib_get_buffer (vm, pi0);
2576 
2577  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
2578 
2579  /* We should never rewrite a pkt using the MISS adjacency */
2580  ASSERT (adj_index0);
2581 
2582  adj0 = ip_get_adjacency (lm, adj_index0);
2583 
2584  ip0 = vlib_buffer_get_current (p0);
2585 
2586  error0 = IP4_ERROR_NONE;
2587  next0 = IP4_REWRITE_NEXT_DROP; /* drop on error */
2588 
2589  /* Decrement TTL & update checksum. */
2591  {
2592  i32 ttl0 = ip0->ttl;
2593 
2594  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
2595 
2596  checksum0 += checksum0 >= 0xffff;
2597 
2598  ip0->checksum = checksum0;
2599 
2600  ASSERT (ip0->ttl > 0);
2601 
2602  ttl0 -= 1;
2603 
2604  ip0->ttl = ttl0;
2605 
2606  ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2607 
2608  if (PREDICT_FALSE (ttl0 <= 0))
2609  {
2610  /*
2611  * If the ttl drops below 1 when forwarding, generate
2612  * an ICMP response.
2613  */
2614  error0 = IP4_ERROR_TIME_EXPIRED;
2616  vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
2617  icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
2618  ICMP4_time_exceeded_ttl_exceeded_in_transit,
2619  0);
2620  }
2621  }
2622  else
2623  {
2625  }
2626 
2627  if (do_counters)
2629  cpu_index, adj_index0);
2630 
2631  /* Guess we are only writing on simple Ethernet header. */
2632  vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
2633  if (is_mcast)
2634  {
2635  /*
2636  * copy bytes from the IP address into the MAC rewrite
2637  */
2638  vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 1);
2639  }
2640 
2641  /* Update packet buffer attributes/set output interface. */
2642  rw_len0 = adj0[0].rewrite_header.data_bytes;
2643  vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
2644 
2645  if (do_counters)
2648  cpu_index, adj_index0, 1,
2649  vlib_buffer_length_in_chain (vm, p0) + rw_len0);
2650 
2651  /* Check MTU of outgoing interface. */
2652  error0 = (vlib_buffer_length_in_chain (vm, p0)
2653  > adj0[0].rewrite_header.max_l3_packet_bytes
2654  ? IP4_ERROR_MTU_EXCEEDED : error0);
2655 
2656  p0->error = error_node->errors[error0];
2657 
2658  /* Don't adjust the buffer for ttl issue; icmp-error node wants
2659  * to see the IP headerr */
2660  if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
2661  {
2662  p0->current_data -= rw_len0;
2663  p0->current_length += rw_len0;
2664  tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
2665 
2666  vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
2667  next0 = adj0[0].rewrite_header.next_index;
2668 
2669  if (is_midchain)
2670  {
2671  adj0->sub_type.midchain.fixup_func (vm, adj0, p0);
2672  }
2673 
2674  if (PREDICT_FALSE
2675  (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2677  tx_sw_if_index0, &next0, p0);
2678 
2679  }
2680 
2681  from += 1;
2682  n_left_from -= 1;
2683  to_next += 1;
2684  n_left_to_next -= 1;
2685 
2686  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2687  to_next, n_left_to_next,
2688  pi0, next0);
2689  }
2690 
2691  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2692  }
2693 
2694  /* Need to do trace after rewrites to pick up new packet data. */
2695  if (node->flags & VLIB_NODE_FLAG_TRACE)
2696  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
2697 
2698  return frame->n_vectors;
2699 }
2700 
2701 
2702 /** @brief IPv4 rewrite node.
2703  @node ip4-rewrite
2704 
2705  This is the IPv4 transit-rewrite node: decrement TTL, fix the ipv4
2706  header checksum, fetch the ip adjacency, check the outbound mtu,
2707  apply the adjacency rewrite, and send pkts to the adjacency
2708  rewrite header's rewrite_next_index.
2709 
2710  @param vm vlib_main_t corresponding to the current thread
2711  @param node vlib_node_runtime_t
2712  @param frame vlib_frame_t whose contents should be dispatched
2713 
2714  @par Graph mechanics: buffer metadata, next index usage
2715 
2716  @em Uses:
2717  - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
2718  - the rewrite adjacency index
2719  - <code>adj->lookup_next_index</code>
2720  - Must be IP_LOOKUP_NEXT_REWRITE or IP_LOOKUP_NEXT_ARP, otherwise
2721  the packet will be dropped.
2722  - <code>adj->rewrite_header</code>
2723  - Rewrite string length, rewrite string, next_index
2724 
2725  @em Sets:
2726  - <code>b->current_data, b->current_length</code>
2727  - Updated net of applying the rewrite string
2728 
2729  <em>Next Indices:</em>
2730  - <code> adj->rewrite_header.next_index </code>
2731  or @c error-drop
2732 */
2733 static uword
2735  vlib_node_runtime_t * node, 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 
2743 static uword
2745  vlib_node_runtime_t * node, 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 
2753 static uword
2755  vlib_node_runtime_t * node, 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 
2763 /* *INDENT-OFF* */
2765  .function = ip4_rewrite,
2766  .name = "ip4-rewrite",
2767  .vector_size = sizeof (u32),
2768 
2769  .format_trace = format_ip4_rewrite_trace,
2770 
2771  .n_next_nodes = 2,
2772  .next_nodes = {
2773  [IP4_REWRITE_NEXT_DROP] = "error-drop",
2774  [IP4_REWRITE_NEXT_ICMP_ERROR] = "ip4-icmp-error",
2775  },
2776 };
2778 
2780  .function = ip4_rewrite_mcast,
2781  .name = "ip4-rewrite-mcast",
2782  .vector_size = sizeof (u32),
2783 
2784  .format_trace = format_ip4_rewrite_trace,
2785  .sibling_of = "ip4-rewrite",
2786 };
2788 
2790  .function = ip4_midchain,
2791  .name = "ip4-midchain",
2792  .vector_size = sizeof (u32),
2793  .format_trace = format_ip4_forward_next_trace,
2794  .sibling_of = "ip4-rewrite",
2795 };
2797 /* *INDENT-ON */
2798 
2799 static clib_error_t *
2801  unformat_input_t * input, vlib_cli_command_t * cmd)
2802 {
2803  vnet_main_t *vnm = vnet_get_main ();
2805  clib_error_t *error = 0;
2806  u32 sw_if_index, table_id;
2807 
2808  sw_if_index = ~0;
2809 
2810  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
2811  {
2812  error = clib_error_return (0, "unknown interface `%U'",
2813  format_unformat_error, input);
2814  goto done;
2815  }
2816 
2817  if (unformat (input, "%d", &table_id))
2818  ;
2819  else
2820  {
2821  error = clib_error_return (0, "expected table id `%U'",
2822  format_unformat_error, input);
2823  goto done;
2824  }
2825 
2826  /*
2827  * If the interface already has in IP address, then a change int
2828  * VRF is not allowed. The IP address applied must first be removed.
2829  * We do not do that automatically here, since VPP has no knowledge
2830  * of whether thoses subnets are valid in the destination VRF.
2831  */
2832  /* *INDENT-OFF* */
2834  ia, sw_if_index,
2835  1 /* honor unnumbered */,
2836  ({
2837  ip4_address_t * a;
2838 
2839  a = ip_interface_address_get_address (&ip4_main.lookup_main, ia);
2840  error = clib_error_return (0, "interface %U has address %U",
2841  format_vnet_sw_if_index_name, vnm,
2842  sw_if_index,
2843  format_ip4_address, a);
2844  goto done;
2845  }));
2846  /* *INDENT-ON* */
2847 
2848 {
2849  ip4_main_t *im = &ip4_main;
2850  u32 fib_index;
2851 
2852  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
2853 
2854  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
2855  im->fib_index_by_sw_if_index[sw_if_index] = fib_index;
2856 
2857  fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
2858  vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
2859  im->mfib_index_by_sw_if_index[sw_if_index] = fib_index;
2860 }
2861 
2862 done:
2863 return error;
2864 }
2865 
2866 /*?
2867  * Place the indicated interface into the supplied IPv4 FIB table (also known
2868  * as a VRF). If the FIB table does not exist, this command creates it. To
2869  * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
2870  * FIB table will only be displayed if a route has been added to the table, or
2871  * an IP Address is assigned to an interface in the table (which adds a route
2872  * automatically).
2873  *
2874  * @note IP addresses added after setting the interface IP table are added to
2875  * the indicated FIB table. If an IP address is added prior to changing the
2876  * table then this is an error. The control plane must remove these addresses
2877  * first and then change the table. VPP will not automatically move the
2878  * addresses from the old to the new table as it does not know the validity
2879  * of such a change.
2880  *
2881  * @cliexpar
2882  * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
2883  * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
2884  ?*/
2885 /* *INDENT-OFF* */
2886 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
2887 {
2888  .path = "set interface ip table",
2889  .function = add_del_interface_table,
2890  .short_help = "set interface ip table <interface> <table-id>",
2891 };
2892 /* *INDENT-ON* */
2893 
2894 int
2896 {
2897  ip4_fib_mtrie_t *mtrie0;
2898  ip4_fib_mtrie_leaf_t leaf0;
2899  u32 lbi0;
2900 
2901  mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
2902 
2903  leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
2904  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 0);
2905  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 1);
2906  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 2);
2907  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 3);
2908 
2909  /* Handle default route. */
2910  leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
2911 
2912  lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
2913 
2914  return lbi0 == ip4_fib_table_lookup_lb (ip4_fib_get (fib_index0), a);
2915 }
2916 
2917 static clib_error_t *
2919  unformat_input_t * input, vlib_cli_command_t * cmd)
2920 {
2921  ip4_fib_t *fib;
2922  u32 table_id = 0;
2923  f64 count = 1;
2924  u32 n;
2925  int i;
2926  ip4_address_t ip4_base_address;
2927  u64 errors = 0;
2928 
2929  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2930  {
2931  if (unformat (input, "table %d", &table_id))
2932  {
2933  /* Make sure the entry exists. */
2934  fib = ip4_fib_get (table_id);
2935  if ((fib) && (fib->index != table_id))
2936  return clib_error_return (0, "<fib-index> %d does not exist",
2937  table_id);
2938  }
2939  else if (unformat (input, "count %f", &count))
2940  ;
2941 
2942  else if (unformat (input, "%U",
2943  unformat_ip4_address, &ip4_base_address))
2944  ;
2945  else
2946  return clib_error_return (0, "unknown input `%U'",
2947  format_unformat_error, input);
2948  }
2949 
2950  n = count;
2951 
2952  for (i = 0; i < n; i++)
2953  {
2954  if (!ip4_lookup_validate (&ip4_base_address, table_id))
2955  errors++;
2956 
2957  ip4_base_address.as_u32 =
2958  clib_host_to_net_u32 (1 +
2959  clib_net_to_host_u32 (ip4_base_address.as_u32));
2960  }
2961 
2962  if (errors)
2963  vlib_cli_output (vm, "%llu errors out of %d lookups\n", errors, n);
2964  else
2965  vlib_cli_output (vm, "No errors in %d lookups\n", n);
2966 
2967  return 0;
2968 }
2969 
2970 /*?
2971  * Perform a lookup of an IPv4 Address (or range of addresses) in the
2972  * given FIB table to determine if there is a conflict with the
2973  * adjacency table. The fib-id can be determined by using the
2974  * '<em>show ip fib</em>' command. If fib-id is not entered, default value
2975  * of 0 is used.
2976  *
2977  * @todo This command uses fib-id, other commands use table-id (not
2978  * just a name, they are different indexes). Would like to change this
2979  * to table-id for consistency.
2980  *
2981  * @cliexpar
2982  * Example of how to run the test lookup command:
2983  * @cliexstart{test lookup 172.16.1.1 table 1 count 2}
2984  * No errors in 2 lookups
2985  * @cliexend
2986 ?*/
2987 /* *INDENT-OFF* */
2988 VLIB_CLI_COMMAND (lookup_test_command, static) =
2989 {
2990  .path = "test lookup",
2991  .short_help = "test lookup <ipv4-addr> [table <fib-id>] [count <nn>]",
2992  .function = test_lookup_command_fn,
2993 };
2994 /* *INDENT-ON* */
2995 
2996 int
2997 vnet_set_ip4_flow_hash (u32 table_id, u32 flow_hash_config)
2998 {
2999  ip4_main_t *im4 = &ip4_main;
3000  ip4_fib_t *fib;
3001  uword *p = hash_get (im4->fib_index_by_table_id, table_id);
3002 
3003  if (p == 0)
3004  return VNET_API_ERROR_NO_SUCH_FIB;
3005 
3006  fib = ip4_fib_get (p[0]);
3007 
3008  fib->flow_hash_config = flow_hash_config;
3009  return 0;
3010 }
3011 
3012 static clib_error_t *
3014  unformat_input_t * input,
3015  vlib_cli_command_t * cmd)
3016 {
3017  int matched = 0;
3018  u32 table_id = 0;
3019  u32 flow_hash_config = 0;
3020  int rv;
3021 
3022  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3023  {
3024  if (unformat (input, "table %d", &table_id))
3025  matched = 1;
3026 #define _(a,v) \
3027  else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;}
3029 #undef _
3030  else
3031  break;
3032  }
3033 
3034  if (matched == 0)
3035  return clib_error_return (0, "unknown input `%U'",
3036  format_unformat_error, input);
3037 
3038  rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3039  switch (rv)
3040  {
3041  case 0:
3042  break;
3043 
3044  case VNET_API_ERROR_NO_SUCH_FIB:
3045  return clib_error_return (0, "no such FIB table %d", table_id);
3046 
3047  default:
3048  clib_warning ("BUG: illegal flow hash config 0x%x", flow_hash_config);
3049  break;
3050  }
3051 
3052  return 0;
3053 }
3054 
3055 /*?
3056  * Configure the set of IPv4 fields used by the flow hash.
3057  *
3058  * @cliexpar
3059  * Example of how to set the flow hash on a given table:
3060  * @cliexcmd{set ip flow-hash table 7 dst sport dport proto}
3061  * Example of display the configured flow hash:
3062  * @cliexstart{show ip fib}
3063  * ipv4-VRF:0, fib_index 0, flow hash: src dst sport dport proto
3064  * 0.0.0.0/0
3065  * unicast-ip4-chain
3066  * [@0]: dpo-load-balance: [index:0 buckets:1 uRPF:0 to:[0:0]]
3067  * [0] [@0]: dpo-drop ip6
3068  * 0.0.0.0/32
3069  * unicast-ip4-chain
3070  * [@0]: dpo-load-balance: [index:1 buckets:1 uRPF:1 to:[0:0]]
3071  * [0] [@0]: dpo-drop ip6
3072  * 224.0.0.0/8
3073  * unicast-ip4-chain
3074  * [@0]: dpo-load-balance: [index:3 buckets:1 uRPF:3 to:[0:0]]
3075  * [0] [@0]: dpo-drop ip6
3076  * 6.0.1.2/32
3077  * unicast-ip4-chain
3078  * [@0]: dpo-load-balance: [index:30 buckets:1 uRPF:29 to:[0:0]]
3079  * [0] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
3080  * 7.0.0.1/32
3081  * unicast-ip4-chain
3082  * [@0]: dpo-load-balance: [index:31 buckets:4 uRPF:30 to:[0:0]]
3083  * [0] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3084  * [1] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3085  * [2] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3086  * [3] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
3087  * 240.0.0.0/8
3088  * unicast-ip4-chain
3089  * [@0]: dpo-load-balance: [index:2 buckets:1 uRPF:2 to:[0:0]]
3090  * [0] [@0]: dpo-drop ip6
3091  * 255.255.255.255/32
3092  * unicast-ip4-chain
3093  * [@0]: dpo-load-balance: [index:4 buckets:1 uRPF:4 to:[0:0]]
3094  * [0] [@0]: dpo-drop ip6
3095  * ipv4-VRF:7, fib_index 1, flow hash: dst sport dport proto
3096  * 0.0.0.0/0
3097  * unicast-ip4-chain
3098  * [@0]: dpo-load-balance: [index:12 buckets:1 uRPF:11 to:[0:0]]
3099  * [0] [@0]: dpo-drop ip6
3100  * 0.0.0.0/32
3101  * unicast-ip4-chain
3102  * [@0]: dpo-load-balance: [index:13 buckets:1 uRPF:12 to:[0:0]]
3103  * [0] [@0]: dpo-drop ip6
3104  * 172.16.1.0/24
3105  * unicast-ip4-chain
3106  * [@0]: dpo-load-balance: [index:17 buckets:1 uRPF:16 to:[0:0]]
3107  * [0] [@4]: ipv4-glean: af_packet0
3108  * 172.16.1.1/32
3109  * unicast-ip4-chain
3110  * [@0]: dpo-load-balance: [index:18 buckets:1 uRPF:17 to:[1:84]]
3111  * [0] [@2]: dpo-receive: 172.16.1.1 on af_packet0
3112  * 172.16.1.2/32
3113  * unicast-ip4-chain
3114  * [@0]: dpo-load-balance: [index:21 buckets:1 uRPF:20 to:[0:0]]
3115  * [0] [@5]: ipv4 via 172.16.1.2 af_packet0: IP4: 02:fe:9e:70:7a:2b -> 26:a5:f6:9c:3a:36
3116  * 172.16.2.0/24
3117  * unicast-ip4-chain
3118  * [@0]: dpo-load-balance: [index:19 buckets:1 uRPF:18 to:[0:0]]
3119  * [0] [@4]: ipv4-glean: af_packet1
3120  * 172.16.2.1/32
3121  * unicast-ip4-chain
3122  * [@0]: dpo-load-balance: [index:20 buckets:1 uRPF:19 to:[0:0]]
3123  * [0] [@2]: dpo-receive: 172.16.2.1 on af_packet1
3124  * 224.0.0.0/8
3125  * unicast-ip4-chain
3126  * [@0]: dpo-load-balance: [index:15 buckets:1 uRPF:14 to:[0:0]]
3127  * [0] [@0]: dpo-drop ip6
3128  * 240.0.0.0/8
3129  * unicast-ip4-chain
3130  * [@0]: dpo-load-balance: [index:14 buckets:1 uRPF:13 to:[0:0]]
3131  * [0] [@0]: dpo-drop ip6
3132  * 255.255.255.255/32
3133  * unicast-ip4-chain
3134  * [@0]: dpo-load-balance: [index:16 buckets:1 uRPF:15 to:[0:0]]
3135  * [0] [@0]: dpo-drop ip6
3136  * @cliexend
3137 ?*/
3138 /* *INDENT-OFF* */
3139 VLIB_CLI_COMMAND (set_ip_flow_hash_command, static) =
3140 {
3141  .path = "set ip flow-hash",
3142  .short_help =
3143  "set ip flow-hash table <table-id> [src] [dst] [sport] [dport] [proto] [reverse]",
3144  .function = set_ip_flow_hash_command_fn,
3145 };
3146 /* *INDENT-ON* */
3147 
3148 int
3150  u32 table_index)
3151 {
3152  vnet_main_t *vnm = vnet_get_main ();
3154  ip4_main_t *ipm = &ip4_main;
3155  ip_lookup_main_t *lm = &ipm->lookup_main;
3157  ip4_address_t *if_addr;
3158 
3159  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
3160  return VNET_API_ERROR_NO_MATCHING_INTERFACE;
3161 
3162  if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
3163  return VNET_API_ERROR_NO_SUCH_ENTRY;
3164 
3166  lm->classify_table_index_by_sw_if_index[sw_if_index] = table_index;
3167 
3168  if_addr = ip4_interface_first_address (ipm, sw_if_index, NULL);
3169 
3170  if (NULL != if_addr)
3171  {
3172  fib_prefix_t pfx = {
3173  .fp_len = 32,
3174  .fp_proto = FIB_PROTOCOL_IP4,
3175  .fp_addr.ip4 = *if_addr,
3176  };
3177  u32 fib_index;
3178 
3180  sw_if_index);
3181 
3182 
3183  if (table_index != (u32) ~ 0)
3184  {
3185  dpo_id_t dpo = DPO_INVALID;
3186 
3187  dpo_set (&dpo,
3188  DPO_CLASSIFY,
3189  DPO_PROTO_IP4,
3190  classify_dpo_create (DPO_PROTO_IP4, table_index));
3191 
3193  &pfx,
3195  FIB_ENTRY_FLAG_NONE, &dpo);
3196  dpo_reset (&dpo);
3197  }
3198  else
3199  {
3200  fib_table_entry_special_remove (fib_index,
3201  &pfx, FIB_SOURCE_CLASSIFY);
3202  }
3203  }
3204 
3205  return 0;
3206 }
3207 
3208 static clib_error_t *
3210  unformat_input_t * input,
3211  vlib_cli_command_t * cmd)
3212 {
3213  u32 table_index = ~0;
3214  int table_index_set = 0;
3215  u32 sw_if_index = ~0;
3216  int rv;
3217 
3218  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3219  {
3220  if (unformat (input, "table-index %d", &table_index))
3221  table_index_set = 1;
3222  else if (unformat (input, "intfc %U", unformat_vnet_sw_interface,
3223  vnet_get_main (), &sw_if_index))
3224  ;
3225  else
3226  break;
3227  }
3228 
3229  if (table_index_set == 0)
3230  return clib_error_return (0, "classify table-index must be specified");
3231 
3232  if (sw_if_index == ~0)
3233  return clib_error_return (0, "interface / subif must be specified");
3234 
3235  rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3236 
3237  switch (rv)
3238  {
3239  case 0:
3240  break;
3241 
3242  case VNET_API_ERROR_NO_MATCHING_INTERFACE:
3243  return clib_error_return (0, "No such interface");
3244 
3245  case VNET_API_ERROR_NO_SUCH_ENTRY:
3246  return clib_error_return (0, "No such classifier table");
3247  }
3248  return 0;
3249 }
3250 
3251 /*?
3252  * Assign a classification table to an interface. The classification
3253  * table is created using the '<em>classify table</em>' and '<em>classify session</em>'
3254  * commands. Once the table is create, use this command to filter packets
3255  * on an interface.
3256  *
3257  * @cliexpar
3258  * Example of how to assign a classification table to an interface:
3259  * @cliexcmd{set ip classify intfc GigabitEthernet2/0/0 table-index 1}
3260 ?*/
3261 /* *INDENT-OFF* */
3262 VLIB_CLI_COMMAND (set_ip_classify_command, static) =
3263 {
3264  .path = "set ip classify",
3265  .short_help =
3266  "set ip classify intfc <interface> table-index <classify-idx>",
3267  .function = set_ip_classify_command_fn,
3268 };
3269 /* *INDENT-ON* */
3270 
3271 /*
3272  * fd.io coding-style-patch-verification: ON
3273  *
3274  * Local Variables:
3275  * eval: (c-set-style "gnu")
3276  * End:
3277  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:417
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, fib_protocol_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, 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:716
#define vnet_rewrite_one_header(rw0, p0, most_likely_size)
Definition: rewrite.h:283
u16 lb_n_buckets
number of buckets in the load-balance.
Definition: load_balance.h:88
#define vnet_fixup_one_header(rw0, addr, p0, clear_first_bit)
Definition: rewrite.h:310
ip_lookup_next_t
Common (IP4/IP6) next index stored in adjacency.
Definition: lookup.h:60
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
vmrglw vmrglh hi
vlib_combined_counter_main_t lbm_to_counters
Definition: load_balance.h:46
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:941
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
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:710
#define CLIB_UNUSED(x)
Definition: clib.h:79
static vlib_node_registration_t ip4_drop_node
(constructor) VLIB_REGISTER_NODE (ip4_drop_node)
Definition: ip4_forward.c:1363
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:1483
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:2997
static int fib_urpf_check_size(index_t ui)
Data-Plane function to check the size of an uRPF list, (i.e.
static uword ip4_drop(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1351
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:138
a
Definition: bitmap.h:516
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:290
ip4_address_t src_address
Definition: ip4_packet.h:163
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:383
ip_interface_address_t * if_address_pool
Pool of addresses that are assigned to interfaces.
Definition: lookup.h:337
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_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:855
struct ip_adjacency_t_::@138::@139 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
vnet_interface_main_t interface_main
Definition: vnet.h:57
static uword ip4_midchain(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:2744
format_function_t format_ip4_header
Definition: format.h:86
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:512
#define PREDICT_TRUE(x)
Definition: clib.h:98
static int ip4_header_bytes(ip4_header_t *i)
Definition: ip4_packet.h:226
#define NULL
Definition: clib.h:55
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
Definition: ip4.h:295
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:185
IP unicast adjacency.
Definition: lookup.h:193
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:892
static void * clib_random_buffer_get_data(clib_random_buffer_t *b, uword n_bytes)
Definition: random_buffer.h:78
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:459
flow_hash_config_t lb_hash_config
the hash config to use when selecting a bucket.
Definition: load_balance.h:128
#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:2918
#define vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, next0, next1, next2, next3)
Finish enqueueing four buffers forward in the graph.
Definition: buffer_node.h:138
unformat_function_t unformat_pg_ip4_header
Definition: format.h:91
ip4_rewrite_next_t
Definition: ip4_forward.c:2315
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:982
ip_lookup_main_t lookup_main
Definition: ip4.h:109
uword ip_csum_t
Definition: ip_packet.h:90
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:93
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:120
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
union ip_adjacency_t_::@138 sub_type
unformat_function_t unformat_vnet_sw_interface
static uword ip4_arp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:2180
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:418
static void vlib_prefetch_combined_counter(const vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index)
Pre-fetch a per-thread combined counter for the given object index.
Definition: counter.h:226
Definition: fib_entry.h:229
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:100
VNET_FEATURE_ARC_INIT(ip4_unicast, static)
struct _tcp_header tcp_header_t
u32 neighbor_probe_adj_index
Definition: lookup.h:303
u8 mcast_feature_arc_index
Feature arc indices.
Definition: lookup.h:350
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:1062
#define IP4_FIB_MTRIE_LEAF_EMPTY
Definition: ip4_mtrie.h:54
u32 index
Definition: ip4.h:60
static pg_node_t * pg_get_node(uword node_index)
Definition: pg.h:350
static ip4_fib_mtrie_leaf_t ip4_fib_mtrie_lookup_step(ip4_fib_mtrie_t *m, ip4_fib_mtrie_leaf_t current_leaf, const ip4_address_t *dst_address, u32 dst_address_byte_index)
Definition: ip4_mtrie.h:164
u8 output_feature_arc_index
Definition: lookup.h:352
vlib_rx_or_tx_t
Definition: defs.h:44
format_function_t format_ip4_address
Definition: format.h:79
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:87
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:1944
u32 * mfib_index_by_sw_if_index
Table index indexed by software interface.
Definition: ip4.h:123
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:67
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:818
unformat_function_t unformat_ip4_address
Definition: format.h:76
#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:170
ethernet_arp_ip4_over_ethernet_address_t ip4_over_ethernet[2]
Definition: arp_packet.h:136
ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
Definition: ip_checksum.c:43
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
format_function_t format_ip_adjacency
Definition: format.h:58
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:388
#define always_inline
Definition: clib.h:84
#define IP_BUFFER_L4_CHECKSUM_CORRECT
Definition: buffer.h:50
static uword pow2_mask(uword x)
Definition: clib.h:257
static uword format_get_indent(u8 *s)
Definition: format.h:72
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:734
u16 lb_n_buckets_minus_1
number of buckets in the load-balance - 1.
Definition: load_balance.h:93
ip4_address_t dst_address
Definition: ip4_packet.h:163
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:113
ip4_error_t
Definition: ip4_error.h:79
int i32
Definition: types.h:81
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:164
u32 ip4_fib_mtrie_leaf_t
Definition: ip4_mtrie.h:52
Aggregrate type for a prefix.
Definition: fib_types.h:160
#define clib_error_return(e, args...)
Definition: error.h:111
#define IP4_LOOKUP_NEXT_NODES
Definition: lookup.h:114
vlib_node_registration_t ip4_arp_node
(constructor) VLIB_REGISTER_NODE (ip4_arp_node)
Definition: ip4_forward.c:2200
unsigned long u64
Definition: types.h:89
void ip4_sw_interface_enable_disable(u32 sw_if_index, u32 is_enable)
Definition: ip4_forward.c:826
static void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:232
#define LOG2_IP_BUFFER_L4_CHECKSUM_CORRECT
Definition: buffer.h:48
u16 fp_len
The mask length.
Definition: fib_types.h:164
#define vlib_call_init_function(vm, x)
Definition: init.h:162
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: lookup.h:78
#define foreach_notrace_ip4_arp_error
Definition: ip4_forward.c:2220
static clib_error_t * vnet_feature_init(vlib_main_t *vm)
Definition: feature.c:22
adj_index_t fib_entry_get_adj(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:447
static u32 ip4_fib_mtrie_leaf_get_adj_index(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:76
Definition: fib_entry.h:227
vlib_node_registration_t ip4_rewrite_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_node)
Definition: ip4_forward.c:2764
static int ip4_is_fragment(ip4_header_t *i)
Definition: ip4_packet.h:204
vnet_api_error_t api_errno
Definition: vnet.h:77
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:146
Definition: fib_entry.h:232
#define hash_get(h, key)
Definition: hash.h:248
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
uword * fib_index_by_table_id
Hash table mapping table id to fib index.
Definition: ip4.h:130
vlib_node_registration_t ip4_input_node
Global ip4 input node.
Definition: ip4_input.c:416
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:71
u32 * classify_table_index_by_sw_if_index
First table index to use for this interface, ~0 => none.
Definition: lookup.h:347
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:183
vlib_node_registration_t ip4_local_node
(constructor) VLIB_REGISTER_NODE (ip4_local_node)
Definition: ip4_forward.c:1887
index_t classify_dpo_create(dpo_proto_t proto, u32 classify_table_index)
Definition: classify_dpo.c:43
clib_error_t * arp_notrace_init(vlib_main_t *vm)
Definition: ip4_forward.c:2227
dpo_type_t dpoi_type
the type
Definition: dpo.h:150
static const dpo_id_t * load_balance_get_bucket_i(const load_balance_t *lb, u32 bucket)
Definition: load_balance.h:202
void ip4_register_protocol(u32 protocol, u32 node_index)
Definition: ip4_forward.c:1932
uword vlib_error_drop_buffers(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u32 next_buffer_stride, u32 n_buffers, u32 next_index, u32 drop_error_node, u32 drop_error_code)
Definition: error.c:44
struct _unformat_input_t unformat_input_t
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:1984
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
static uword ip4_punt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1357
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:1244
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
u8 * ip_enabled_by_sw_if_index
Definition: ip4.h:126
static uword ip4_local_end_of_arc(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1906
static uword ip4_glean(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:2186
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:2322
The FIB DPO provieds;.
Definition: load_balance.h:84
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1117
#define PREDICT_FALSE(x)
Definition: clib.h:97
u8 local_next_by_ip_protocol[256]
Table mapping ip protocol to ip[46]-local node next index.
Definition: lookup.h:370
static uword ip4_load_balance(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:521
load_balance_main_t load_balance_main
The one instance of load-balance main.
Definition: load_balance.c:55
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
Definition: buffer_node.h:70
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
Definition: buffer_node.h:216
#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:350
vlib_combined_counter_main_t adjacency_counters
Adjacency packet counters.
Definition: adj.c:31
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:113
static vlib_node_registration_t ip4_punt_node
(constructor) VLIB_REGISTER_NODE (ip4_punt_node)
Definition: ip4_forward.c:1377
static u8 * format_ip4_lookup_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1209
clib_error_t * ip4_probe_neighbor(vlib_main_t *vm, ip4_address_t *dst, u32 sw_if_index)
Definition: ip4_forward.c:2246
static u8 * format_ip4_rewrite_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1225
static uword ip4_policer_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: node_funcs.c:850
static void vlib_buffer_copy_trace_flag(vlib_main_t *vm, vlib_buffer_t *b, u32 bi_target)
Definition: trace_funcs.h:134
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
#define VNET_BUFFER_LOCALLY_ORIGINATED
Definition: buffer.h:68
u16 n_vectors
Definition: node.h:344
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
vlib_main_t * vm
Definition: buffer.c:276
vec_header_t h
Definition: buffer.c:275
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
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:798
void icmp4_error_set_vnet_buffer(vlib_buffer_t *b, u8 type, u8 code, u32 data)
Definition: icmp4.c:431
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:94
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_fib.h:80
static clib_error_t * add_del_interface_table(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_forward.c:2800
Definition: ip4.h:48
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
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:88
#define clib_memcpy(a, b, c)
Definition: string.h:69
int ip4_lookup_validate(ip4_address_t *a, u32 fib_index0)
Definition: ip4_forward.c:2895
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:3013
unformat_function_t * unformat_edit
Definition: pg.h:307
u8 packet_data[64-1 *sizeof(u32)]
Definition: ip4_forward.c:1191
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
void ip_lookup_init(ip_lookup_main_t *lm, u32 is_ip6)
Definition: lookup.c:189
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:238
#define ARRAY_LEN(x)
Definition: clib.h:59
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: lookup.h:73
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:157
vlib_combined_counter_main_t lbm_via_counters
Definition: load_balance.h:47
static void ip4_addr_fib_init(ip4_address_fib_t *addr_fib, ip4_address_t *address, u32 fib_index)
Definition: ip4_packet.h:66
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:3209
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
static clib_error_t * ip4_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: ip4_forward.c:1097
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:69
#define foreach_flow_hash_bit
Definition: lookup.h:154
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:288
vlib_packet_template_t ip4_arp_request_packet_template
Template used to generate IP4 ARP packets.
Definition: ip4.h:141
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:455
vlib_node_registration_t ip4_load_balance_node
(constructor) VLIB_REGISTER_NODE (ip4_load_balance_node)
Definition: ip4_forward.c:700
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:536
#define ASSERT(truth)
#define IP4_FIB_MTRIE_LEAF_ROOT
Definition: ip4_mtrie.h:55
index_t lb_urpf
This is the index of the uRPF list for this LB.
Definition: load_balance.h:123
unsigned int u32
Definition: types.h:88
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
Definition: counter.h:211
u32 ip4_tcp_udp_validate_checksum(vlib_main_t *vm, vlib_buffer_t *p0)
Definition: ip4_forward.c:1449
#define IP_BUFFER_L4_CHECKSUM_COMPUTED
Definition: buffer.h:49
static load_balance_t * load_balance_get(index_t lbi)
Definition: load_balance.h:193
#define hash_v3_finalize32(a, b, c)
Definition: hash.h:540
IPv4 main type.
Definition: ip4.h:107
Classify.
Definition: fib_entry.h:44
vlib_node_registration_t ip4_glean_node
(constructor) VLIB_REGISTER_NODE (ip4_glean_node)
Definition: ip4_forward.c:2210
VLIB_NODE_FUNCTION_MULTIARCH(ip4_lookup_node, ip4_lookup)
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:109
struct ip_adjacency_t_::@138::@140 midchain
IP_LOOKUP_NEXT_MIDCHAIN.
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:954
vlib_node_registration_t ip4_midchain_node
(constructor) VLIB_REGISTER_NODE (ip4_midchain_node)
Definition: ip4_forward.c:2789
static uword ip4_inacl(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip_input_acl.c:386
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:259
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:22
vlib_node_registration_t ip4_rewrite_mcast_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_mcast_node)
Definition: ip4_forward.c:2779
Route added as a result of interface configuration.
Definition: fib_entry.h:50
clib_error_t * ip4_lookup_init(vlib_main_t *vm)
Definition: ip4_forward.c:1120
u32 flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
Definition: lookup.h:165
#define VNET_FEATURES(...)
Definition: feature.h:368
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static uword is_pow2(uword x)
Definition: clib.h:272
static uword ip4_local(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1881
u64 uword
Definition: types.h:112
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
#define vec_elt(v, i)
Get vector value at index i.
u8 ucast_feature_arc_index
Definition: lookup.h:351
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1394
Definition: defs.h:47
unsigned short u16
Definition: types.h:57
u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: mfib_table.c:420
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:162
VNET_FEATURE_INIT(ip4_flow_classify, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:142
unsigned char u8
Definition: types.h:56
ip_lookup_next_t lookup_next_index
Definition: lookup.h:204
Definition: fib_entry.h:228
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:617
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
ip4_fib_mtrie_t mtrie
Definition: ip4.h:54
u8 * format_ip4_forward_next_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1196
#define DPO_INVALID
An initialiser for DPOs declared on the stack.
Definition: dpo.h:173
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_physmem_alloc, char *fmt,...)
Definition: buffer.c:768
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:61
A collection of combined counters.
Definition: counter.h:180
static uword ip4_flow_classify(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
flow_hash_config_t flow_hash_config
Definition: ip4.h:63
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
static void ip4_del_interface_routes(ip4_main_t *im, u32 fib_index, ip4_address_t *address, u32 address_length)
Definition: ip4_forward.c:806
#define vnet_buffer(b)
Definition: buffer.h:294
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)
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:143
int vnet_set_ip4_classify_intfc(vlib_main_t *vm, u32 sw_if_index, u32 table_index)
Definition: ip4_forward.c:3149
u8 data[0]
Packet data.
Definition: buffer.h:152
This packet is to be rewritten and forwarded to the next processing node.
Definition: lookup.h:83
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:194
#define vec_foreach(var, vec)
Vector iterator.
ip_local_next_t
Definition: lookup.h:317
index_t ip4_fib_table_lookup_lb(ip4_fib_t *fib, const ip4_address_t *addr)
Definition: ip4_fib.c:260
static uword ip4_drop_or_punt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, ip4_error_t error_code)
Definition: ip4_forward.c:1331
static uword ip4_rewrite_mcast(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:2754
u16 flags
Copy of main node flags.
Definition: node.h:449
u16 dpoi_next_node
The next VLIB node to follow.
Definition: dpo.h:158
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(ip4_sw_interface_add_del)
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:410
static uword ip4_lookup(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
IPv4 lookup node.
Definition: ip4_forward.c:501
static uword ip4_rewrite(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
IPv4 rewrite node.
Definition: ip4_forward.c:2734
#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:485
#define vnet_rewrite_two_headers(rw0, rw1, p0, p1, most_likely_size)
Definition: rewrite.h:288
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
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:203
#define BITS(x)
Definition: clib.h:58
static uword ip4_vxlan_bypass(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: decap.c:1180
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:577
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
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:238
clib_random_buffer_t random_buffer
Definition: main.h:153
Definition: pg.h:304
static u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:145
static int adj_are_counters_enabled(void)
Get the global configuration option for enabling per-adj counters.
Definition: adj.h:137
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:971
static char * ip4_arp_error_strings[]
Definition: ip4_forward.c:2191
Definition: defs.h:46
static uword ip4_lookup_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int lookup_for_responses_to_locally_received_packets)
Definition: ip4_forward.c:69
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:225
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
static ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:377
struct ip_adjacency_t_::@138::@141 glean
IP_LOOKUP_NEXT_GLEAN.
static vlib_node_registration_t ip4_local_end_of_arc_node
(constructor) VLIB_REGISTER_NODE (ip4_local_end_of_arc_node)
Definition: ip4_forward.c:1913
u32 fib_masks[33]
Definition: ip4.h:117
ip4_fib_mtrie_leaf_t default_leaf
Definition: ip4_mtrie.h:145
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:224
static_always_inline void vnet_feature_arc_start(u8 arc, u32 sw_if_index, u32 *next0, vlib_buffer_t *b0)
Definition: feature.h:201
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109