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