Register TCP with IP only if session is enabled
[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   vnet_main_t *vnm = vnet_get_main ();
1236   uword indent = format_get_indent (s);
1237
1238   s = format (s, "tx_sw_if_index %d dpo-idx %d : %U flow hash: 0x%08x",
1239               t->fib_index, t->dpo_index, format_ip_adjacency,
1240               t->dpo_index, FORMAT_IP_ADJACENCY_NONE, t->flow_hash);
1241   s = format (s, "\n%U%U",
1242               format_white_space, indent,
1243               format_ip_adjacency_packet_data,
1244               vnm, t->dpo_index, t->packet_data, sizeof (t->packet_data));
1245   return s;
1246 }
1247
1248 /* Common trace function for all ip4-forward next nodes. */
1249 void
1250 ip4_forward_next_trace (vlib_main_t * vm,
1251                         vlib_node_runtime_t * node,
1252                         vlib_frame_t * frame, vlib_rx_or_tx_t which_adj_index)
1253 {
1254   u32 *from, n_left;
1255   ip4_main_t *im = &ip4_main;
1256
1257   n_left = frame->n_vectors;
1258   from = vlib_frame_vector_args (frame);
1259
1260   while (n_left >= 4)
1261     {
1262       u32 bi0, bi1;
1263       vlib_buffer_t *b0, *b1;
1264       ip4_forward_next_trace_t *t0, *t1;
1265
1266       /* Prefetch next iteration. */
1267       vlib_prefetch_buffer_with_index (vm, from[2], LOAD);
1268       vlib_prefetch_buffer_with_index (vm, from[3], LOAD);
1269
1270       bi0 = from[0];
1271       bi1 = from[1];
1272
1273       b0 = vlib_get_buffer (vm, bi0);
1274       b1 = vlib_get_buffer (vm, bi1);
1275
1276       if (b0->flags & VLIB_BUFFER_IS_TRACED)
1277         {
1278           t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1279           t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
1280           t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
1281           t0->fib_index =
1282             (vnet_buffer (b0)->sw_if_index[VLIB_TX] !=
1283              (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] :
1284             vec_elt (im->fib_index_by_sw_if_index,
1285                      vnet_buffer (b0)->sw_if_index[VLIB_RX]);
1286
1287           clib_memcpy (t0->packet_data,
1288                        vlib_buffer_get_current (b0),
1289                        sizeof (t0->packet_data));
1290         }
1291       if (b1->flags & VLIB_BUFFER_IS_TRACED)
1292         {
1293           t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
1294           t1->dpo_index = vnet_buffer (b1)->ip.adj_index[which_adj_index];
1295           t1->flow_hash = vnet_buffer (b1)->ip.flow_hash;
1296           t1->fib_index =
1297             (vnet_buffer (b1)->sw_if_index[VLIB_TX] !=
1298              (u32) ~ 0) ? vnet_buffer (b1)->sw_if_index[VLIB_TX] :
1299             vec_elt (im->fib_index_by_sw_if_index,
1300                      vnet_buffer (b1)->sw_if_index[VLIB_RX]);
1301           clib_memcpy (t1->packet_data, vlib_buffer_get_current (b1),
1302                        sizeof (t1->packet_data));
1303         }
1304       from += 2;
1305       n_left -= 2;
1306     }
1307
1308   while (n_left >= 1)
1309     {
1310       u32 bi0;
1311       vlib_buffer_t *b0;
1312       ip4_forward_next_trace_t *t0;
1313
1314       bi0 = from[0];
1315
1316       b0 = vlib_get_buffer (vm, bi0);
1317
1318       if (b0->flags & VLIB_BUFFER_IS_TRACED)
1319         {
1320           t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
1321           t0->dpo_index = vnet_buffer (b0)->ip.adj_index[which_adj_index];
1322           t0->flow_hash = vnet_buffer (b0)->ip.flow_hash;
1323           t0->fib_index =
1324             (vnet_buffer (b0)->sw_if_index[VLIB_TX] !=
1325              (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] :
1326             vec_elt (im->fib_index_by_sw_if_index,
1327                      vnet_buffer (b0)->sw_if_index[VLIB_RX]);
1328           clib_memcpy (t0->packet_data, vlib_buffer_get_current (b0),
1329                        sizeof (t0->packet_data));
1330         }
1331       from += 1;
1332       n_left -= 1;
1333     }
1334 }
1335
1336 static uword
1337 ip4_drop_or_punt (vlib_main_t * vm,
1338                   vlib_node_runtime_t * node,
1339                   vlib_frame_t * frame, ip4_error_t error_code)
1340 {
1341   u32 *buffers = vlib_frame_vector_args (frame);
1342   uword n_packets = frame->n_vectors;
1343
1344   vlib_error_drop_buffers (vm, node, buffers,
1345                            /* stride */ 1,
1346                            n_packets,
1347                            /* next */ 0,
1348                            ip4_input_node.index, error_code);
1349
1350   if (node->flags & VLIB_NODE_FLAG_TRACE)
1351     ip4_forward_next_trace (vm, node, frame, VLIB_TX);
1352
1353   return n_packets;
1354 }
1355
1356 static uword
1357 ip4_drop (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1358 {
1359   return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_ADJACENCY_DROP);
1360 }
1361
1362 static uword
1363 ip4_punt (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1364 {
1365   return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_ADJACENCY_PUNT);
1366 }
1367
1368 /* *INDENT-OFF* */
1369 VLIB_REGISTER_NODE (ip4_drop_node, static) =
1370 {
1371   .function = ip4_drop,.
1372   name = "ip4-drop",
1373   .vector_size = sizeof (u32),
1374   .format_trace = format_ip4_forward_next_trace,
1375   .n_next_nodes = 1,
1376   .next_nodes = {
1377     [0] = "error-drop",
1378   },
1379 };
1380
1381 VLIB_NODE_FUNCTION_MULTIARCH (ip4_drop_node, ip4_drop);
1382
1383 VLIB_REGISTER_NODE (ip4_punt_node, static) =
1384 {
1385   .function = ip4_punt,
1386   .name = "ip4-punt",
1387   .vector_size = sizeof (u32),
1388   .format_trace = format_ip4_forward_next_trace,
1389   .n_next_nodes = 1,
1390   .next_nodes = {
1391     [0] = "error-punt",
1392   },
1393 };
1394
1395 VLIB_NODE_FUNCTION_MULTIARCH (ip4_punt_node, ip4_punt);
1396 /* *INDENT-ON */
1397
1398 /* Compute TCP/UDP/ICMP4 checksum in software. */
1399 u16
1400 ip4_tcp_udp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
1401                               ip4_header_t * ip0)
1402 {
1403   ip_csum_t sum0;
1404   u32 ip_header_length, payload_length_host_byte_order;
1405   u32 n_this_buffer, n_bytes_left;
1406   u16 sum16;
1407   void *data_this_buffer;
1408
1409   /* Initialize checksum with ip header. */
1410   ip_header_length = ip4_header_bytes (ip0);
1411   payload_length_host_byte_order =
1412     clib_net_to_host_u16 (ip0->length) - ip_header_length;
1413   sum0 =
1414     clib_host_to_net_u32 (payload_length_host_byte_order +
1415                           (ip0->protocol << 16));
1416
1417   if (BITS (uword) == 32)
1418     {
1419       sum0 =
1420         ip_csum_with_carry (sum0,
1421                             clib_mem_unaligned (&ip0->src_address, u32));
1422       sum0 =
1423         ip_csum_with_carry (sum0,
1424                             clib_mem_unaligned (&ip0->dst_address, u32));
1425     }
1426   else
1427     sum0 =
1428       ip_csum_with_carry (sum0, clib_mem_unaligned (&ip0->src_address, u64));
1429
1430   n_bytes_left = n_this_buffer = payload_length_host_byte_order;
1431   data_this_buffer = (void *) ip0 + ip_header_length;
1432   if (n_this_buffer + ip_header_length > p0->current_length)
1433     n_this_buffer =
1434       p0->current_length >
1435       ip_header_length ? p0->current_length - ip_header_length : 0;
1436   while (1)
1437     {
1438       sum0 = ip_incremental_checksum (sum0, data_this_buffer, n_this_buffer);
1439       n_bytes_left -= n_this_buffer;
1440       if (n_bytes_left == 0)
1441         break;
1442
1443       ASSERT (p0->flags & VLIB_BUFFER_NEXT_PRESENT);
1444       p0 = vlib_get_buffer (vm, p0->next_buffer);
1445       data_this_buffer = vlib_buffer_get_current (p0);
1446       n_this_buffer = p0->current_length;
1447     }
1448
1449   sum16 = ~ip_csum_fold (sum0);
1450
1451   return sum16;
1452 }
1453
1454 u32
1455 ip4_tcp_udp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0)
1456 {
1457   ip4_header_t *ip0 = vlib_buffer_get_current (p0);
1458   udp_header_t *udp0;
1459   u16 sum16;
1460
1461   ASSERT (ip0->protocol == IP_PROTOCOL_TCP
1462           || ip0->protocol == IP_PROTOCOL_UDP);
1463
1464   udp0 = (void *) (ip0 + 1);
1465   if (ip0->protocol == IP_PROTOCOL_UDP && udp0->checksum == 0)
1466     {
1467       p0->flags |= (IP_BUFFER_L4_CHECKSUM_COMPUTED
1468                     | IP_BUFFER_L4_CHECKSUM_CORRECT);
1469       return p0->flags;
1470     }
1471
1472   sum16 = ip4_tcp_udp_compute_checksum (vm, p0, ip0);
1473
1474   p0->flags |= (IP_BUFFER_L4_CHECKSUM_COMPUTED
1475                 | ((sum16 == 0) << LOG2_IP_BUFFER_L4_CHECKSUM_CORRECT));
1476
1477   return p0->flags;
1478 }
1479
1480 /* *INDENT-OFF* */
1481 VNET_FEATURE_ARC_INIT (ip4_local) =
1482 {
1483   .arc_name  = "ip4-local",
1484   .start_nodes = VNET_FEATURES ("ip4-local"),
1485 };
1486 /* *INDENT-ON* */
1487
1488 static inline uword
1489 ip4_local_inline (vlib_main_t * vm,
1490                   vlib_node_runtime_t * node,
1491                   vlib_frame_t * frame, int head_of_feature_arc)
1492 {
1493   ip4_main_t *im = &ip4_main;
1494   ip_lookup_main_t *lm = &im->lookup_main;
1495   ip_local_next_t next_index;
1496   u32 *from, *to_next, n_left_from, n_left_to_next;
1497   vlib_node_runtime_t *error_node =
1498     vlib_node_get_runtime (vm, ip4_input_node.index);
1499   u8 arc_index = vnet_feat_arc_ip4_local.feature_arc_index;
1500
1501   from = vlib_frame_vector_args (frame);
1502   n_left_from = frame->n_vectors;
1503   next_index = node->cached_next_index;
1504
1505   if (node->flags & VLIB_NODE_FLAG_TRACE)
1506     ip4_forward_next_trace (vm, node, frame, VLIB_TX);
1507
1508   while (n_left_from > 0)
1509     {
1510       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1511
1512       while (n_left_from >= 4 && n_left_to_next >= 2)
1513         {
1514           vlib_buffer_t *p0, *p1;
1515           ip4_header_t *ip0, *ip1;
1516           udp_header_t *udp0, *udp1;
1517           ip4_fib_mtrie_t *mtrie0, *mtrie1;
1518           ip4_fib_mtrie_leaf_t leaf0, leaf1;
1519           const dpo_id_t *dpo0, *dpo1;
1520           const load_balance_t *lb0, *lb1;
1521           u32 pi0, ip_len0, udp_len0, flags0, next0, fib_index0, lbi0;
1522           u32 pi1, ip_len1, udp_len1, flags1, next1, fib_index1, lbi1;
1523           i32 len_diff0, len_diff1;
1524           u8 error0, is_udp0, is_tcp_udp0, good_tcp_udp0, proto0;
1525           u8 error1, is_udp1, is_tcp_udp1, good_tcp_udp1, proto1;
1526           u32 sw_if_index0, sw_if_index1;
1527
1528           pi0 = to_next[0] = from[0];
1529           pi1 = to_next[1] = from[1];
1530           from += 2;
1531           n_left_from -= 2;
1532           to_next += 2;
1533           n_left_to_next -= 2;
1534
1535           next0 = next1 = IP_LOCAL_NEXT_DROP;
1536
1537           p0 = vlib_get_buffer (vm, pi0);
1538           p1 = vlib_get_buffer (vm, pi1);
1539
1540           ip0 = vlib_buffer_get_current (p0);
1541           ip1 = vlib_buffer_get_current (p1);
1542
1543           vnet_buffer (p0)->ip.start_of_ip_header = p0->current_data;
1544           vnet_buffer (p1)->ip.start_of_ip_header = p1->current_data;
1545
1546           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1547           sw_if_index1 = vnet_buffer (p1)->sw_if_index[VLIB_RX];
1548
1549           fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
1550           fib_index1 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index1);
1551
1552           fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
1553           fib_index0 =
1554             (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
1555              (u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
1556
1557           fib_index1 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index1);
1558           fib_index1 =
1559             (vnet_buffer (p1)->sw_if_index[VLIB_TX] ==
1560              (u32) ~ 0) ? fib_index1 : vnet_buffer (p1)->sw_if_index[VLIB_TX];
1561
1562           mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
1563           mtrie1 = &ip4_fib_get (fib_index1)->mtrie;
1564
1565           leaf0 = leaf1 = IP4_FIB_MTRIE_LEAF_ROOT;
1566
1567           leaf0 =
1568             ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 0);
1569           leaf1 =
1570             ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 0);
1571
1572           /* Treat IP frag packets as "experimental" protocol for now
1573              until support of IP frag reassembly is implemented */
1574           proto0 = ip4_is_fragment (ip0) ? 0xfe : ip0->protocol;
1575           proto1 = ip4_is_fragment (ip1) ? 0xfe : ip1->protocol;
1576
1577           if (head_of_feature_arc == 0)
1578             {
1579               error0 = error1 = IP4_ERROR_UNKNOWN_PROTOCOL;
1580               goto skip_checks;
1581             }
1582
1583           is_udp0 = proto0 == IP_PROTOCOL_UDP;
1584           is_udp1 = proto1 == IP_PROTOCOL_UDP;
1585           is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
1586           is_tcp_udp1 = is_udp1 || proto1 == IP_PROTOCOL_TCP;
1587
1588           flags0 = p0->flags;
1589           flags1 = p1->flags;
1590
1591           good_tcp_udp0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1592           good_tcp_udp1 = (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1593
1594           udp0 = ip4_next_header (ip0);
1595           udp1 = ip4_next_header (ip1);
1596
1597           /* Don't verify UDP checksum for packets with explicit zero checksum. */
1598           good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1599           good_tcp_udp1 |= is_udp1 && udp1->checksum == 0;
1600
1601           leaf0 =
1602             ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 1);
1603           leaf1 =
1604             ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 1);
1605
1606           /* Verify UDP length. */
1607           ip_len0 = clib_net_to_host_u16 (ip0->length);
1608           ip_len1 = clib_net_to_host_u16 (ip1->length);
1609           udp_len0 = clib_net_to_host_u16 (udp0->length);
1610           udp_len1 = clib_net_to_host_u16 (udp1->length);
1611
1612           len_diff0 = ip_len0 - udp_len0;
1613           len_diff1 = ip_len1 - udp_len1;
1614
1615           len_diff0 = is_udp0 ? len_diff0 : 0;
1616           len_diff1 = is_udp1 ? len_diff1 : 0;
1617
1618           if (PREDICT_FALSE (!(is_tcp_udp0 & is_tcp_udp1
1619                                & good_tcp_udp0 & good_tcp_udp1)))
1620             {
1621               if (is_tcp_udp0)
1622                 {
1623                   if (is_tcp_udp0
1624                       && !(flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
1625                     flags0 = ip4_tcp_udp_validate_checksum (vm, p0);
1626                   good_tcp_udp0 =
1627                     (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1628                   good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1629                 }
1630               if (is_tcp_udp1)
1631                 {
1632                   if (is_tcp_udp1
1633                       && !(flags1 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
1634                     flags1 = ip4_tcp_udp_validate_checksum (vm, p1);
1635                   good_tcp_udp1 =
1636                     (flags1 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1637                   good_tcp_udp1 |= is_udp1 && udp1->checksum == 0;
1638                 }
1639             }
1640
1641           good_tcp_udp0 &= len_diff0 >= 0;
1642           good_tcp_udp1 &= len_diff1 >= 0;
1643
1644           leaf0 =
1645             ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 2);
1646           leaf1 =
1647             ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 2);
1648
1649           error0 = error1 = IP4_ERROR_UNKNOWN_PROTOCOL;
1650
1651           error0 = len_diff0 < 0 ? IP4_ERROR_UDP_LENGTH : error0;
1652           error1 = len_diff1 < 0 ? IP4_ERROR_UDP_LENGTH : error1;
1653
1654           ASSERT (IP4_ERROR_TCP_CHECKSUM + 1 == IP4_ERROR_UDP_CHECKSUM);
1655           error0 = (is_tcp_udp0 && !good_tcp_udp0
1656                     ? IP4_ERROR_TCP_CHECKSUM + is_udp0 : error0);
1657           error1 = (is_tcp_udp1 && !good_tcp_udp1
1658                     ? IP4_ERROR_TCP_CHECKSUM + is_udp1 : error1);
1659
1660           leaf0 =
1661             ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 3);
1662           leaf1 =
1663             ip4_fib_mtrie_lookup_step (mtrie1, leaf1, &ip1->src_address, 3);
1664           leaf0 =
1665             (leaf0 ==
1666              IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
1667           leaf1 =
1668             (leaf1 ==
1669              IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie1->default_leaf : leaf1);
1670
1671           vnet_buffer (p0)->ip.adj_index[VLIB_RX] = lbi0 =
1672             ip4_fib_mtrie_leaf_get_adj_index (leaf0);
1673           vnet_buffer (p0)->ip.adj_index[VLIB_TX] = lbi0;
1674
1675           vnet_buffer (p1)->ip.adj_index[VLIB_RX] = lbi1 =
1676             ip4_fib_mtrie_leaf_get_adj_index (leaf1);
1677           vnet_buffer (p1)->ip.adj_index[VLIB_TX] = lbi1;
1678
1679           lb0 = load_balance_get (lbi0);
1680           lb1 = load_balance_get (lbi1);
1681           dpo0 = load_balance_get_bucket_i (lb0, 0);
1682           dpo1 = load_balance_get_bucket_i (lb1, 0);
1683
1684           /*
1685            * Must have a route to source otherwise we drop the packet.
1686            * ip4 broadcasts are accepted, e.g. to make dhcp client work
1687            *
1688            * The checks are:
1689            *  - the source is a recieve => it's from us => bogus, do this
1690            *    first since it sets a different error code.
1691            *  - uRPF check for any route to source - accept if passes.
1692            *  - allow packets destined to the broadcast address from unknown sources
1693            */
1694           error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1695                      dpo0->dpoi_type == DPO_RECEIVE) ?
1696                     IP4_ERROR_SPOOFED_LOCAL_PACKETS : error0);
1697           error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1698                      !fib_urpf_check_size (lb0->lb_urpf) &&
1699                      ip0->dst_address.as_u32 != 0xFFFFFFFF)
1700                     ? IP4_ERROR_SRC_LOOKUP_MISS : error0);
1701           error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1702                      dpo1->dpoi_type == DPO_RECEIVE) ?
1703                     IP4_ERROR_SPOOFED_LOCAL_PACKETS : error1);
1704           error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1705                      !fib_urpf_check_size (lb1->lb_urpf) &&
1706                      ip1->dst_address.as_u32 != 0xFFFFFFFF)
1707                     ? IP4_ERROR_SRC_LOOKUP_MISS : error1);
1708
1709         skip_checks:
1710
1711           next0 = lm->local_next_by_ip_protocol[proto0];
1712           next1 = lm->local_next_by_ip_protocol[proto1];
1713
1714           next0 =
1715             error0 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0;
1716           next1 =
1717             error1 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next1;
1718
1719           p0->error = error0 ? error_node->errors[error0] : 0;
1720           p1->error = error1 ? error_node->errors[error1] : 0;
1721
1722           if (head_of_feature_arc)
1723             {
1724               if (PREDICT_TRUE (error0 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
1725                 vnet_feature_arc_start (arc_index, sw_if_index0, &next0, p0);
1726               if (PREDICT_TRUE (error1 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
1727                 vnet_feature_arc_start (arc_index, sw_if_index1, &next1, p1);
1728             }
1729
1730           vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
1731                                            n_left_to_next, pi0, pi1,
1732                                            next0, next1);
1733         }
1734
1735       while (n_left_from > 0 && n_left_to_next > 0)
1736         {
1737           vlib_buffer_t *p0;
1738           ip4_header_t *ip0;
1739           udp_header_t *udp0;
1740           ip4_fib_mtrie_t *mtrie0;
1741           ip4_fib_mtrie_leaf_t leaf0;
1742           u32 pi0, next0, ip_len0, udp_len0, flags0, fib_index0, lbi0;
1743           i32 len_diff0;
1744           u8 error0, is_udp0, is_tcp_udp0, good_tcp_udp0, proto0;
1745           load_balance_t *lb0;
1746           const dpo_id_t *dpo0;
1747           u32 sw_if_index0;
1748
1749           pi0 = to_next[0] = from[0];
1750           from += 1;
1751           n_left_from -= 1;
1752           to_next += 1;
1753           n_left_to_next -= 1;
1754
1755           next0 = IP_LOCAL_NEXT_DROP;
1756
1757           p0 = vlib_get_buffer (vm, pi0);
1758
1759           ip0 = vlib_buffer_get_current (p0);
1760
1761           vnet_buffer (p0)->ip.start_of_ip_header = p0->current_data;
1762
1763           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1764
1765           fib_index0 = vec_elt (im->fib_index_by_sw_if_index, sw_if_index0);
1766
1767           fib_index0 =
1768             (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
1769              (u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
1770
1771           mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
1772
1773           leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
1774
1775           leaf0 =
1776             ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 0);
1777
1778           /* Treat IP frag packets as "experimental" protocol for now
1779              until support of IP frag reassembly is implemented */
1780           proto0 = ip4_is_fragment (ip0) ? 0xfe : ip0->protocol;
1781
1782           if (head_of_feature_arc == 0)
1783             {
1784               error0 = IP4_ERROR_UNKNOWN_PROTOCOL;
1785               goto skip_check;
1786             }
1787
1788           is_udp0 = proto0 == IP_PROTOCOL_UDP;
1789           is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
1790
1791           flags0 = p0->flags;
1792
1793           good_tcp_udp0 = (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1794
1795           udp0 = ip4_next_header (ip0);
1796
1797           /* Don't verify UDP checksum for packets with explicit zero checksum. */
1798           good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1799
1800           leaf0 =
1801             ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 1);
1802
1803           /* Verify UDP length. */
1804           ip_len0 = clib_net_to_host_u16 (ip0->length);
1805           udp_len0 = clib_net_to_host_u16 (udp0->length);
1806
1807           len_diff0 = ip_len0 - udp_len0;
1808
1809           len_diff0 = is_udp0 ? len_diff0 : 0;
1810
1811           if (PREDICT_FALSE (!(is_tcp_udp0 & good_tcp_udp0)))
1812             {
1813               if (is_tcp_udp0)
1814                 {
1815                   if (is_tcp_udp0
1816                       && !(flags0 & IP_BUFFER_L4_CHECKSUM_COMPUTED))
1817                     flags0 = ip4_tcp_udp_validate_checksum (vm, p0);
1818                   good_tcp_udp0 =
1819                     (flags0 & IP_BUFFER_L4_CHECKSUM_CORRECT) != 0;
1820                   good_tcp_udp0 |= is_udp0 && udp0->checksum == 0;
1821                 }
1822             }
1823
1824           good_tcp_udp0 &= len_diff0 >= 0;
1825
1826           leaf0 =
1827             ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 2);
1828
1829           error0 = IP4_ERROR_UNKNOWN_PROTOCOL;
1830
1831           error0 = len_diff0 < 0 ? IP4_ERROR_UDP_LENGTH : error0;
1832
1833           ASSERT (IP4_ERROR_TCP_CHECKSUM + 1 == IP4_ERROR_UDP_CHECKSUM);
1834           error0 = (is_tcp_udp0 && !good_tcp_udp0
1835                     ? IP4_ERROR_TCP_CHECKSUM + is_udp0 : error0);
1836
1837           leaf0 =
1838             ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address, 3);
1839           leaf0 =
1840             (leaf0 ==
1841              IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
1842
1843           lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
1844           vnet_buffer (p0)->ip.adj_index[VLIB_TX] = lbi0;
1845
1846           lb0 = load_balance_get (lbi0);
1847           dpo0 = load_balance_get_bucket_i (lb0, 0);
1848
1849           vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
1850             vnet_buffer (p0)->ip.adj_index[VLIB_RX] = lbi0;
1851
1852           error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1853                      dpo0->dpoi_type == DPO_RECEIVE) ?
1854                     IP4_ERROR_SPOOFED_LOCAL_PACKETS : error0);
1855           error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
1856                      !fib_urpf_check_size (lb0->lb_urpf) &&
1857                      ip0->dst_address.as_u32 != 0xFFFFFFFF)
1858                     ? IP4_ERROR_SRC_LOOKUP_MISS : error0);
1859
1860         skip_check:
1861
1862           next0 = lm->local_next_by_ip_protocol[proto0];
1863
1864           next0 =
1865             error0 != IP4_ERROR_UNKNOWN_PROTOCOL ? IP_LOCAL_NEXT_DROP : next0;
1866
1867           p0->error = error0 ? error_node->errors[error0] : 0;
1868
1869           if (head_of_feature_arc)
1870             {
1871               if (PREDICT_TRUE (error0 == (u8) IP4_ERROR_UNKNOWN_PROTOCOL))
1872                 vnet_feature_arc_start (arc_index, sw_if_index0, &next0, p0);
1873             }
1874
1875           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1876                                            n_left_to_next, pi0, next0);
1877
1878         }
1879
1880       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1881     }
1882
1883   return frame->n_vectors;
1884 }
1885
1886 static uword
1887 ip4_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1888 {
1889   return ip4_local_inline (vm, node, frame, 1 /* head of feature arc */ );
1890 }
1891
1892 /* *INDENT-OFF* */
1893 VLIB_REGISTER_NODE (ip4_local_node) =
1894 {
1895   .function = ip4_local,
1896   .name = "ip4-local",
1897   .vector_size = sizeof (u32),
1898   .format_trace = format_ip4_forward_next_trace,
1899   .n_next_nodes = IP_LOCAL_N_NEXT,
1900   .next_nodes =
1901   {
1902     [IP_LOCAL_NEXT_DROP] = "error-drop",
1903     [IP_LOCAL_NEXT_PUNT] = "error-punt",
1904     [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
1905     [IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",},
1906 };
1907 /* *INDENT-ON* */
1908
1909 VLIB_NODE_FUNCTION_MULTIARCH (ip4_local_node, ip4_local);
1910
1911 static uword
1912 ip4_local_end_of_arc (vlib_main_t * vm,
1913                       vlib_node_runtime_t * node, vlib_frame_t * frame)
1914 {
1915   return ip4_local_inline (vm, node, frame, 0 /* head of feature arc */ );
1916 }
1917
1918 /* *INDENT-OFF* */
1919 VLIB_REGISTER_NODE (ip4_local_end_of_arc_node,static) = {
1920   .function = ip4_local_end_of_arc,
1921   .name = "ip4-local-end-of-arc",
1922   .vector_size = sizeof (u32),
1923
1924   .format_trace = format_ip4_forward_next_trace,
1925   .sibling_of = "ip4-local",
1926 };
1927
1928 VLIB_NODE_FUNCTION_MULTIARCH (ip4_local_end_of_arc_node, ip4_local_end_of_arc)
1929
1930 VNET_FEATURE_INIT (ip4_local_end_of_arc, static) = {
1931   .arc_name = "ip4-local",
1932   .node_name = "ip4-local-end-of-arc",
1933   .runs_before = 0, /* not before any other features */
1934 };
1935 /* *INDENT-ON* */
1936
1937 void
1938 ip4_register_protocol (u32 protocol, u32 node_index)
1939 {
1940   vlib_main_t *vm = vlib_get_main ();
1941   ip4_main_t *im = &ip4_main;
1942   ip_lookup_main_t *lm = &im->lookup_main;
1943
1944   ASSERT (protocol < ARRAY_LEN (lm->local_next_by_ip_protocol));
1945   lm->local_next_by_ip_protocol[protocol] =
1946     vlib_node_add_next (vm, ip4_local_node.index, node_index);
1947 }
1948
1949 static clib_error_t *
1950 show_ip_local_command_fn (vlib_main_t * vm,
1951                           unformat_input_t * input, vlib_cli_command_t * cmd)
1952 {
1953   ip4_main_t *im = &ip4_main;
1954   ip_lookup_main_t *lm = &im->lookup_main;
1955   int i;
1956
1957   vlib_cli_output (vm, "Protocols handled by ip4_local");
1958   for (i = 0; i < ARRAY_LEN (lm->local_next_by_ip_protocol); i++)
1959     {
1960       if (lm->local_next_by_ip_protocol[i] != IP_LOCAL_NEXT_PUNT)
1961         vlib_cli_output (vm, "%d", i);
1962     }
1963   return 0;
1964 }
1965
1966
1967
1968 /*?
1969  * Display the set of protocols handled by the local IPv4 stack.
1970  *
1971  * @cliexpar
1972  * Example of how to display local protocol table:
1973  * @cliexstart{show ip local}
1974  * Protocols handled by ip4_local
1975  * 1
1976  * 17
1977  * 47
1978  * @cliexend
1979 ?*/
1980 /* *INDENT-OFF* */
1981 VLIB_CLI_COMMAND (show_ip_local, static) =
1982 {
1983   .path = "show ip local",
1984   .function = show_ip_local_command_fn,
1985   .short_help = "show ip local",
1986 };
1987 /* *INDENT-ON* */
1988
1989 always_inline uword
1990 ip4_arp_inline (vlib_main_t * vm,
1991                 vlib_node_runtime_t * node,
1992                 vlib_frame_t * frame, int is_glean)
1993 {
1994   vnet_main_t *vnm = vnet_get_main ();
1995   ip4_main_t *im = &ip4_main;
1996   ip_lookup_main_t *lm = &im->lookup_main;
1997   u32 *from, *to_next_drop;
1998   uword n_left_from, n_left_to_next_drop, next_index;
1999   static f64 time_last_seed_change = -1e100;
2000   static u32 hash_seeds[3];
2001   static uword hash_bitmap[256 / BITS (uword)];
2002   f64 time_now;
2003
2004   if (node->flags & VLIB_NODE_FLAG_TRACE)
2005     ip4_forward_next_trace (vm, node, frame, VLIB_TX);
2006
2007   time_now = vlib_time_now (vm);
2008   if (time_now - time_last_seed_change > 1e-3)
2009     {
2010       uword i;
2011       u32 *r = clib_random_buffer_get_data (&vm->random_buffer,
2012                                             sizeof (hash_seeds));
2013       for (i = 0; i < ARRAY_LEN (hash_seeds); i++)
2014         hash_seeds[i] = r[i];
2015
2016       /* Mark all hash keys as been no-seen before. */
2017       for (i = 0; i < ARRAY_LEN (hash_bitmap); i++)
2018         hash_bitmap[i] = 0;
2019
2020       time_last_seed_change = time_now;
2021     }
2022
2023   from = vlib_frame_vector_args (frame);
2024   n_left_from = frame->n_vectors;
2025   next_index = node->cached_next_index;
2026   if (next_index == IP4_ARP_NEXT_DROP)
2027     next_index = IP4_ARP_N_NEXT;        /* point to first interface */
2028
2029   while (n_left_from > 0)
2030     {
2031       vlib_get_next_frame (vm, node, IP4_ARP_NEXT_DROP,
2032                            to_next_drop, n_left_to_next_drop);
2033
2034       while (n_left_from > 0 && n_left_to_next_drop > 0)
2035         {
2036           u32 pi0, adj_index0, a0, b0, c0, m0, sw_if_index0, drop0;
2037           ip_adjacency_t *adj0;
2038           vlib_buffer_t *p0;
2039           ip4_header_t *ip0;
2040           uword bm0;
2041
2042           pi0 = from[0];
2043
2044           p0 = vlib_get_buffer (vm, pi0);
2045
2046           adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
2047           adj0 = ip_get_adjacency (lm, adj_index0);
2048           ip0 = vlib_buffer_get_current (p0);
2049
2050           a0 = hash_seeds[0];
2051           b0 = hash_seeds[1];
2052           c0 = hash_seeds[2];
2053
2054           sw_if_index0 = adj0->rewrite_header.sw_if_index;
2055           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2056
2057           if (is_glean)
2058             {
2059               /*
2060                * this is the Glean case, so we are ARPing for the
2061                * packet's destination
2062                */
2063               a0 ^= ip0->dst_address.data_u32;
2064             }
2065           else
2066             {
2067               a0 ^= adj0->sub_type.nbr.next_hop.ip4.data_u32;
2068             }
2069           b0 ^= sw_if_index0;
2070
2071           hash_v3_finalize32 (a0, b0, c0);
2072
2073           c0 &= BITS (hash_bitmap) - 1;
2074           c0 = c0 / BITS (uword);
2075           m0 = (uword) 1 << (c0 % BITS (uword));
2076
2077           bm0 = hash_bitmap[c0];
2078           drop0 = (bm0 & m0) != 0;
2079
2080           /* Mark it as seen. */
2081           hash_bitmap[c0] = bm0 | m0;
2082
2083           from += 1;
2084           n_left_from -= 1;
2085           to_next_drop[0] = pi0;
2086           to_next_drop += 1;
2087           n_left_to_next_drop -= 1;
2088
2089           p0->error =
2090             node->errors[drop0 ? IP4_ARP_ERROR_DROP :
2091                          IP4_ARP_ERROR_REQUEST_SENT];
2092
2093           /*
2094            * the adj has been updated to a rewrite but the node the DPO that got
2095            * us here hasn't - yet. no big deal. we'll drop while we wait.
2096            */
2097           if (IP_LOOKUP_NEXT_REWRITE == adj0->lookup_next_index)
2098             continue;
2099
2100           if (drop0)
2101             continue;
2102
2103           /*
2104            * Can happen if the control-plane is programming tables
2105            * with traffic flowing; at least that's today's lame excuse.
2106            */
2107           if ((is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_GLEAN)
2108               || (!is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP))
2109             {
2110               p0->error = node->errors[IP4_ARP_ERROR_NON_ARP_ADJ];
2111             }
2112           else
2113             /* Send ARP request. */
2114             {
2115               u32 bi0 = 0;
2116               vlib_buffer_t *b0;
2117               ethernet_arp_header_t *h0;
2118               vnet_hw_interface_t *hw_if0;
2119
2120               h0 =
2121                 vlib_packet_template_get_packet (vm,
2122                                                  &im->ip4_arp_request_packet_template,
2123                                                  &bi0);
2124
2125               /* Add rewrite/encap string for ARP packet. */
2126               vnet_rewrite_one_header (adj0[0], h0,
2127                                        sizeof (ethernet_header_t));
2128
2129               hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
2130
2131               /* Src ethernet address in ARP header. */
2132               clib_memcpy (h0->ip4_over_ethernet[0].ethernet,
2133                            hw_if0->hw_address,
2134                            sizeof (h0->ip4_over_ethernet[0].ethernet));
2135
2136               if (is_glean)
2137                 {
2138                   /* The interface's source address is stashed in the Glean Adj */
2139                   h0->ip4_over_ethernet[0].ip4 =
2140                     adj0->sub_type.glean.receive_addr.ip4;
2141
2142                   /* Copy in destination address we are requesting. This is the
2143                    * glean case, so it's the packet's destination.*/
2144                   h0->ip4_over_ethernet[1].ip4.data_u32 =
2145                     ip0->dst_address.data_u32;
2146                 }
2147               else
2148                 {
2149                   /* Src IP address in ARP header. */
2150                   if (ip4_src_address_for_packet (lm, sw_if_index0,
2151                                                   &h0->
2152                                                   ip4_over_ethernet[0].ip4))
2153                     {
2154                       /* No source address available */
2155                       p0->error =
2156                         node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
2157                       vlib_buffer_free (vm, &bi0, 1);
2158                       continue;
2159                     }
2160
2161                   /* Copy in destination address we are requesting from the
2162                      incomplete adj */
2163                   h0->ip4_over_ethernet[1].ip4.data_u32 =
2164                     adj0->sub_type.nbr.next_hop.ip4.as_u32;
2165                 }
2166
2167               vlib_buffer_copy_trace_flag (vm, p0, bi0);
2168               b0 = vlib_get_buffer (vm, bi0);
2169               vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
2170
2171               vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
2172
2173               vlib_set_next_frame_buffer (vm, node,
2174                                           adj0->rewrite_header.next_index,
2175                                           bi0);
2176             }
2177         }
2178
2179       vlib_put_next_frame (vm, node, IP4_ARP_NEXT_DROP, n_left_to_next_drop);
2180     }
2181
2182   return frame->n_vectors;
2183 }
2184
2185 static uword
2186 ip4_arp (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
2187 {
2188   return (ip4_arp_inline (vm, node, frame, 0));
2189 }
2190
2191 static uword
2192 ip4_glean (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
2193 {
2194   return (ip4_arp_inline (vm, node, frame, 1));
2195 }
2196
2197 static char *ip4_arp_error_strings[] = {
2198   [IP4_ARP_ERROR_DROP] = "address overflow drops",
2199   [IP4_ARP_ERROR_REQUEST_SENT] = "ARP requests sent",
2200   [IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies",
2201   [IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed",
2202   [IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed",
2203   [IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request",
2204 };
2205
2206 VLIB_REGISTER_NODE (ip4_arp_node) =
2207 {
2208   .function = ip4_arp,.name = "ip4-arp",.vector_size =
2209     sizeof (u32),.format_trace = format_ip4_forward_next_trace,.n_errors =
2210     ARRAY_LEN (ip4_arp_error_strings),.error_strings =
2211     ip4_arp_error_strings,.n_next_nodes = IP4_ARP_N_NEXT,.next_nodes =
2212   {
2213   [IP4_ARP_NEXT_DROP] = "error-drop",}
2214 ,};
2215
2216 VLIB_REGISTER_NODE (ip4_glean_node) =
2217 {
2218   .function = ip4_glean,.name = "ip4-glean",.vector_size =
2219     sizeof (u32),.format_trace = format_ip4_forward_next_trace,.n_errors =
2220     ARRAY_LEN (ip4_arp_error_strings),.error_strings =
2221     ip4_arp_error_strings,.n_next_nodes = IP4_ARP_N_NEXT,.next_nodes =
2222   {
2223   [IP4_ARP_NEXT_DROP] = "error-drop",}
2224 ,};
2225
2226 #define foreach_notrace_ip4_arp_error           \
2227 _(DROP)                                         \
2228 _(REQUEST_SENT)                                 \
2229 _(REPLICATE_DROP)                               \
2230 _(REPLICATE_FAIL)
2231
2232 clib_error_t *
2233 arp_notrace_init (vlib_main_t * vm)
2234 {
2235   vlib_node_runtime_t *rt = vlib_node_get_runtime (vm, ip4_arp_node.index);
2236
2237   /* don't trace ARP request packets */
2238 #define _(a)                                    \
2239     vnet_pcap_drop_trace_filter_add_del         \
2240         (rt->errors[IP4_ARP_ERROR_##a],         \
2241          1 /* is_add */);
2242   foreach_notrace_ip4_arp_error;
2243 #undef _
2244   return 0;
2245 }
2246
2247 VLIB_INIT_FUNCTION (arp_notrace_init);
2248
2249
2250 /* Send an ARP request to see if given destination is reachable on given interface. */
2251 clib_error_t *
2252 ip4_probe_neighbor (vlib_main_t * vm, ip4_address_t * dst, u32 sw_if_index)
2253 {
2254   vnet_main_t *vnm = vnet_get_main ();
2255   ip4_main_t *im = &ip4_main;
2256   ethernet_arp_header_t *h;
2257   ip4_address_t *src;
2258   ip_interface_address_t *ia;
2259   ip_adjacency_t *adj;
2260   vnet_hw_interface_t *hi;
2261   vnet_sw_interface_t *si;
2262   vlib_buffer_t *b;
2263   u32 bi = 0;
2264
2265   si = vnet_get_sw_interface (vnm, sw_if_index);
2266
2267   if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
2268     {
2269       return clib_error_return (0, "%U: interface %U down",
2270                                 format_ip4_address, dst,
2271                                 format_vnet_sw_if_index_name, vnm,
2272                                 sw_if_index);
2273     }
2274
2275   src =
2276     ip4_interface_address_matching_destination (im, dst, sw_if_index, &ia);
2277   if (!src)
2278     {
2279       vnm->api_errno = VNET_API_ERROR_NO_MATCHING_INTERFACE;
2280       return clib_error_return
2281         (0,
2282          "no matching interface address for destination %U (interface %U)",
2283          format_ip4_address, dst, format_vnet_sw_if_index_name, vnm,
2284          sw_if_index);
2285     }
2286
2287   adj = ip_get_adjacency (&im->lookup_main, ia->neighbor_probe_adj_index);
2288
2289   h =
2290     vlib_packet_template_get_packet (vm,
2291                                      &im->ip4_arp_request_packet_template,
2292                                      &bi);
2293
2294   hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
2295
2296   clib_memcpy (h->ip4_over_ethernet[0].ethernet, hi->hw_address,
2297                sizeof (h->ip4_over_ethernet[0].ethernet));
2298
2299   h->ip4_over_ethernet[0].ip4 = src[0];
2300   h->ip4_over_ethernet[1].ip4 = dst[0];
2301
2302   b = vlib_get_buffer (vm, bi);
2303   vnet_buffer (b)->sw_if_index[VLIB_RX] =
2304     vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
2305
2306   /* Add encapsulation string for software interface (e.g. ethernet header). */
2307   vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
2308   vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
2309
2310   {
2311     vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index);
2312     u32 *to_next = vlib_frame_vector_args (f);
2313     to_next[0] = bi;
2314     f->n_vectors = 1;
2315     vlib_put_frame_to_node (vm, hi->output_node_index, f);
2316   }
2317
2318   return /* no error */ 0;
2319 }
2320
2321 typedef enum
2322 {
2323   IP4_REWRITE_NEXT_DROP,
2324   IP4_REWRITE_NEXT_ICMP_ERROR,
2325 } ip4_rewrite_next_t;
2326
2327 always_inline uword
2328 ip4_rewrite_inline (vlib_main_t * vm,
2329                     vlib_node_runtime_t * node,
2330                     vlib_frame_t * frame,
2331                     int do_counters, int is_midchain, int is_mcast)
2332 {
2333   ip_lookup_main_t *lm = &ip4_main.lookup_main;
2334   u32 *from = vlib_frame_vector_args (frame);
2335   u32 n_left_from, n_left_to_next, *to_next, next_index;
2336   vlib_node_runtime_t *error_node =
2337     vlib_node_get_runtime (vm, ip4_input_node.index);
2338
2339   n_left_from = frame->n_vectors;
2340   next_index = node->cached_next_index;
2341   u32 cpu_index = os_get_cpu_number ();
2342
2343   while (n_left_from > 0)
2344     {
2345       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2346
2347       while (n_left_from >= 4 && n_left_to_next >= 2)
2348         {
2349           ip_adjacency_t *adj0, *adj1;
2350           vlib_buffer_t *p0, *p1;
2351           ip4_header_t *ip0, *ip1;
2352           u32 pi0, rw_len0, next0, error0, checksum0, adj_index0;
2353           u32 pi1, rw_len1, next1, error1, checksum1, adj_index1;
2354           u32 tx_sw_if_index0, tx_sw_if_index1;
2355
2356           /* Prefetch next iteration. */
2357           {
2358             vlib_buffer_t *p2, *p3;
2359
2360             p2 = vlib_get_buffer (vm, from[2]);
2361             p3 = vlib_get_buffer (vm, from[3]);
2362
2363             vlib_prefetch_buffer_header (p2, STORE);
2364             vlib_prefetch_buffer_header (p3, STORE);
2365
2366             CLIB_PREFETCH (p2->data, sizeof (ip0[0]), STORE);
2367             CLIB_PREFETCH (p3->data, sizeof (ip0[0]), STORE);
2368           }
2369
2370           pi0 = to_next[0] = from[0];
2371           pi1 = to_next[1] = from[1];
2372
2373           from += 2;
2374           n_left_from -= 2;
2375           to_next += 2;
2376           n_left_to_next -= 2;
2377
2378           p0 = vlib_get_buffer (vm, pi0);
2379           p1 = vlib_get_buffer (vm, pi1);
2380
2381           adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
2382           adj_index1 = vnet_buffer (p1)->ip.adj_index[VLIB_TX];
2383
2384           /* We should never rewrite a pkt using the MISS adjacency */
2385           ASSERT (adj_index0 && adj_index1);
2386
2387           ip0 = vlib_buffer_get_current (p0);
2388           ip1 = vlib_buffer_get_current (p1);
2389
2390           error0 = error1 = IP4_ERROR_NONE;
2391           next0 = next1 = IP4_REWRITE_NEXT_DROP;
2392
2393           /* Decrement TTL & update checksum.
2394              Works either endian, so no need for byte swap. */
2395           if (PREDICT_TRUE (!(p0->flags & VNET_BUFFER_LOCALLY_ORIGINATED)))
2396             {
2397               i32 ttl0 = ip0->ttl;
2398
2399               /* Input node should have reject packets with ttl 0. */
2400               ASSERT (ip0->ttl > 0);
2401
2402               checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
2403               checksum0 += checksum0 >= 0xffff;
2404
2405               ip0->checksum = checksum0;
2406               ttl0 -= 1;
2407               ip0->ttl = ttl0;
2408
2409               /*
2410                * If the ttl drops below 1 when forwarding, generate
2411                * an ICMP response.
2412                */
2413               if (PREDICT_FALSE (ttl0 <= 0))
2414                 {
2415                   error0 = IP4_ERROR_TIME_EXPIRED;
2416                   vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
2417                   icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
2418                                                ICMP4_time_exceeded_ttl_exceeded_in_transit,
2419                                                0);
2420                   next0 = IP4_REWRITE_NEXT_ICMP_ERROR;
2421                 }
2422
2423               /* Verify checksum. */
2424               ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2425             }
2426           else
2427             {
2428               p0->flags &= ~VNET_BUFFER_LOCALLY_ORIGINATED;
2429             }
2430           if (PREDICT_TRUE (!(p1->flags & VNET_BUFFER_LOCALLY_ORIGINATED)))
2431             {
2432               i32 ttl1 = ip1->ttl;
2433
2434               /* Input node should have reject packets with ttl 0. */
2435               ASSERT (ip1->ttl > 0);
2436
2437               checksum1 = ip1->checksum + clib_host_to_net_u16 (0x0100);
2438               checksum1 += checksum1 >= 0xffff;
2439
2440               ip1->checksum = checksum1;
2441               ttl1 -= 1;
2442               ip1->ttl = ttl1;
2443
2444               /*
2445                * If the ttl drops below 1 when forwarding, generate
2446                * an ICMP response.
2447                */
2448               if (PREDICT_FALSE (ttl1 <= 0))
2449                 {
2450                   error1 = IP4_ERROR_TIME_EXPIRED;
2451                   vnet_buffer (p1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
2452                   icmp4_error_set_vnet_buffer (p1, ICMP4_time_exceeded,
2453                                                ICMP4_time_exceeded_ttl_exceeded_in_transit,
2454                                                0);
2455                   next1 = IP4_REWRITE_NEXT_ICMP_ERROR;
2456                 }
2457
2458               /* Verify checksum. */
2459               ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2460               ASSERT (ip1->checksum == ip4_header_checksum (ip1));
2461             }
2462           else
2463             {
2464               p1->flags &= ~VNET_BUFFER_LOCALLY_ORIGINATED;
2465             }
2466
2467           /* Rewrite packet header and updates lengths. */
2468           adj0 = ip_get_adjacency (lm, adj_index0);
2469           adj1 = ip_get_adjacency (lm, adj_index1);
2470
2471           /* Worth pipelining. No guarantee that adj0,1 are hot... */
2472           rw_len0 = adj0[0].rewrite_header.data_bytes;
2473           rw_len1 = adj1[0].rewrite_header.data_bytes;
2474           vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
2475           vnet_buffer (p1)->ip.save_rewrite_length = rw_len1;
2476
2477           /* Check MTU of outgoing interface. */
2478           error0 =
2479             (vlib_buffer_length_in_chain (vm, p0) >
2480              adj0[0].
2481              rewrite_header.max_l3_packet_bytes ? IP4_ERROR_MTU_EXCEEDED :
2482              error0);
2483           error1 =
2484             (vlib_buffer_length_in_chain (vm, p1) >
2485              adj1[0].
2486              rewrite_header.max_l3_packet_bytes ? IP4_ERROR_MTU_EXCEEDED :
2487              error1);
2488
2489           /*
2490            * pre-fetch the per-adjacency counters
2491            */
2492           if (do_counters)
2493             {
2494               vlib_prefetch_combined_counter (&adjacency_counters,
2495                                               cpu_index, adj_index0);
2496               vlib_prefetch_combined_counter (&adjacency_counters,
2497                                               cpu_index, adj_index1);
2498             }
2499
2500           /* Don't adjust the buffer for ttl issue; icmp-error node wants
2501            * to see the IP headerr */
2502           if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
2503             {
2504               next0 = adj0[0].rewrite_header.next_index;
2505               p0->current_data -= rw_len0;
2506               p0->current_length += rw_len0;
2507               tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
2508               vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
2509
2510               vnet_feature_arc_start (lm->output_feature_arc_index,
2511                                       tx_sw_if_index0, &next0, p0);
2512             }
2513           if (PREDICT_TRUE (error1 == IP4_ERROR_NONE))
2514             {
2515               next1 = adj1[0].rewrite_header.next_index;
2516               p1->current_data -= rw_len1;
2517               p1->current_length += rw_len1;
2518
2519               tx_sw_if_index1 = adj1[0].rewrite_header.sw_if_index;
2520               vnet_buffer (p1)->sw_if_index[VLIB_TX] = tx_sw_if_index1;
2521
2522               vnet_feature_arc_start (lm->output_feature_arc_index,
2523                                       tx_sw_if_index1, &next1, p1);
2524             }
2525
2526           /* Guess we are only writing on simple Ethernet header. */
2527           vnet_rewrite_two_headers (adj0[0], adj1[0],
2528                                     ip0, ip1, sizeof (ethernet_header_t));
2529
2530           /*
2531            * Bump the per-adjacency counters
2532            */
2533           if (do_counters)
2534             {
2535               vlib_increment_combined_counter
2536                 (&adjacency_counters,
2537                  cpu_index,
2538                  adj_index0, 1,
2539                  vlib_buffer_length_in_chain (vm, p0) + rw_len0);
2540
2541               vlib_increment_combined_counter
2542                 (&adjacency_counters,
2543                  cpu_index,
2544                  adj_index1, 1,
2545                  vlib_buffer_length_in_chain (vm, p1) + rw_len1);
2546             }
2547
2548           if (is_midchain)
2549             {
2550               adj0->sub_type.midchain.fixup_func (vm, adj0, p0);
2551               adj1->sub_type.midchain.fixup_func (vm, adj1, p1);
2552             }
2553           if (is_mcast)
2554             {
2555               /*
2556                * copy bytes from the IP address into the MAC rewrite
2557                */
2558               vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 1);
2559               vnet_fixup_one_header (adj1[0], &ip1->dst_address, ip1, 1);
2560             }
2561
2562           vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
2563                                            to_next, n_left_to_next,
2564                                            pi0, pi1, next0, next1);
2565         }
2566
2567       while (n_left_from > 0 && n_left_to_next > 0)
2568         {
2569           ip_adjacency_t *adj0;
2570           vlib_buffer_t *p0;
2571           ip4_header_t *ip0;
2572           u32 pi0, rw_len0, adj_index0, next0, error0, checksum0;
2573           u32 tx_sw_if_index0;
2574
2575           pi0 = to_next[0] = from[0];
2576
2577           p0 = vlib_get_buffer (vm, pi0);
2578
2579           adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
2580
2581           /* We should never rewrite a pkt using the MISS adjacency */
2582           ASSERT (adj_index0);
2583
2584           adj0 = ip_get_adjacency (lm, adj_index0);
2585
2586           ip0 = vlib_buffer_get_current (p0);
2587
2588           error0 = IP4_ERROR_NONE;
2589           next0 = IP4_REWRITE_NEXT_DROP;        /* drop on error */
2590
2591           /* Decrement TTL & update checksum. */
2592           if (PREDICT_TRUE (!(p0->flags & VNET_BUFFER_LOCALLY_ORIGINATED)))
2593             {
2594               i32 ttl0 = ip0->ttl;
2595
2596               checksum0 = ip0->checksum + clib_host_to_net_u16 (0x0100);
2597
2598               checksum0 += checksum0 >= 0xffff;
2599
2600               ip0->checksum = checksum0;
2601
2602               ASSERT (ip0->ttl > 0);
2603
2604               ttl0 -= 1;
2605
2606               ip0->ttl = ttl0;
2607
2608               ASSERT (ip0->checksum == ip4_header_checksum (ip0));
2609
2610               if (PREDICT_FALSE (ttl0 <= 0))
2611                 {
2612                   /*
2613                    * If the ttl drops below 1 when forwarding, generate
2614                    * an ICMP response.
2615                    */
2616                   error0 = IP4_ERROR_TIME_EXPIRED;
2617                   next0 = IP4_REWRITE_NEXT_ICMP_ERROR;
2618                   vnet_buffer (p0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
2619                   icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
2620                                                ICMP4_time_exceeded_ttl_exceeded_in_transit,
2621                                                0);
2622                 }
2623             }
2624           else
2625             {
2626               p0->flags &= ~VNET_BUFFER_LOCALLY_ORIGINATED;
2627             }
2628
2629           vlib_prefetch_combined_counter (&adjacency_counters,
2630                                           cpu_index, adj_index0);
2631
2632           /* Guess we are only writing on simple Ethernet header. */
2633           vnet_rewrite_one_header (adj0[0], ip0, sizeof (ethernet_header_t));
2634           if (is_mcast)
2635             {
2636               /*
2637                * copy bytes from the IP address into the MAC rewrite
2638                */
2639               vnet_fixup_one_header (adj0[0], &ip0->dst_address, ip0, 1);
2640             }
2641
2642           /* Update packet buffer attributes/set output interface. */
2643           rw_len0 = adj0[0].rewrite_header.data_bytes;
2644           vnet_buffer (p0)->ip.save_rewrite_length = rw_len0;
2645
2646           vlib_increment_combined_counter
2647             (&adjacency_counters,
2648              cpu_index,
2649              adj_index0, 1, vlib_buffer_length_in_chain (vm, p0) + rw_len0);
2650
2651           /* Check MTU of outgoing interface. */
2652           error0 = (vlib_buffer_length_in_chain (vm, p0)
2653                     > adj0[0].rewrite_header.max_l3_packet_bytes
2654                     ? IP4_ERROR_MTU_EXCEEDED : error0);
2655
2656           p0->error = error_node->errors[error0];
2657
2658           /* Don't adjust the buffer for ttl issue; icmp-error node wants
2659            * to see the IP headerr */
2660           if (PREDICT_TRUE (error0 == IP4_ERROR_NONE))
2661             {
2662               p0->current_data -= rw_len0;
2663               p0->current_length += rw_len0;
2664               tx_sw_if_index0 = adj0[0].rewrite_header.sw_if_index;
2665
2666               vnet_buffer (p0)->sw_if_index[VLIB_TX] = tx_sw_if_index0;
2667               next0 = adj0[0].rewrite_header.next_index;
2668
2669               if (is_midchain)
2670                 {
2671                   adj0->sub_type.midchain.fixup_func (vm, adj0, p0);
2672                 }
2673
2674               vnet_feature_arc_start (lm->output_feature_arc_index,
2675                                       tx_sw_if_index0, &next0, p0);
2676
2677             }
2678
2679           from += 1;
2680           n_left_from -= 1;
2681           to_next += 1;
2682           n_left_to_next -= 1;
2683
2684           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2685                                            to_next, n_left_to_next,
2686                                            pi0, next0);
2687         }
2688
2689       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2690     }
2691
2692   /* Need to do trace after rewrites to pick up new packet data. */
2693   if (node->flags & VLIB_NODE_FLAG_TRACE)
2694     ip4_forward_next_trace (vm, node, frame, VLIB_TX);
2695
2696   return frame->n_vectors;
2697 }
2698
2699
2700 /** @brief IPv4 rewrite node.
2701     @node ip4-rewrite
2702
2703     This is the IPv4 transit-rewrite node: decrement TTL, fix the ipv4
2704     header checksum, fetch the ip adjacency, check the outbound mtu,
2705     apply the adjacency rewrite, and send pkts to the adjacency
2706     rewrite header's rewrite_next_index.
2707
2708     @param vm vlib_main_t corresponding to the current thread
2709     @param node vlib_node_runtime_t
2710     @param frame vlib_frame_t whose contents should be dispatched
2711
2712     @par Graph mechanics: buffer metadata, next index usage
2713
2714     @em Uses:
2715     - <code>vnet_buffer(b)->ip.adj_index[VLIB_TX]</code>
2716         - the rewrite adjacency index
2717     - <code>adj->lookup_next_index</code>
2718         - Must be IP_LOOKUP_NEXT_REWRITE or IP_LOOKUP_NEXT_ARP, otherwise
2719           the packet will be dropped.
2720     - <code>adj->rewrite_header</code>
2721         - Rewrite string length, rewrite string, next_index
2722
2723     @em Sets:
2724     - <code>b->current_data, b->current_length</code>
2725         - Updated net of applying the rewrite string
2726
2727     <em>Next Indices:</em>
2728     - <code> adj->rewrite_header.next_index </code>
2729       or @c error-drop
2730 */
2731 static uword
2732 ip4_rewrite (vlib_main_t * vm,
2733              vlib_node_runtime_t * node, vlib_frame_t * frame)
2734 {
2735   if (adj_are_counters_enabled ())
2736     return ip4_rewrite_inline (vm, node, frame, 1, 0, 0);
2737   else
2738     return ip4_rewrite_inline (vm, node, frame, 0, 0, 0);
2739 }
2740
2741 static uword
2742 ip4_midchain (vlib_main_t * vm,
2743               vlib_node_runtime_t * node, vlib_frame_t * frame)
2744 {
2745   if (adj_are_counters_enabled ())
2746     return ip4_rewrite_inline (vm, node, frame, 1, 1, 0);
2747   else
2748     return ip4_rewrite_inline (vm, node, frame, 0, 1, 0);
2749 }
2750
2751 static uword
2752 ip4_rewrite_mcast (vlib_main_t * vm,
2753                    vlib_node_runtime_t * node, vlib_frame_t * frame)
2754 {
2755   if (adj_are_counters_enabled ())
2756     return ip4_rewrite_inline (vm, node, frame, 1, 0, 1);
2757   else
2758     return ip4_rewrite_inline (vm, node, frame, 0, 0, 1);
2759 }
2760
2761 /* *INDENT-OFF* */
2762 VLIB_REGISTER_NODE (ip4_rewrite_node) = {
2763   .function = ip4_rewrite,
2764   .name = "ip4-rewrite",
2765   .vector_size = sizeof (u32),
2766
2767   .format_trace = format_ip4_rewrite_trace,
2768
2769   .n_next_nodes = 2,
2770   .next_nodes = {
2771     [IP4_REWRITE_NEXT_DROP] = "error-drop",
2772     [IP4_REWRITE_NEXT_ICMP_ERROR] = "ip4-icmp-error",
2773   },
2774 };
2775 VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_node, ip4_rewrite)
2776
2777 VLIB_REGISTER_NODE (ip4_rewrite_mcast_node) = {
2778   .function = ip4_rewrite_mcast,
2779   .name = "ip4-rewrite-mcast",
2780   .vector_size = sizeof (u32),
2781
2782   .format_trace = format_ip4_rewrite_trace,
2783   .sibling_of = "ip4-rewrite",
2784 };
2785 VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_mcast_node, ip4_rewrite_mcast)
2786
2787 VLIB_REGISTER_NODE (ip4_midchain_node) = {
2788   .function = ip4_midchain,
2789   .name = "ip4-midchain",
2790   .vector_size = sizeof (u32),
2791   .format_trace = format_ip4_forward_next_trace,
2792   .sibling_of =  "ip4-rewrite",
2793 };
2794 VLIB_NODE_FUNCTION_MULTIARCH (ip4_midchain_node, ip4_midchain);
2795 /* *INDENT-ON */
2796
2797 static clib_error_t *
2798 add_del_interface_table (vlib_main_t * vm,
2799                          unformat_input_t * input, vlib_cli_command_t * cmd)
2800 {
2801   vnet_main_t *vnm = vnet_get_main ();
2802   ip_interface_address_t *ia;
2803   clib_error_t *error = 0;
2804   u32 sw_if_index, table_id;
2805
2806   sw_if_index = ~0;
2807
2808   if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
2809     {
2810       error = clib_error_return (0, "unknown interface `%U'",
2811                                  format_unformat_error, input);
2812       goto done;
2813     }
2814
2815   if (unformat (input, "%d", &table_id))
2816     ;
2817   else
2818     {
2819       error = clib_error_return (0, "expected table id `%U'",
2820                                  format_unformat_error, input);
2821       goto done;
2822     }
2823
2824   /*
2825    * If the interface already has in IP address, then a change int
2826    * VRF is not allowed. The IP address applied must first be removed.
2827    * We do not do that automatically here, since VPP has no knowledge
2828    * of whether thoses subnets are valid in the destination VRF.
2829    */
2830   /* *INDENT-OFF* */
2831   foreach_ip_interface_address (&ip4_main.lookup_main,
2832                                 ia, sw_if_index,
2833                                 1 /* honor unnumbered */,
2834   ({
2835       ip4_address_t * a;
2836
2837       a = ip_interface_address_get_address (&ip4_main.lookup_main, ia);
2838       error = clib_error_return (0, "interface %U has address %U",
2839                                  format_vnet_sw_if_index_name, vnm,
2840                                  sw_if_index,
2841                                  format_ip4_address, a);
2842       goto done;
2843    }));
2844    /* *INDENT-ON* */
2845
2846 {
2847   ip4_main_t *im = &ip4_main;
2848   u32 fib_index;
2849
2850   fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
2851
2852   vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
2853   im->fib_index_by_sw_if_index[sw_if_index] = fib_index;
2854
2855   fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id);
2856   vec_validate (im->mfib_index_by_sw_if_index, sw_if_index);
2857   im->mfib_index_by_sw_if_index[sw_if_index] = fib_index;
2858 }
2859
2860 done:
2861 return error;
2862 }
2863
2864 /*?
2865  * Place the indicated interface into the supplied IPv4 FIB table (also known
2866  * as a VRF). If the FIB table does not exist, this command creates it. To
2867  * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
2868  * FIB table will only be displayed if a route has been added to the table, or
2869  * an IP Address is assigned to an interface in the table (which adds a route
2870  * automatically).
2871  *
2872  * @note IP addresses added after setting the interface IP table are added to
2873  * the indicated FIB table. If an IP address is added prior to changing the
2874  * table then this is an error. The control plane must remove these addresses
2875  * first and then change the table. VPP will not automatically move the
2876  * addresses from the old to the new table as it does not know the validity
2877  * of such a change.
2878  *
2879  * @cliexpar
2880  * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id):
2881  * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
2882  ?*/
2883 /* *INDENT-OFF* */
2884 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
2885 {
2886   .path = "set interface ip table",
2887   .function = add_del_interface_table,
2888   .short_help = "set interface ip table <interface> <table-id>",
2889 };
2890 /* *INDENT-ON* */
2891
2892 int
2893 ip4_lookup_validate (ip4_address_t * a, u32 fib_index0)
2894 {
2895   ip4_fib_mtrie_t *mtrie0;
2896   ip4_fib_mtrie_leaf_t leaf0;
2897   u32 lbi0;
2898
2899   mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
2900
2901   leaf0 = IP4_FIB_MTRIE_LEAF_ROOT;
2902   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 0);
2903   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 1);
2904   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 2);
2905   leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, a, 3);
2906
2907   /* Handle default route. */
2908   leaf0 = (leaf0 == IP4_FIB_MTRIE_LEAF_EMPTY ? mtrie0->default_leaf : leaf0);
2909
2910   lbi0 = ip4_fib_mtrie_leaf_get_adj_index (leaf0);
2911
2912   return lbi0 == ip4_fib_table_lookup_lb (ip4_fib_get (fib_index0), a);
2913 }
2914
2915 static clib_error_t *
2916 test_lookup_command_fn (vlib_main_t * vm,
2917                         unformat_input_t * input, vlib_cli_command_t * cmd)
2918 {
2919   ip4_fib_t *fib;
2920   u32 table_id = 0;
2921   f64 count = 1;
2922   u32 n;
2923   int i;
2924   ip4_address_t ip4_base_address;
2925   u64 errors = 0;
2926
2927   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2928     {
2929       if (unformat (input, "table %d", &table_id))
2930         {
2931           /* Make sure the entry exists. */
2932           fib = ip4_fib_get (table_id);
2933           if ((fib) && (fib->index != table_id))
2934             return clib_error_return (0, "<fib-index> %d does not exist",
2935                                       table_id);
2936         }
2937       else if (unformat (input, "count %f", &count))
2938         ;
2939
2940       else if (unformat (input, "%U",
2941                          unformat_ip4_address, &ip4_base_address))
2942         ;
2943       else
2944         return clib_error_return (0, "unknown input `%U'",
2945                                   format_unformat_error, input);
2946     }
2947
2948   n = count;
2949
2950   for (i = 0; i < n; i++)
2951     {
2952       if (!ip4_lookup_validate (&ip4_base_address, table_id))
2953         errors++;
2954
2955       ip4_base_address.as_u32 =
2956         clib_host_to_net_u32 (1 +
2957                               clib_net_to_host_u32 (ip4_base_address.as_u32));
2958     }
2959
2960   if (errors)
2961     vlib_cli_output (vm, "%llu errors out of %d lookups\n", errors, n);
2962   else
2963     vlib_cli_output (vm, "No errors in %d lookups\n", n);
2964
2965   return 0;
2966 }
2967
2968 /*?
2969  * Perform a lookup of an IPv4 Address (or range of addresses) in the
2970  * given FIB table to determine if there is a conflict with the
2971  * adjacency table. The fib-id can be determined by using the
2972  * '<em>show ip fib</em>' command. If fib-id is not entered, default value
2973  * of 0 is used.
2974  *
2975  * @todo This command uses fib-id, other commands use table-id (not
2976  * just a name, they are different indexes). Would like to change this
2977  * to table-id for consistency.
2978  *
2979  * @cliexpar
2980  * Example of how to run the test lookup command:
2981  * @cliexstart{test lookup 172.16.1.1 table 1 count 2}
2982  * No errors in 2 lookups
2983  * @cliexend
2984 ?*/
2985 /* *INDENT-OFF* */
2986 VLIB_CLI_COMMAND (lookup_test_command, static) =
2987 {
2988   .path = "test lookup",
2989   .short_help = "test lookup <ipv4-addr> [table <fib-id>] [count <nn>]",
2990   .function = test_lookup_command_fn,
2991 };
2992 /* *INDENT-ON* */
2993
2994 int
2995 vnet_set_ip4_flow_hash (u32 table_id, u32 flow_hash_config)
2996 {
2997   ip4_main_t *im4 = &ip4_main;
2998   ip4_fib_t *fib;
2999   uword *p = hash_get (im4->fib_index_by_table_id, table_id);
3000
3001   if (p == 0)
3002     return VNET_API_ERROR_NO_SUCH_FIB;
3003
3004   fib = ip4_fib_get (p[0]);
3005
3006   fib->flow_hash_config = flow_hash_config;
3007   return 0;
3008 }
3009
3010 static clib_error_t *
3011 set_ip_flow_hash_command_fn (vlib_main_t * vm,
3012                              unformat_input_t * input,
3013                              vlib_cli_command_t * cmd)
3014 {
3015   int matched = 0;
3016   u32 table_id = 0;
3017   u32 flow_hash_config = 0;
3018   int rv;
3019
3020   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3021     {
3022       if (unformat (input, "table %d", &table_id))
3023         matched = 1;
3024 #define _(a,v) \
3025     else if (unformat (input, #a)) { flow_hash_config |= v; matched=1;}
3026       foreach_flow_hash_bit
3027 #undef _
3028         else
3029         break;
3030     }
3031
3032   if (matched == 0)
3033     return clib_error_return (0, "unknown input `%U'",
3034                               format_unformat_error, input);
3035
3036   rv = vnet_set_ip4_flow_hash (table_id, flow_hash_config);
3037   switch (rv)
3038     {
3039     case 0:
3040       break;
3041
3042     case VNET_API_ERROR_NO_SUCH_FIB:
3043       return clib_error_return (0, "no such FIB table %d", table_id);
3044
3045     default:
3046       clib_warning ("BUG: illegal flow hash config 0x%x", flow_hash_config);
3047       break;
3048     }
3049
3050   return 0;
3051 }
3052
3053 /*?
3054  * Configure the set of IPv4 fields used by the flow hash.
3055  *
3056  * @cliexpar
3057  * Example of how to set the flow hash on a given table:
3058  * @cliexcmd{set ip flow-hash table 7 dst sport dport proto}
3059  * Example of display the configured flow hash:
3060  * @cliexstart{show ip fib}
3061  * ipv4-VRF:0, fib_index 0, flow hash: src dst sport dport proto
3062  * 0.0.0.0/0
3063  *   unicast-ip4-chain
3064  *   [@0]: dpo-load-balance: [index:0 buckets:1 uRPF:0 to:[0:0]]
3065  *     [0] [@0]: dpo-drop ip6
3066  * 0.0.0.0/32
3067  *   unicast-ip4-chain
3068  *   [@0]: dpo-load-balance: [index:1 buckets:1 uRPF:1 to:[0:0]]
3069  *     [0] [@0]: dpo-drop ip6
3070  * 224.0.0.0/8
3071  *   unicast-ip4-chain
3072  *   [@0]: dpo-load-balance: [index:3 buckets:1 uRPF:3 to:[0:0]]
3073  *     [0] [@0]: dpo-drop ip6
3074  * 6.0.1.2/32
3075  *   unicast-ip4-chain
3076  *   [@0]: dpo-load-balance: [index:30 buckets:1 uRPF:29 to:[0:0]]
3077  *     [0] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
3078  * 7.0.0.1/32
3079  *   unicast-ip4-chain
3080  *   [@0]: dpo-load-balance: [index:31 buckets:4 uRPF:30 to:[0:0]]
3081  *     [0] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3082  *     [1] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3083  *     [2] [@3]: arp-ipv4: via 6.0.0.2 af_packet0
3084  *     [3] [@3]: arp-ipv4: via 6.0.0.1 af_packet0
3085  * 240.0.0.0/8
3086  *   unicast-ip4-chain
3087  *   [@0]: dpo-load-balance: [index:2 buckets:1 uRPF:2 to:[0:0]]
3088  *     [0] [@0]: dpo-drop ip6
3089  * 255.255.255.255/32
3090  *   unicast-ip4-chain
3091  *   [@0]: dpo-load-balance: [index:4 buckets:1 uRPF:4 to:[0:0]]
3092  *     [0] [@0]: dpo-drop ip6
3093  * ipv4-VRF:7, fib_index 1, flow hash: dst sport dport proto
3094  * 0.0.0.0/0
3095  *   unicast-ip4-chain
3096  *   [@0]: dpo-load-balance: [index:12 buckets:1 uRPF:11 to:[0:0]]
3097  *     [0] [@0]: dpo-drop ip6
3098  * 0.0.0.0/32
3099  *   unicast-ip4-chain
3100  *   [@0]: dpo-load-balance: [index:13 buckets:1 uRPF:12 to:[0:0]]
3101  *     [0] [@0]: dpo-drop ip6
3102  * 172.16.1.0/24
3103  *   unicast-ip4-chain
3104  *   [@0]: dpo-load-balance: [index:17 buckets:1 uRPF:16 to:[0:0]]
3105  *     [0] [@4]: ipv4-glean: af_packet0
3106  * 172.16.1.1/32
3107  *   unicast-ip4-chain
3108  *   [@0]: dpo-load-balance: [index:18 buckets:1 uRPF:17 to:[1:84]]
3109  *     [0] [@2]: dpo-receive: 172.16.1.1 on af_packet0
3110  * 172.16.1.2/32
3111  *   unicast-ip4-chain
3112  *   [@0]: dpo-load-balance: [index:21 buckets:1 uRPF:20 to:[0:0]]
3113  *     [0] [@5]: ipv4 via 172.16.1.2 af_packet0: IP4: 02:fe:9e:70:7a:2b -> 26:a5:f6:9c:3a:36
3114  * 172.16.2.0/24
3115  *   unicast-ip4-chain
3116  *   [@0]: dpo-load-balance: [index:19 buckets:1 uRPF:18 to:[0:0]]
3117  *     [0] [@4]: ipv4-glean: af_packet1
3118  * 172.16.2.1/32
3119  *   unicast-ip4-chain
3120  *   [@0]: dpo-load-balance: [index:20 buckets:1 uRPF:19 to:[0:0]]
3121  *     [0] [@2]: dpo-receive: 172.16.2.1 on af_packet1
3122  * 224.0.0.0/8
3123  *   unicast-ip4-chain
3124  *   [@0]: dpo-load-balance: [index:15 buckets:1 uRPF:14 to:[0:0]]
3125  *     [0] [@0]: dpo-drop ip6
3126  * 240.0.0.0/8
3127  *   unicast-ip4-chain
3128  *   [@0]: dpo-load-balance: [index:14 buckets:1 uRPF:13 to:[0:0]]
3129  *     [0] [@0]: dpo-drop ip6
3130  * 255.255.255.255/32
3131  *   unicast-ip4-chain
3132  *   [@0]: dpo-load-balance: [index:16 buckets:1 uRPF:15 to:[0:0]]
3133  *     [0] [@0]: dpo-drop ip6
3134  * @cliexend
3135 ?*/
3136 /* *INDENT-OFF* */
3137 VLIB_CLI_COMMAND (set_ip_flow_hash_command, static) =
3138 {
3139   .path = "set ip flow-hash",
3140   .short_help =
3141   "set ip flow-hash table <table-id> [src] [dst] [sport] [dport] [proto] [reverse]",
3142   .function = set_ip_flow_hash_command_fn,
3143 };
3144 /* *INDENT-ON* */
3145
3146 int
3147 vnet_set_ip4_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
3148                              u32 table_index)
3149 {
3150   vnet_main_t *vnm = vnet_get_main ();
3151   vnet_interface_main_t *im = &vnm->interface_main;
3152   ip4_main_t *ipm = &ip4_main;
3153   ip_lookup_main_t *lm = &ipm->lookup_main;
3154   vnet_classify_main_t *cm = &vnet_classify_main;
3155   ip4_address_t *if_addr;
3156
3157   if (pool_is_free_index (im->sw_interfaces, sw_if_index))
3158     return VNET_API_ERROR_NO_MATCHING_INTERFACE;
3159
3160   if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
3161     return VNET_API_ERROR_NO_SUCH_ENTRY;
3162
3163   vec_validate (lm->classify_table_index_by_sw_if_index, sw_if_index);
3164   lm->classify_table_index_by_sw_if_index[sw_if_index] = table_index;
3165
3166   if_addr = ip4_interface_first_address (ipm, sw_if_index, NULL);
3167
3168   if (NULL != if_addr)
3169     {
3170       fib_prefix_t pfx = {
3171         .fp_len = 32,
3172         .fp_proto = FIB_PROTOCOL_IP4,
3173         .fp_addr.ip4 = *if_addr,
3174       };
3175       u32 fib_index;
3176
3177       fib_index = fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
3178                                                        sw_if_index);
3179
3180
3181       if (table_index != (u32) ~ 0)
3182         {
3183           dpo_id_t dpo = DPO_INVALID;
3184
3185           dpo_set (&dpo,
3186                    DPO_CLASSIFY,
3187                    DPO_PROTO_IP4,
3188                    classify_dpo_create (DPO_PROTO_IP4, table_index));
3189
3190           fib_table_entry_special_dpo_add (fib_index,
3191                                            &pfx,
3192                                            FIB_SOURCE_CLASSIFY,
3193                                            FIB_ENTRY_FLAG_NONE, &dpo);
3194           dpo_reset (&dpo);
3195         }
3196       else
3197         {
3198           fib_table_entry_special_remove (fib_index,
3199                                           &pfx, FIB_SOURCE_CLASSIFY);
3200         }
3201     }
3202
3203   return 0;
3204 }
3205
3206 static clib_error_t *
3207 set_ip_classify_command_fn (vlib_main_t * vm,
3208                             unformat_input_t * input,
3209                             vlib_cli_command_t * cmd)
3210 {
3211   u32 table_index = ~0;
3212   int table_index_set = 0;
3213   u32 sw_if_index = ~0;
3214   int rv;
3215
3216   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3217     {
3218       if (unformat (input, "table-index %d", &table_index))
3219         table_index_set = 1;
3220       else if (unformat (input, "intfc %U", unformat_vnet_sw_interface,
3221                          vnet_get_main (), &sw_if_index))
3222         ;
3223       else
3224         break;
3225     }
3226
3227   if (table_index_set == 0)
3228     return clib_error_return (0, "classify table-index must be specified");
3229
3230   if (sw_if_index == ~0)
3231     return clib_error_return (0, "interface / subif must be specified");
3232
3233   rv = vnet_set_ip4_classify_intfc (vm, sw_if_index, table_index);
3234
3235   switch (rv)
3236     {
3237     case 0:
3238       break;
3239
3240     case VNET_API_ERROR_NO_MATCHING_INTERFACE:
3241       return clib_error_return (0, "No such interface");
3242
3243     case VNET_API_ERROR_NO_SUCH_ENTRY:
3244       return clib_error_return (0, "No such classifier table");
3245     }
3246   return 0;
3247 }
3248
3249 /*?
3250  * Assign a classification table to an interface. The classification
3251  * table is created using the '<em>classify table</em>' and '<em>classify session</em>'
3252  * commands. Once the table is create, use this command to filter packets
3253  * on an interface.
3254  *
3255  * @cliexpar
3256  * Example of how to assign a classification table to an interface:
3257  * @cliexcmd{set ip classify intfc GigabitEthernet2/0/0 table-index 1}
3258 ?*/
3259 /* *INDENT-OFF* */
3260 VLIB_CLI_COMMAND (set_ip_classify_command, static) =
3261 {
3262     .path = "set ip classify",
3263     .short_help =
3264     "set ip classify intfc <interface> table-index <classify-idx>",
3265     .function = set_ip_classify_command_fn,
3266 };
3267 /* *INDENT-ON* */
3268
3269 /*
3270  * fd.io coding-style-patch-verification: ON
3271  *
3272  * Local Variables:
3273  * eval: (c-set-style "gnu")
3274  * End:
3275  */