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