FD.io VPP  v16.06
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 
48 /* This is really, really simple but stupid fib. */
49 u32
51  ip4_address_t * dst,
52  u32 disable_default_route)
53 {
54  ip_lookup_main_t * lm = &im->lookup_main;
55  ip4_fib_t * fib = vec_elt_at_index (im->fibs, fib_index);
56  uword * p, * hash, key;
57  i32 i, i_min, dst_address, ai;
58 
59  i_min = disable_default_route ? 1 : 0;
60  dst_address = clib_mem_unaligned (&dst->data_u32, u32);
61  for (i = ARRAY_LEN (fib->adj_index_by_dst_address) - 1; i >= i_min; i--)
62  {
63  hash = fib->adj_index_by_dst_address[i];
64  if (! hash)
65  continue;
66 
67  key = dst_address & im->fib_masks[i];
68  if ((p = hash_get (hash, key)) != 0)
69  {
70  ai = p[0];
71  goto done;
72  }
73  }
74 
75  /* Nothing matches in table. */
76  ai = lm->miss_adj_index;
77 
78  done:
79  return ai;
80 }
81 
82 static ip4_fib_t *
84 {
85  ip4_fib_t * fib;
86  hash_set (im->fib_index_by_table_id, table_id, vec_len (im->fibs));
87  vec_add2 (im->fibs, fib, 1);
88  fib->table_id = table_id;
89  fib->index = fib - im->fibs;
91  fib->fwd_classify_table_index = ~0;
92  fib->rev_classify_table_index = ~0;
93  ip4_mtrie_init (&fib->mtrie);
94  return fib;
95 }
96 
97 ip4_fib_t *
99  u32 table_index_or_id, u32 flags)
100 {
101  uword * p, fib_index;
102 
103  fib_index = table_index_or_id;
104  if (! (flags & IP4_ROUTE_FLAG_FIB_INDEX))
105  {
106  if (table_index_or_id == ~0) {
107  table_index_or_id = 0;
108  while ((p = hash_get (im->fib_index_by_table_id, table_index_or_id))) {
109  table_index_or_id++;
110  }
111  return create_fib_with_table_id (im, table_index_or_id);
112  }
113 
114  p = hash_get (im->fib_index_by_table_id, table_index_or_id);
115  if (! p)
116  return create_fib_with_table_id (im, table_index_or_id);
117  fib_index = p[0];
118  }
119  return vec_elt_at_index (im->fibs, fib_index);
120 }
121 
122 static void
124  ip4_fib_t * fib,
125  u32 address_length)
126 {
127  hash_t * h;
128  uword max_index;
129 
130  ASSERT (lm->fib_result_n_bytes >= sizeof (uword));
131  lm->fib_result_n_words = round_pow2 (lm->fib_result_n_bytes, sizeof (uword)) / sizeof (uword);
132 
133  fib->adj_index_by_dst_address[address_length] =
134  hash_create (32 /* elts */, lm->fib_result_n_words * sizeof (uword));
135 
136  hash_set_flags (fib->adj_index_by_dst_address[address_length],
138 
139  h = hash_header (fib->adj_index_by_dst_address[address_length]);
140  max_index = (hash_value_bytes (h) / sizeof (fib->new_hash_values[0])) - 1;
141 
142  /* Initialize new/old hash value vectors. */
143  vec_validate_init_empty (fib->new_hash_values, max_index, ~0);
144  vec_validate_init_empty (fib->old_hash_values, max_index, ~0);
145 }
146 
147 static void
149  ip4_fib_t * fib,
150  u32 flags,
151  u32 dst_address_u32,
152  u32 dst_address_length,
153  u32 adj_index)
154 {
155  ip_lookup_main_t * lm = &im->lookup_main;
156  uword * hash;
157 
158  if (vec_bytes(fib->old_hash_values))
159  memset (fib->old_hash_values, ~0, vec_bytes (fib->old_hash_values));
160  if (vec_bytes(fib->new_hash_values))
161  memset (fib->new_hash_values, ~0, vec_bytes (fib->new_hash_values));
162  fib->new_hash_values[0] = adj_index;
163 
164  /* Make sure adj index is valid. */
165  if (CLIB_DEBUG > 0)
166  (void) ip_get_adjacency (lm, adj_index);
167 
168  hash = fib->adj_index_by_dst_address[dst_address_length];
169 
170  hash = _hash_set3 (hash, dst_address_u32,
171  fib->new_hash_values,
172  fib->old_hash_values);
173 
174  fib->adj_index_by_dst_address[dst_address_length] = hash;
175 
176  if (vec_len (im->add_del_route_callbacks) > 0)
177  {
179  ip4_address_t d;
180  uword * p;
181 
182  d.data_u32 = dst_address_u32;
184  if ((flags & cb->required_flags) == cb->required_flags)
185  cb->function (im, cb->function_opaque,
186  fib, flags,
187  &d, dst_address_length,
188  fib->old_hash_values,
189  fib->new_hash_values);
190 
191  p = hash_get (hash, dst_address_u32);
193  }
194 }
195 
197 {
198  ip_lookup_main_t * lm = &im->lookup_main;
199  ip4_fib_t * fib;
200  u32 dst_address, dst_address_length, adj_index, old_adj_index;
201  uword * hash, is_del;
203 
204  /* Either create new adjacency or use given one depending on arguments. */
205  if (a->n_add_adj > 0)
206  {
207  ip_add_adjacency (lm, a->add_adj, a->n_add_adj, &adj_index);
208  ip_call_add_del_adjacency_callbacks (lm, adj_index, /* is_del */ 0);
209  }
210  else
211  adj_index = a->adj_index;
212 
213  dst_address = a->dst_address.data_u32;
214  dst_address_length = a->dst_address_length;
216 
217  ASSERT (dst_address_length < ARRAY_LEN (im->fib_masks));
218  dst_address &= im->fib_masks[dst_address_length];
219 
220  if (! fib->adj_index_by_dst_address[dst_address_length])
221  ip4_fib_init_adj_index_by_dst_address (lm, fib, dst_address_length);
222 
223  hash = fib->adj_index_by_dst_address[dst_address_length];
224 
225  is_del = (a->flags & IP4_ROUTE_FLAG_DEL) != 0;
226 
227  if (is_del)
228  {
229  fib->old_hash_values[0] = ~0;
230  hash = _hash_unset (hash, dst_address, fib->old_hash_values);
231  fib->adj_index_by_dst_address[dst_address_length] = hash;
232 
233  if (vec_len (im->add_del_route_callbacks) > 0
234  && fib->old_hash_values[0] != ~0) /* make sure destination was found in hash */
235  {
236  fib->new_hash_values[0] = ~0;
238  if ((a->flags & cb->required_flags) == cb->required_flags)
239  cb->function (im, cb->function_opaque,
240  fib, a->flags,
241  &a->dst_address, dst_address_length,
242  fib->old_hash_values,
243  fib->new_hash_values);
244  }
245  }
246  else
247  ip4_fib_set_adj_index (im, fib, a->flags, dst_address, dst_address_length,
248  adj_index);
249 
250  old_adj_index = fib->old_hash_values[0];
251 
252  /* Avoid spurious reference count increments */
253  if (old_adj_index == adj_index
254  && adj_index != ~0
256  {
257  ip_adjacency_t * adj = ip_get_adjacency (lm, adj_index);
258  if (adj->share_count > 0)
259  adj->share_count --;
260  }
261 
262  ip4_fib_mtrie_add_del_route (fib, a->dst_address, dst_address_length,
263  is_del ? old_adj_index : adj_index,
264  is_del);
265 
266  /* Delete old adjacency index if present and changed. */
268  && old_adj_index != ~0
269  && old_adj_index != adj_index)
270  ip_del_adjacency (lm, old_adj_index);
271 }
272 
273 void
275  u32 flags,
276  ip4_address_t * dst_address,
277  u32 dst_address_length,
278  ip4_address_t * next_hop,
279  u32 next_hop_sw_if_index,
280  u32 next_hop_weight, u32 adj_index,
281  u32 explicit_fib_index)
282 {
283  vnet_main_t * vnm = vnet_get_main();
284  ip_lookup_main_t * lm = &im->lookup_main;
285  u32 fib_index;
286  ip4_fib_t * fib;
287  u32 dst_address_u32, old_mp_adj_index, new_mp_adj_index;
288  u32 dst_adj_index, nh_adj_index;
289  uword * dst_hash, * dst_result;
290  uword * nh_hash, * nh_result;
291  ip_adjacency_t * dst_adj;
292  ip_multipath_adjacency_t * old_mp, * new_mp;
293  int is_del = (flags & IP4_ROUTE_FLAG_DEL) != 0;
294  int is_interface_next_hop;
295  clib_error_t * error = 0;
296 
297  if (explicit_fib_index == (u32)~0)
298  fib_index = vec_elt (im->fib_index_by_sw_if_index, next_hop_sw_if_index);
299  else
300  fib_index = explicit_fib_index;
301 
302  fib = vec_elt_at_index (im->fibs, fib_index);
303 
304  /* Lookup next hop to be added or deleted. */
305  is_interface_next_hop = next_hop->data_u32 == 0;
306  if (adj_index == (u32)~0)
307  {
308  if (is_interface_next_hop)
309  {
310  nh_result = hash_get (im->interface_route_adj_index_by_sw_if_index, next_hop_sw_if_index);
311  if (nh_result)
312  nh_adj_index = *nh_result;
313  else
314  {
315  ip_adjacency_t * adj;
316  adj = ip_add_adjacency (lm, /* template */ 0, /* block size */ 1,
317  &nh_adj_index);
318  ip4_adjacency_set_interface_route (vnm, adj, next_hop_sw_if_index, /* if_address_index */ ~0);
319  ip_call_add_del_adjacency_callbacks (lm, nh_adj_index, /* is_del */ 0);
320  hash_set (im->interface_route_adj_index_by_sw_if_index, next_hop_sw_if_index, nh_adj_index);
321  }
322  }
323  else
324  {
325  nh_hash = fib->adj_index_by_dst_address[32];
326  nh_result = hash_get (nh_hash, next_hop->data_u32);
327 
328  /* Next hop must be known. */
329  if (! nh_result)
330  {
331  ip_adjacency_t * adj;
332 
333  nh_adj_index = ip4_fib_lookup_with_table (im, fib_index,
334  next_hop, 0);
335  adj = ip_get_adjacency (lm, nh_adj_index);
336  /* if ARP interface adjacencty is present, we need to
337  install ARP adjaceny for specific next hop */
339  adj->arp.next_hop.ip4.as_u32 == 0)
340  {
341  nh_adj_index = vnet_arp_glean_add(fib_index, next_hop);
342  }
343  else
344  {
345  /* Next hop is not known, so create indirect adj */
346  ip_adjacency_t add_adj;
347  memset (&add_adj, 0, sizeof(add_adj));
348  add_adj.n_adj = 1;
350  add_adj.indirect.next_hop.ip4.as_u32 = next_hop->as_u32;
351  add_adj.explicit_fib_index = explicit_fib_index;
352  ip_add_adjacency (lm, &add_adj, 1, &nh_adj_index);
353  }
354  }
355  else
356  nh_adj_index = *nh_result;
357  }
358  }
359  else
360  {
361  nh_adj_index = adj_index;
362  }
363  ASSERT (dst_address_length < ARRAY_LEN (im->fib_masks));
364  dst_address_u32 = dst_address->data_u32 & im->fib_masks[dst_address_length];
365 
366  dst_hash = fib->adj_index_by_dst_address[dst_address_length];
367  dst_result = hash_get (dst_hash, dst_address_u32);
368  if (dst_result)
369  {
370  dst_adj_index = dst_result[0];
371  dst_adj = ip_get_adjacency (lm, dst_adj_index);
372  }
373  else
374  {
375  /* For deletes destination must be known. */
376  if (is_del)
377  {
378  vnm->api_errno = VNET_API_ERROR_UNKNOWN_DESTINATION;
379  error = clib_error_return (0, "unknown destination %U/%d",
380  format_ip4_address, dst_address,
381  dst_address_length);
382  goto done;
383  }
384 
385  dst_adj_index = ~0;
386  dst_adj = 0;
387  }
388 
389  /* Ignore adds of X/32 with next hop of X. */
390  if (! is_del
391  && dst_address_length == 32
392  && dst_address->data_u32 == next_hop->data_u32
393  && adj_index != (u32)~0)
394  {
395  vnm->api_errno = VNET_API_ERROR_PREFIX_MATCHES_NEXT_HOP;
396  error = clib_error_return (0, "prefix matches next hop %U/%d",
397  format_ip4_address, dst_address,
398  dst_address_length);
399  goto done;
400  }
401 
402  /* Destination is not known and default weight is set so add route
403  to existing non-multipath adjacency */
404  if (dst_adj_index == ~0 && next_hop_weight == 1 && next_hop_sw_if_index == ~0)
405  {
406  /* create new adjacency */
408  a.table_index_or_table_id = fib_index;
414  a.dst_address = dst_address[0];
415  a.dst_address_length = dst_address_length;
416  a.adj_index = nh_adj_index;
417  a.add_adj = 0;
418  a.n_add_adj = 0;
419 
420  ip4_add_del_route (im, &a);
421 
422  goto done;
423  }
424 
425  old_mp_adj_index = dst_adj ? dst_adj->heap_handle : ~0;
426 
428  (lm, is_del,
429  old_mp_adj_index,
430  nh_adj_index,
431  next_hop_weight,
432  &new_mp_adj_index))
433  {
434  vnm->api_errno = VNET_API_ERROR_NEXT_HOP_NOT_FOUND_MP;
435  error = clib_error_return (0, "requested deleting next-hop %U not found in multi-path",
436  format_ip4_address, next_hop);
437  goto done;
438  }
439 
440  old_mp = new_mp = 0;
441  if (old_mp_adj_index != ~0)
442  old_mp = vec_elt_at_index (lm->multipath_adjacencies, old_mp_adj_index);
443  if (new_mp_adj_index != ~0)
444  new_mp = vec_elt_at_index (lm->multipath_adjacencies, new_mp_adj_index);
445 
446  if (old_mp != new_mp)
447  {
449  a.table_index_or_table_id = fib_index;
450  a.flags = ((is_del && ! new_mp ? IP4_ROUTE_FLAG_DEL : IP4_ROUTE_FLAG_ADD)
454  a.dst_address = dst_address[0];
455  a.dst_address_length = dst_address_length;
456  a.adj_index = new_mp ? new_mp->adj_index : dst_adj_index;
457  a.add_adj = 0;
458  a.n_add_adj = 0;
459 
460  ip4_add_del_route (im, &a);
461  }
462 
463  done:
464  if (error)
465  clib_error_report (error);
466 }
467 
468 void *
470  u32 table_index_or_table_id,
471  u32 flags,
472  u8 * address,
473  u32 address_length)
474 {
475  ip4_fib_t * fib = find_ip4_fib_by_table_index_or_id (im, table_index_or_table_id, flags);
476  u32 dst_address = * (u32 *) address;
477  uword * hash, * p;
478 
479  ASSERT (address_length < ARRAY_LEN (im->fib_masks));
480  dst_address &= im->fib_masks[address_length];
481 
482  hash = fib->adj_index_by_dst_address[address_length];
483  p = hash_get (hash, dst_address);
484  return (void *) p;
485 }
486 
487 void
489  u32 table_index_or_table_id,
490  u32 flags,
491  ip4_address_t * address,
492  u32 address_length,
493  ip4_address_t ** results,
494  u8 ** result_lengths)
495 {
496  ip4_fib_t * fib = find_ip4_fib_by_table_index_or_id (im, table_index_or_table_id, flags);
497  u32 dst_address = address->data_u32;
498  u32 this_length = address_length;
499 
500  if (*results)
501  _vec_len (*results) = 0;
502  if (*result_lengths)
503  _vec_len (*result_lengths) = 0;
504 
505  while (this_length <= 32 && vec_len (results) == 0)
506  {
507  uword k, v;
508  hash_foreach (k, v, fib->adj_index_by_dst_address[this_length], ({
509  if (0 == ((k ^ dst_address) & im->fib_masks[address_length]))
510  {
511  ip4_address_t a;
512  a.data_u32 = k;
513  vec_add1 (*results, a);
514  vec_add1 (*result_lengths, this_length);
515  }
516  }));
517 
518  this_length++;
519  }
520 }
521 
523  u32 table_index_or_table_id,
524  u32 flags)
525 {
526  ip4_fib_t * fib = find_ip4_fib_by_table_index_or_id (im, table_index_or_table_id, flags);
527  ip_lookup_main_t * lm = &im->lookup_main;
528  u32 i, l;
531  static ip4_address_t * to_delete;
532 
533  if (lm->n_adjacency_remaps == 0)
534  return;
535 
536  for (l = 0; l <= 32; l++)
537  {
538  hash_pair_t * p;
539  uword * hash = fib->adj_index_by_dst_address[l];
540 
541  if (hash_elts (hash) == 0)
542  continue;
543 
544  if (to_delete)
545  _vec_len (to_delete) = 0;
546 
547  hash_foreach_pair (p, hash, ({
548  u32 adj_index = p->value[0];
549  u32 m = vec_elt (lm->adjacency_remap_table, adj_index);
550 
551  if (m)
552  {
553  /* Record destination address from hash key. */
554  a.data_u32 = p->key;
555 
556  /* New adjacency points to nothing: so delete prefix. */
557  if (m == ~0)
558  vec_add1 (to_delete, a);
559  else
560  {
561  /* Remap to new adjacency. */
563 
564  /* Set new adjacency value. */
565  fib->new_hash_values[0] = p->value[0] = m - 1;
566 
568  if ((flags & cb->required_flags) == cb->required_flags)
569  cb->function (im, cb->function_opaque,
570  fib, flags | IP4_ROUTE_FLAG_ADD,
571  &a, l,
572  fib->old_hash_values,
573  fib->new_hash_values);
574  }
575  }
576  }));
577 
578  fib->new_hash_values[0] = ~0;
579  for (i = 0; i < vec_len (to_delete); i++)
580  {
581  hash = _hash_unset (hash, to_delete[i].data_u32, fib->old_hash_values);
583  if ((flags & cb->required_flags) == cb->required_flags)
584  cb->function (im, cb->function_opaque,
585  fib, flags | IP4_ROUTE_FLAG_DEL,
586  &a, l,
587  fib->old_hash_values,
588  fib->new_hash_values);
589  }
590  }
591 
592  /* Also remap adjacencies in mtrie. */
594 
595  /* Reset mapping table. */
597 
598  /* All remaps have been performed. */
599  lm->n_adjacency_remaps = 0;
600 }
601 
603  u32 table_index_or_table_id,
604  u32 flags,
605  ip4_address_t * address,
606  u32 address_length)
607 {
608  static ip4_address_t * matching_addresses;
609  static u8 * matching_address_lengths;
610  u32 l, i;
612 
614  a.table_index_or_table_id = table_index_or_table_id;
615  a.adj_index = ~0;
616  a.add_adj = 0;
617  a.n_add_adj = 0;
618 
619  for (l = address_length + 1; l <= 32; l++)
620  {
621  ip4_foreach_matching_route (im, table_index_or_table_id, flags,
622  address,
623  l,
624  &matching_addresses,
625  &matching_address_lengths);
626  for (i = 0; i < vec_len (matching_addresses); i++)
627  {
628  a.dst_address = matching_addresses[i];
629  a.dst_address_length = matching_address_lengths[i];
630  ip4_add_del_route (im, &a);
631  }
632  }
633 
634  ip4_maybe_remap_adjacencies (im, table_index_or_table_id, flags);
635 }
636 
637 void
639  vlib_node_runtime_t * node,
640  vlib_frame_t * frame,
641  vlib_rx_or_tx_t which_adj_index);
642 
645  vlib_node_runtime_t * node,
646  vlib_frame_t * frame,
647  int lookup_for_responses_to_locally_received_packets,
648  int is_indirect)
649 {
650  ip4_main_t * im = &ip4_main;
651  ip_lookup_main_t * lm = &im->lookup_main;
653  u32 n_left_from, n_left_to_next, * from, * to_next;
654  ip_lookup_next_t next;
655  u32 cpu_index = os_get_cpu_number();
656 
657  from = vlib_frame_vector_args (frame);
658  n_left_from = frame->n_vectors;
659  next = node->cached_next_index;
660 
661  while (n_left_from > 0)
662  {
663  vlib_get_next_frame (vm, node, next,
664  to_next, n_left_to_next);
665 
666  while (n_left_from >= 4 && n_left_to_next >= 2)
667  {
668  vlib_buffer_t * p0, * p1;
669  ip4_header_t * ip0, * ip1;
670  __attribute__((unused)) tcp_header_t * tcp0, * tcp1;
671  ip_lookup_next_t next0, next1;
672  ip_adjacency_t * adj0, * adj1;
673  ip4_fib_mtrie_t * mtrie0, * mtrie1;
674  ip4_fib_mtrie_leaf_t leaf0, leaf1;
675  ip4_address_t * dst_addr0, *dst_addr1;
676  __attribute__((unused)) u32 pi0, fib_index0, adj_index0, is_tcp_udp0;
677  __attribute__((unused)) u32 pi1, fib_index1, adj_index1, is_tcp_udp1;
678  u32 flow_hash_config0, flow_hash_config1;
679  u32 hash_c0, hash_c1;
680  u32 wrong_next;
681 
682  /* Prefetch next iteration. */
683  {
684  vlib_buffer_t * p2, * p3;
685 
686  p2 = vlib_get_buffer (vm, from[2]);
687  p3 = vlib_get_buffer (vm, from[3]);
688 
689  vlib_prefetch_buffer_header (p2, LOAD);
690  vlib_prefetch_buffer_header (p3, LOAD);
691 
692  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
693  CLIB_PREFETCH (p3->data, sizeof (ip0[0]), LOAD);
694  }
695 
696  pi0 = to_next[0] = from[0];
697  pi1 = to_next[1] = from[1];
698 
699  p0 = vlib_get_buffer (vm, pi0);
700  p1 = vlib_get_buffer (vm, pi1);
701 
702  ip0 = vlib_buffer_get_current (p0);
703  ip1 = vlib_buffer_get_current (p1);
704 
705  if (is_indirect)
706  {
707  ip_adjacency_t * iadj0, * iadj1;
708  iadj0 = ip_get_adjacency (lm, vnet_buffer(p0)->ip.adj_index[VLIB_TX]);
709  iadj1 = ip_get_adjacency (lm, vnet_buffer(p1)->ip.adj_index[VLIB_TX]);
710  dst_addr0 = &iadj0->indirect.next_hop.ip4;
711  dst_addr1 = &iadj1->indirect.next_hop.ip4;
712  }
713  else
714  {
715  dst_addr0 = &ip0->dst_address;
716  dst_addr1 = &ip1->dst_address;
717  }
718 
719  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (p0)->sw_if_index[VLIB_RX]);
720  fib_index1 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (p1)->sw_if_index[VLIB_RX]);
721  fib_index0 = (vnet_buffer(p0)->sw_if_index[VLIB_TX] == (u32)~0) ?
722  fib_index0 : vnet_buffer(p0)->sw_if_index[VLIB_TX];
723  fib_index1 = (vnet_buffer(p1)->sw_if_index[VLIB_TX] == (u32)~0) ?
724  fib_index1 : vnet_buffer(p1)->sw_if_index[VLIB_TX];
725 
726 
727  if (! lookup_for_responses_to_locally_received_packets)
728  {
729  mtrie0 = &vec_elt_at_index (im->fibs, fib_index0)->mtrie;
730  mtrie1 = &vec_elt_at_index (im->fibs, fib_index1)->mtrie;
731 
732  leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
733 
734  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 0);
735  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, dst_addr1, 0);
736  }
737 
738  tcp0 = (void *) (ip0 + 1);
739  tcp1 = (void *) (ip1 + 1);
740 
741  is_tcp_udp0 = (ip0->protocol == IP_PROTOCOL_TCP
742  || ip0->protocol == IP_PROTOCOL_UDP);
743  is_tcp_udp1 = (ip1->protocol == IP_PROTOCOL_TCP
744  || ip1->protocol == IP_PROTOCOL_UDP);
745 
746  if (! lookup_for_responses_to_locally_received_packets)
747  {
748  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 1);
749  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, dst_addr1, 1);
750  }
751 
752  if (! lookup_for_responses_to_locally_received_packets)
753  {
754  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 2);
755  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, dst_addr1, 2);
756  }
757 
758  if (! lookup_for_responses_to_locally_received_packets)
759  {
760  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 3);
761  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, dst_addr1, 3);
762  }
763 
764  if (lookup_for_responses_to_locally_received_packets)
765  {
766  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_RX];
767  adj_index1 = vnet_buffer (p1)->ip.adj_index[VLIB_RX];
768  }
769  else
770  {
771  /* Handle default route. */
772  leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
773  leaf1 = (leaf1 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie1->default_leaf : leaf1);
774 
775  adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
776  adj_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
777  }
778 
779  ASSERT (adj_index0 == ip4_fib_lookup_with_table (im, fib_index0,
780  dst_addr0,
781  /* no_default_route */ 0));
782  ASSERT (adj_index1 == ip4_fib_lookup_with_table (im, fib_index1,
783  dst_addr1,
784  /* no_default_route */ 0));
785  adj0 = ip_get_adjacency (lm, adj_index0);
786  adj1 = ip_get_adjacency (lm, adj_index1);
787 
788  next0 = adj0->lookup_next_index;
789  next1 = adj1->lookup_next_index;
790 
791  /* Use flow hash to compute multipath adjacency. */
792  hash_c0 = vnet_buffer (p0)->ip.flow_hash = 0;
793  hash_c1 = vnet_buffer (p1)->ip.flow_hash = 0;
794  if (PREDICT_FALSE (adj0->n_adj > 1))
795  {
796  flow_hash_config0 =
797  vec_elt_at_index (im->fibs, fib_index0)->flow_hash_config;
798  hash_c0 = vnet_buffer (p0)->ip.flow_hash =
799  ip4_compute_flow_hash (ip0, flow_hash_config0);
800  }
801  if (PREDICT_FALSE(adj1->n_adj > 1))
802  {
803  flow_hash_config1 =
804  vec_elt_at_index (im->fibs, fib_index1)->flow_hash_config;
805  hash_c1 = vnet_buffer (p1)->ip.flow_hash =
806  ip4_compute_flow_hash (ip1, flow_hash_config1);
807  }
808 
809  ASSERT (adj0->n_adj > 0);
810  ASSERT (adj1->n_adj > 0);
811  ASSERT (is_pow2 (adj0->n_adj));
812  ASSERT (is_pow2 (adj1->n_adj));
813  adj_index0 += (hash_c0 & (adj0->n_adj - 1));
814  adj_index1 += (hash_c1 & (adj1->n_adj - 1));
815 
816  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = adj_index0;
817  vnet_buffer (p1)->ip.adj_index[VLIB_TX] = adj_index1;
818 
820  (cm, cpu_index, adj_index0, 1,
822  + sizeof(ethernet_header_t));
824  (cm, cpu_index, adj_index1, 1,
826  + sizeof(ethernet_header_t));
827 
828  from += 2;
829  to_next += 2;
830  n_left_to_next -= 2;
831  n_left_from -= 2;
832 
833  wrong_next = (next0 != next) + 2*(next1 != next);
834  if (PREDICT_FALSE (wrong_next != 0))
835  {
836  switch (wrong_next)
837  {
838  case 1:
839  /* A B A */
840  to_next[-2] = pi1;
841  to_next -= 1;
842  n_left_to_next += 1;
843  vlib_set_next_frame_buffer (vm, node, next0, pi0);
844  break;
845 
846  case 2:
847  /* A A B */
848  to_next -= 1;
849  n_left_to_next += 1;
850  vlib_set_next_frame_buffer (vm, node, next1, pi1);
851  break;
852 
853  case 3:
854  /* A B C */
855  to_next -= 2;
856  n_left_to_next += 2;
857  vlib_set_next_frame_buffer (vm, node, next0, pi0);
858  vlib_set_next_frame_buffer (vm, node, next1, pi1);
859  if (next0 == next1)
860  {
861  /* A B B */
862  vlib_put_next_frame (vm, node, next, n_left_to_next);
863  next = next1;
864  vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
865  }
866  }
867  }
868  }
869 
870  while (n_left_from > 0 && n_left_to_next > 0)
871  {
872  vlib_buffer_t * p0;
873  ip4_header_t * ip0;
874  __attribute__((unused)) tcp_header_t * tcp0;
875  ip_lookup_next_t next0;
876  ip_adjacency_t * adj0;
877  ip4_fib_mtrie_t * mtrie0;
878  ip4_fib_mtrie_leaf_t leaf0;
879  ip4_address_t * dst_addr0;
880  __attribute__((unused)) u32 pi0, fib_index0, adj_index0, is_tcp_udp0;
881  u32 flow_hash_config0, hash_c0;
882 
883  pi0 = from[0];
884  to_next[0] = pi0;
885 
886  p0 = vlib_get_buffer (vm, pi0);
887 
888  ip0 = vlib_buffer_get_current (p0);
889 
890  if (is_indirect)
891  {
892  ip_adjacency_t * iadj0;
893  iadj0 = ip_get_adjacency (lm, vnet_buffer(p0)->ip.adj_index[VLIB_TX]);
894  dst_addr0 = &iadj0->indirect.next_hop.ip4;
895  }
896  else
897  {
898  dst_addr0 = &ip0->dst_address;
899  }
900 
901  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (p0)->sw_if_index[VLIB_RX]);
902  fib_index0 = (vnet_buffer(p0)->sw_if_index[VLIB_TX] == (u32)~0) ?
903  fib_index0 : vnet_buffer(p0)->sw_if_index[VLIB_TX];
904 
905  if (! lookup_for_responses_to_locally_received_packets)
906  {
907  mtrie0 = &vec_elt_at_index (im->fibs, fib_index0)->mtrie;
908 
909  leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
910 
911  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 0);
912  }
913 
914  tcp0 = (void *) (ip0 + 1);
915 
916  is_tcp_udp0 = (ip0->protocol == IP_PROTOCOL_TCP
917  || ip0->protocol == IP_PROTOCOL_UDP);
918 
919  if (! lookup_for_responses_to_locally_received_packets)
920  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 1);
921 
922  if (! lookup_for_responses_to_locally_received_packets)
923  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 2);
924 
925  if (! lookup_for_responses_to_locally_received_packets)
926  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, dst_addr0, 3);
927 
928  if (lookup_for_responses_to_locally_received_packets)
929  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_RX];
930  else
931  {
932  /* Handle default route. */
933  leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
934  adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
935  }
936 
937  ASSERT (adj_index0 == ip4_fib_lookup_with_table (im, fib_index0,
938  dst_addr0,
939  /* no_default_route */ 0));
940 
941  adj0 = ip_get_adjacency (lm, adj_index0);
942 
943  next0 = adj0->lookup_next_index;
944 
945  /* Use flow hash to compute multipath adjacency. */
946  hash_c0 = vnet_buffer (p0)->ip.flow_hash = 0;
947  if (PREDICT_FALSE(adj0->n_adj > 1))
948  {
949  flow_hash_config0 =
950  vec_elt_at_index (im->fibs, fib_index0)->flow_hash_config;
951 
952  hash_c0 = vnet_buffer (p0)->ip.flow_hash =
953  ip4_compute_flow_hash (ip0, flow_hash_config0);
954  }
955 
956  ASSERT (adj0->n_adj > 0);
957  ASSERT (is_pow2 (adj0->n_adj));
958  adj_index0 += (hash_c0 & (adj0->n_adj - 1));
959 
960  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = adj_index0;
961 
963  (cm, cpu_index, adj_index0, 1,
965  + sizeof(ethernet_header_t));
966 
967  from += 1;
968  to_next += 1;
969  n_left_to_next -= 1;
970  n_left_from -= 1;
971 
972  if (PREDICT_FALSE (next0 != next))
973  {
974  n_left_to_next += 1;
975  vlib_put_next_frame (vm, node, next, n_left_to_next);
976  next = next0;
977  vlib_get_next_frame (vm, node, next,
978  to_next, n_left_to_next);
979  to_next[0] = pi0;
980  to_next += 1;
981  n_left_to_next -= 1;
982  }
983  }
984 
985  vlib_put_next_frame (vm, node, next, n_left_to_next);
986  }
987 
988  if (node->flags & VLIB_NODE_FLAG_TRACE)
989  ip4_forward_next_trace(vm, node, frame, VLIB_TX);
990 
991  return frame->n_vectors;
992 }
993 
994 static uword
996  vlib_node_runtime_t * node,
997  vlib_frame_t * frame)
998 {
999  return ip4_lookup_inline (vm, node, frame,
1000  /* lookup_for_responses_to_locally_received_packets */ 0,
1001  /* is_indirect */ 0);
1002 
1003 }
1004 
1006  ip_adjacency_t * adj,
1007  u32 sw_if_index,
1008  u32 if_address_index)
1009 {
1010  vnet_hw_interface_t * hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
1011  ip_lookup_next_t n;
1012  vnet_l3_packet_type_t packet_type;
1013  u32 node_index;
1014 
1016  || hw->hw_class_index == srp_hw_interface_class.index)
1017  {
1018  /*
1019  * We have a bit of a problem in this case. ip4-arp uses
1020  * the rewrite_header.next_index to hand pkts to the
1021  * indicated inteface output node. We can end up in
1022  * ip4_rewrite_local, too, which also pays attention to
1023  * rewrite_header.next index. Net result: a hack in
1024  * ip4_rewrite_local...
1025  */
1026  n = IP_LOOKUP_NEXT_ARP;
1027  node_index = ip4_arp_node.index;
1028  adj->if_address_index = if_address_index;
1029  adj->arp.next_hop.ip4.as_u32 = 0;
1030  ip46_address_reset(&adj->arp.next_hop);
1031  packet_type = VNET_L3_PACKET_TYPE_ARP;
1032  }
1033  else
1034  {
1036  node_index = ip4_rewrite_node.index;
1037  packet_type = VNET_L3_PACKET_TYPE_IP4;
1038  }
1039 
1040  adj->lookup_next_index = n;
1042  (vnm,
1043  packet_type,
1044  sw_if_index,
1045  node_index,
1047  &adj->rewrite_header,
1048  sizeof (adj->rewrite_data));
1049 }
1050 
1051 static void
1053  ip4_main_t * im, u32 fib_index,
1055 {
1056  vnet_main_t * vnm = vnet_get_main();
1057  ip_lookup_main_t * lm = &im->lookup_main;
1058  ip_adjacency_t * adj;
1059  ip4_address_t * address = ip_interface_address_get_address (lm, a);
1061  vnet_hw_interface_t * hw_if = vnet_get_sup_hw_interface (vnm, sw_if_index);
1062  u32 classify_table_index;
1063 
1064  /* Add e.g. 1.0.0.0/8 as interface route (arp for Ethernet). */
1065  x.table_index_or_table_id = fib_index;
1069  x.dst_address = address[0];
1071  x.n_add_adj = 0;
1072  x.add_adj = 0;
1073 
1074  a->neighbor_probe_adj_index = ~0;
1075  if (a->address_length < 32)
1076  {
1077  adj = ip_add_adjacency (lm, /* template */ 0, /* block size */ 1,
1078  &x.adj_index);
1079  ip4_adjacency_set_interface_route (vnm, adj, sw_if_index, a - lm->if_address_pool);
1080  ip_call_add_del_adjacency_callbacks (lm, x.adj_index, /* is_del */ 0);
1081  ip4_add_del_route (im, &x);
1083  }
1084 
1085  /* Add e.g. 1.1.1.1/32 as local to this host. */
1086  adj = ip_add_adjacency (lm, /* template */ 0, /* block size */ 1,
1087  &x.adj_index);
1088 
1089  classify_table_index = ~0;
1090  if (sw_if_index < vec_len (lm->classify_table_index_by_sw_if_index))
1091  classify_table_index = lm->classify_table_index_by_sw_if_index [sw_if_index];
1092  if (classify_table_index != (u32) ~0)
1093  {
1095  adj->classify.table_index = classify_table_index;
1096  }
1097  else
1099 
1100  adj->if_address_index = a - lm->if_address_pool;
1101  adj->rewrite_header.sw_if_index = sw_if_index;
1102  adj->rewrite_header.max_l3_packet_bytes = hw_if->max_l3_packet_bytes[VLIB_RX];
1103  /*
1104  * Local adjs are never to be rewritten. Spoofed pkts w/ src = dst = local
1105  * fail an RPF-ish check, but still go thru the rewrite code...
1106  */
1107  adj->rewrite_header.data_bytes = 0;
1108 
1109  ip_call_add_del_adjacency_callbacks (lm, x.adj_index, /* is_del */ 0);
1110  x.dst_address_length = 32;
1111  ip4_add_del_route (im, &x);
1112 }
1113 
1114 static void
1115 ip4_del_interface_routes (ip4_main_t * im, u32 fib_index, ip4_address_t * address, u32 address_length)
1116 {
1118 
1119  /* Add e.g. 1.0.0.0/8 as interface route (arp for Ethernet). */
1120  x.table_index_or_table_id = fib_index;
1124  x.dst_address = address[0];
1125  x.dst_address_length = address_length;
1126  x.adj_index = ~0;
1127  x.n_add_adj = 0;
1128  x.add_adj = 0;
1129 
1130  if (address_length < 32)
1131  ip4_add_del_route (im, &x);
1132 
1133  x.dst_address_length = 32;
1134  ip4_add_del_route (im, &x);
1135 
1137  fib_index,
1139  address,
1140  address_length);
1141 }
1142 
1143 typedef struct {
1148 
1149 static clib_error_t *
1151  u32 sw_if_index,
1152  ip4_address_t * new_address,
1153  u32 new_length,
1154  u32 redistribute,
1155  u32 insert_routes,
1156  u32 is_del);
1157 
1158 static clib_error_t *
1160  u32 sw_if_index,
1161  ip4_address_t * address,
1162  u32 address_length,
1163  u32 redistribute,
1164  u32 insert_routes,
1165  u32 is_del)
1166 {
1167  vnet_main_t * vnm = vnet_get_main();
1168  ip4_main_t * im = &ip4_main;
1169  ip_lookup_main_t * lm = &im->lookup_main;
1170  clib_error_t * error = 0;
1171  u32 if_address_index, elts_before;
1172  ip4_address_fib_t ip4_af, * addr_fib = 0;
1173 
1174  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1175  ip4_addr_fib_init (&ip4_af, address,
1176  vec_elt (im->fib_index_by_sw_if_index, sw_if_index));
1177  vec_add1 (addr_fib, ip4_af);
1178 
1179  /* When adding an address check that it does not conflict with an existing address. */
1180  if (! is_del)
1181  {
1183  foreach_ip_interface_address (&im->lookup_main, ia, sw_if_index,
1184  0 /* honor unnumbered */,
1185  ({
1186  ip4_address_t * x = ip_interface_address_get_address (&im->lookup_main, ia);
1187 
1188  if (ip4_destination_matches_route (im, address, x, ia->address_length)
1189  || ip4_destination_matches_route (im, x, address, address_length))
1190  return clib_error_create ("failed to add %U which conflicts with %U for interface %U",
1191  format_ip4_address_and_length, address, address_length,
1192  format_ip4_address_and_length, x, ia->address_length,
1193  format_vnet_sw_if_index_name, vnm, sw_if_index);
1194  }));
1195  }
1196 
1197  elts_before = pool_elts (lm->if_address_pool);
1198 
1200  (lm,
1201  sw_if_index,
1202  addr_fib,
1203  address_length,
1204  is_del,
1205  &if_address_index);
1206  if (error)
1207  goto done;
1208 
1209  if (vnet_sw_interface_is_admin_up (vnm, sw_if_index) && insert_routes)
1210  {
1211  if (is_del)
1212  ip4_del_interface_routes (im, ip4_af.fib_index, address,
1213  address_length);
1214 
1215  else
1216  ip4_add_interface_routes (sw_if_index,
1217  im, ip4_af.fib_index,
1219  (lm->if_address_pool, if_address_index));
1220  }
1221 
1222  /* If pool did not grow/shrink: add duplicate address. */
1223  if (elts_before != pool_elts (lm->if_address_pool))
1224  {
1227  cb->function (im, cb->function_opaque, sw_if_index,
1228  address, address_length,
1229  if_address_index,
1230  is_del);
1231  }
1232 
1233  done:
1234  vec_free (addr_fib);
1235  return error;
1236 }
1237 
1238 clib_error_t *
1240  ip4_address_t * address, u32 address_length,
1241  u32 is_del)
1242 {
1244  (vm, sw_if_index, address, address_length,
1245  /* redistribute */ 1,
1246  /* insert_routes */ 1,
1247  is_del);
1248 }
1249 
1250 static clib_error_t *
1252  u32 sw_if_index,
1253  u32 flags)
1254 {
1255  ip4_main_t * im = &ip4_main;
1257  ip4_address_t * a;
1258  u32 is_admin_up, fib_index;
1259 
1260  /* Fill in lookup tables with default table (0). */
1261  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
1262 
1264 
1265  is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
1266 
1267  fib_index = vec_elt (im->fib_index_by_sw_if_index, sw_if_index);
1268 
1269  foreach_ip_interface_address (&im->lookup_main, ia, sw_if_index,
1270  0 /* honor unnumbered */,
1271  ({
1272  a = ip_interface_address_get_address (&im->lookup_main, ia);
1273  if (is_admin_up)
1274  ip4_add_interface_routes (sw_if_index,
1275  im, fib_index,
1276  ia);
1277  else
1278  ip4_del_interface_routes (im, fib_index,
1279  a, ia->address_length);
1280  }));
1281 
1282  return 0;
1283 }
1284 
1286 
1287 static clib_error_t *
1289  u32 sw_if_index,
1290  u32 is_add)
1291 {
1292  vlib_main_t * vm = vnm->vlib_main;
1293  ip4_main_t * im = &ip4_main;
1294  ip_lookup_main_t * lm = &im->lookup_main;
1295  u32 ci, cast;
1296 
1297  for (cast = 0; cast < VNET_N_CAST; cast++)
1298  {
1299  ip_config_main_t * cm = &lm->rx_config_mains[cast];
1300  vnet_config_main_t * vcm = &cm->config_main;
1301 
1302  if (! vcm->node_index_by_feature_index)
1303  {
1304  if (cast == VNET_UNICAST)
1305  {
1306  static char * start_nodes[] = { "ip4-input", "ip4-input-no-checksum", };
1307  static char * feature_nodes[] = {
1308  [IP4_RX_FEATURE_CHECK_ACCESS] = "ip4-inacl",
1309  [IP4_RX_FEATURE_SOURCE_CHECK_REACHABLE_VIA_RX] = "ip4-source-check-via-rx",
1310  [IP4_RX_FEATURE_SOURCE_CHECK_REACHABLE_VIA_ANY] = "ip4-source-check-via-any",
1311  [IP4_RX_FEATURE_IPSEC] = "ipsec-input-ip4",
1312  [IP4_RX_FEATURE_VPATH] = "vpath-input-ip4",
1313  [IP4_RX_FEATURE_LOOKUP] = "ip4-lookup",
1314  };
1315 
1316  vnet_config_init (vm, vcm,
1317  start_nodes, ARRAY_LEN (start_nodes),
1318  feature_nodes, ARRAY_LEN (feature_nodes));
1319  }
1320  else
1321  {
1322  static char * start_nodes[] = { "ip4-input", "ip4-input-no-checksum", };
1323  static char * feature_nodes[] = {
1324  [IP4_RX_FEATURE_VPATH] = "vpath-input-ip4",
1325  [IP4_RX_FEATURE_LOOKUP] = "ip4-lookup-multicast",
1326  };
1327 
1328  vnet_config_init (vm, vcm,
1329  start_nodes, ARRAY_LEN (start_nodes),
1330  feature_nodes, ARRAY_LEN (feature_nodes));
1331  }
1332  }
1333 
1335  ci = cm->config_index_by_sw_if_index[sw_if_index];
1336 
1337  if (is_add)
1338  ci = vnet_config_add_feature (vm, vcm,
1339  ci,
1341  /* config data */ 0,
1342  /* # bytes of config data */ 0);
1343  else
1344  ci = vnet_config_del_feature (vm, vcm,
1345  ci,
1347  /* config data */ 0,
1348  /* # bytes of config data */ 0);
1349 
1350  cm->config_index_by_sw_if_index[sw_if_index] = ci;
1351  }
1352 
1353  return /* no error */ 0;
1354 }
1355 
1357 
1358 static u8 * format_ip4_lookup_trace (u8 * s, va_list * args);
1359 
1361  .function = ip4_lookup,
1362  .name = "ip4-lookup",
1363  .vector_size = sizeof (u32),
1364 
1365  .format_trace = format_ip4_lookup_trace,
1366 
1367  .n_next_nodes = IP_LOOKUP_N_NEXT,
1368  .next_nodes = IP4_LOOKUP_NEXT_NODES,
1369 };
1370 
1371 static uword
1373  vlib_node_runtime_t * node,
1374  vlib_frame_t * frame)
1375 {
1376  return ip4_lookup_inline (vm, node, frame,
1377  /* lookup_for_responses_to_locally_received_packets */ 0,
1378  /* is_indirect */ 1);
1379 }
1380 
1382  .function = ip4_indirect,
1383  .name = "ip4-indirect",
1384  .vector_size = sizeof (u32),
1385 
1386  .format_trace = format_ip4_lookup_trace,
1387 
1388  .n_next_nodes = IP_LOOKUP_N_NEXT,
1389  .next_nodes = IP4_LOOKUP_NEXT_NODES,
1390 };
1391 
1392 
1393 /* Global IP4 main. */
1395 
1396 clib_error_t *
1398 {
1399  ip4_main_t * im = &ip4_main;
1400  uword i;
1401 
1402  for (i = 0; i < ARRAY_LEN (im->fib_masks); i++)
1403  {
1404  u32 m;
1405 
1406  if (i < 32)
1407  m = pow2_mask (i) << (32 - i);
1408  else
1409  m = ~0;
1410  im->fib_masks[i] = clib_host_to_net_u32 (m);
1411  }
1412 
1413  /* Create FIB with index 0 and table id of 0. */
1415 
1416  ip_lookup_init (&im->lookup_main, /* is_ip6 */ 0);
1417 
1418  {
1419  pg_node_t * pn;
1420  pn = pg_get_node (ip4_lookup_node.index);
1422  }
1423 
1424  {
1426 
1427  memset (&h, 0, sizeof (h));
1428 
1429  /* Set target ethernet address to all zeros. */
1430  memset (h.ip4_over_ethernet[1].ethernet, 0, sizeof (h.ip4_over_ethernet[1].ethernet));
1431 
1432 #define _16(f,v) h.f = clib_host_to_net_u16 (v);
1433 #define _8(f,v) h.f = v;
1434  _16 (l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1435  _16 (l3_type, ETHERNET_TYPE_IP4);
1436  _8 (n_l2_address_bytes, 6);
1437  _8 (n_l3_address_bytes, 4);
1438  _16 (opcode, ETHERNET_ARP_OPCODE_request);
1439 #undef _16
1440 #undef _8
1441 
1444  /* data */ &h,
1445  sizeof (h),
1446  /* alloc chunk size */ 8,
1447  "ip4 arp");
1448  }
1449 
1450  return 0;
1451 }
1452 
1454 
1455 typedef struct {
1456  /* Adjacency taken. */
1460 
1461  /* Packet data, possibly *after* rewrite. */
1462  u8 packet_data[64 - 1*sizeof(u32)];
1464 
1465 static u8 * format_ip4_forward_next_trace (u8 * s, va_list * args)
1466 {
1467  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1468  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1469  ip4_forward_next_trace_t * t = va_arg (*args, ip4_forward_next_trace_t *);
1470  uword indent = format_get_indent (s);
1471  s = format (s, "%U%U",
1472  format_white_space, indent,
1474  return s;
1475 }
1476 
1477 static u8 * format_ip4_lookup_trace (u8 * s, va_list * args)
1478 {
1479  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1480  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1481  ip4_forward_next_trace_t * t = va_arg (*args, ip4_forward_next_trace_t *);
1482  vnet_main_t * vnm = vnet_get_main();
1483  ip4_main_t * im = &ip4_main;
1484  uword indent = format_get_indent (s);
1485 
1486  s = format (s, "fib %d adj-idx %d : %U flow hash: 0x%08x",
1488  vnm, &im->lookup_main, t->adj_index, t->flow_hash);
1489  s = format (s, "\n%U%U",
1490  format_white_space, indent,
1492  return s;
1493 }
1494 
1495 static u8 * format_ip4_rewrite_trace (u8 * s, va_list * args)
1496 {
1497  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
1498  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
1499  ip4_forward_next_trace_t * t = va_arg (*args, ip4_forward_next_trace_t *);
1500  vnet_main_t * vnm = vnet_get_main();
1501  ip4_main_t * im = &ip4_main;
1502  uword indent = format_get_indent (s);
1503 
1504  s = format (s, "tx_sw_if_index %d adj-idx %d : %U flow hash: 0x%08x",
1506  vnm, &im->lookup_main, t->adj_index, t->flow_hash);
1507  s = format (s, "\n%U%U",
1508  format_white_space, indent,
1510  vnm, &im->lookup_main, t->adj_index,
1511  t->packet_data, sizeof (t->packet_data));
1512  return s;
1513 }
1514 
1515 /* Common trace function for all ip4-forward next nodes. */
1516 void
1518  vlib_node_runtime_t * node,
1519  vlib_frame_t * frame,
1520  vlib_rx_or_tx_t which_adj_index)
1521 {
1522  u32 * from, n_left;
1523  ip4_main_t * im = &ip4_main;
1524 
1525  n_left = frame->n_vectors;
1526  from = vlib_frame_vector_args (frame);
1527 
1528  while (n_left >= 4)
1529  {
1530  u32 bi0, bi1;
1531  vlib_buffer_t * b0, * b1;
1532  ip4_forward_next_trace_t * t0, * t1;
1533 
1534  /* Prefetch next iteration. */
1535  vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
1536  vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
1537 
1538  bi0 = from[0];
1539  bi1 = from[1];
1540 
1541  b0 = vlib_get_buffer (vm, bi0);
1542  b1 = vlib_get_buffer (vm, bi1);
1543 
1544  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1545  {
1546  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1547  t0->adj_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
1548  t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
1549  t0->fib_index = (vnet_buffer(b0)->sw_if_index[VLIB_TX] != (u32)~0) ?
1550  vnet_buffer(b0)->sw_if_index[VLIB_TX] :
1552  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
1553 
1554  clib_memcpy (t0->packet_data,
1556  sizeof (t0->packet_data));
1557  }
1558  if (b1->flags & VLIB_BUFFER_IS_TRACED)
1559  {
1560  t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
1561  t1->adj_index = vnet_buffer (b1)->ip.adj_index[which_adj_index];
1562  t1->flow_hash = vnet_buffer (b1)->ip.flow_hash;
1563  t1->fib_index = (vnet_buffer(b1)->sw_if_index[VLIB_TX] != (u32)~0) ?
1564  vnet_buffer(b1)->sw_if_index[VLIB_TX] :
1566  vnet_buffer(b1)->sw_if_index[VLIB_RX]);
1567  clib_memcpy (t1->packet_data,
1569  sizeof (t1->packet_data));
1570  }
1571  from += 2;
1572  n_left -= 2;
1573  }
1574 
1575  while (n_left >= 1)
1576  {
1577  u32 bi0;
1578  vlib_buffer_t * b0;
1580 
1581  bi0 = from[0];
1582 
1583  b0 = vlib_get_buffer (vm, bi0);
1584 
1585  if (b0->flags & VLIB_BUFFER_IS_TRACED)
1586  {
1587  t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1588  t0->adj_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
1589  t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
1590  t0->fib_index = (vnet_buffer(b0)->sw_if_index[VLIB_TX] != (u32)~0) ?
1591  vnet_buffer(b0)->sw_if_index[VLIB_TX] :
1593  vnet_buffer(b0)->sw_if_index[VLIB_RX]);
1594  clib_memcpy (t0->packet_data,
1596  sizeof (t0->packet_data));
1597  }
1598  from += 1;
1599  n_left -= 1;
1600  }
1601 }
1602 
1603 static uword
1605  vlib_node_runtime_t * node,
1606  vlib_frame_t * frame,
1607  ip4_error_t error_code)
1608 {
1609  u32 * buffers = vlib_frame_vector_args (frame);
1610  uword n_packets = frame->n_vectors;
1611 
1612  vlib_error_drop_buffers (vm, node,
1613  buffers,
1614  /* stride */ 1,
1615  n_packets,
1616  /* next */ 0,
1617  ip4_input_node.index,
1618  error_code);
1619 
1620  if (node->flags & VLIB_NODE_FLAG_TRACE)
1621  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
1622 
1623  return n_packets;
1624 }
1625 
1626 static uword
1628  vlib_node_runtime_t * node,
1629  vlib_frame_t * frame)
1630 { return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_ADJACENCY_DROP); }
1631 
1632 static uword
1634  vlib_node_runtime_t * node,
1635  vlib_frame_t * frame)
1636 { return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_ADJACENCY_PUNT); }
1637 
1638 static uword
1640  vlib_node_runtime_t * node,
1641  vlib_frame_t * frame)
1642 { return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_DST_LOOKUP_MISS); }
1643 
1645  .function = ip4_drop,
1646  .name = "ip4-drop",
1647  .vector_size = sizeof (u32),
1648 
1649  .format_trace = format_ip4_forward_next_trace,
1650 
1651  .n_next_nodes = 1,
1652  .next_nodes = {
1653  [0] = "error-drop",
1654  },
1655 };
1656 
1658  .function = ip4_punt,
1659  .name = "ip4-punt",
1660  .vector_size = sizeof (u32),
1661 
1662  .format_trace = format_ip4_forward_next_trace,
1663 
1664  .n_next_nodes = 1,
1665  .next_nodes = {
1666  [0] = "error-punt",
1667  },
1668 };
1669 
1671  .function = ip4_miss,
1672  .name = "ip4-miss",
1673  .vector_size = sizeof (u32),
1674 
1675  .format_trace = format_ip4_forward_next_trace,
1676 
1677  .n_next_nodes = 1,
1678  .next_nodes = {
1679  [0] = "error-drop",
1680  },
1681 };
1682 
1683 /* Compute TCP/UDP/ICMP4 checksum in software. */
1684 u16
1686  ip4_header_t * ip0)
1687 {
1688  ip_csum_t sum0;
1689  u32 ip_header_length, payload_length_host_byte_order;
1690  u32 n_this_buffer, n_bytes_left;
1691  u16 sum16;
1692  void * data_this_buffer;
1693 
1694  /* Initialize checksum with ip header. */
1695  ip_header_length = ip4_header_bytes (ip0);
1696  payload_length_host_byte_order = clib_net_to_host_u16 (ip0->length) - ip_header_length;
1697  sum0 = clib_host_to_net_u32 (payload_length_host_byte_order + (ip0->protocol << 16));
1698 
1699  if (BITS (uword) == 32)
1700  {
1701  sum0 = ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->src_address, u32));
1702  sum0 = ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->dst_address, u32));
1703  }
1704  else
1705  sum0 = ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->src_address, u64));
1706 
1707  n_bytes_left = n_this_buffer = payload_length_host_byte_order;
1708  data_this_buffer = (void *) ip0 + ip_header_length;
1709  if (n_this_buffer + ip_header_length > p0->current_length)
1710  n_this_buffer = p0->current_length > ip_header_length ? p0->current_length - ip_header_length : 0;
1711  while (1)
1712  {
1713  sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer);
1714  n_bytes_left -= n_this_buffer;
1715  if (n_bytes_left == 0)
1716  break;
1717 
1719  p0 = vlib_get_buffer (vm, p0->next_buffer);
1720  data_this_buffer = vlib_buffer_get_current (p0);
1721  n_this_buffer = p0->current_length;
1722  }
1723 
1724  sum16 = ~ ip_csum_fold (sum0);
1725 
1726  return sum16;
1727 }
1728 
1729 static u32
1731 {
1733  udp_header_t * udp0;
1734  u16 sum16;
1735 
1736  ASSERT (ip0->protocol == IP_PROTOCOL_TCP
1737  || ip0->protocol == IP_PROTOCOL_UDP);
1738 
1739  udp0 = (void *) (ip0 + 1);
1740  if (ip0->protocol == IP_PROTOCOL_UDP && udp0->checksum == 0)
1741  {
1744  return p0->flags;
1745  }
1746 
1747  sum16 = ip4_tcp_udp_compute_checksum (vm, p0, ip0);
1748 
1750  | ((sum16 == 0) << LOG2_IP_BUFFER_L4_CHECKSUM_CORRECT));
1751 
1752  return p0->flags;
1753 }
1754 
1755 static uword
1757  vlib_node_runtime_t * node,
1758  vlib_frame_t * frame)
1759 {
1760  ip4_main_t * im = &ip4_main;
1761  ip_lookup_main_t * lm = &im->lookup_main;
1762  ip_local_next_t next_index;
1763  u32 * from, * to_next, n_left_from, n_left_to_next;
1764  vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip4_input_node.index);
1765 
1766  from = vlib_frame_vector_args (frame);
1767  n_left_from = frame->n_vectors;
1768  next_index = node->cached_next_index;
1769 
1770  if (node->flags & VLIB_NODE_FLAG_TRACE)
1771  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
1772 
1773  while (n_left_from > 0)
1774  {
1775  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1776 
1777  while (n_left_from >= 4 && n_left_to_next >= 2)
1778  {
1779  vlib_buffer_t * p0, * p1;
1780  ip4_header_t * ip0, * ip1;
1781  udp_header_t * udp0, * udp1;
1782  ip4_fib_mtrie_t * mtrie0, * mtrie1;
1783  ip4_fib_mtrie_leaf_t leaf0, leaf1;
1784  ip_adjacency_t * adj0, * adj1;
1785  u32 pi0, ip_len0, udp_len0, flags0, next0, fib_index0, adj_index0;
1786  u32 pi1, ip_len1, udp_len1, flags1, next1, fib_index1, adj_index1;
1787  i32 len_diff0, len_diff1;
1788  u8 error0, is_udp0, is_tcp_udp0, good_tcp_udp0, proto0;
1789  u8 error1, is_udp1, is_tcp_udp1, good_tcp_udp1, proto1;
1790  u8 enqueue_code;
1791 
1792  pi0 = to_next[0] = from[0];
1793  pi1 = to_next[1] = from[1];
1794  from += 2;
1795  n_left_from -= 2;
1796  to_next += 2;
1797  n_left_to_next -= 2;
1798 
1799  p0 = vlib_get_buffer (vm, pi0);
1800  p1 = vlib_get_buffer (vm, pi1);
1801 
1802  ip0 = vlib_buffer_get_current (p0);
1803  ip1 = vlib_buffer_get_current (p1);
1804 
1805  fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
1806  vnet_buffer(p0)->sw_if_index[VLIB_RX]);
1807  fib_index1 = vec_elt (im->fib_index_by_sw_if_index,
1808  vnet_buffer(p1)->sw_if_index[VLIB_RX]);
1809 
1810  mtrie0 = &vec_elt_at_index (im->fibs, fib_index0)->mtrie;
1811  mtrie1 = &vec_elt_at_index (im->fibs, fib_index1)->mtrie;
1812 
1813  leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
1814 
1815  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 0);
1816  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 0);
1817 
1818  /* Treat IP frag packets as "experimental" protocol for now
1819  until support of IP frag reassembly is implemented */
1820  proto0 = ip4_is_fragment(ip0) ? 0xfe : ip0->protocol;
1821  proto1 = ip4_is_fragment(ip1) ? 0xfe : ip1->protocol;
1822  is_udp0 = proto0 == IP_PROTOCOL_UDP;
1823  is_udp1 = proto1 == IP_PROTOCOL_UDP;
1824  is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
1825  is_tcp_udp1 = is_udp1 || proto1 == IP_PROTOCOL_TCP;
1826 
1827  flags0 = p0->flags;
1828  flags1 = p1->flags;
1829 
1830  good_tcp_udp0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1831  good_tcp_udp1 = (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1832 
1833  udp0 = ip4_next_header (ip0);
1834  udp1 = ip4_next_header (ip1);
1835 
1836  /* Don't verify UDP checksum for packets with explicit zero checksum. */
1837  good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1838  good_tcp_udp1 |= is_udp1 && udp1->checksum == 0;
1839 
1840  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 1);
1841  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 1);
1842 
1843  /* Verify UDP length. */
1844  ip_len0 = clib_net_to_host_u16 (ip0->length);
1845  ip_len1 = clib_net_to_host_u16 (ip1->length);
1846  udp_len0 = clib_net_to_host_u16 (udp0->length);
1847  udp_len1 = clib_net_to_host_u16 (udp1->length);
1848 
1849  len_diff0 = ip_len0 - udp_len0;
1850  len_diff1 = ip_len1 - udp_len1;
1851 
1852  len_diff0 = is_udp0 ? len_diff0 : 0;
1853  len_diff1 = is_udp1 ? len_diff1 : 0;
1854 
1855  if (PREDICT_FALSE (! (is_tcp_udp0 & is_tcp_udp1
1856  & good_tcp_udp0 & good_tcp_udp1)))
1857  {
1858  if (is_tcp_udp0)
1859  {
1860  if (is_tcp_udp0
1861  && ! (flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
1862  flags0 = ip4_tcp_udp_validate_checksum (vm, p0);
1863  good_tcp_udp0 =
1864  (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1865  good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1866  }
1867  if (is_tcp_udp1)
1868  {
1869  if (is_tcp_udp1
1870  && ! (flags1 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
1871  flags1 = ip4_tcp_udp_validate_checksum (vm, p1);
1872  good_tcp_udp1 =
1873  (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1874  good_tcp_udp1 |= is_udp1 && udp1->checksum == 0;
1875  }
1876  }
1877 
1878  good_tcp_udp0 &= len_diff0 >= 0;
1879  good_tcp_udp1 &= len_diff1 >= 0;
1880 
1881  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 2);
1882  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 2);
1883 
1884  error0 = error1 = IP4_ERROR_UNKNOWN_PROTOCOL;
1885 
1886  error0 = len_diff0 < 0 ? IP4_ERROR_UDP_LENGTH : error0;
1887  error1 = len_diff1 < 0 ? IP4_ERROR_UDP_LENGTH : error1;
1888 
1889  ASSERT (IP4_ERROR_TCP_CHECKSUM + 1 == IP4_ERROR_UDP_CHECKSUM);
1890  error0 = (is_tcp_udp0 && ! good_tcp_udp0
1891  ? IP4_ERROR_TCP_CHECKSUM + is_udp0
1892  : error0);
1893  error1 = (is_tcp_udp1 && ! good_tcp_udp1
1894  ? IP4_ERROR_TCP_CHECKSUM + is_udp1
1895  : error1);
1896 
1897  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 3);
1898  leaf1 = ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 3);
1899 
1900  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
1901  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = adj_index0;
1902 
1903  vnet_buffer (p1)->ip.adj_index[VLIB_RX] = adj_index1 = ip4_fib_mtrie_leaf_get_adj_index (leaf1);
1904  vnet_buffer (p1)->ip.adj_index[VLIB_TX] = adj_index1;
1905 
1906  ASSERT (adj_index0 == ip4_fib_lookup_with_table (im, fib_index0,
1907  &ip0->src_address,
1908  /* no_default_route */ 1));
1909  ASSERT (adj_index1 == ip4_fib_lookup_with_table (im, fib_index1,
1910  &ip1->src_address,
1911  /* no_default_route */ 1));
1912 
1913  adj0 = ip_get_adjacency (lm, adj_index0);
1914  adj1 = ip_get_adjacency (lm, adj_index1);
1915 
1916  /*
1917  * Must have a route to source otherwise we drop the packet.
1918  * ip4 broadcasts are accepted, e.g. to make dhcp client work
1919  */
1920  error0 = (error0 == IP4_ERROR_UNKNOWN_PROTOCOL
1924  && ip0->dst_address.as_u32 != 0xFFFFFFFF
1925  ? IP4_ERROR_SRC_LOOKUP_MISS
1926  : error0);
1927  error1 = (error1 == IP4_ERROR_UNKNOWN_PROTOCOL
1931  && ip0->dst_address.as_u32 != 0xFFFFFFFF
1932  ? IP4_ERROR_SRC_LOOKUP_MISS
1933  : error1);
1934 
1935  next0 = lm->local_next_by_ip_protocol[proto0];
1936  next1 = lm->local_next_by_ip_protocol[proto1];
1937 
1938  next0 = error0 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0;
1939  next1 = error1 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next1;
1940 
1941  p0->error = error0 ? error_node->errors[error0] : 0;
1942  p1->error = error1 ? error_node->errors[error1] : 0;
1943 
1944  enqueue_code = (next0 != next_index) + 2*(next1 != next_index);
1945 
1946  if (PREDICT_FALSE (enqueue_code != 0))
1947  {
1948  switch (enqueue_code)
1949  {
1950  case 1:
1951  /* A B A */
1952  to_next[-2] = pi1;
1953  to_next -= 1;
1954  n_left_to_next += 1;
1955  vlib_set_next_frame_buffer (vm, node, next0, pi0);
1956  break;
1957 
1958  case 2:
1959  /* A A B */
1960  to_next -= 1;
1961  n_left_to_next += 1;
1962  vlib_set_next_frame_buffer (vm, node, next1, pi1);
1963  break;
1964 
1965  case 3:
1966  /* A B B or A B C */
1967  to_next -= 2;
1968  n_left_to_next += 2;
1969  vlib_set_next_frame_buffer (vm, node, next0, pi0);
1970  vlib_set_next_frame_buffer (vm, node, next1, pi1);
1971  if (next0 == next1)
1972  {
1973  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1974  next_index = next1;
1975  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1976  }
1977  break;
1978  }
1979  }
1980  }
1981 
1982  while (n_left_from > 0 && n_left_to_next > 0)
1983  {
1984  vlib_buffer_t * p0;
1985  ip4_header_t * ip0;
1986  udp_header_t * udp0;
1987  ip4_fib_mtrie_t * mtrie0;
1988  ip4_fib_mtrie_leaf_t leaf0;
1989  ip_adjacency_t * adj0;
1990  u32 pi0, next0, ip_len0, udp_len0, flags0, fib_index0, adj_index0;
1991  i32 len_diff0;
1992  u8 error0, is_udp0, is_tcp_udp0, good_tcp_udp0, proto0;
1993 
1994  pi0 = to_next[0] = from[0];
1995  from += 1;
1996  n_left_from -= 1;
1997  to_next += 1;
1998  n_left_to_next -= 1;
1999 
2000  p0 = vlib_get_buffer (vm, pi0);
2001 
2002  ip0 = vlib_buffer_get_current (p0);
2003 
2004  fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
2005  vnet_buffer(p0)->sw_if_index[VLIB_RX]);
2006 
2007  mtrie0 = &vec_elt_at_index (im->fibs, fib_index0)->mtrie;
2008 
2009  leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
2010 
2011  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 0);
2012 
2013  /* Treat IP frag packets as "experimental" protocol for now
2014  until support of IP frag reassembly is implemented */
2015  proto0 = ip4_is_fragment(ip0) ? 0xfe : ip0->protocol;
2016  is_udp0 = proto0 == IP_PROTOCOL_UDP;
2017  is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
2018 
2019  flags0 = p0->flags;
2020 
2021  good_tcp_udp0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
2022 
2023  udp0 = ip4_next_header (ip0);
2024 
2025  /* Don't verify UDP checksum for packets with explicit zero checksum. */
2026  good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
2027 
2028  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 1);
2029 
2030  /* Verify UDP length. */
2031  ip_len0 = clib_net_to_host_u16 (ip0->length);
2032  udp_len0 = clib_net_to_host_u16 (udp0->length);
2033 
2034  len_diff0 = ip_len0 - udp_len0;
2035 
2036  len_diff0 = is_udp0 ? len_diff0 : 0;
2037 
2038  if (PREDICT_FALSE (! (is_tcp_udp0 & good_tcp_udp0)))
2039  {
2040  if (is_tcp_udp0)
2041  {
2042  if (is_tcp_udp0
2043  && ! (flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
2044  flags0 = ip4_tcp_udp_validate_checksum (vm, p0);
2045  good_tcp_udp0 =
2046  (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
2047  good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
2048  }
2049  }
2050 
2051  good_tcp_udp0 &= len_diff0 >= 0;
2052 
2053  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 2);
2054 
2055  error0 = IP4_ERROR_UNKNOWN_PROTOCOL;
2056 
2057  error0 = len_diff0 < 0 ? IP4_ERROR_UDP_LENGTH : error0;
2058 
2059  ASSERT (IP4_ERROR_TCP_CHECKSUM + 1 == IP4_ERROR_UDP_CHECKSUM);
2060  error0 = (is_tcp_udp0 && ! good_tcp_udp0
2061  ? IP4_ERROR_TCP_CHECKSUM + is_udp0
2062  : error0);
2063 
2064  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 3);
2065 
2066  vnet_buffer (p0)->ip.adj_index[VLIB_RX] = adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
2067  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = adj_index0;
2068 
2069  ASSERT (adj_index0 == ip4_fib_lookup_with_table (im, fib_index0,
2070  &ip0->src_address,
2071  /* no_default_route */ 1));
2072 
2073  adj0 = ip_get_adjacency (lm, adj_index0);
2074 
2075  /* Must have a route to source otherwise we drop the packet. */
2076  error0 = (error0 == IP4_ERROR_UNKNOWN_PROTOCOL
2080  && ip0->dst_address.as_u32 != 0xFFFFFFFF
2081  ? IP4_ERROR_SRC_LOOKUP_MISS
2082  : error0);
2083 
2084  next0 = lm->local_next_by_ip_protocol[proto0];
2085 
2086  next0 = error0 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0;
2087 
2088  p0->error = error0? error_node->errors[error0] : 0;
2089 
2090  if (PREDICT_FALSE (next0 != next_index))
2091  {
2092  n_left_to_next += 1;
2093  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2094 
2095  next_index = next0;
2096  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2097  to_next[0] = pi0;
2098  to_next += 1;
2099  n_left_to_next -= 1;
2100  }
2101  }
2102 
2103  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2104  }
2105 
2106  return frame->n_vectors;
2107 }
2108 
2110  .function = ip4_local,
2111  .name = "ip4-local",
2112  .vector_size = sizeof (u32),
2113 
2114  .format_trace = format_ip4_forward_next_trace,
2115 
2116  .n_next_nodes = IP_LOCAL_N_NEXT,
2117  .next_nodes = {
2118  [IP_LOCAL_NEXT_DROP] = "error-drop",
2119  [IP_LOCAL_NEXT_PUNT] = "error-punt",
2120  [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
2121  [IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",
2122  },
2123 };
2124 
2125 void ip4_register_protocol (u32 protocol, u32 node_index)
2126 {
2127  vlib_main_t * vm = vlib_get_main();
2128  ip4_main_t * im = &ip4_main;
2129  ip_lookup_main_t * lm = &im->lookup_main;
2130 
2131  ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
2132  lm->local_next_by_ip_protocol[protocol] = vlib_node_add_next (vm, ip4_local_node.index, node_index);
2133 }
2134 
2135 static clib_error_t *
2137  unformat_input_t * input,
2138  vlib_cli_command_t * cmd)
2139 {
2140  ip4_main_t * im = &ip4_main;
2141  ip_lookup_main_t * lm = &im->lookup_main;
2142  int i;
2143 
2144  vlib_cli_output (vm, "Protocols handled by ip4_local");
2145  for (i = 0; i < ARRAY_LEN(lm->local_next_by_ip_protocol); i++)
2146  {
2148  vlib_cli_output (vm, "%d", i);
2149  }
2150  return 0;
2151 }
2152 
2153 
2154 
2155 VLIB_CLI_COMMAND (show_ip_local, static) = {
2156  .path = "show ip local",
2157  .function = show_ip_local_command_fn,
2158  .short_help = "Show ip local protocol table",
2159 };
2160 
2161 static uword
2163  vlib_node_runtime_t * node,
2164  vlib_frame_t * frame)
2165 {
2166  vnet_main_t * vnm = vnet_get_main();
2167  ip4_main_t * im = &ip4_main;
2168  ip_lookup_main_t * lm = &im->lookup_main;
2169  u32 * from, * to_next_drop;
2170  uword n_left_from, n_left_to_next_drop, next_index;
2171  static f64 time_last_seed_change = -1e100;
2172  static u32 hash_seeds[3];
2173  static uword hash_bitmap[256 / BITS (uword)];
2174  f64 time_now;
2175 
2176  if (node->flags & VLIB_NODE_FLAG_TRACE)
2177  ip4_forward_next_trace (vm, node, frame, VLIB_TX);
2178 
2179  time_now = vlib_time_now (vm);
2180  if (time_now - time_last_seed_change > 1e-3)
2181  {
2182  uword i;
2184  sizeof (hash_seeds));
2185  for (i = 0; i < ARRAY_LEN (hash_seeds); i++)
2186  hash_seeds[i] = r[i];
2187 
2188  /* Mark all hash keys as been no-seen before. */
2189  for (i = 0; i < ARRAY_LEN (hash_bitmap); i++)
2190  hash_bitmap[i] = 0;
2191 
2192  time_last_seed_change = time_now;
2193  }
2194 
2195  from = vlib_frame_vector_args (frame);
2196  n_left_from = frame->n_vectors;
2197  next_index = node->cached_next_index;
2198  if (next_index == IP4_ARP_NEXT_DROP)
2199  next_index = IP4_ARP_N_NEXT; /* point to first interface */
2200 
2201  while (n_left_from > 0)
2202  {
2204  to_next_drop, n_left_to_next_drop);
2205 
2206  while (n_left_from > 0 && n_left_to_next_drop > 0)
2207  {
2208  vlib_buffer_t * p0;
2209  ip4_header_t * ip0;
2210  ethernet_header_t * eh0;
2211  u32 pi0, adj_index0, a0, b0, c0, m0, sw_if_index0, drop0;
2212  uword bm0;
2213  ip_adjacency_t * adj0;
2214 
2215  pi0 = from[0];
2216 
2217  p0 = vlib_get_buffer (vm, pi0);
2218 
2219  adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
2220  adj0 = ip_get_adjacency (lm, adj_index0);
2221  ip0 = vlib_buffer_get_current (p0);
2222 
2223  /* If packet destination is not local, send ARP to next hop */
2224  if (adj0->arp.next_hop.ip4.as_u32)
2225  ip0->dst_address.data_u32 = adj0->arp.next_hop.ip4.as_u32;
2226 
2227  /*
2228  * if ip4_rewrite_local applied the IP_LOOKUP_NEXT_ARP
2229  * rewrite to this packet, we need to skip it here.
2230  * Note, to distinguish from src IP addr *.8.6.*, we
2231  * check for a bcast eth dest instead of IPv4 version.
2232  */
2233  eh0 = (ethernet_header_t*)ip0;
2234  if ((ip0->ip_version_and_header_length & 0xF0) != 0x40)
2235  {
2236  u32 vlan_num = 0;
2237  u16 * etype = &eh0->type;
2238  while ((*etype == clib_host_to_net_u16 (0x8100)) //dot1q
2239  || (*etype == clib_host_to_net_u16 (0x88a8)))//dot1ad
2240  {
2241  vlan_num += 1;
2242  etype += 2; //vlan tag also 16 bits, same as etype
2243  }
2244  if (*etype == clib_host_to_net_u16 (0x0806)) //arp
2245  {
2247  p0, sizeof(ethernet_header_t) + (4*vlan_num));
2248  ip0 = vlib_buffer_get_current (p0);
2249  }
2250  }
2251 
2252  a0 = hash_seeds[0];
2253  b0 = hash_seeds[1];
2254  c0 = hash_seeds[2];
2255 
2256  sw_if_index0 = adj0->rewrite_header.sw_if_index;
2257  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2258 
2259  a0 ^= ip0->dst_address.data_u32;
2260  b0 ^= sw_if_index0;
2261 
2262  hash_v3_finalize32 (a0, b0, c0);
2263 
2264  c0 &= BITS (hash_bitmap) - 1;
2265  c0 = c0 / BITS (uword);
2266  m0 = (uword) 1 << (c0 % BITS (uword));
2267 
2268  bm0 = hash_bitmap[c0];
2269  drop0 = (bm0 & m0) != 0;
2270 
2271  /* Mark it as seen. */
2272  hash_bitmap[c0] = bm0 | m0;
2273 
2274  from += 1;
2275  n_left_from -= 1;
2276  to_next_drop[0] = pi0;
2277  to_next_drop += 1;
2278  n_left_to_next_drop -= 1;
2279 
2281 
2282  if (drop0)
2283  continue;
2284 
2285  /*
2286  * Can happen if the control-plane is programming tables
2287  * with traffic flowing; at least that's today's lame excuse.
2288  */
2289  if (adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP)
2290  {
2291  p0->error = node->errors[IP4_ARP_ERROR_NON_ARP_ADJ];
2292  }
2293  else
2294  /* Send ARP request. */
2295  {
2296  u32 bi0 = 0;
2297  vlib_buffer_t * b0;
2298  ethernet_arp_header_t * h0;
2299  vnet_hw_interface_t * hw_if0;
2300 
2302 
2303  /* Add rewrite/encap string for ARP packet. */
2304  vnet_rewrite_one_header (adj0[0], h0, sizeof (ethernet_header_t));
2305 
2306  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
2307 
2308  /* Src ethernet address in ARP header. */
2309  clib_memcpy (h0->ip4_over_ethernet[0].ethernet, hw_if0->hw_address,
2310  sizeof (h0->ip4_over_ethernet[0].ethernet));
2311 
2312  ip4_src_address_for_packet (im, p0, &h0->ip4_over_ethernet[0].ip4, sw_if_index0);
2313 
2314  /* Copy in destination address we are requesting. */
2315  h0->ip4_over_ethernet[1].ip4.data_u32 = ip0->dst_address.data_u32;
2316 
2317  vlib_buffer_copy_trace_flag (vm, p0, bi0);
2318  b0 = vlib_get_buffer (vm, bi0);
2319  vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
2320 
2321  vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
2322 
2323  vlib_set_next_frame_buffer (vm, node, adj0->rewrite_header.next_index, bi0);
2324  }
2325  }
2326 
2327  vlib_put_next_frame (vm, node, IP4_ARP_NEXT_DROP, n_left_to_next_drop);
2328  }
2329 
2330  return frame->n_vectors;
2331 }
2332 
2333 static char * ip4_arp_error_strings[] = {
2334  [IP4_ARP_ERROR_DROP] = "address overflow drops",
2335  [IP4_ARP_ERROR_REQUEST_SENT] = "ARP requests sent",
2336  [IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies",
2337  [IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed",
2338  [IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed",
2339 };
2340 
2342  .function = ip4_arp,
2343  .name = "ip4-arp",
2344  .vector_size = sizeof (u32),
2345 
2346  .format_trace = format_ip4_forward_next_trace,
2347 
2348  .n_errors = ARRAY_LEN (ip4_arp_error_strings),
2349  .error_strings = ip4_arp_error_strings,
2350 
2351  .n_next_nodes = IP4_ARP_N_NEXT,
2352  .next_nodes = {
2353  [IP4_ARP_NEXT_DROP] = "error-drop",
2354  },
2355 };
2356 
2357 #define foreach_notrace_ip4_arp_error \
2358 _(DROP) \
2359 _(REQUEST_SENT) \
2360 _(REPLICATE_DROP) \
2361 _(REPLICATE_FAIL)
2362 
2364 {
2365  vlib_node_runtime_t *rt =
2366  vlib_node_get_runtime (vm, ip4_arp_node.index);
2367 
2368  /* don't trace ARP request packets */
2369 #define _(a) \
2370  vnet_pcap_drop_trace_filter_add_del \
2371  (rt->errors[IP4_ARP_ERROR_##a], \
2372  1 /* is_add */);
2374 #undef _
2375  return 0;
2376 }
2377 
2379 
2380 
2381 /* Send an ARP request to see if given destination is reachable on given interface. */
2382 clib_error_t *
2384 {
2385  vnet_main_t * vnm = vnet_get_main();
2386  ip4_main_t * im = &ip4_main;
2388  ip4_address_t * src;
2390  ip_adjacency_t * adj;
2392  vnet_sw_interface_t * si;
2393  vlib_buffer_t * b;
2394  u32 bi = 0;
2395 
2396  si = vnet_get_sw_interface (vnm, sw_if_index);
2397 
2399  {
2400  return clib_error_return (0, "%U: interface %U down",
2401  format_ip4_address, dst,
2403  sw_if_index);
2404  }
2405 
2406  src = ip4_interface_address_matching_destination (im, dst, sw_if_index, &ia);
2407  if (! src)
2408  {
2409  vnm->api_errno = VNET_API_ERROR_NO_MATCHING_INTERFACE;
2410  return clib_error_return
2411  (0, "no matching interface address for destination %U (interface %U)",
2412  format_ip4_address, dst,
2413  format_vnet_sw_if_index_name, vnm, sw_if_index);
2414  }
2415 
2417 
2419 
2420  hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
2421 
2422  clib_memcpy (h->ip4_over_ethernet[0].ethernet, hi->hw_address, sizeof (h->ip4_over_ethernet[0].ethernet));
2423 
2424  h->ip4_over_ethernet[0].ip4 = src[0];
2425  h->ip4_over_ethernet[1].ip4 = dst[0];
2426 
2427  b = vlib_get_buffer (vm, bi);
2428  vnet_buffer (b)->sw_if_index[VLIB_RX] = vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
2429 
2430  /* Add encapsulation string for software interface (e.g. ethernet header). */
2431  vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
2432  vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
2433 
2434  {
2436  u32 * to_next = vlib_frame_vector_args (f);
2437  to_next[0] = bi;
2438  f->n_vectors = 1;
2440  }
2441 
2442  return /* no error */ 0;
2443 }
2444 
2445 typedef enum {
2449 
2452  vlib_node_runtime_t * node,
2453  vlib_frame_t * frame,
2454  int rewrite_for_locally_received_packets)
2455 {
2456  ip_lookup_main_t * lm = &ip4_main.lookup_main;
2457  u32 * from = vlib_frame_vector_args (frame);
2458  u32 n_left_from, n_left_to_next, * to_next, next_index;
2459  vlib_node_runtime_t * error_node = vlib_node_get_runtime (vm, ip4_input_node.index);
2460  vlib_rx_or_tx_t adj_rx_tx = rewrite_for_locally_received_packets ? VLIB_RX : VLIB_TX;
2461 
2462  n_left_from = frame->n_vectors;
2463  next_index = node->cached_next_index;
2464  u32 cpu_index = os_get_cpu_number();
2465 
2466  while (n_left_from > 0)
2467  {
2468  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2469 
2470  while (n_left_from >= 4 && n_left_to_next >= 2)
2471  {
2472  ip_adjacency_t * adj0, * adj1;
2473  vlib_buffer_t * p0, * p1;
2474  ip4_header_t * ip0, * ip1;
2475  u32 pi0, rw_len0, next0, error0, checksum0, adj_index0;
2476  u32 pi1, rw_len1, next1, error1, checksum1, adj_index1;
2477  u32 next0_override, next1_override;
2478 
2479  if (rewrite_for_locally_received_packets)
2480  next0_override = next1_override = 0;
2481 
2482  /* Prefetch next iteration. */
2483  {
2484  vlib_buffer_t * p2, * p3;
2485 
2486  p2 = vlib_get_buffer (vm, from[2]);
2487  p3 = vlib_get_buffer (vm, from[3]);
2488 
2489  vlib_prefetch_buffer_header (p2, STORE);
2490  vlib_prefetch_buffer_header (p3, STORE);
2491 
2492  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE);
2493  CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE);
2494  }
2495 
2496  pi0 = to_next[0] = from[0];
2497  pi1 = to_next[1] = from[1];
2498 
2499  from += 2;
2500  n_left_from -= 2;
2501  to_next += 2;
2502  n_left_to_next -= 2;
2503 
2504  p0 = vlib_get_buffer (vm, pi0);
2505  p1 = vlib_get_buffer (vm, pi1);
2506 
2507  adj_index0 = vnet_buffer (p0)->ip.adj_index[adj_rx_tx];
2508  adj_index1 = vnet_buffer (p1)->ip.adj_index[adj_rx_tx];
2509 
2510  /* We should never rewrite a pkt using the MISS adjacency */
2511  ASSERT(adj_index0 && adj_index1);
2512 
2513  ip0 = vlib_buffer_get_current (p0);
2514  ip1 = vlib_buffer_get_current (p1);
2515 
2516  error0 = error1 = IP4_ERROR_NONE;
2517 
2518  /* Decrement TTL & update checksum.
2519  Works either endian, so no need for byte swap. */
2520  if (! rewrite_for_locally_received_packets)
2521  {
2522  i32 ttl0 = ip0->ttl, ttl1 = ip1->ttl;
2523 
2524  /* Input node should have reject packets with ttl 0. */
2525  ASSERT (ip0->ttl > 0);
2526  ASSERT (ip1->ttl > 0);
2527 
2528  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
2529  checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
2530 
2531  checksum0 += checksum0 >= 0xffff;
2532  checksum1 += checksum1 >= 0xffff;
2533 
2534  ip0->checksum = checksum0;
2535  ip1->checksum = checksum1;
2536 
2537  ttl0 -= 1;
2538  ttl1 -= 1;
2539 
2540  ip0->ttl = ttl0;
2541  ip1->ttl = ttl1;
2542 
2543  error0 = ttl0 <= 0 ? IP4_ERROR_TIME_EXPIRED : error0;
2544  error1 = ttl1 <= 0 ? IP4_ERROR_TIME_EXPIRED : error1;
2545 
2546  /* Verify checksum. */
2547  ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2548  ASSERT (ip1->checksum == ip4_header_checksum (ip1));
2549  }
2550 
2551  /* Rewrite packet header and updates lengths. */
2552  adj0 = ip_get_adjacency (lm, adj_index0);
2553  adj1 = ip_get_adjacency (lm, adj_index1);
2554 
2555  if (rewrite_for_locally_received_packets)
2556  {
2557  /*
2558  * If someone sends e.g. an icmp4 w/ src = dst = interface addr,
2559  * we end up here with a local adjacency in hand
2560  * The local adj rewrite data is 0xfefe on purpose.
2561  * Bad engineer, no donut for you.
2562  */
2563  if (PREDICT_FALSE(adj0->lookup_next_index
2565  error0 = IP4_ERROR_SPOOFED_LOCAL_PACKETS;
2567  == IP_LOOKUP_NEXT_ARP))
2568  next0_override = IP4_REWRITE_NEXT_ARP;
2569  if (PREDICT_FALSE(adj1->lookup_next_index
2571  error1 = IP4_ERROR_SPOOFED_LOCAL_PACKETS;
2573  == IP_LOOKUP_NEXT_ARP))
2574  next1_override = IP4_REWRITE_NEXT_ARP;
2575  }
2576 
2577  /* Worth pipelining. No guarantee that adj0,1 are hot... */
2578  rw_len0 = adj0[0].rewrite_header.data_bytes;
2579  rw_len1 = adj1[0].rewrite_header.data_bytes;
2580  next0 = (error0 == IP4_ERROR_NONE)
2581  ? adj0[0].rewrite_header.next_index : 0;
2582 
2583  if (rewrite_for_locally_received_packets)
2584  next0 = next0 && next0_override ? next0_override : next0;
2585 
2586  next1 = (error1 == IP4_ERROR_NONE)
2587  ? adj1[0].rewrite_header.next_index : 0;
2588 
2589  if (rewrite_for_locally_received_packets)
2590  next1 = next1 && next1_override ? next1_override : next1;
2591 
2592  /*
2593  * We've already accounted for an ethernet_header_t elsewhere
2594  */
2595  if (PREDICT_FALSE (rw_len0 > sizeof(ethernet_header_t)))
2597  (&lm->adjacency_counters,
2598  cpu_index, adj_index0,
2599  /* packet increment */ 0,
2600  /* byte increment */ rw_len0-sizeof(ethernet_header_t));
2601 
2602  if (PREDICT_FALSE (rw_len1 > sizeof(ethernet_header_t)))
2604  (&lm->adjacency_counters,
2605  cpu_index, adj_index1,
2606  /* packet increment */ 0,
2607  /* byte increment */ rw_len1-sizeof(ethernet_header_t));
2608 
2609  /* Check MTU of outgoing interface. */
2610  error0 = (vlib_buffer_length_in_chain (vm, p0) > adj0[0].rewrite_header.max_l3_packet_bytes
2611  ? IP4_ERROR_MTU_EXCEEDED
2612  : error0);
2613  error1 = (vlib_buffer_length_in_chain (vm, p1) > adj1[0].rewrite_header.max_l3_packet_bytes
2614  ? IP4_ERROR_MTU_EXCEEDED
2615  : error1);
2616 
2617  p0->current_data -= rw_len0;
2618  p1->current_data -= rw_len1;
2619 
2620  p0->current_length += rw_len0;
2621  p1->current_length += rw_len1;
2622 
2623  vnet_buffer (p0)->sw_if_index[VLIB_TX] = adj0[0].rewrite_header.sw_if_index;
2624  vnet_buffer (p1)->sw_if_index[VLIB_TX] = adj1[0].rewrite_header.sw_if_index;
2625 
2626  p0->error = error_node->errors[error0];
2627  p1->error = error_node->errors[error1];
2628 
2629  /* Guess we are only writing on simple Ethernet header. */
2630  vnet_rewrite_two_headers (adj0[0], adj1[0],
2631  ip0, ip1,
2632  sizeof (ethernet_header_t));
2633 
2634  vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
2635  to_next, n_left_to_next,
2636  pi0, pi1, next0, next1);
2637  }
2638 
2639  while (n_left_from > 0 && n_left_to_next > 0)
2640  {
2641  ip_adjacency_t * adj0;
2642  vlib_buffer_t * p0;
2643  ip4_header_t * ip0;
2644  u32 pi0, rw_len0, adj_index0, next0, error0, checksum0;
2645  u32 next0_override;
2646 
2647  if (rewrite_for_locally_received_packets)
2648  next0_override = 0;
2649 
2650  pi0 = to_next[0] = from[0];
2651 
2652  p0 = vlib_get_buffer (vm, pi0);
2653 
2654  adj_index0 = vnet_buffer (p0)->ip.adj_index[adj_rx_tx];
2655 
2656  /* We should never rewrite a pkt using the MISS adjacency */
2657  ASSERT(adj_index0);
2658 
2659  adj0 = ip_get_adjacency (lm, adj_index0);
2660 
2661  ip0 = vlib_buffer_get_current (p0);
2662 
2663  error0 = IP4_ERROR_NONE;
2664  next0 = 0; /* drop on error */
2665 
2666  /* Decrement TTL & update checksum. */
2667  if (! rewrite_for_locally_received_packets)
2668  {
2669  i32 ttl0 = ip0->ttl;
2670 
2671  checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
2672 
2673  checksum0 += checksum0 >= 0xffff;
2674 
2675  ip0->checksum = checksum0;
2676 
2677  ASSERT (ip0->ttl > 0);
2678 
2679  ttl0 -= 1;
2680 
2681  ip0->ttl = ttl0;
2682 
2683  ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2684 
2685  error0 = ttl0 <= 0 ? IP4_ERROR_TIME_EXPIRED : error0;
2686  }
2687 
2688  if (rewrite_for_locally_received_packets)
2689  {
2690  /*
2691  * If someone sends e.g. an icmp4 w/ src = dst = interface addr,
2692  * we end up here with a local adjacency in hand
2693  * The local adj rewrite data is 0xfefe on purpose.
2694  * Bad engineer, no donut for you.
2695  */
2696  if (PREDICT_FALSE(adj0->lookup_next_index
2698  error0 = IP4_ERROR_SPOOFED_LOCAL_PACKETS;
2699  /*
2700  * We have to override the next_index in ARP adjacencies,
2701  * because they're set up for ip4-arp, not this node...
2702  */
2704  == IP_LOOKUP_NEXT_ARP))
2705  next0_override = IP4_REWRITE_NEXT_ARP;
2706  }
2707 
2708  /* Guess we are only writing on simple Ethernet header. */
2709  vnet_rewrite_one_header (adj0[0], ip0,
2710  sizeof (ethernet_header_t));
2711 
2712  /* Update packet buffer attributes/set output interface. */
2713  rw_len0 = adj0[0].rewrite_header.data_bytes;
2714 
2715  if (PREDICT_FALSE (rw_len0 > sizeof(ethernet_header_t)))
2717  (&lm->adjacency_counters,
2718  cpu_index, adj_index0,
2719  /* packet increment */ 0,
2720  /* byte increment */ rw_len0-sizeof(ethernet_header_t));
2721 
2722  /* Check MTU of outgoing interface. */
2723  error0 = (vlib_buffer_length_in_chain (vm, p0)
2724  > adj0[0].rewrite_header.max_l3_packet_bytes
2725  ? IP4_ERROR_MTU_EXCEEDED
2726  : error0);
2727 
2728  p0->error = error_node->errors[error0];
2729  p0->current_data -= rw_len0;
2730  p0->current_length += rw_len0;
2731  vnet_buffer (p0)->sw_if_index[VLIB_TX] =
2732  adj0[0].rewrite_header.sw_if_index;
2733 
2734  next0 = (error0 == IP4_ERROR_NONE)
2735  ? adj0[0].rewrite_header.next_index : 0;
2736 
2737  if (rewrite_for_locally_received_packets)
2738  next0 = next0 && next0_override ? next0_override : next0;
2739 
2740  from += 1;
2741  n_left_from -= 1;
2742  to_next += 1;
2743  n_left_to_next -= 1;
2744 
2745  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2746  to_next, n_left_to_next,
2747  pi0, next0);
2748  }
2749 
2750  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2751  }
2752 
2753  /* Need to do trace after rewrites to pick up new packet data. */
2754  if (node->flags & VLIB_NODE_FLAG_TRACE)
2755  ip4_forward_next_trace (vm, node, frame, adj_rx_tx);
2756 
2757  return frame->n_vectors;
2758 }
2759 
2760 static uword
2762  vlib_node_runtime_t * node,
2763  vlib_frame_t * frame)
2764 {
2765  return ip4_rewrite_inline (vm, node, frame,
2766  /* rewrite_for_locally_received_packets */ 0);
2767 }
2768 
2769 static uword
2771  vlib_node_runtime_t * node,
2772  vlib_frame_t * frame)
2773 {
2774  return ip4_rewrite_inline (vm, node, frame,
2775  /* rewrite_for_locally_received_packets */ 1);
2776 }
2777 
2779  .function = ip4_rewrite_transit,
2780  .name = "ip4-rewrite-transit",
2781  .vector_size = sizeof (u32),
2782 
2783  .format_trace = format_ip4_rewrite_trace,
2784 
2785  .n_next_nodes = 2,
2786  .next_nodes = {
2787  [IP4_REWRITE_NEXT_DROP] = "error-drop",
2788  [IP4_REWRITE_NEXT_ARP] = "ip4-arp",
2789  },
2790 };
2791 
2793  .function = ip4_rewrite_local,
2794  .name = "ip4-rewrite-local",
2795  .vector_size = sizeof (u32),
2796 
2797  .sibling_of = "ip4-rewrite-transit",
2798 
2799  .format_trace = format_ip4_rewrite_trace,
2800 
2801  .n_next_nodes = 2,
2802  .next_nodes = {
2803  [IP4_REWRITE_NEXT_DROP] = "error-drop",
2804  [IP4_REWRITE_NEXT_ARP] = "ip4-arp",
2805  },
2806 };
2807 
2808 static clib_error_t *
2810  unformat_input_t * input,
2811  vlib_cli_command_t * cmd)
2812 {
2813  vnet_main_t * vnm = vnet_get_main();
2814  clib_error_t * error = 0;
2815  u32 sw_if_index, table_id;
2816 
2817  sw_if_index = ~0;
2818 
2819  if (! unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
2820  {
2821  error = clib_error_return (0, "unknown interface `%U'",
2822  format_unformat_error, input);
2823  goto done;
2824  }
2825 
2826  if (unformat (input, "%d", &table_id))
2827  ;
2828  else
2829  {
2830  error = clib_error_return (0, "expected table id `%U'",
2831  format_unformat_error, input);
2832  goto done;
2833  }
2834 
2835  {
2836  ip4_main_t * im = &ip4_main;
2838 
2839  if (fib)
2840  {
2841  vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
2842  im->fib_index_by_sw_if_index[sw_if_index] = fib->index;
2843  }
2844  }
2845 
2846  done:
2847  return error;
2848 }
2849 
2850 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) = {
2851  .path = "set interface ip table",
2852  .function = add_del_interface_table,
2853  .short_help = "Add/delete FIB table id for interface",
2854 };
2855 
2856 
2857 static uword
2859  vlib_node_runtime_t * node,
2860  vlib_frame_t * frame)
2861 {
2862  ip4_main_t * im = &ip4_main;
2863  ip_lookup_main_t * lm = &im->lookup_main;
2865  u32 n_left_from, n_left_to_next, * from, * to_next;
2866  ip_lookup_next_t next;
2867  u32 cpu_index = os_get_cpu_number();
2868 
2869  from = vlib_frame_vector_args (frame);
2870  n_left_from = frame->n_vectors;
2871  next = node->cached_next_index;
2872 
2873  while (n_left_from > 0)
2874  {
2875  vlib_get_next_frame (vm, node, next,
2876  to_next, n_left_to_next);
2877 
2878  while (n_left_from >= 4 && n_left_to_next >= 2)
2879  {
2880  vlib_buffer_t * p0, * p1;
2881  u32 pi0, pi1, adj_index0, adj_index1, wrong_next;
2882  ip_lookup_next_t next0, next1;
2883  ip4_header_t * ip0, * ip1;
2884  ip_adjacency_t * adj0, * adj1;
2885  u32 fib_index0, fib_index1;
2886  u32 flow_hash_config0, flow_hash_config1;
2887 
2888  /* Prefetch next iteration. */
2889  {
2890  vlib_buffer_t * p2, * p3;
2891 
2892  p2 = vlib_get_buffer (vm, from[2]);
2893  p3 = vlib_get_buffer (vm, from[3]);
2894 
2895  vlib_prefetch_buffer_header (p2, LOAD);
2896  vlib_prefetch_buffer_header (p3, LOAD);
2897 
2898  CLIB_PREFETCH (p2->data, sizeof (ip0[0]), LOAD);
2899  CLIB_PREFETCH (p3->data, sizeof (ip0[0]), LOAD);
2900  }
2901 
2902  pi0 = to_next[0] = from[0];
2903  pi1 = to_next[1] = from[1];
2904 
2905  p0 = vlib_get_buffer (vm, pi0);
2906  p1 = vlib_get_buffer (vm, pi1);
2907 
2908  ip0 = vlib_buffer_get_current (p0);
2909  ip1 = vlib_buffer_get_current (p1);
2910 
2911  fib_index0 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (p0)->sw_if_index[VLIB_RX]);
2912  fib_index1 = vec_elt (im->fib_index_by_sw_if_index, vnet_buffer (p1)->sw_if_index[VLIB_RX]);
2913  fib_index0 = (vnet_buffer(p0)->sw_if_index[VLIB_TX] == (u32)~0) ?
2914  fib_index0 : vnet_buffer(p0)->sw_if_index[VLIB_TX];
2915  fib_index1 = (vnet_buffer(p1)->sw_if_index[VLIB_TX] == (u32)~0) ?
2916  fib_index1 : vnet_buffer(p1)->sw_if_index[VLIB_TX];
2917 
2918  adj_index0 = ip4_fib_lookup_buffer (im, fib_index0,
2919  &ip0->dst_address, p0);
2920  adj_index1 = ip4_fib_lookup_buffer (im, fib_index1,
2921  &ip1->dst_address, p1);
2922 
2923  adj0 = ip_get_adjacency (lm, adj_index0);
2924  adj1 = ip_get_adjacency (lm, adj_index1);
2925 
2926  next0 = adj0->lookup_next_index;
2927  next1 = adj1->lookup_next_index;
2928 
2929  flow_hash_config0 =
2930  vec_elt_at_index (im->fibs, fib_index0)->flow_hash_config;
2931 
2932  flow_hash_config1 =
2933  vec_elt_at_index (im->fibs, fib_index1)->flow_hash_config;
2934 
2935  vnet_buffer (p0)->ip.flow_hash = ip4_compute_flow_hash
2936  (ip0, flow_hash_config0);
2937 
2938  vnet_buffer (p1)->ip.flow_hash = ip4_compute_flow_hash
2939  (ip1, flow_hash_config1);
2940 
2941  ASSERT (adj0->n_adj > 0);
2942  ASSERT (adj1->n_adj > 0);
2943  ASSERT (is_pow2 (adj0->n_adj));
2944  ASSERT (is_pow2 (adj1->n_adj));
2945  adj_index0 += (vnet_buffer (p0)->ip.flow_hash & (adj0->n_adj - 1));
2946  adj_index1 += (vnet_buffer (p1)->ip.flow_hash & (adj1->n_adj - 1));
2947 
2948  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = adj_index0;
2949  vnet_buffer (p1)->ip.adj_index[VLIB_TX] = adj_index1;
2950 
2951  if (1) /* $$$$$$ HACK FIXME */
2953  (cm, cpu_index, adj_index0, 1,
2954  vlib_buffer_length_in_chain (vm, p0));
2955  if (1) /* $$$$$$ HACK FIXME */
2957  (cm, cpu_index, adj_index1, 1,
2958  vlib_buffer_length_in_chain (vm, p1));
2959 
2960  from += 2;
2961  to_next += 2;
2962  n_left_to_next -= 2;
2963  n_left_from -= 2;
2964 
2965  wrong_next = (next0 != next) + 2*(next1 != next);
2966  if (PREDICT_FALSE (wrong_next != 0))
2967  {
2968  switch (wrong_next)
2969  {
2970  case 1:
2971  /* A B A */
2972  to_next[-2] = pi1;
2973  to_next -= 1;
2974  n_left_to_next += 1;
2975  vlib_set_next_frame_buffer (vm, node, next0, pi0);
2976  break;
2977 
2978  case 2:
2979  /* A A B */
2980  to_next -= 1;
2981  n_left_to_next += 1;
2982  vlib_set_next_frame_buffer (vm, node, next1, pi1);
2983  break;
2984 
2985  case 3:
2986  /* A B C */
2987  to_next -= 2;
2988  n_left_to_next += 2;
2989  vlib_set_next_frame_buffer (vm, node, next0, pi0);
2990  vlib_set_next_frame_buffer (vm, node, next1, pi1);
2991  if (next0 == next1)
2992  {
2993  /* A B B */
2994  vlib_put_next_frame (vm, node, next, n_left_to_next);
2995  next = next1;
2996  vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
2997  }
2998  }
2999  }
3000  }
3001 
3002  while (n_left_from > 0 && n_left_to_next > 0)
3003  {
3004  vlib_buffer_t * p0;
3005  ip4_header_t * ip0;
3006  u32 pi0, adj_index0;
3007  ip_lookup_next_t next0;
3008  ip_adjacency_t * adj0;
3009  u32 fib_index0;
3010  u32 flow_hash_config0;
3011 
3012  pi0 = from[0];
3013  to_next[0] = pi0;
3014 
3015  p0 = vlib_get_buffer (vm, pi0);
3016 
3017  ip0 = vlib_buffer_get_current (p0);
3018 
3019  fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
3020  vnet_buffer (p0)->sw_if_index[VLIB_RX]);
3021  fib_index0 = (vnet_buffer(p0)->sw_if_index[VLIB_TX] == (u32)~0) ?
3022  fib_index0 : vnet_buffer(p0)->sw_if_index[VLIB_TX];
3023 
3024  adj_index0 = ip4_fib_lookup_buffer (im, fib_index0,
3025  &ip0->dst_address, p0);
3026 
3027  adj0 = ip_get_adjacency (lm, adj_index0);
3028 
3029  next0 = adj0->lookup_next_index;
3030 
3031  flow_hash_config0 =
3032  vec_elt_at_index (im->fibs, fib_index0)->flow_hash_config;
3033 
3034  vnet_buffer (p0)->ip.flow_hash =
3035  ip4_compute_flow_hash (ip0, flow_hash_config0);
3036 
3037  ASSERT (adj0->n_adj > 0);
3038  ASSERT (is_pow2 (adj0->n_adj));
3039  adj_index0 += (vnet_buffer (p0)->ip.flow_hash & (adj0->n_adj - 1));
3040 
3041  vnet_buffer (p0)->ip.adj_index[VLIB_TX] = adj_index0;
3042 
3043  if (1) /* $$$$$$ HACK FIXME */
3045  (cm, cpu_index, adj_index0, 1,
3046  vlib_buffer_length_in_chain (vm, p0));
3047 
3048  from += 1;
3049  to_next += 1;
3050  n_left_to_next -= 1;
3051  n_left_from -= 1;
3052 
3053  if (PREDICT_FALSE (next0 != next))
3054  {
3055  n_left_to_next += 1;
3056  vlib_put_next_frame (vm, node, next, n_left_to_next);
3057  next = next0;
3058  vlib_get_next_frame (vm, node, next,
3059  to_next, n_left_to_next);
3060  to_next[0] = pi0;
3061  to_next += 1;
3062  n_left_to_next -= 1;
3063  }
3064  }
3065 
3066  vlib_put_next_frame (vm, node, next, n_left_to_next);
3067  }
3068 
3069  if (node->flags & VLIB_NODE_FLAG_TRACE)
3070  ip4_forward_next_trace(vm, node, frame, VLIB_TX);
3071 
3072  return frame->n_vectors;
3073 }
3074 
3076  .function = ip4_lookup_multicast,
3077  .name = "ip4-lookup-multicast",
3078  .vector_size = sizeof (u32),
3079 
3080  .format_trace = format_ip4_lookup_trace,
3081 
3082  .n_next_nodes = IP_LOOKUP_N_NEXT,
3083  .next_nodes = IP4_LOOKUP_NEXT_NODES,
3084 };
3085 
3087  .function = ip4_drop,
3088  .name = "ip4-multicast",
3089  .vector_size = sizeof (u32),
3090 
3091  .format_trace = format_ip4_forward_next_trace,
3092 
3093  .n_next_nodes = 1,
3094  .next_nodes = {
3095  [0] = "error-drop",
3096  },
3097 };
3098 
3100 {
3101  ip4_main_t * im = &ip4_main;
3102  ip4_fib_mtrie_t * mtrie0;
3103  ip4_fib_mtrie_leaf_t leaf0;
3104  u32 adj_index0;
3105 
3106  mtrie0 = &vec_elt_at_index (im->fibs, fib_index0)->mtrie;
3107 
3108  leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
3109  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 0);
3110  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 1);
3111  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 2);
3112  leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 3);
3113 
3114  /* Handle default route. */
3115  leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
3116 
3117  adj_index0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
3118 
3119  return adj_index0 == ip4_fib_lookup_with_table (im, fib_index0,
3120  a,
3121  /* no_default_route */ 0);
3122 }
3123 
3124 static clib_error_t *
3126  unformat_input_t * input,
3127  vlib_cli_command_t * cmd)
3128 {
3129  u32 table_id = 0;
3130  f64 count = 1;
3131  u32 n;
3132  int i;
3133  ip4_address_t ip4_base_address;
3134  u64 errors = 0;
3135 
3136  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
3137  if (unformat (input, "table %d", &table_id))
3138  ;
3139  else if (unformat (input, "count %f", &count))
3140  ;
3141 
3142  else if (unformat (input, "%U",
3143  unformat_ip4_address, &ip4_base_address))
3144  ;
3145  else
3146  return clib_error_return (0, "unknown input `%U'",
3147  format_unformat_error, input);
3148  }
3149 
3150  n = count;
3151 
3152  for (i = 0; i < n; i++)
3153  {
3154  if (!ip4_lookup_validate (&ip4_base_address, table_id))
3155  errors++;
3156 
3157  ip4_base_address.as_u32 =
3158  clib_host_to_net_u32 (1 +
3159  clib_net_to_host_u32 (ip4_base_address.as_u32));
3160  }
3161 
3162  if (errors)
3163  vlib_cli_output (vm, "%llu errors out of %d lookups\n", errors, n);
3164  else
3165  vlib_cli_output (vm, "No errors in %d lookups\n", n);
3166 
3167  return 0;
3168 }
3169 
3170 VLIB_CLI_COMMAND (lookup_test_command, static) = {
3171  .path = "test lookup",
3172  .short_help = "test lookup",
3173  .function = test_lookup_command_fn,
3174 };
3175 
3176 int vnet_set_ip4_flow_hash (u32 table_id, u32 flow_hash_config)
3177 {
3178  ip4_main_t * im4 = &ip4_main;
3179  ip4_fib_t * fib;
3180  uword * p = hash_get (im4->fib_index_by_table_id, table_id);
3181 
3182  if (p == 0)
3183  return VNET_API_ERROR_NO_SUCH_FIB;
3184 
3185  fib = vec_elt_at_index (im4->fibs, p[0]);
3186 
3187  fib->flow_hash_config = flow_hash_config;
3188  return 0;
3189 }
3190 
3191 static clib_error_t *
3193  unformat_input_t * input,
3194  vlib_cli_command_t * cmd)
3195 {
3196  int matched = 0;
3197  u32 table_id = 0;
3198  u32 flow_hash_config = 0;
3199  int rv;
3200 
3201  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
3202  if (unformat (input, "table %d", &table_id))
3203  matched = 1;
3204 #define _(a,v) \
3205  else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;}
3207 #undef _
3208  else break;
3209  }
3210 
3211  if (matched == 0)
3212  return clib_error_return (0, "unknown input `%U'",
3213  format_unformat_error, input);
3214 
3215  rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3216  switch (rv)
3217  {
3218  case 0:
3219  break;
3220 
3221  case VNET_API_ERROR_NO_SUCH_FIB:
3222  return clib_error_return (0, "no such FIB table %d", table_id);
3223 
3224  default:
3225  clib_warning ("BUG: illegal flow hash config 0x%x", flow_hash_config);
3226  break;
3227  }
3228 
3229  return 0;
3230 }
3231 
3232 VLIB_CLI_COMMAND (set_ip_flow_hash_command, static) = {
3233  .path = "set ip flow-hash",
3234  .short_help =
3235  "set ip table flow-hash table <fib-id> src dst sport dport proto reverse",
3236  .function = set_ip_flow_hash_command_fn,
3237 };
3238 
3240  u32 table_index)
3241 {
3242  vnet_main_t * vnm = vnet_get_main();
3244  ip4_main_t * ipm = &ip4_main;
3245  ip_lookup_main_t * lm = &ipm->lookup_main;
3247 
3248  if (pool_is_free_index (im->sw_interfaces, sw_if_index))
3249  return VNET_API_ERROR_NO_MATCHING_INTERFACE;
3250 
3251  if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
3252  return VNET_API_ERROR_NO_SUCH_ENTRY;
3253 
3255  lm->classify_table_index_by_sw_if_index [sw_if_index] = table_index;
3256 
3257  return 0;
3258 }
3259 
3260 static clib_error_t *
3262  unformat_input_t * input,
3263  vlib_cli_command_t * cmd)
3264 {
3265  u32 table_index = ~0;
3266  int table_index_set = 0;
3267  u32 sw_if_index = ~0;
3268  int rv;
3269 
3270  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) {
3271  if (unformat (input, "table-index %d", &table_index))
3272  table_index_set = 1;
3273  else if (unformat (input, "intfc %U", unformat_vnet_sw_interface,
3274  vnet_get_main(), &sw_if_index))
3275  ;
3276  else
3277  break;
3278  }
3279 
3280  if (table_index_set == 0)
3281  return clib_error_return (0, "classify table-index must be specified");
3282 
3283  if (sw_if_index == ~0)
3284  return clib_error_return (0, "interface / subif must be specified");
3285 
3286  rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3287 
3288  switch (rv)
3289  {
3290  case 0:
3291  break;
3292 
3293  case VNET_API_ERROR_NO_MATCHING_INTERFACE:
3294  return clib_error_return (0, "No such interface");
3295 
3296  case VNET_API_ERROR_NO_SUCH_ENTRY:
3297  return clib_error_return (0, "No such classifier table");
3298  }
3299  return 0;
3300 }
3301 
3302 VLIB_CLI_COMMAND (set_ip_classify_command, static) = {
3303  .path = "set ip classify",
3304  .short_help =
3305  "set ip classify intfc <int> table-index <index>",
3306  .function = set_ip_classify_command_fn,
3307 };
3308 
vlib_node_registration_t ip4_miss_node
(constructor) VLIB_REGISTER_NODE (ip4_miss_node)
Definition: ip4_forward.c:1670
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:394
static void ip4_fib_set_adj_index(ip4_main_t *im, ip4_fib_t *fib, u32 flags, u32 dst_address_u32, u32 dst_address_length, u32 adj_index)
Definition: ip4_forward.c:148
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Definition: main.c:459
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
Definition: lookup.h:534
#define vnet_rewrite_one_header(rw0, p0, most_likely_size)
Definition: rewrite.h:245
ip_lookup_next_t
Definition: lookup.h:49
#define vec_zero(var)
Zero all vector elements.
Definition: vec.h:840
always_inline 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:233
always_inline void * clib_random_buffer_get_data(clib_random_buffer_t *b, uword n_bytes)
Definition: random_buffer.h:75
vmrglw vmrglh hi
static uword ip4_rewrite_local(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:2770
always_inline uword round_pow2(uword x, uword pow2)
Definition: clib.h:255
always_inline ip4_fib_mtrie_leaf_t ip4_fib_mtrie_lookup_step(ip4_fib_mtrie_t *m, ip4_fib_mtrie_leaf_t current_leaf, ip4_address_t *dst_address, u32 dst_address_byte_index)
Definition: ip4_mtrie.h:145
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:1239
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:256
#define hash_set(h, key, value)
Definition: hash.h:237
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
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
#define CLIB_UNUSED(x)
Definition: clib.h:79
vlib_node_registration_t ip4_drop_node
(constructor) VLIB_REGISTER_NODE (ip4_drop_node)
Definition: ip4_forward.c:1644
u32 * config_index_by_sw_if_index
Definition: lookup.h:345
uword unformat(unformat_input_t *i, char *fmt,...)
Definition: unformat.c:942
int vnet_set_ip4_flow_hash(u32 table_id, u32 flow_hash_config)
Definition: ip4_forward.c:3176
void vnet_config_init(vlib_main_t *vm, vnet_config_main_t *cm, char *start_node_names[], int n_start_node_names, char *feature_node_names[], int n_feature_node_names)
Definition: config.c:161
static uword ip4_drop(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1627
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Definition: ip4.h:150
a
Definition: bitmap.h:393
always_inline pg_node_t * pg_get_node(uword node_index)
Definition: pg.h:335
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
Definition: buffer.c:1133
ip4_address_t src_address
Definition: ip4_packet.h:138
static void(BVT(clib_bihash)*h, BVT(clib_bihash_value)*v)
uword * interface_route_adj_index_by_sw_if_index
Definition: ip4.h:147
ip_interface_address_t * if_address_pool
Definition: lookup.h:388
vnet_interface_main_t interface_main
Definition: vnet.h:62
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
Definition: ip4_forward.c:1360
ip_lookup_next_t lookup_next_index
Definition: lookup.h:163
u32 table_id
Definition: ip4.h:58
unformat_function_t unformat_pg_ip4_header
Definition: format.h:83
always_inline u32 ip4_fib_mtrie_leaf_get_adj_index(ip4_fib_mtrie_leaf_t n)
Definition: ip4_mtrie.h:66
void ip4_add_del_route(ip4_main_t *im, ip4_add_del_route_args_t *a)
Definition: ip4_forward.c:196
#define UNFORMAT_END_OF_INPUT
Definition: format.h:142
u32 miss_adj_index
Definition: lookup.h:380
ip4_fib_t * find_ip4_fib_by_table_index_or_id(ip4_main_t *im, u32 table_index_or_id, u32 flags)
Get or create an IPv4 fib.
Definition: ip4_forward.c:98
always_inline hash_t * hash_header(void *v)
Definition: hash.h:107
u32 vnet_config_del_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:284
vlib_node_registration_t ip4_indirect_node
(constructor) VLIB_REGISTER_NODE (ip4_indirect_node)
Definition: ip4_forward.c:1381
ip_config_main_t rx_config_mains[VNET_N_CAST]
Definition: lookup.h:401
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
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:3125
u32 share_count
Definition: lookup.h:192
ip_adjacency_t * ip_add_adjacency(ip_lookup_main_t *lm, ip_adjacency_t *copy_adj, u32 n_adj, u32 *adj_index_return)
Definition: lookup.c:139
always_inline 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, int is_indirect)
Definition: ip4_forward.c:644
ip4_rewrite_next_t
Definition: ip4_forward.c:2445
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
ip_lookup_main_t lookup_main
Definition: ip4.h:129
uword ip_csum_t
Definition: ip_packet.h:86
void ip4_foreach_matching_route(ip4_main_t *im, u32 table_index_or_table_id, u32 flags, ip4_address_t *address, u32 address_length, ip4_address_t **results, u8 **result_lengths)
Definition: ip4_forward.c:488
u32 * fib_index_by_sw_if_index
Definition: ip4.h:137
always_inline int ip4_is_fragment(ip4_header_t *i)
Definition: ip4_packet.h:170
unformat_function_t unformat_vnet_sw_interface
#define clib_error_report(e)
Definition: error.h:126
static u8 * format_ip4_forward_next_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1465
#define vec_bytes(v)
Number of data bytes in vector.
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
Definition: node.h:378
format_function_t format_ip4_address
Definition: format.h:71
u32 neighbor_probe_adj_index
Definition: lookup.h:313
format_function_t format_vnet_sw_if_index_name
always_inline void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:184
always_inline vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
u32 * node_index_by_feature_index
Definition: config.h:96
void * ip4_get_route(ip4_main_t *im, u32 table_index_or_table_id, u32 flags, u8 *address, u32 address_length)
Definition: ip4_forward.c:469
always_inline u32 ip4_fib_lookup_buffer(ip4_main_t *im, u32 fib_index, ip4_address_t *dst, vlib_buffer_t *b)
Definition: ip4.h:183
#define IP4_FIB_MTRIE_LEAF_EMPTY
Definition: ip4_mtrie.h:54
u32 index
Definition: ip4.h:61
uword value[0]
Definition: hash.h:151
always_inline void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
Definition: lookup.h:513
always_inline uword unformat_check_input(unformat_input_t *i)
Definition: format.h:168
u32 fwd_classify_table_index
Definition: ip4.h:67
vlib_rx_or_tx_t
Definition: defs.h:44
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
static void ip4_fib_init_adj_index_by_dst_address(ip_lookup_main_t *lm, ip4_fib_t *fib, u32 address_length)
Definition: ip4_forward.c:123
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:2136
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:77
vnet_l3_packet_type_t
Definition: l3_types.h:44
void ip4_adjacency_set_interface_route(vnet_main_t *vnm, ip_adjacency_t *adj, u32 sw_if_index, u32 if_address_index)
Definition: ip4_forward.c:1005
format_function_t format_ip_adjacency_packet_data
Definition: format.h:52
void ip4_add_del_route_next_hop(ip4_main_t *im, u32 flags, ip4_address_t *dst_address, u32 dst_address_length, ip4_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_weight, u32 adj_index, u32 explicit_fib_index)
Definition: ip4_forward.c:274
#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:181
ethernet_arp_ip4_over_ethernet_address_t ip4_over_ethernet[2]
Definition: arp_packet.h:127
static ip4_fib_t * create_fib_with_table_id(ip4_main_t *im, u32 table_id)
Definition: ip4_forward.c:83
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:109
#define always_inline
Definition: clib.h:84
static u32 ip4_tcp_udp_validate_checksum(vlib_main_t *vm, vlib_buffer_t *p0)
Definition: ip4_forward.c:1730
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:1052
ip4_address_t dst_address
Definition: ip4_packet.h:138
#define IP_BUFFER_L4_CHECKSUM_CORRECT
Definition: buffer.h:50
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:107
always_inline void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u32 packet_increment, u32 byte_increment)
Definition: counter.h:210
u32 * adjacency_remap_table
Definition: lookup.h:372
ip4_error_t
Definition: ip4_error.h:79
u32 vnet_arp_glean_add(u32 fib_index, void *next_hop_arg)
Definition: arp.c:1569
int i32
Definition: types.h:81
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:380
u32 ip4_fib_mtrie_leaf_t
Definition: ip4_mtrie.h:52
uword * old_hash_values
Definition: ip4.h:52
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
void ip4_fib_mtrie_add_del_route(ip4_fib_t *fib, ip4_address_t dst_address, u32 dst_address_length, u32 adj_index, u32 is_del)
Definition: ip4_mtrie.c:363
u32 flow_hash_config
Definition: ip4.h:64
u32 ip_multipath_adjacency_add_del_next_hop(ip_lookup_main_t *lm, u32 is_del, u32 old_mp_adj_index, u32 next_hop_adj_index, u32 next_hop_weight, u32 *new_mp_adj_index)
Definition: lookup.c:495
always_inline uword pool_elts(void *v)
Definition: pool.h:97
always_inline 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:112
#define IP4_LOOKUP_NEXT_NODES
Definition: lookup.h:93
#define clib_warning(format, args...)
Definition: error.h:59
vlib_node_registration_t ip4_arp_node
(constructor) VLIB_REGISTER_NODE (ip4_arp_node)
Definition: ip4_forward.c:2341
static uword ip4_indirect(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1372
unsigned long u64
Definition: types.h:89
always_inline int ip4_header_bytes(ip4_header_t *i)
Definition: ip4_packet.h:186
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:953
u32 rev_classify_table_index
Definition: ip4.h:68
uword * new_hash_values
Definition: ip4.h:52
always_inline void * vlib_frame_vector_args(vlib_frame_t *f)
Definition: node_funcs.h:202
void ip_del_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.c:285
#define foreach_notrace_ip4_arp_error
Definition: ip4_forward.c:2357
#define VLIB_BUFFER_NEXT_PRESENT
Definition: buffer.h:93
vlib_node_registration_t ip4_rewrite_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_node)
Definition: ip4_forward.c:2778
unformat_function_t unformat_ip4_address
Definition: format.h:68
always_inline void vlib_buffer_copy_trace_flag(vlib_main_t *vm, vlib_buffer_t *b, u32 bi_target)
Definition: trace_funcs.h:136
always_inline u16 ip_csum_fold(ip_csum_t c)
Definition: ip_packet.h:138
vnet_api_error_t api_errno
Definition: vnet.h:76
#define hash_get(h, key)
Definition: hash.h:231
#define pool_elt_at_index(p, i)
Definition: pool.h:346
uword * fib_index_by_table_id
Definition: ip4.h:141
vlib_main_t * vlib_main
Definition: vnet.h:78
vlib_node_registration_t ip4_input_node
(constructor) VLIB_REGISTER_NODE (ip4_input_node)
Definition: ip4_input.c:353
u16 current_length
Nbytes between current data and the end of this buffer.
Definition: buffer.h:81
u32 * classify_table_index_by_sw_if_index
Definition: lookup.h:398
vlib_node_registration_t ip4_local_node
(constructor) VLIB_REGISTER_NODE (ip4_local_node)
Definition: ip4_forward.c:2109
clib_error_t * arp_notrace_init(vlib_main_t *vm)
Definition: ip4_forward.c:2363
static uword ip4_rewrite_transit(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:2761
void ip4_register_protocol(u32 protocol, u32 node_index)
Definition: ip4_forward.c:2125
uword os_get_cpu_number(void)
Definition: unix-misc.c:206
static uword ip4_punt(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1633
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:1517
ip4_main_t ip4_main
Definition: ip4_forward.c:1394
#define PREDICT_FALSE(x)
Definition: clib.h:97
u8 local_next_by_ip_protocol[256]
Definition: lookup.h:416
vnet_hw_interface_class_t srp_hw_interface_class
always_inline void hash_set_flags(void *v, uword flags)
Definition: hash.h:142
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:191
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Definition: buffer_node.h:43
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Definition: buffer_node.h:83
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Definition: node_funcs.h:265
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:538
always_inline void ip4_src_address_for_packet(ip4_main_t *im, vlib_buffer_t *p, ip4_address_t *src, u32 sw_if_index)
Definition: ip4.h:223
vlib_error_t error
Error code for buffers to be enqueued to error handler.
Definition: buffer.h:129
vlib_node_registration_t ip4_punt_node
(constructor) VLIB_REGISTER_NODE (ip4_punt_node)
Definition: ip4_forward.c:1657
always_inline u16 ip4_header_checksum(ip4_header_t *i)
Definition: ip4_packet.h:194
ip_adjacency_t * add_adj
Definition: ip4.h:293
vnet_hw_interface_class_t ethernet_hw_interface_class
static u8 * format_ip4_lookup_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1477
clib_error_t * ip4_probe_neighbor(vlib_main_t *vm, ip4_address_t *dst, u32 sw_if_index)
Definition: ip4_forward.c:2383
static uword ip4_miss(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1639
static u8 * format_ip4_rewrite_trace(u8 *s, va_list *args)
Definition: ip4_forward.c:1495
u16 n_vectors
Definition: node.h:307
void ip4_mtrie_init(ip4_fib_mtrie_t *m)
Definition: ip4_mtrie.c:353
#define CLIB_PREFETCH(addr, size, type)
Definition: cache.h:82
void ip4_maybe_remap_adjacencies(ip4_main_t *im, u32 table_index_or_table_id, u32 flags)
Definition: ip4_forward.c:522
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:298
void vnet_rewrite_for_sw_interface(vnet_main_t *vnm, vnet_l3_packet_type_t packet_type, u32 sw_if_index, u32 node_index, void *dst_address, vnet_rewrite_header_t *rw, u32 max_rewrite_bytes)
Definition: rewrite.c:187
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:100
static clib_error_t * add_del_interface_table(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ip4_forward.c:2809
Definition: ip4.h:47
#define clib_memcpy(a, b, c)
Definition: string.h:63
always_inline vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
int ip4_lookup_validate(ip4_address_t *a, u32 fib_index0)
Definition: ip4_forward.c:3099
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:3192
unformat_function_t * unformat_edit
Definition: pg.h:290
vlib_node_registration_t ip4_multicast_node
(constructor) VLIB_REGISTER_NODE (ip4_multicast_node)
Definition: ip4_forward.c:3086
u8 packet_data[64-1 *sizeof(u32)]
Definition: ip4_forward.c:1462
void ip4_delete_matching_routes(ip4_main_t *im, u32 table_index_or_table_id, u32 flags, ip4_address_t *address, u32 address_length)
Definition: ip4_forward.c:602
void ip_lookup_init(ip_lookup_main_t *lm, u32 is_ip6)
Definition: lookup.c:841
#define pool_is_free_index(P, I)
Definition: pool.h:197
#define ARRAY_LEN(x)
Definition: clib.h:59
always_inline uword vnet_sw_interface_is_admin_up(vnet_main_t *vnm, u32 sw_if_index)
#define IP4_ROUTE_FLAG_DEL
Definition: ip4.h:265
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:3261
always_inline uword hash_elts(void *v)
Definition: hash.h:111
vlib_combined_counter_main_t adjacency_counters
Definition: lookup.h:353
static clib_error_t * ip4_add_del_interface_address_internal(vlib_main_t *vm, u32 sw_if_index, ip4_address_t *new_address, u32 new_length, u32 redistribute, u32 insert_routes, u32 is_del)
Definition: ip4_forward.c:1159
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:150
static clib_error_t * ip4_sw_interface_add_del(vnet_main_t *vnm, u32 sw_if_index, u32 is_add)
Definition: ip4_forward.c:1288
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:50
#define foreach_flow_hash_bit
Definition: lookup.h:138
u32 * if_address_pool_index_by_sw_if_index
Definition: lookup.h:395
vlib_packet_template_t ip4_arp_request_packet_template
Definition: ip4.h:153
always_inline uword is_pow2(uword x)
Definition: clib.h:252
#define hash_create(elts, value_bytes)
Definition: hash.h:615
always_inline uword ip4_rewrite_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int rewrite_for_locally_received_packets)
Definition: ip4_forward.c:2451
u16 cached_next_index
Definition: node.h:422
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:373
u32 max_l3_packet_bytes[VLIB_N_RX_TX]
Definition: interface.h:313
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:1093
#define ASSERT(truth)
#define IP4_FIB_MTRIE_LEAF_ROOT
Definition: ip4_mtrie.h:55
format_function_t format_ip4_header
Definition: format.h:78
unsigned int u32
Definition: types.h:88
ip4_fib_t * fibs
Definition: ip4.h:132
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:87
ip4_address_t dst_address
Definition: ip4.h:284
#define vnet_buffer(b)
Definition: buffer.h:300
#define IP4_ROUTE_FLAG_ADD
Definition: ip4.h:264
#define LOG2_IP_BUFFER_L4_CHECKSUM_CORRECT
Definition: buffer.h:48
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
#define hash_v3_finalize32(a, b, c)
Definition: hash.h:497
u32 next_buffer
Next buffer for this linked-list of buffers.
Definition: buffer.h:112
u32 fib_result_n_words
Definition: lookup.h:405
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:225
u32 vnet_config_add_feature(vlib_main_t *vm, vnet_config_main_t *cm, u32 config_string_heap_index, u32 feature_index, void *feature_config, u32 n_feature_config_bytes)
Definition: config.c:233
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:21
#define IP_FLOW_HASH_DEFAULT
Definition: lookup.h:136
u32 n_adjacency_remaps
Definition: lookup.h:373
always_inline void ip4_addr_fib_init(ip4_address_fib_t *addr_fib, ip4_address_t *address, u32 fib_index)
Definition: ip4_packet.h:64
clib_error_t * ip4_lookup_init(vlib_main_t *vm)
Definition: ip4_forward.c:1397
always_inline uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:919
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:91
vlib_node_registration_t ip4_rewrite_local_node
(constructor) VLIB_REGISTER_NODE (ip4_rewrite_local_node)
Definition: ip4_forward.c:2792
always_inline ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:423
always_inline ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
Definition: ip_packet.h:89
u32 ip4_fib_lookup_with_table(ip4_main_t *im, u32 fib_index, ip4_address_t *dst, u32 disable_default_route)
Definition: ip4_forward.c:50
static uword ip4_local(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:1756
always_inline uword format_get_indent(u8 *s)
Definition: format.h:72
u64 uword
Definition: types.h:112
#define vec_elt(v, i)
Get vector value at index i.
#define ip46_address_reset(ip46)
Definition: ip6_packet.h:72
#define IP_BUFFER_L4_CHECKSUM_COMPUTED
Definition: buffer.h:49
u16 ip4_tcp_udp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip4_header_t *ip0)
Definition: ip4_forward.c:1685
Definition: defs.h:46
unsigned short u16
Definition: types.h:57
struct ip_adjacency_t::@112::@114 arp
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
double f64
Definition: types.h:140
always_inline void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:197
unsigned char u8
Definition: types.h:56
#define hash_foreach_pair(p, v, body)
Definition: hash.h:311
always_inline vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 heap_handle
Definition: lookup.h:150
always_inline u32 ip4_compute_flow_hash(ip4_header_t *ip, u32 flow_hash_config)
Definition: ip4.h:397
#define IP4_ROUTE_FLAG_FIB_INDEX
Definition: ip4.h:267
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:449
struct ip_adjacency_t::@112::@115 classify
ip4_fib_mtrie_t mtrie
Definition: ip4.h:55
always_inline 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:292
always_inline uword hash_value_bytes(hash_t *h)
Definition: hash.h:274
u32 table_index_or_table_id
Definition: ip4.h:281
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:735
always_inline void * ip4_next_header(ip4_header_t *i)
Definition: ip4_packet.h:190
static clib_error_t * ip4_sw_interface_admin_up_down(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Definition: ip4_forward.c:1251
always_inline 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 IP4_ROUTE_FLAG_KEEP_OLD_ADJACENCY
Definition: ip4.h:268
struct ip_adjacency_t::@112::@116 indirect
#define clib_mem_unaligned(pointer, type)
Definition: types.h:153
#define IP4_ROUTE_FLAG_NOT_LAST_IN_GROUP
Definition: ip4.h:271
static void ip4_del_interface_routes(ip4_main_t *im, u32 fib_index, ip4_address_t *address, u32 address_length)
Definition: ip4_forward.c:1115
static uword ip4_lookup_multicast(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:2858
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Definition: buffer.h:162
ip_multipath_adjacency_t * multipath_adjacencies
Definition: lookup.h:359
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:140
#define IP4_ROUTE_FLAG_TABLE_ID
Definition: ip4.h:266
always_inline vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Definition: node_funcs.h:61
always_inline void ip_call_add_del_adjacency_callbacks(ip_lookup_main_t *lm, u32 adj_index, u32 is_del)
Definition: lookup.h:449
int vnet_set_ip4_classify_intfc(vlib_main_t *vm, u32 sw_if_index, u32 table_index)
Definition: ip4_forward.c:3239
u8 data[0]
Packet data.
Definition: buffer.h:150
ip4_add_del_route_callback_t * add_del_route_callbacks
Definition: ip4.h:144
u32 if_address_index
Definition: lookup.h:155
#define vec_foreach(var, vec)
Vector iterator.
ip_local_next_t
Definition: lookup.h:327
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:1604
i16 explicit_fib_index
Definition: lookup.h:168
always_inline f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:182
uword * adj_index_by_dst_address[33]
Definition: ip4.h:49
#define clib_error_return(e, args...)
Definition: error.h:112
VNET_SW_INTERFACE_ADD_DEL_FUNCTION(ip4_sw_interface_add_del)
u8 ip_version_and_header_length
Definition: ip4_packet.h:108
struct _unformat_input_t unformat_input_t
always_inline uword pow2_mask(uword x)
Definition: clib.h:242
static uword ip4_lookup(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: ip4_forward.c:995
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:184
u32 flags
Definition: vhost-user.h:73
#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:443
#define vnet_rewrite_two_headers(rw0, rw1, p0, p1, most_likely_size)
Definition: rewrite.h:250
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(ip4_sw_interface_admin_up_down)
void ip4_mtrie_maybe_remap_adjacencies(ip_lookup_main_t *lm, ip4_fib_mtrie_t *m)
Definition: ip4_mtrie.c:463
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:84
#define HASH_FLAG_NO_AUTO_SHRINK
Definition: hash.h:64
#define BITS(x)
Definition: clib.h:58
always_inline vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:69
vlib_node_registration_t ip4_lookup_multicast_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_multicast_node)
Definition: ip4_forward.c:3075
ip4_add_del_route_function_t * function
Definition: ip4.h:85
clib_random_buffer_t random_buffer
Definition: main.h:153
Definition: pg.h:288
vnet_config_main_t config_main
Definition: lookup.h:343
uword key
Definition: hash.h:148
static char * ip4_arp_error_strings[]
Definition: ip4_forward.c:2333
Definition: defs.h:45
u32 fib_result_n_bytes
Definition: lookup.h:405
#define IP4_ROUTE_FLAG_NO_REDISTRIBUTE
Definition: ip4.h:269
format_function_t format_ip_adjacency
Definition: format.h:51
u32 fib_masks[33]
Definition: ip4.h:134
ip4_fib_mtrie_leaf_t default_leaf
Definition: ip4_mtrie.h:123