FD.io VPP  v17.04.2-2-ga8f93f8
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 (ip1->checksum == ip4_header_checksum (ip1));
2465  }
2466  else
2467  {
2469  }
2470 
2471  /* Rewrite packet header and updates lengths. */
2472  adj0 = ip_get_adjacency (lm, adj_index0);
2473  adj1 = ip_get_adjacency (lm, adj_index1);
2474 
2475  /* Worth pipelining. No guarantee that adj0,1 are hot... */
2476  rw_len0 = adj0[0].rewrite_header.data_bytes;
2477  rw_len1 = adj1[0].rewrite_header.data_bytes;
2478  vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
2479  vnet_buffer (p1)->ip.save_rewrite_length = rw_len1;
2480 
2481  /* Check MTU of outgoing interface. */
2482  error0 =
2483  (vlib_buffer_length_in_chain (vm, p0) >
2484  adj0[0].
2485  rewrite_header.max_l3_packet_bytes ? IP4_ERROR_MTU_EXCEEDED :
2486  error0);
2487  error1 =
2488  (vlib_buffer_length_in_chain (vm, p1) >
2489  adj1[0].
2490  rewrite_header.max_l3_packet_bytes ? IP4_ERROR_MTU_EXCEEDED :
2491  error1);
2492 
2493  /* Don't adjust the buffer for ttl issue; icmp-error node wants
2494  * to see the IP headerr */
2495  if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
2496  {
2497  next0 = adj0[0].rewrite_header.next_index;
2498  p0->current_data -= rw_len0;
2499  p0->current_length += rw_len0;
2500  tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
2501  vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
2502 
2503  if (PREDICT_FALSE
2504  (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2506  tx_sw_if_index0, &next0, p0);
2507  }
2508  if (PREDICT_TRUE (error1 == IP4_ERROR_NONE))
2509  {
2510  next1 = adj1[0].rewrite_header.next_index;
2511  p1->current_data -= rw_len1;
2512  p1->current_length += rw_len1;
2513 
2514  tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index;
2515  vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1;
2516 
2517  if (PREDICT_FALSE
2518  (adj1[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2520  tx_sw_if_index1, &next1, p1);
2521  }
2522 
2523  /* Guess we are only writing on simple Ethernet header. */
2524  vnet_rewrite_two_headers (adj0[0], adj1[0],
2525  ip0, ip1, sizeof (ethernet_header_t));
2526 
2527  /*
2528  * Bump the per-adjacency counters
2529  */
2530  if (do_counters)
2531  {
2534  cpu_index,
2535  adj_index0, 1,
2536  vlib_buffer_length_in_chain (vm, p0) + rw_len0);
2537 
2540  cpu_index,
2541  adj_index1, 1,
2542  vlib_buffer_length_in_chain (vm, p1) + rw_len1);
2543  }
2544 
2545  if (is_midchain)
2546  {
2547  adj0->sub_type.midchain.fixup_func (vm, adj0, p0);
2548  adj1->sub_type.midchain.fixup_func (vm, adj1, p1);
2549  }
2550  if (is_mcast)
2551  {
2552  /*
2553  * copy bytes from the IP address into the MAC rewrite
2554  */
2555  vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 1);
2556  vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1, 1);
2557  }
2558 
2559  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
2560  to_next, n_left_to_next,
2561  pi0, pi1, next0, next1);
2562  }
2563 
2564  while (n_left_from > 0 && n_left_to_next > 0)
2565  {
2566  ip_adjacency_t *adj0;
2567  vlib_buffer_t *p0;
2568  ip4_header_t *ip0;
2569  u32 pi0, rw_len0, adj_index0, next0, error0, checksum0;
2570  u32 tx_sw_if_index0;
2571 
2572  pi0 = to_next[0] = from[0];
2573 
2574  p0 = vlib_get_buffer (vm, pi0);
2575 
2576  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
2577 
2578  /* We should never rewrite a pkt using the MISS adjacency */
2579  ASSERT (adj_index0);
2580 
2581  adj0 = ip_get_adjacency (lm, adj_index0);
2582 
2583  ip0 = vlib_buffer_get_current (p0);
2584 
2585  error0 = IP4_ERROR_NONE;
2586  next0 = IP4_REWRITE_NEXT_DROP; /* drop on error */
2587 
2588  /* Decrement TTL & update checksum. */
2590  {
2591  i32 ttl0 = ip0->ttl;
2592 
2593  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
2594 
2595  checksum0 += checksum0 >= 0xffff;
2596 
2597  ip0->checksum = checksum0;
2598 
2599  ASSERT (ip0->ttl > 0);
2600 
2601  ttl0 -= 1;
2602 
2603  ip0->ttl = ttl0;
2604 
2605  ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2606 
2607  if (PREDICT_FALSE (ttl0 <= 0))
2608  {
2609  /*
2610  * If the ttl drops below 1 when forwarding, generate
2611  * an ICMP response.
2612  */
2613  error0 = IP4_ERROR_TIME_EXPIRED;
2615  vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
2616  icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
2617  ICMP4_time_exceeded_ttl_exceeded_in_transit,
2618  0);
2619  }
2620  }
2621  else
2622  {
2624  }
2625 
2626  if (do_counters)
2628  cpu_index, adj_index0);
2629 
2630  /* Guess we are only writing on simple Ethernet header. */
2631  vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
2632  if (is_mcast)
2633  {
2634  /*
2635  * copy bytes from the IP address into the MAC rewrite
2636  */
2637  vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 1);
2638  }
2639 
2640  /* Update packet buffer attributes/set output interface. */
2641  rw_len0 = adj0[0].rewrite_header.data_bytes;
2642  vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
2643 
2644  if (do_counters)
2647  cpu_index, adj_index0, 1,
2648  vlib_buffer_length_in_chain (vm, p0) + rw_len0);
2649 
2650  /* Check MTU of outgoing interface. */
2651  error0 = (vlib_buffer_length_in_chain (vm, p0)
2652  > adj0[0].rewrite_header.max_l3_packet_bytes
2653  ? IP4_ERROR_MTU_EXCEEDED : error0);
2654 
2655  p0->error = error_node->errors[error0];
2656 
2657  /* Don't adjust the buffer for ttl issue; icmp-error node wants
2658  * to see the IP headerr */
2659  if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
2660  {
2661  p0->current_data -= rw_len0;
2662  p0->current_length += rw_len0;
2663  tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
2664 
2665  vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
2666  next0 = adj0[0].rewrite_header.next_index;
2667 
2668  if (is_midchain)
2669  {
2670  adj0->sub_type.midchain.fixup_func (vm, adj0, p0);
2671  }
2672 
2673  if (PREDICT_FALSE
2674  (adj0[0].rewrite_header.flags & VNET_REWRITE_HAS_FEATURES))
2676  tx_sw_if_index0, &next0, p0);
2677 
2678  }
2679 
2680  from += 1;
2681  n_left_from -= 1;
2682  to_next += 1;
2683  n_left_to_next -= 1;
2684 
2685  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2686  to_next, n_left_to_next,
2687  pi0, next0);
2688  }
2689 
2690  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2691  }
2692 
2693  /* Need to do trace after rewrites to pick up new packet data. */
2694  if (node->flags & VLIB_NODE_FLAG_TRACE)
2695  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
2696 
2697  return frame->n_vectors;
2698 }
2699 
2700 
2701 /** @brief IPv4 rewrite node.
2702  @node ip4-rewrite
2703 
2704  This is the IPv4 transit-rewrite node: decrement TTL, fix the ipv4
2705  header checksum, fetch the ip adjacency, check the outbound mtu,
2706  apply the adjacency rewrite, and send pkts to the adjacency
2707  rewrite header's rewrite_next_index.
2708 
2709  @param vm vlib_main_t corresponding to the current thread
2710  @param node vlib_node_runtime_t
2711  @param frame vlib_frame_t whose contents should be dispatched
2712 
2713  @par Graph mechanics: buffer metadata, next index usage
2714 
2715  @em Uses:
2716  - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
2717  - the rewrite adjacency index
2718  - <code>adj->lookup_next_index</code>
2719  - Must be IP_LOOKUP_NEXT_REWRITE or IP_LOOKUP_NEXT_ARP, otherwise
2720  the packet will be dropped.
2721  - <code>adj->rewrite_header</code>
2722  - Rewrite string length, rewrite string, next_index
2723 
2724  @em Sets:
2725  - <code>b->current_data, b->current_length</code>
2726  - Updated net of applying the rewrite string
2727 
2728  <em>Next Indices:</em>
2729  - <code> adj->rewrite_header.next_index </code>
2730  or @c error-drop
2731 */
2732 static uword
2734  vlib_node_runtime_t * node, vlib_frame_t * frame)
2735 {
2736  if (adj_are_counters_enabled ())
2737  return ip4_rewrite_inline (vm, node, frame, 1, 0, 0);
2738  else
2739  return ip4_rewrite_inline (vm, node, frame, 0, 0, 0);
2740 }
2741 
2742 static uword
2744  vlib_node_runtime_t * node, vlib_frame_t * frame)
2745 {
2746  if (adj_are_counters_enabled ())
2747  return ip4_rewrite_inline (vm, node, frame, 1, 1, 0);
2748  else
2749  return ip4_rewrite_inline (vm, node, frame, 0, 1, 0);
2750 }
2751 
2752 static uword
2754  vlib_node_runtime_t * node, vlib_frame_t * frame)
2755 {
2756  if (adj_are_counters_enabled ())
2757  return ip4_rewrite_inline (vm, node, frame, 1, 0, 1);
2758  else
2759  return ip4_rewrite_inline (vm, node, frame, 0, 0, 1);
2760 }
2761 
2762 /* *INDENT-OFF* */
2764  .function = ip4_rewrite,
2765  .name = "ip4-rewrite",
2766  .vector_size = sizeof (u32),
2767 
2768  .format_trace = format_ip4_rewrite_trace,
2769 
2770  .n_next_nodes = 2,
2771  .next_nodes = {
2772  [IP4_REWRITE_NEXT_DROP] = "error-drop",
2773  [IP4_REWRITE_NEXT_ICMP_ERROR] = "ip4-icmp-error",
2774  },
2775 };
2777 
2779  .function = ip4_rewrite_mcast,
2780  .name = "ip4-rewrite-mcast",
2781  .vector_size = sizeof (u32),
2782 
2783  .format_trace = format_ip4_rewrite_trace,
2784  .sibling_of = "ip4-rewrite",
2785 };
2787 
2789  .function = ip4_midchain,
2790  .name = "ip4-midchain",
2791  .vector_size = sizeof (u32),
2792  .format_trace = format_ip4_forward_next_trace,
2793  .sibling_of = "ip4-rewrite",
2794 };
2796 /* *INDENT-ON */
2797 
2798 static clib_error_t *
2800  unformat_input_t * input, vlib_cli_command_t * cmd)
2801 {
2802  vnet_main_t *vnm = vnet_get_main ();
2804  clib_error_t *error = 0;
2805  u32 sw_if_index, table_id;
2806 
2807  sw_if_index = ~0;
2808 
2809  if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
2810  {
2811  error = clib_error_return (0, "unknown interface `%U'",
2812  format_unformat_error, input);
2813  goto done;
2814  }
2815 
2816  if (unformat (input, "%d", &table_id))
2817  ;
2818  else
2819  {
2820  error = clib_error_return (0, "expected table id `%U'",
2821  format_unformat_error, input);
2822  goto done;
2823  }
2824 
2825  /*
2826  * If the interface already has in IP address, then a change int
2827  * VRF is not allowed. The IP address applied must first be removed.
2828  * We do not do that automatically here, since VPP has no knowledge
2829  * of whether thoses subnets are valid in the destination VRF.
2830  */
2831  /* *INDENT-OFF* */
2833  ia, sw_if_index,
2834  1 /* honor unnumbered */,
2835  ({
2836  ip4_address_t * a;
2837 
2838  a = ip_interface_address_get_address (&ip4_main.lookup_main, ia);
2839  error = clib_error_return (0, "interface %U has address %U",
2840  format_vnet_sw_if_index_name, vnm,
2841  sw_if_index,
2842  format_ip4_address, a);
2843  goto done;
2844  }));
2845  /* *INDENT-ON* */
2846 
2847 {
2848  ip4_main_t *im = &ip4_main;
2849  u32 fib_index;
2850 
2851  fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
2852 
2853  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
2854  im->fib_index_by_sw_if_index[sw_if_index] = fib_index;
2855 
2856  fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
2857  vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
2858  im->mfib_index_by_sw_if_index[sw_if_index] = fib_index;
2859 }
2860 
2861 done:
2862 return error;
2863 }
2864 
2865 /*?
2866  * Place the indicated interface into the supplied IPv4 FIB table (also known
2867  * as a VRF). If the FIB table does not exist, this command creates it. To
2868  * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
2869  * FIB table will only be displayed if a route has been added to the table, or
2870  * an IP Address is assigned to an interface in the table (which adds a route
2871  * automatically).
2872  *
2873  * @note IP addresses added after setting the interface IP table are added to
2874  * the indicated FIB table. If an IP address is added prior to changing the
2875  * table then this is an error. The control plane must remove these addresses
2876  * first and then change the table. VPP will not automatically move the
2877  * addresses from the old to the new table as it does not know the validity
2878  * of such a change.
2879  *
2880  * @cliexpar
2881  * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
2882  * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
2883  ?*/
2884 /* *INDENT-OFF* */
2885 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
2886 {
2887  .path = "set interface ip table",
2888  .function = add_del_interface_table,
2889  .short_help = "set interface ip table <interface> <table-id>",
2890 };
2891 /* *INDENT-ON* */
2892 
2893 int
2895 {
2896  ip4_fib_mtrie_t *mtrie0;
2897  ip4_fib_mtrie_leaf_t leaf0;
2898  u32 lbi0;
2899 
2900  mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
2901 
2902  leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
2903  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 0);
2904  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 1);
2905  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 2);
2906  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 3);
2907 
2908  /* Handle default route. */
2909  leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
2910 
2911  lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
2912 
2913  return lbi0 == ip4_fib_table_lookup_lb (ip4_fib_get (fib_index0), a);
2914 }
2915 
2916 static clib_error_t *
2918  unformat_input_t * input, vlib_cli_command_t * cmd)
2919 {
2920  ip4_fib_t *fib;
2921  u32 table_id = 0;
2922  f64 count = 1;
2923  u32 n;
2924  int i;
2925  ip4_address_t ip4_base_address;
2926  u64 errors = 0;
2927 
2928  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2929  {
2930  if (unformat (input, "table %d", &table_id))
2931  {
2932  /* Make sure the entry exists. */
2933  fib = ip4_fib_get (table_id);
2934  if ((fib) && (fib->index != table_id))
2935  return clib_error_return (0, "<fib-index> %d does not exist",
2936  table_id);
2937  }
2938  else if (unformat (input, "count %f", &count))
2939  ;
2940 
2941  else if (unformat (input, "%U",
2942  unformat_ip4_address, &ip4_base_address))
2943  ;
2944  else
2945  return clib_error_return (0, "unknown input `%U'",
2946  format_unformat_error, input);
2947  }
2948 
2949  n = count;
2950 
2951  for (i = 0; i < n; i++)
2952  {
2953  if (!ip4_lookup_validate (&ip4_base_address, table_id))
2954  errors++;
2955 
2956  ip4_base_address.as_u32 =
2957  clib_host_to_net_u32 (1 +
2958  clib_net_to_host_u32 (ip4_base_address.as_u32));
2959  }
2960 
2961  if (errors)
2962  vlib_cli_output (vm, "%llu errors out of %d lookups\n", errors, n);
2963  else
2964  vlib_cli_output (vm, "No errors in %d lookups\n", n);
2965 
2966  return 0;
2967 }
2968 
2969 /*?
2970  * Perform a lookup of an IPv4 Address (or range of addresses) in the
2971  * given FIB table to determine if there is a conflict with the
2972  * adjacency table. The fib-id can be determined by using the
2973  * '<em>show ip fib</em>' command. If fib-id is not entered, default value
2974  * of 0 is used.
2975  *
2976  * @todo This command uses fib-id, other commands use table-id (not
2977  * just a name, they are different indexes). Would like to change this
2978  * to table-id for consistency.
2979  *
2980  * @cliexpar
2981  * Example of how to run the test lookup command:
2982  * @cliexstart{test lookup 172.16.1.1 table 1 count 2}
2983  * No errors in 2 lookups
2984  * @cliexend
2985 ?*/
2986 /* *INDENT-OFF* */
2987 VLIB_CLI_COMMAND (lookup_test_command, static) =
2988 {
2989  .path = "test lookup",
2990  .short_help = "test lookup <ipv4-addr> [table <fib-id>] [count <nn>]",
2991  .function = test_lookup_command_fn,
2992 };
2993 /* *INDENT-ON* */
2994 
2995 int
2996 vnet_set_ip4_flow_hash (u32 table_id, u32 flow_hash_config)
2997 {
2998  ip4_main_t *im4 = &ip4_main;
2999  ip4_fib_t *fib;
3000  uword *p = hash_get (im4->fib_index_by_table_id, table_id);
3001 
3002  if (p == 0)
3003  return VNET_API_ERROR_NO_SUCH_FIB;
3004 
3005  fib = ip4_fib_get (p[0]);
3006 
3007  fib->flow_hash_config = flow_hash_config;
3008  return 0;
3009 }
3010 
3011 static clib_error_t *
3013  unformat_input_t * input,
3014  vlib_cli_command_t * cmd)
3015 {
3016  int matched = 0;
3017  u32 table_id = 0;
3018  u32 flow_hash_config = 0;
3019  int rv;
3020 
3021  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3022  {
3023  if (unformat (input, "table %d", &table_id))
3024  matched = 1;
3025 #define _(a,v) \
3026  else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;}
3028 #undef _
3029  else
3030  break;
3031  }
3032 
3033  if (matched == 0)
3034  return clib_error_return (0, "unknown input `%U'",
3035  format_unformat_error, input);
3036 
3037  rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3038  switch (rv)
3039  {
3040  case 0:
3041  break;
3042 
3043  case VNET_API_ERROR_NO_SUCH_FIB:
3044  return clib_error_return (0, "no such FIB table %d", table_id);
3045 
3046  default:
3047  clib_warning ("BUG: illegal flow hash config 0x%x", flow_hash_config);
3048  break;
3049  }
3050 
3051  return 0;
3052 }
3053 
3054 /*?
3055  * Configure the set of IPv4 fields used by the flow hash.
3056  *
3057  * @cliexpar
3058  * Example of how to set the flow hash on a given table:
3059  * @cliexcmd{set ip flow-hash table 7 dst sport dport proto}
3060  * Example of display the configured flow hash:
3061  * @cliexstart{show ip fib}
3062  * ipv4-VRF:0, fib_index 0, flow hash: src dst sport dport proto
3063  * 0.0.0.0/0
3064  * unicast-ip4-chain
3065  * [@0]: dpo-load-balance: [index:0 buckets:1 uRPF:0 to:[0:0]]
3066  * [0] [@0]: dpo-drop ip6
3067  * 0.0.0.0/32
3068  * unicast-ip4-chain
3069  * [@0]: dpo-load-balance: [index:1 buckets:1 uRPF:1 to:[0:0]]
3070  * [0] [@0]: dpo-drop ip6
3071  * 224.0.0.0/8
3072  * unicast-ip4-chain
3073  * [@0]: dpo-load-balance: [index:3 buckets:1 uRPF:3 to:[0:0]]
3074  * [0] [@0]: dpo-drop ip6
3075  * 6.0.1.2/32
3076  * unicast-ip4-chain
3077  * [@0]: dpo-load-balance: [index:30 buckets:1 uRPF:29 to:[0:0]]
3078  * [0] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
3079  * 7.0.0.1/32
3080  * unicast-ip4-chain
3081  * [@0]: dpo-load-balance: [index:31 buckets:4 uRPF:30 to:[0:0]]
3082  * [0] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3083  * [1] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3084  * [2] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3085  * [3] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
3086  * 240.0.0.0/8
3087  * unicast-ip4-chain
3088  * [@0]: dpo-load-balance: [index:2 buckets:1 uRPF:2 to:[0:0]]
3089  * [0] [@0]: dpo-drop ip6
3090  * 255.255.255.255/32
3091  * unicast-ip4-chain
3092  * [@0]: dpo-load-balance: [index:4 buckets:1 uRPF:4 to:[0:0]]
3093  * [0] [@0]: dpo-drop ip6
3094  * ipv4-VRF:7, fib_index 1, flow hash: dst sport dport proto
3095  * 0.0.0.0/0
3096  * unicast-ip4-chain
3097  * [@0]: dpo-load-balance: [index:12 buckets:1 uRPF:11 to:[0:0]]
3098  * [0] [@0]: dpo-drop ip6
3099  * 0.0.0.0/32
3100  * unicast-ip4-chain
3101  * [@0]: dpo-load-balance: [index:13 buckets:1 uRPF:12 to:[0:0]]
3102  * [0] [@0]: dpo-drop ip6
3103  * 172.16.1.0/24
3104  * unicast-ip4-chain
3105  * [@0]: dpo-load-balance: [index:17 buckets:1 uRPF:16 to:[0:0]]
3106  * [0] [@4]: ipv4-glean: af_packet0
3107  * 172.16.1.1/32
3108  * unicast-ip4-chain
3109  * [@0]: dpo-load-balance: [index:18 buckets:1 uRPF:17 to:[1:84]]
3110  * [0] [@2]: dpo-receive: 172.16.1.1 on af_packet0
3111  * 172.16.1.2/32
3112  * unicast-ip4-chain
3113  * [@0]: dpo-load-balance: [index:21 buckets:1 uRPF:20 to:[0:0]]
3114  * [0] [@5]: ipv4 via 172.16.1.2 af_packet0: IP4: 02:fe:9e:70:7a:2b -> 26:a5:f6:9c:3a:36
3115  * 172.16.2.0/24
3116  * unicast-ip4-chain
3117  * [@0]: dpo-load-balance: [index:19 buckets:1 uRPF:18 to:[0:0]]
3118  * [0] [@4]: ipv4-glean: af_packet1
3119  * 172.16.2.1/32
3120  * unicast-ip4-chain
3121  * [@0]: dpo-load-balance: [index:20 buckets:1 uRPF:19 to:[0:0]]
3122  * [0] [@2]: dpo-receive: 172.16.2.1 on af_packet1
3123  * 224.0.0.0/8
3124  * unicast-ip4-chain
3125  * [@0]: dpo-load-balance: [index:15 buckets:1 uRPF:14 to:[0:0]]
3126  * [0] [@0]: dpo-drop ip6
3127  * 240.0.0.0/8
3128  * unicast-ip4-chain
3129  * [@0]: dpo-load-balance: [index:14 buckets:1 uRPF:13 to:[0:0]]
3130  * [0] [@0]: dpo-drop ip6
3131  * 255.255.255.255/32
3132  * unicast-ip4-chain
3133  * [@0]: dpo-load-balance: [index:16 buckets:1 uRPF:15 to:[0:0]]
3134  * [0] [@0]: dpo-drop ip6
3135  * @cliexend
3136 ?*/
3137 /* *INDENT-OFF* */
3138 VLIB_CLI_COMMAND (set_ip_flow_hash_command, static) =
3139 {
3140  .path = "set ip flow-hash",
3141  .short_help =
3142  "set ip flow-hash table <table-id> [src] [dst] [sport] [dport] [proto] [reverse]",
3143  .function = set_ip_flow_hash_command_fn,
3144 };
3145 /* *INDENT-ON* */
3146 
3147 int
3149  u32 table_index)
3150 {
3151  vnet_main_t *vnm = vnet_get_main ();
3153  ip4_main_t *ipm = &ip4_main;
3154  ip_lookup_main_t *lm = &ipm->lookup_main;
3156  ip4_address_t *if_addr;
3157 
3158  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
3159  return VNET_API_ERROR_NO_MATCHING_INTERFACE;
3160 
3161  if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
3162  return VNET_API_ERROR_NO_SUCH_ENTRY;
3163 
3165  lm->classify_table_index_by_sw_if_index[sw_if_index] = table_index;
3166 
3167  if_addr = ip4_interface_first_address (ipm, sw_if_index, NULL);
3168 
3169  if (NULL != if_addr)
3170  {
3171  fib_prefix_t pfx = {
3172  .fp_len = 32,
3173  .fp_proto = FIB_PROTOCOL_IP4,
3174  .fp_addr.ip4 = *if_addr,
3175  };
3176  u32 fib_index;
3177 
3179  sw_if_index);
3180 
3181 
3182  if (table_index != (u32) ~ 0)
3183  {
3184  dpo_id_t dpo = DPO_INVALID;
3185 
3186  dpo_set (&dpo,
3187  DPO_CLASSIFY,
3188  DPO_PROTO_IP4,
3189  classify_dpo_create (DPO_PROTO_IP4, table_index));
3190 
3192  &pfx,
3194  FIB_ENTRY_FLAG_NONE, &dpo);
3195  dpo_reset (&dpo);
3196  }
3197  else
3198  {
3199  fib_table_entry_special_remove (fib_index,
3200  &pfx, FIB_SOURCE_CLASSIFY);
3201  }
3202  }
3203 
3204  return 0;
3205 }
3206 
3207 static clib_error_t *
3209  unformat_input_t * input,
3210  vlib_cli_command_t * cmd)
3211 {
3212  u32 table_index = ~0;
3213  int table_index_set = 0;
3214  u32 sw_if_index = ~0;
3215  int rv;
3216 
3217  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3218  {
3219  if (unformat (input, "table-index %d", &table_index))
3220  table_index_set = 1;
3221  else if (unformat (input, "intfc %U", unformat_vnet_sw_interface,
3222  vnet_get_main (), &sw_if_index))
3223  ;
3224  else
3225  break;
3226  }
3227 
3228  if (table_index_set == 0)
3229  return clib_error_return (0, "classify table-index must be specified");
3230 
3231  if (sw_if_index == ~0)
3232  return clib_error_return (0, "interface / subif must be specified");
3233 
3234  rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3235 
3236  switch (rv)
3237  {
3238  case 0:
3239  break;
3240 
3241  case VNET_API_ERROR_NO_MATCHING_INTERFACE:
3242  return clib_error_return (0, "No such interface");
3243 
3244  case VNET_API_ERROR_NO_SUCH_ENTRY:
3245  return clib_error_return (0, "No such classifier table");
3246  }
3247  return 0;
3248 }
3249 
3250 /*?
3251  * Assign a classification table to an interface. The classification
3252  * table is created using the '<em>classify table</em>' and '<em>classify session</em>'
3253  * commands. Once the table is create, use this command to filter packets
3254  * on an interface.
3255  *
3256  * @cliexpar
3257  * Example of how to assign a classification table to an interface:
3258  * @cliexcmd{set ip classify intfc GigabitEthernet2/0/0 table-index 1}
3259 ?*/
3260 /* *INDENT-OFF* */
3261 VLIB_CLI_COMMAND (set_ip_classify_command, static) =
3262 {
3263  .path = "set ip classify",
3264  .short_help =
3265  "set ip classify intfc <interface> table-index <classify-idx>",
3266  .function = set_ip_classify_command_fn,
3267 };
3268 /* *INDENT-ON* */
3269 
3270 /*
3271  * fd.io coding-style-patch-verification: ON
3272  *
3273  * Local Variables:
3274  * eval: (c-set-style "gnu")
3275  * End:
3276  */
#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:2996
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:2743
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:2917
#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:1065
#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:2763
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:2799
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:2894
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:3012
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:3208
#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:2788
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:2778
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:3148
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:2753
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:2733
#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