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