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