ip: check all fib src for a connected dst entry
[vpp.git] / src / vnet / ethernet / arp.c
1 /*
2  * ethernet/arp.c: IP v4 ARP node
3  *
4  * Copyright (c) 2010 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vnet/ip/ip.h>
19 #include <vnet/ip/ip_neighbor.h>
20 #include <vnet/ip/ip6.h>
21 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/ethernet/arp.h>
23 #include <vnet/l2/l2_input.h>
24 #include <vppinfra/mhash.h>
25 #include <vnet/fib/ip4_fib.h>
26 #include <vnet/fib/fib_entry_src.h>
27 #include <vnet/adj/adj_nbr.h>
28 #include <vnet/adj/adj_mcast.h>
29 #include <vnet/mpls/mpls.h>
30 #include <vnet/l2/feat_bitmap.h>
31
32 #include <vlibmemory/api.h>
33
34 /**
35  * @file
36  * @brief IPv4 ARP.
37  *
38  * This file contains code to manage the IPv4 ARP tables (IP Address
39  * to MAC Address lookup).
40  */
41
42
43 /**
44  * @brief Per-interface ARP configuration and state
45  */
46 typedef struct ethernet_arp_interface_t_
47 {
48   /**
49    * Hash table of ARP entries.
50    * Since this hash table is per-interface, the key is only the IPv4 address.
51    */
52   uword *arp_entries;
53   /**
54    * Is ARP enabled on this interface
55    */
56   u32 enabled;
57   /**
58    * Is Proxy ARP enabled on this interface
59    */
60   u32 proxy_enabled;
61 } ethernet_arp_interface_t;
62
63 typedef struct
64 {
65   ip4_address_t lo_addr;
66   ip4_address_t hi_addr;
67   u32 fib_index;
68 } ethernet_proxy_arp_t;
69
70 typedef struct
71 {
72   u32 next_index;
73   uword node_index;
74   uword type_opaque;
75   uword data;
76   /* Used for arp event notification only */
77   arp_change_event_cb_t data_callback;
78   u32 pid;
79 } pending_resolution_t;
80
81 typedef struct
82 {
83   /* Hash tables mapping name to opcode. */
84   uword *opcode_by_name;
85
86   /* lite beer "glean" adjacency handling */
87   uword *pending_resolutions_by_address;
88   pending_resolution_t *pending_resolutions;
89
90   /* Mac address change notification */
91   uword *mac_changes_by_address;
92   pending_resolution_t *mac_changes;
93
94   ethernet_arp_ip4_entry_t *ip4_entry_pool;
95
96   /* ARP attack mitigation */
97   u32 arp_delete_rotor;
98   u32 limit_arp_cache_size;
99
100   /** Per interface state */
101   ethernet_arp_interface_t *ethernet_arp_by_sw_if_index;
102
103   /* Proxy arp vector */
104   ethernet_proxy_arp_t *proxy_arps;
105
106   uword wc_ip4_arp_publisher_node;
107   uword wc_ip4_arp_publisher_et;
108
109   /* ARP feature arc index */
110   u8 feature_arc_index;
111 } ethernet_arp_main_t;
112
113 static ethernet_arp_main_t ethernet_arp_main;
114
115 typedef struct
116 {
117   u32 sw_if_index;
118   ip4_address_t ip4;
119   mac_address_t mac;
120   ip_neighbor_flags_t nbr_flags;
121   u32 flags;
122 #define ETHERNET_ARP_ARGS_REMOVE (1<<0)
123 #define ETHERNET_ARP_ARGS_FLUSH  (1<<1)
124 #define ETHERNET_ARP_ARGS_POPULATE  (1<<2)
125 #define ETHERNET_ARP_ARGS_WC_PUB  (1<<3)
126 } vnet_arp_set_ip4_over_ethernet_rpc_args_t;
127
128 static const u8 vrrp_prefix[] = { 0x00, 0x00, 0x5E, 0x00, 0x01 };
129
130 /* Node index for send_garp_na_process */
131 u32 send_garp_na_process_node_index;
132
133 static void
134 set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t
135                                     * a);
136
137 static u8 *
138 format_ethernet_arp_hardware_type (u8 * s, va_list * va)
139 {
140   ethernet_arp_hardware_type_t h = va_arg (*va, ethernet_arp_hardware_type_t);
141   char *t = 0;
142   switch (h)
143     {
144 #define _(n,f) case n: t = #f; break;
145       foreach_ethernet_arp_hardware_type;
146 #undef _
147
148     default:
149       return format (s, "unknown 0x%x", h);
150     }
151
152   return format (s, "%s", t);
153 }
154
155 static u8 *
156 format_ethernet_arp_opcode (u8 * s, va_list * va)
157 {
158   ethernet_arp_opcode_t o = va_arg (*va, ethernet_arp_opcode_t);
159   char *t = 0;
160   switch (o)
161     {
162 #define _(f) case ETHERNET_ARP_OPCODE_##f: t = #f; break;
163       foreach_ethernet_arp_opcode;
164 #undef _
165
166     default:
167       return format (s, "unknown 0x%x", o);
168     }
169
170   return format (s, "%s", t);
171 }
172
173 static uword
174 unformat_ethernet_arp_opcode_host_byte_order (unformat_input_t * input,
175                                               va_list * args)
176 {
177   int *result = va_arg (*args, int *);
178   ethernet_arp_main_t *am = &ethernet_arp_main;
179   int x, i;
180
181   /* Numeric opcode. */
182   if (unformat (input, "0x%x", &x) || unformat (input, "%d", &x))
183     {
184       if (x >= (1 << 16))
185         return 0;
186       *result = x;
187       return 1;
188     }
189
190   /* Named type. */
191   if (unformat_user (input, unformat_vlib_number_by_name,
192                      am->opcode_by_name, &i))
193     {
194       *result = i;
195       return 1;
196     }
197
198   return 0;
199 }
200
201 static uword
202 unformat_ethernet_arp_opcode_net_byte_order (unformat_input_t * input,
203                                              va_list * args)
204 {
205   int *result = va_arg (*args, int *);
206   if (!unformat_user
207       (input, unformat_ethernet_arp_opcode_host_byte_order, result))
208     return 0;
209
210   *result = clib_host_to_net_u16 ((u16) * result);
211   return 1;
212 }
213
214 static u8 *
215 format_ethernet_arp_header (u8 * s, va_list * va)
216 {
217   ethernet_arp_header_t *a = va_arg (*va, ethernet_arp_header_t *);
218   u32 max_header_bytes = va_arg (*va, u32);
219   u32 indent;
220   u16 l2_type, l3_type;
221
222   if (max_header_bytes != 0 && sizeof (a[0]) > max_header_bytes)
223     return format (s, "ARP header truncated");
224
225   l2_type = clib_net_to_host_u16 (a->l2_type);
226   l3_type = clib_net_to_host_u16 (a->l3_type);
227
228   indent = format_get_indent (s);
229
230   s = format (s, "%U, type %U/%U, address size %d/%d",
231               format_ethernet_arp_opcode, clib_net_to_host_u16 (a->opcode),
232               format_ethernet_arp_hardware_type, l2_type,
233               format_ethernet_type, l3_type,
234               a->n_l2_address_bytes, a->n_l3_address_bytes);
235
236   if (l2_type == ETHERNET_ARP_HARDWARE_TYPE_ethernet
237       && l3_type == ETHERNET_TYPE_IP4)
238     {
239       s = format (s, "\n%U%U/%U -> %U/%U",
240                   format_white_space, indent,
241                   format_mac_address_t, &a->ip4_over_ethernet[0].mac,
242                   format_ip4_address, &a->ip4_over_ethernet[0].ip4,
243                   format_mac_address_t, &a->ip4_over_ethernet[1].mac,
244                   format_ip4_address, &a->ip4_over_ethernet[1].ip4);
245     }
246   else
247     {
248       uword n2 = a->n_l2_address_bytes;
249       uword n3 = a->n_l3_address_bytes;
250       s = format (s, "\n%U%U/%U -> %U/%U",
251                   format_white_space, indent,
252                   format_hex_bytes, a->data + 0 * n2 + 0 * n3, n2,
253                   format_hex_bytes, a->data + 1 * n2 + 0 * n3, n3,
254                   format_hex_bytes, a->data + 1 * n2 + 1 * n3, n2,
255                   format_hex_bytes, a->data + 2 * n2 + 1 * n3, n3);
256     }
257
258   return s;
259 }
260
261 u8 *
262 format_ethernet_arp_ip4_entry (u8 * s, va_list * va)
263 {
264   vnet_main_t *vnm = va_arg (*va, vnet_main_t *);
265   ethernet_arp_ip4_entry_t *e = va_arg (*va, ethernet_arp_ip4_entry_t *);
266   vnet_sw_interface_t *si;
267   u8 *flags = 0;
268
269   if (!e)
270     return format (s, "%=12s%=16s%=6s%=20s%=24s", "Time", "IP4",
271                    "Flags", "Ethernet", "Interface");
272
273   si = vnet_get_sw_interface (vnm, e->sw_if_index);
274
275   if (e->flags & IP_NEIGHBOR_FLAG_STATIC)
276     flags = format (flags, "S");
277
278   if (e->flags & IP_NEIGHBOR_FLAG_DYNAMIC)
279     flags = format (flags, "D");
280
281   if (e->flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY)
282     flags = format (flags, "N");
283
284   s = format (s, "%=12U%=16U%=6s%=20U%U",
285               format_vlib_time, vnm->vlib_main, e->time_last_updated,
286               format_ip4_address, &e->ip4_address,
287               flags ? (char *) flags : "",
288               format_mac_address_t, &e->mac,
289               format_vnet_sw_interface_name, vnm, si);
290
291   vec_free (flags);
292   return s;
293 }
294
295 typedef struct
296 {
297   u8 packet_data[64];
298 } ethernet_arp_input_trace_t;
299
300 static u8 *
301 format_ethernet_arp_input_trace (u8 * s, va_list * va)
302 {
303   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
304   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
305   ethernet_arp_input_trace_t *t = va_arg (*va, ethernet_arp_input_trace_t *);
306
307   s = format (s, "%U",
308               format_ethernet_arp_header,
309               t->packet_data, sizeof (t->packet_data));
310
311   return s;
312 }
313
314 static u8 *
315 format_arp_term_input_trace (u8 * s, va_list * va)
316 {
317   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
318   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
319   ethernet_arp_input_trace_t *t = va_arg (*va, ethernet_arp_input_trace_t *);
320
321   /* arp-term trace data saved is either arp or ip6/icmp6 packet:
322      - for arp, the 1st 16-bit field is hw type of value of 0x0001.
323      - for ip6, the first nibble has value of 6. */
324   s = format (s, "%U", t->packet_data[0] == 0 ?
325               format_ethernet_arp_header : format_ip6_header,
326               t->packet_data, sizeof (t->packet_data));
327
328   return s;
329 }
330
331 static void
332 arp_nbr_probe (ip_adjacency_t * adj)
333 {
334   vnet_main_t *vnm = vnet_get_main ();
335   ip4_main_t *im = &ip4_main;
336   ip_interface_address_t *ia;
337   ethernet_arp_header_t *h;
338   vnet_hw_interface_t *hi;
339   vnet_sw_interface_t *si;
340   ip4_address_t *src;
341   vlib_buffer_t *b;
342   vlib_main_t *vm;
343   u32 bi = 0;
344
345   vm = vlib_get_main ();
346
347   si = vnet_get_sw_interface (vnm, adj->rewrite_header.sw_if_index);
348
349   if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
350     {
351       return;
352     }
353
354   src =
355     ip4_interface_address_matching_destination (im,
356                                                 &adj->sub_type.nbr.next_hop.
357                                                 ip4,
358                                                 adj->rewrite_header.
359                                                 sw_if_index, &ia);
360   if (!src)
361     {
362       return;
363     }
364
365   h =
366     vlib_packet_template_get_packet (vm, &im->ip4_arp_request_packet_template,
367                                      &bi);
368   if (!h)
369     return;
370
371   hi = vnet_get_sup_hw_interface (vnm, adj->rewrite_header.sw_if_index);
372
373   mac_address_from_bytes (&h->ip4_over_ethernet[0].mac, hi->hw_address);
374
375   h->ip4_over_ethernet[0].ip4 = src[0];
376   h->ip4_over_ethernet[1].ip4 = adj->sub_type.nbr.next_hop.ip4;
377
378   b = vlib_get_buffer (vm, bi);
379   vnet_buffer (b)->sw_if_index[VLIB_RX] =
380     vnet_buffer (b)->sw_if_index[VLIB_TX] = adj->rewrite_header.sw_if_index;
381
382   /* Add encapsulation string for software interface (e.g. ethernet header). */
383   vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
384   vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
385
386   {
387     vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index);
388     u32 *to_next = vlib_frame_vector_args (f);
389     to_next[0] = bi;
390     f->n_vectors = 1;
391     vlib_put_frame_to_node (vm, hi->output_node_index, f);
392   }
393 }
394
395 static void
396 arp_mk_complete (adj_index_t ai, ethernet_arp_ip4_entry_t * e)
397 {
398   adj_nbr_update_rewrite
399     (ai, ADJ_NBR_REWRITE_FLAG_COMPLETE,
400      ethernet_build_rewrite (vnet_get_main (),
401                              e->sw_if_index,
402                              adj_get_link_type (ai), &e->mac));
403 }
404
405 static void
406 arp_mk_incomplete (adj_index_t ai)
407 {
408   ip_adjacency_t *adj = adj_get (ai);
409
410   adj_nbr_update_rewrite
411     (ai,
412      ADJ_NBR_REWRITE_FLAG_INCOMPLETE,
413      ethernet_build_rewrite (vnet_get_main (),
414                              adj->rewrite_header.sw_if_index,
415                              VNET_LINK_ARP,
416                              VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
417 }
418
419 static ethernet_arp_ip4_entry_t *
420 arp_entry_find (ethernet_arp_interface_t * eai, const ip4_address_t * addr)
421 {
422   ethernet_arp_main_t *am = &ethernet_arp_main;
423   ethernet_arp_ip4_entry_t *e = NULL;
424   uword *p;
425
426   if (NULL != eai->arp_entries)
427     {
428       p = hash_get (eai->arp_entries, addr->as_u32);
429       if (!p)
430         return (NULL);
431
432       e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
433     }
434
435   return (e);
436 }
437
438 static adj_walk_rc_t
439 arp_mk_complete_walk (adj_index_t ai, void *ctx)
440 {
441   ethernet_arp_ip4_entry_t *e = ctx;
442
443   arp_mk_complete (ai, e);
444
445   return (ADJ_WALK_RC_CONTINUE);
446 }
447
448 static adj_walk_rc_t
449 arp_mk_incomplete_walk (adj_index_t ai, void *ctx)
450 {
451   arp_mk_incomplete (ai);
452
453   return (ADJ_WALK_RC_CONTINUE);
454 }
455
456 static int
457 arp_is_enabled (ethernet_arp_main_t * am, u32 sw_if_index)
458 {
459   if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
460     return 0;
461
462   return (am->ethernet_arp_by_sw_if_index[sw_if_index].enabled);
463 }
464
465 static void
466 arp_enable (ethernet_arp_main_t * am, u32 sw_if_index)
467 {
468   if (arp_is_enabled (am, sw_if_index))
469     return;
470
471   vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index);
472
473   am->ethernet_arp_by_sw_if_index[sw_if_index].enabled = 1;
474
475   vnet_feature_enable_disable ("arp", "arp-reply", sw_if_index, 1, NULL, 0);
476 }
477
478 static int
479 vnet_arp_flush_ip4_over_ethernet_internal (vnet_main_t * vnm,
480                                            vnet_arp_set_ip4_over_ethernet_rpc_args_t
481                                            * args);
482
483 static void
484 arp_disable (ethernet_arp_main_t * am, u32 sw_if_index)
485 {
486   ethernet_arp_interface_t *eai;
487   ethernet_arp_ip4_entry_t *e;
488   u32 i, *to_delete = 0;
489   hash_pair_t *pair;
490
491   if (!arp_is_enabled (am, sw_if_index))
492     return;
493
494   vnet_feature_enable_disable ("arp", "arp-reply", sw_if_index, 0, NULL, 0);
495
496   eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
497
498
499   /* *INDENT-OFF* */
500   hash_foreach_pair (pair, eai->arp_entries,
501   ({
502     e = pool_elt_at_index(am->ip4_entry_pool,
503                           pair->value[0]);
504     vec_add1 (to_delete, e - am->ip4_entry_pool);
505   }));
506   /* *INDENT-ON* */
507
508   for (i = 0; i < vec_len (to_delete); i++)
509     {
510       e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
511
512       vnet_arp_set_ip4_over_ethernet_rpc_args_t delme = {
513         .ip4.as_u32 = e->ip4_address.as_u32,
514         .sw_if_index = e->sw_if_index,
515         .flags = ETHERNET_ARP_ARGS_FLUSH,
516       };
517       mac_address_copy (&delme.mac, &e->mac);
518
519       vnet_arp_flush_ip4_over_ethernet_internal (vnet_get_main (), &delme);
520     }
521
522   vec_free (to_delete);
523
524   eai->enabled = 0;
525 }
526
527 void
528 arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
529 {
530   ethernet_arp_main_t *am = &ethernet_arp_main;
531   ethernet_arp_interface_t *arp_int;
532   ethernet_arp_ip4_entry_t *e;
533   ip_adjacency_t *adj;
534
535   adj = adj_get (ai);
536
537   arp_enable (am, sw_if_index);
538   arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
539   e = arp_entry_find (arp_int, &adj->sub_type.nbr.next_hop.ip4);
540
541   switch (adj->lookup_next_index)
542     {
543     case IP_LOOKUP_NEXT_GLEAN:
544       adj_glean_update_rewrite (ai);
545       break;
546     case IP_LOOKUP_NEXT_ARP:
547       if (NULL != e)
548         {
549           adj_nbr_walk_nh4 (sw_if_index,
550                             &e->ip4_address, arp_mk_complete_walk, e);
551         }
552       else
553         {
554           /*
555            * no matching ARP entry.
556            * construct the rewrite required to for an ARP packet, and stick
557            * that in the adj's pipe to smoke.
558            */
559           adj_nbr_update_rewrite
560             (ai,
561              ADJ_NBR_REWRITE_FLAG_INCOMPLETE,
562              ethernet_build_rewrite
563              (vnm,
564               sw_if_index,
565               VNET_LINK_ARP,
566               VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
567
568           /*
569            * since the FIB has added this adj for a route, it makes sense it
570            * may want to forward traffic sometime soon. Let's send a
571            * speculative ARP. just one. If we were to do periodically that
572            * wouldn't be bad either, but that's more code than i'm prepared to
573            * write at this time for relatively little reward.
574            */
575           arp_nbr_probe (adj);
576         }
577       break;
578     case IP_LOOKUP_NEXT_BCAST:
579       adj_nbr_update_rewrite (ai,
580                               ADJ_NBR_REWRITE_FLAG_COMPLETE,
581                               ethernet_build_rewrite
582                               (vnm,
583                                sw_if_index,
584                                VNET_LINK_IP4,
585                                VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
586       break;
587     case IP_LOOKUP_NEXT_MCAST:
588       {
589         /*
590          * Construct a partial rewrite from the known ethernet mcast dest MAC
591          */
592         u8 *rewrite;
593         u8 offset;
594
595         rewrite = ethernet_build_rewrite (vnm,
596                                           sw_if_index,
597                                           adj->ia_link,
598                                           ethernet_ip4_mcast_dst_addr ());
599         offset = vec_len (rewrite) - 2;
600
601         /*
602          * Complete the remaining fields of the adj's rewrite to direct the
603          * complete of the rewrite at switch time by copying in the IP
604          * dst address's bytes.
605          * Offset is 2 bytes into the MAC destination address.
606          */
607         adj_mcast_update_rewrite (ai, rewrite, offset);
608
609         break;
610       }
611     case IP_LOOKUP_NEXT_DROP:
612     case IP_LOOKUP_NEXT_PUNT:
613     case IP_LOOKUP_NEXT_LOCAL:
614     case IP_LOOKUP_NEXT_REWRITE:
615     case IP_LOOKUP_NEXT_MCAST_MIDCHAIN:
616     case IP_LOOKUP_NEXT_MIDCHAIN:
617     case IP_LOOKUP_NEXT_ICMP_ERROR:
618     case IP_LOOKUP_N_NEXT:
619       ASSERT (0);
620       break;
621     }
622 }
623
624 static void
625 arp_adj_fib_add (ethernet_arp_ip4_entry_t * e, u32 fib_index)
626 {
627   fib_prefix_t pfx = {
628     .fp_len = 32,
629     .fp_proto = FIB_PROTOCOL_IP4,
630     .fp_addr.ip4 = e->ip4_address,
631   };
632
633   e->fib_entry_index =
634     fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
635                               FIB_ENTRY_FLAG_ATTACHED,
636                               DPO_PROTO_IP4, &pfx.fp_addr,
637                               e->sw_if_index, ~0, 1, NULL,
638                               FIB_ROUTE_PATH_FLAG_NONE);
639   fib_table_lock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_ADJ);
640 }
641
642 static void
643 arp_adj_fib_remove (ethernet_arp_ip4_entry_t * e, u32 fib_index)
644 {
645   if (FIB_NODE_INDEX_INVALID != e->fib_entry_index)
646     {
647       fib_prefix_t pfx = {
648         .fp_len = 32,
649         .fp_proto = FIB_PROTOCOL_IP4,
650         .fp_addr.ip4 = e->ip4_address,
651       };
652       u32 fib_index;
653
654       fib_index = ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
655
656       fib_table_entry_path_remove (fib_index, &pfx,
657                                    FIB_SOURCE_ADJ,
658                                    DPO_PROTO_IP4,
659                                    &pfx.fp_addr,
660                                    e->sw_if_index, ~0, 1,
661                                    FIB_ROUTE_PATH_FLAG_NONE);
662       fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_ADJ);
663     }
664 }
665
666 static ethernet_arp_ip4_entry_t *
667 force_reuse_arp_entry (void)
668 {
669   ethernet_arp_ip4_entry_t *e;
670   ethernet_arp_main_t *am = &ethernet_arp_main;
671   u32 count = 0;
672   u32 index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
673   if (index == ~0)              /* Try again from elt 0 */
674     index = pool_next_index (am->ip4_entry_pool, index);
675
676   /* Find a non-static random entry to free up for reuse */
677   do
678     {
679       if ((count++ == 100) || (index == ~0))
680         return NULL;            /* give up after 100 entries */
681       e = pool_elt_at_index (am->ip4_entry_pool, index);
682       am->arp_delete_rotor = index;
683       index = pool_next_index (am->ip4_entry_pool, index);
684     }
685   while (e->flags & IP_NEIGHBOR_FLAG_STATIC);
686
687   /* Remove ARP entry from its interface and update fib */
688   hash_unset
689     (am->ethernet_arp_by_sw_if_index[e->sw_if_index].arp_entries,
690      e->ip4_address.as_u32);
691   arp_adj_fib_remove
692     (e, ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index));
693   adj_nbr_walk_nh4 (e->sw_if_index,
694                     &e->ip4_address, arp_mk_incomplete_walk, e);
695   return e;
696 }
697
698 static int
699 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
700                                          vnet_arp_set_ip4_over_ethernet_rpc_args_t
701                                          * args)
702 {
703   ethernet_arp_ip4_entry_t *e = 0;
704   ethernet_arp_main_t *am = &ethernet_arp_main;
705   vlib_main_t *vm = vlib_get_main ();
706   int make_new_arp_cache_entry = 1;
707   uword *p;
708   pending_resolution_t *pr, *mc;
709   ethernet_arp_interface_t *arp_int;
710   u32 sw_if_index = args->sw_if_index;
711
712   arp_enable (am, sw_if_index);
713
714   arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
715
716   if (NULL != arp_int->arp_entries)
717     {
718       p = hash_get (arp_int->arp_entries, args->ip4.as_u32);
719       if (p)
720         {
721           e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
722
723           /* Refuse to over-write static arp. */
724           if (!(args->nbr_flags & IP_NEIGHBOR_FLAG_STATIC) &&
725               (e->flags & IP_NEIGHBOR_FLAG_STATIC))
726             {
727               /* if MAC address match, still check to send event */
728               if (mac_address_equal (&e->mac, &args->mac))
729                 goto check_customers;
730               return -2;
731             }
732           make_new_arp_cache_entry = 0;
733         }
734     }
735
736   if (make_new_arp_cache_entry)
737     {
738       if (am->limit_arp_cache_size &&
739           pool_elts (am->ip4_entry_pool) >= am->limit_arp_cache_size)
740         {
741           e = force_reuse_arp_entry ();
742           if (NULL == e)
743             return -2;
744         }
745       else
746         pool_get (am->ip4_entry_pool, e);
747
748       if (NULL == arp_int->arp_entries)
749         arp_int->arp_entries = hash_create (0, sizeof (u32));
750
751       hash_set (arp_int->arp_entries, args->ip4.as_u32,
752                 e - am->ip4_entry_pool);
753
754       e->sw_if_index = sw_if_index;
755       e->ip4_address = args->ip4;
756       e->fib_entry_index = FIB_NODE_INDEX_INVALID;
757       mac_address_copy (&e->mac, &args->mac);
758
759       if (!(args->nbr_flags & IP_NEIGHBOR_FLAG_NO_FIB_ENTRY))
760         {
761           arp_adj_fib_add (e,
762                            ip4_fib_table_get_index_for_sw_if_index
763                            (e->sw_if_index));
764         }
765       else
766         {
767           e->flags |= IP_NEIGHBOR_FLAG_NO_FIB_ENTRY;
768         }
769     }
770   else
771     {
772       /*
773        * prevent a DoS attack from the data-plane that
774        * spams us with no-op updates to the MAC address
775        */
776       if (mac_address_equal (&e->mac, &args->mac))
777         {
778           e->time_last_updated = vlib_time_now (vm);
779           goto check_customers;
780         }
781
782       /* Update ethernet address. */
783       mac_address_copy (&e->mac, &args->mac);
784     }
785
786   /* Update time stamp and flags. */
787   e->time_last_updated = vlib_time_now (vm);
788   if (args->nbr_flags & IP_NEIGHBOR_FLAG_STATIC)
789     {
790       e->flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
791       e->flags |= IP_NEIGHBOR_FLAG_STATIC;
792     }
793   else
794     {
795       e->flags &= ~IP_NEIGHBOR_FLAG_STATIC;
796       e->flags |= IP_NEIGHBOR_FLAG_DYNAMIC;
797     }
798
799   adj_nbr_walk_nh4 (sw_if_index, &e->ip4_address, arp_mk_complete_walk, e);
800
801 check_customers:
802   /* Customer(s) waiting for this address to be resolved? */
803   p = hash_get (am->pending_resolutions_by_address, args->ip4.as_u32);
804   if (p)
805     {
806       u32 next_index;
807       next_index = p[0];
808
809       while (next_index != (u32) ~ 0)
810         {
811           pr = pool_elt_at_index (am->pending_resolutions, next_index);
812           vlib_process_signal_event (vm, pr->node_index,
813                                      pr->type_opaque, pr->data);
814           next_index = pr->next_index;
815           pool_put (am->pending_resolutions, pr);
816         }
817
818       hash_unset (am->pending_resolutions_by_address, args->ip4.as_u32);
819     }
820
821   /* Customer(s) requesting ARP event for this address? */
822   p = hash_get (am->mac_changes_by_address, args->ip4.as_u32);
823   if (p)
824     {
825       u32 next_index;
826       next_index = p[0];
827
828       while (next_index != (u32) ~ 0)
829         {
830           int rv = 1;
831           mc = pool_elt_at_index (am->mac_changes, next_index);
832
833           /* Call the user's data callback, return 1 to suppress dup events */
834           if (mc->data_callback)
835             rv = (mc->data_callback) (mc->data, &args->mac, sw_if_index, 0);
836
837           /*
838            * Signal the resolver process, as long as the user
839            * says they want to be notified
840            */
841           if (rv == 0)
842             vlib_process_signal_event (vm, mc->node_index,
843                                        mc->type_opaque, mc->data);
844           next_index = mc->next_index;
845         }
846     }
847
848   return 0;
849 }
850
851 void
852 vnet_register_ip4_arp_resolution_event (vnet_main_t * vnm,
853                                         void *address_arg,
854                                         uword node_index,
855                                         uword type_opaque, uword data)
856 {
857   ethernet_arp_main_t *am = &ethernet_arp_main;
858   ip4_address_t *address = address_arg;
859   uword *p;
860   pending_resolution_t *pr;
861
862   pool_get (am->pending_resolutions, pr);
863
864   pr->next_index = ~0;
865   pr->node_index = node_index;
866   pr->type_opaque = type_opaque;
867   pr->data = data;
868   pr->data_callback = 0;
869
870   p = hash_get (am->pending_resolutions_by_address, address->as_u32);
871   if (p)
872     {
873       /* Insert new resolution at the head of the list */
874       pr->next_index = p[0];
875       hash_unset (am->pending_resolutions_by_address, address->as_u32);
876     }
877
878   hash_set (am->pending_resolutions_by_address, address->as_u32,
879             pr - am->pending_resolutions);
880 }
881
882 int
883 vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm,
884                                    arp_change_event_cb_t data_callback,
885                                    u32 pid,
886                                    void *address_arg,
887                                    uword node_index,
888                                    uword type_opaque, uword data, int is_add)
889 {
890   ethernet_arp_main_t *am = &ethernet_arp_main;
891   ip4_address_t *address = address_arg;
892
893   /* Try to find an existing entry */
894   u32 *first = (u32 *) hash_get (am->mac_changes_by_address, address->as_u32);
895   u32 *p = first;
896   pending_resolution_t *mc;
897   while (p && *p != ~0)
898     {
899       mc = pool_elt_at_index (am->mac_changes, *p);
900       if (mc->node_index == node_index && mc->type_opaque == type_opaque
901           && mc->pid == pid)
902         break;
903       p = &mc->next_index;
904     }
905
906   int found = p && *p != ~0;
907   if (is_add)
908     {
909       if (found)
910         return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
911
912       pool_get (am->mac_changes, mc);
913       /* *INDENT-OFF* */
914       *mc = (pending_resolution_t)
915       {
916         .next_index = ~0,
917         .node_index = node_index,
918         .type_opaque = type_opaque,
919         .data = data,
920         .data_callback = data_callback,
921         .pid = pid,
922       };
923       /* *INDENT-ON* */
924
925       /* Insert new resolution at the end of the list */
926       u32 new_idx = mc - am->mac_changes;
927       if (p)
928         p[0] = new_idx;
929       else
930         hash_set (am->mac_changes_by_address, address->as_u32, new_idx);
931     }
932   else
933     {
934       if (!found)
935         return VNET_API_ERROR_NO_SUCH_ENTRY;
936
937       /* Clients may need to clean up pool entries, too */
938       if (data_callback)
939         /* no new mac addrs */
940         (data_callback) (mc->data, NULL, ~0, NULL);
941
942       /* Remove the entry from the list and delete the entry */
943       *p = mc->next_index;
944       pool_put (am->mac_changes, mc);
945
946       /* Remove from hash if we deleted the last entry */
947       if (*p == ~0 && p == first)
948         hash_unset (am->mac_changes_by_address, address->as_u32);
949     }
950   return 0;
951 }
952
953 /* Either we drop the packet or we send a reply to the sender. */
954 typedef enum
955 {
956   ARP_REPLY_NEXT_DROP,
957   ARP_REPLY_NEXT_REPLY_TX,
958   ARP_REPLY_N_NEXT,
959 } arp_reply_next_t;
960
961 #define foreach_ethernet_arp_error                                      \
962   _ (replies_sent, "ARP replies sent")                                  \
963   _ (l2_type_not_ethernet, "L2 type not ethernet")                      \
964   _ (l3_type_not_ip4, "L3 type not IP4")                                \
965   _ (l3_src_address_not_local, "IP4 source address not local to subnet") \
966   _ (l3_dst_address_not_local, "IP4 destination address not local to subnet") \
967   _ (l3_dst_address_unset, "IP4 destination address is unset")          \
968   _ (l3_src_address_is_local, "IP4 source address matches local interface") \
969   _ (l3_src_address_learned, "ARP request IP4 source address learned")  \
970   _ (replies_received, "ARP replies received")                          \
971   _ (opcode_not_request, "ARP opcode not request")                      \
972   _ (proxy_arp_replies_sent, "Proxy ARP replies sent")                  \
973   _ (l2_address_mismatch, "ARP hw addr does not match L2 frame src addr") \
974   _ (gratuitous_arp, "ARP probe or announcement dropped") \
975   _ (interface_no_table, "Interface is not mapped to an IP table") \
976   _ (interface_not_ip_enabled, "Interface is not IP enabled") \
977   _ (unnumbered_mismatch, "RX interface is unnumbered to different subnet") \
978
979 typedef enum
980 {
981 #define _(sym,string) ETHERNET_ARP_ERROR_##sym,
982   foreach_ethernet_arp_error
983 #undef _
984     ETHERNET_ARP_N_ERROR,
985 } ethernet_arp_reply_error_t;
986
987 static int
988 arp_unnumbered (vlib_buffer_t * p0,
989                 u32 input_sw_if_index, u32 conn_sw_if_index)
990 {
991   vnet_main_t *vnm = vnet_get_main ();
992   vnet_interface_main_t *vim = &vnm->interface_main;
993   vnet_sw_interface_t *si;
994
995   /* verify that the input interface is unnumbered to the connected.
996    * the connected interface is the interface on which the subnet is
997    * configured */
998   si = &vim->sw_interfaces[input_sw_if_index];
999
1000   if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
1001         (si->unnumbered_sw_if_index == conn_sw_if_index)))
1002     {
1003       /* the input interface is not unnumbered to the interface on which
1004        * the sub-net is configured that covers the ARP request.
1005        * So this is not the case for unnumbered.. */
1006       return 0;
1007     }
1008
1009   return !0;
1010 }
1011
1012 static u32
1013 arp_learn (vnet_main_t * vnm,
1014            ethernet_arp_main_t * am, u32 sw_if_index,
1015            const ethernet_arp_ip4_over_ethernet_address_t * addr)
1016 {
1017   vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index, addr, 0);
1018   return (ETHERNET_ARP_ERROR_l3_src_address_learned);
1019 }
1020
1021 typedef enum arp_input_next_t_
1022 {
1023   ARP_INPUT_NEXT_DROP,
1024   ARP_INPUT_N_NEXT,
1025 } arp_input_next_t;
1026
1027 static uword
1028 arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1029 {
1030   u32 n_left_from, next_index, *from, *to_next, n_left_to_next;
1031   ethernet_arp_main_t *am = &ethernet_arp_main;
1032
1033   from = vlib_frame_vector_args (frame);
1034   n_left_from = frame->n_vectors;
1035   next_index = node->cached_next_index;
1036
1037   if (node->flags & VLIB_NODE_FLAG_TRACE)
1038     vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
1039                                    /* stride */ 1,
1040                                    sizeof (ethernet_arp_input_trace_t));
1041
1042   while (n_left_from > 0)
1043     {
1044       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1045
1046       while (n_left_from > 0 && n_left_to_next > 0)
1047         {
1048           const ethernet_arp_header_t *arp0;
1049           arp_input_next_t next0;
1050           vlib_buffer_t *p0;
1051           u32 pi0, error0;
1052
1053           pi0 = to_next[0] = from[0];
1054           from += 1;
1055           to_next += 1;
1056           n_left_from -= 1;
1057           n_left_to_next -= 1;
1058
1059           p0 = vlib_get_buffer (vm, pi0);
1060           arp0 = vlib_buffer_get_current (p0);
1061
1062           error0 = ETHERNET_ARP_ERROR_replies_sent;
1063           next0 = ARP_INPUT_NEXT_DROP;
1064
1065           error0 =
1066             (arp0->l2_type !=
1067              clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ?
1068              ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
1069           error0 =
1070             (arp0->l3_type !=
1071              clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
1072              ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
1073           error0 =
1074             (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ?
1075              ETHERNET_ARP_ERROR_l3_dst_address_unset : error0);
1076
1077           if (ETHERNET_ARP_ERROR_replies_sent == error0)
1078             vnet_feature_arc_start (am->feature_arc_index,
1079                                     vnet_buffer (p0)->sw_if_index[VLIB_RX],
1080                                     &next0, p0);
1081           else
1082             p0->error = node->errors[error0];
1083
1084           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1085                                            n_left_to_next, pi0, next0);
1086         }
1087
1088       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1089     }
1090
1091   return frame->n_vectors;
1092 }
1093
1094 static_always_inline u32
1095 arp_mk_reply (vnet_main_t * vnm,
1096               vlib_buffer_t * p0,
1097               u32 sw_if_index0,
1098               const ip4_address_t * if_addr0,
1099               ethernet_arp_header_t * arp0, ethernet_header_t * eth_rx)
1100 {
1101   vnet_hw_interface_t *hw_if0;
1102   u8 *rewrite0, rewrite0_len;
1103   ethernet_header_t *eth_tx;
1104   u32 next0;
1105
1106   /* Send a reply.
1107      An adjacency to the sender is not always present,
1108      so we use the interface to build us a rewrite string
1109      which will contain all the necessary tags. */
1110   rewrite0 = ethernet_build_rewrite (vnm, sw_if_index0,
1111                                      VNET_LINK_ARP, eth_rx->src_address);
1112   rewrite0_len = vec_len (rewrite0);
1113
1114   /* Figure out how much to rewind current data from adjacency. */
1115   vlib_buffer_advance (p0, -rewrite0_len);
1116   eth_tx = vlib_buffer_get_current (p0);
1117
1118   vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1119   hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1120
1121   /* Send reply back through input interface */
1122   vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1123   next0 = ARP_REPLY_NEXT_REPLY_TX;
1124
1125   arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1126
1127   arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1128
1129   mac_address_from_bytes (&arp0->ip4_over_ethernet[0].mac,
1130                           hw_if0->hw_address);
1131   clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) =
1132     if_addr0->data_u32;
1133
1134   /* Hardware must be ethernet-like. */
1135   ASSERT (vec_len (hw_if0->hw_address) == 6);
1136
1137   /* the rx nd tx ethernet headers wil overlap in the case
1138    * when we received a tagged VLAN=0 packet, but we are sending
1139    * back untagged */
1140   clib_memcpy_fast (eth_tx, rewrite0, vec_len (rewrite0));
1141   vec_free (rewrite0);
1142
1143   return (next0);
1144 }
1145
1146 enum arp_dst_fib_type
1147 {
1148   ARP_DST_FIB_NONE,
1149   ARP_DST_FIB_ADJ,
1150   ARP_DST_FIB_CONN
1151 };
1152
1153 /*
1154  * we're looking for FIB sources that indicate the destination
1155  * is attached. There may be interposed DPO prior to the one
1156  * we are looking for
1157  */
1158 static enum arp_dst_fib_type
1159 arp_dst_fib_check (const fib_node_index_t fei, fib_entry_flag_t * flags)
1160 {
1161   const fib_entry_t *entry = fib_entry_get (fei);
1162   const fib_entry_src_t *entry_src;
1163   fib_source_t src;
1164   /* *INDENT-OFF* */
1165   FOR_EACH_SRC_ADDED(entry, entry_src, src,
1166   ({
1167     *flags = fib_entry_get_flags_for_source (fei, src);
1168     if (fib_entry_is_sourced (fei, FIB_SOURCE_ADJ))
1169         return ARP_DST_FIB_ADJ;
1170       else if (FIB_ENTRY_FLAG_CONNECTED & *flags)
1171         return ARP_DST_FIB_CONN;
1172   }))
1173   /* *INDENT-ON* */
1174
1175   return ARP_DST_FIB_NONE;
1176 }
1177
1178 static uword
1179 arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1180 {
1181   ethernet_arp_main_t *am = &ethernet_arp_main;
1182   vnet_main_t *vnm = vnet_get_main ();
1183   u32 n_left_from, next_index, *from, *to_next;
1184   u32 n_replies_sent = 0;
1185
1186   from = vlib_frame_vector_args (frame);
1187   n_left_from = frame->n_vectors;
1188   next_index = node->cached_next_index;
1189
1190   if (node->flags & VLIB_NODE_FLAG_TRACE)
1191     vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
1192                                    /* stride */ 1,
1193                                    sizeof (ethernet_arp_input_trace_t));
1194
1195   while (n_left_from > 0)
1196     {
1197       u32 n_left_to_next;
1198
1199       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1200
1201       while (n_left_from > 0 && n_left_to_next > 0)
1202         {
1203           vlib_buffer_t *p0;
1204           ethernet_arp_header_t *arp0;
1205           ethernet_header_t *eth_rx;
1206           const ip4_address_t *if_addr0;
1207           u32 pi0, error0, next0, sw_if_index0, conn_sw_if_index0, fib_index0;
1208           u8 dst_is_local0, is_vrrp_reply0;
1209           fib_node_index_t dst_fei, src_fei;
1210           const fib_prefix_t *pfx0;
1211           fib_entry_flag_t src_flags, dst_flags;
1212
1213           pi0 = from[0];
1214           to_next[0] = pi0;
1215           from += 1;
1216           to_next += 1;
1217           n_left_from -= 1;
1218           n_left_to_next -= 1;
1219
1220           p0 = vlib_get_buffer (vm, pi0);
1221           arp0 = vlib_buffer_get_current (p0);
1222           /* Fill in ethernet header. */
1223           eth_rx = ethernet_buffer_get_header (p0);
1224
1225           next0 = ARP_REPLY_NEXT_DROP;
1226           error0 = ETHERNET_ARP_ERROR_replies_sent;
1227           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1228
1229           /* Check that IP address is local and matches incoming interface. */
1230           fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
1231           if (~0 == fib_index0)
1232             {
1233               error0 = ETHERNET_ARP_ERROR_interface_no_table;
1234               goto drop;
1235
1236             }
1237
1238           {
1239             /*
1240              * we're looking for FIB entries that indicate the source
1241              * is attached. There may be more specific non-attached
1242              * routes that match the source, but these do not influence
1243              * whether we respond to an ARP request, i.e. they do not
1244              * influence whether we are the correct way for the sender
1245              * to reach us, they only affect how we reach the sender.
1246              */
1247             fib_entry_t *src_fib_entry;
1248             const fib_prefix_t *pfx;
1249             fib_entry_src_t *src;
1250             fib_source_t source;
1251             int attached;
1252             int mask;
1253
1254             mask = 32;
1255             attached = 0;
1256
1257             do
1258               {
1259                 src_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1260                                                 &arp0->
1261                                                 ip4_over_ethernet[0].ip4,
1262                                                 mask);
1263                 src_fib_entry = fib_entry_get (src_fei);
1264
1265                 /*
1266                  * It's possible that the source that provides the
1267                  * flags we need, or the flags we must not have,
1268                  * is not the best source, so check then all.
1269                  */
1270                 /* *INDENT-OFF* */
1271                 FOR_EACH_SRC_ADDED(src_fib_entry, src, source,
1272                 ({
1273                   src_flags = fib_entry_get_flags_for_source (src_fei, source);
1274
1275                   /* Reject requests/replies with our local interface
1276                      address. */
1277                   if (FIB_ENTRY_FLAG_LOCAL & src_flags)
1278                     {
1279                       error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
1280                       /*
1281                        * When VPP has an interface whose address is also
1282                        * applied to a TAP interface on the host, then VPP's
1283                        * TAP interface will be unnumbered  to the 'real'
1284                        * interface and do proxy ARP from the host.
1285                        * The curious aspect of this setup is that ARP requests
1286                        * from the host will come from the VPP's own address.
1287                        * So don't drop immediately here, instead go see if this
1288                        * is a proxy ARP case.
1289                        */
1290                       goto next_feature;
1291                     }
1292                   /* A Source must also be local to subnet of matching
1293                    * interface address. */
1294                   if ((FIB_ENTRY_FLAG_ATTACHED & src_flags) ||
1295                       (FIB_ENTRY_FLAG_CONNECTED & src_flags))
1296                     {
1297                       attached = 1;
1298                       break;
1299                     }
1300                   /*
1301                    * else
1302                    *  The packet was sent from an address that is not
1303                    *  connected nor attached i.e. it is not from an
1304                    *  address that is covered by a link's sub-net,
1305                    *  nor is it a already learned host resp.
1306                    */
1307                 }));
1308                 /* *INDENT-ON* */
1309
1310                 /*
1311                  * shorter mask lookup for the next iteration.
1312                  */
1313                 pfx = fib_entry_get_prefix (src_fei);
1314                 mask = pfx->fp_len - 1;
1315
1316                 /*
1317                  * continue until we hit the default route or we find
1318                  * the attached we are looking for. The most likely
1319                  * outcome is we find the attached with the first source
1320                  * on the first lookup.
1321                  */
1322               }
1323             while (!attached &&
1324                    !fib_entry_is_sourced (src_fei, FIB_SOURCE_DEFAULT_ROUTE));
1325
1326             if (!attached)
1327               {
1328                 /*
1329                  * the matching route is a not attached, i.e. it was
1330                  * added as a result of routing, rather than interface/ARP
1331                  * configuration. If the matching route is not a host route
1332                  * (i.e. a /32)
1333                  */
1334                 error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
1335                 goto drop;
1336               }
1337           }
1338
1339           dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1340                                           &arp0->ip4_over_ethernet[1].ip4,
1341                                           32);
1342           switch (arp_dst_fib_check (dst_fei, &dst_flags))
1343             {
1344             case ARP_DST_FIB_ADJ:
1345               /*
1346                * We matched an adj-fib on ths source subnet (a /32 previously
1347                * added as a result of ARP). If this request is a gratuitous
1348                * ARP, then learn from it.
1349                * The check for matching an adj-fib, is to prevent hosts
1350                * from spamming us with gratuitous ARPS that might otherwise
1351                * blow our ARP cache
1352                */
1353               if (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1354                   arp0->ip4_over_ethernet[1].ip4.as_u32)
1355                 error0 = arp_learn (vnm, am, sw_if_index0,
1356                                     &arp0->ip4_over_ethernet[0]);
1357               goto drop;
1358             case ARP_DST_FIB_CONN:
1359               /* destination is connected, continue to process */
1360               break;
1361             case ARP_DST_FIB_NONE:
1362               /* destination is not connected, stop here */
1363               error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
1364               goto next_feature;
1365             }
1366
1367           dst_is_local0 = (FIB_ENTRY_FLAG_LOCAL & dst_flags);
1368           pfx0 = fib_entry_get_prefix (dst_fei);
1369           if_addr0 = &pfx0->fp_addr.ip4;
1370
1371           is_vrrp_reply0 =
1372             ((arp0->opcode ==
1373               clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply))
1374              &&
1375              (!memcmp
1376               (arp0->ip4_over_ethernet[0].mac.bytes, vrrp_prefix,
1377                sizeof (vrrp_prefix))));
1378
1379           /* Trash ARP packets whose ARP-level source addresses do not
1380              match their L2-frame-level source addresses, unless it's
1381              a reply from a VRRP virtual router */
1382           if (!ethernet_mac_address_equal
1383               (eth_rx->src_address,
1384                arp0->ip4_over_ethernet[0].mac.bytes) && !is_vrrp_reply0)
1385             {
1386               error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1387               goto drop;
1388             }
1389
1390           /* Learn or update sender's mapping only for replies to addresses
1391            * that are local to the subnet */
1392           if (arp0->opcode ==
1393               clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply))
1394             {
1395               if (dst_is_local0)
1396                 error0 = arp_learn (vnm, am, sw_if_index0,
1397                                     &arp0->ip4_over_ethernet[0]);
1398               else
1399                 /* a reply for a non-local destination could be a GARP.
1400                  * GARPs for hosts we know were handled above, so this one
1401                  * we drop */
1402                 error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
1403
1404               goto next_feature;
1405             }
1406           else if (arp0->opcode ==
1407                    clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request) &&
1408                    (dst_is_local0 == 0))
1409             {
1410               goto next_feature;
1411             }
1412
1413           /* Honor unnumbered interface, if any */
1414           conn_sw_if_index0 = fib_entry_get_resolving_interface (dst_fei);
1415           if (sw_if_index0 != conn_sw_if_index0 ||
1416               sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
1417             {
1418               /*
1419                * The interface the ARP is sent to or was received on is not the
1420                * interface on which the covering prefix is configured.
1421                * Maybe this is a case for unnumbered.
1422                */
1423               if (!arp_unnumbered (p0, sw_if_index0, conn_sw_if_index0))
1424                 {
1425                   error0 = ETHERNET_ARP_ERROR_unnumbered_mismatch;
1426                   goto drop;
1427                 }
1428             }
1429           if (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1430               arp0->ip4_over_ethernet[1].ip4.as_u32)
1431             {
1432               error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1433               goto drop;
1434             }
1435
1436           next0 = arp_mk_reply (vnm, p0, sw_if_index0,
1437                                 if_addr0, arp0, eth_rx);
1438
1439           /* We are going to reply to this request, so, in the absence of
1440              errors, learn the sender */
1441           if (!error0)
1442             error0 = arp_learn (vnm, am, sw_if_index0,
1443                                 &arp0->ip4_over_ethernet[1]);
1444
1445           n_replies_sent += 1;
1446           goto enqueue;
1447
1448         next_feature:
1449           vnet_feature_next (&next0, p0);
1450           goto enqueue;
1451
1452         drop:
1453           p0->error = node->errors[error0];
1454
1455         enqueue:
1456           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1457                                            n_left_to_next, pi0, next0);
1458         }
1459
1460       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1461     }
1462
1463   vlib_error_count (vm, node->node_index,
1464                     ETHERNET_ARP_ERROR_replies_sent, n_replies_sent);
1465
1466   return frame->n_vectors;
1467 }
1468
1469 static uword
1470 arp_proxy (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
1471 {
1472   ethernet_arp_main_t *am = &ethernet_arp_main;
1473   vnet_main_t *vnm = vnet_get_main ();
1474   u32 n_left_from, next_index, *from, *to_next;
1475   u32 n_arp_replies_sent = 0;
1476
1477   from = vlib_frame_vector_args (frame);
1478   n_left_from = frame->n_vectors;
1479   next_index = node->cached_next_index;
1480
1481   if (node->flags & VLIB_NODE_FLAG_TRACE)
1482     vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
1483                                    /* stride */ 1,
1484                                    sizeof (ethernet_arp_input_trace_t));
1485
1486   while (n_left_from > 0)
1487     {
1488       u32 n_left_to_next;
1489
1490       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1491
1492       while (n_left_from > 0 && n_left_to_next > 0)
1493         {
1494           vlib_buffer_t *p0;
1495           ethernet_arp_header_t *arp0;
1496           ethernet_header_t *eth_rx;
1497           ip4_address_t proxy_src;
1498           u32 pi0, error0, next0, sw_if_index0, fib_index0;
1499           u8 is_request0;
1500           ethernet_proxy_arp_t *pa;
1501
1502           pi0 = from[0];
1503           to_next[0] = pi0;
1504           from += 1;
1505           to_next += 1;
1506           n_left_from -= 1;
1507           n_left_to_next -= 1;
1508
1509           p0 = vlib_get_buffer (vm, pi0);
1510           arp0 = vlib_buffer_get_current (p0);
1511           /* Fill in ethernet header. */
1512           eth_rx = ethernet_buffer_get_header (p0);
1513
1514           is_request0 = arp0->opcode
1515             == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
1516
1517           error0 = ETHERNET_ARP_ERROR_replies_sent;
1518           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1519           next0 = ARP_REPLY_NEXT_DROP;
1520
1521           fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
1522           if (~0 == fib_index0)
1523             {
1524               error0 = ETHERNET_ARP_ERROR_interface_no_table;
1525             }
1526
1527           if (0 == error0 && is_request0)
1528             {
1529               u32 this_addr = clib_net_to_host_u32
1530                 (arp0->ip4_over_ethernet[1].ip4.as_u32);
1531
1532               vec_foreach (pa, am->proxy_arps)
1533               {
1534                 u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr.as_u32);
1535                 u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr.as_u32);
1536
1537                 /* an ARP request hit in the proxy-arp table? */
1538                 if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1539                     (fib_index0 == pa->fib_index))
1540                   {
1541                     proxy_src.as_u32 =
1542                       arp0->ip4_over_ethernet[1].ip4.data_u32;
1543
1544                     /*
1545                      * change the interface address to the proxied
1546                      */
1547                     n_arp_replies_sent++;
1548
1549                     next0 =
1550                       arp_mk_reply (vnm, p0, sw_if_index0, &proxy_src, arp0,
1551                                     eth_rx);
1552                   }
1553               }
1554             }
1555           else
1556             {
1557               p0->error = node->errors[error0];
1558             }
1559
1560           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1561                                            n_left_to_next, pi0, next0);
1562         }
1563
1564       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1565     }
1566
1567   vlib_error_count (vm, node->node_index,
1568                     ETHERNET_ARP_ERROR_replies_sent, n_arp_replies_sent);
1569
1570   return frame->n_vectors;
1571 }
1572
1573 static char *ethernet_arp_error_strings[] = {
1574 #define _(sym,string) string,
1575   foreach_ethernet_arp_error
1576 #undef _
1577 };
1578
1579 /* *INDENT-OFF* */
1580
1581 /* Built-in ARP rx feature path definition */
1582 VNET_FEATURE_ARC_INIT (arp_feat, static) =
1583 {
1584   .arc_name = "arp",
1585   .start_nodes = VNET_FEATURES ("arp-input"),
1586   .last_in_arc = "error-drop",
1587   .arc_index_ptr = &ethernet_arp_main.feature_arc_index,
1588 };
1589
1590 VLIB_REGISTER_NODE (arp_input_node, static) =
1591 {
1592   .function = arp_input,
1593   .name = "arp-input",
1594   .vector_size = sizeof (u32),
1595   .n_errors = ETHERNET_ARP_N_ERROR,
1596   .error_strings = ethernet_arp_error_strings,
1597   .n_next_nodes = ARP_INPUT_N_NEXT,
1598   .next_nodes = {
1599     [ARP_INPUT_NEXT_DROP] = "error-drop",
1600   },
1601   .format_buffer = format_ethernet_arp_header,
1602   .format_trace = format_ethernet_arp_input_trace,
1603 };
1604
1605 VLIB_REGISTER_NODE (arp_reply_node, static) =
1606 {
1607   .function = arp_reply,
1608   .name = "arp-reply",
1609   .vector_size = sizeof (u32),
1610   .n_errors = ETHERNET_ARP_N_ERROR,
1611   .error_strings = ethernet_arp_error_strings,
1612   .n_next_nodes = ARP_REPLY_N_NEXT,
1613   .next_nodes = {
1614     [ARP_REPLY_NEXT_DROP] = "error-drop",
1615     [ARP_REPLY_NEXT_REPLY_TX] = "interface-output",
1616   },
1617   .format_buffer = format_ethernet_arp_header,
1618   .format_trace = format_ethernet_arp_input_trace,
1619 };
1620
1621 VLIB_REGISTER_NODE (arp_proxy_node, static) =
1622 {
1623   .function = arp_proxy,
1624   .name = "arp-proxy",
1625   .vector_size = sizeof (u32),
1626   .n_errors = ETHERNET_ARP_N_ERROR,
1627   .error_strings = ethernet_arp_error_strings,
1628   .n_next_nodes = ARP_REPLY_N_NEXT,
1629   .next_nodes = {
1630     [ARP_REPLY_NEXT_DROP] = "error-drop",
1631     [ARP_REPLY_NEXT_REPLY_TX] = "interface-output",
1632   },
1633   .format_buffer = format_ethernet_arp_header,
1634   .format_trace = format_ethernet_arp_input_trace,
1635 };
1636
1637 VNET_FEATURE_INIT (arp_reply_feat_node, static) =
1638 {
1639   .arc_name = "arp",
1640   .node_name = "arp-reply",
1641   .runs_before = VNET_FEATURES ("error-drop"),
1642 };
1643
1644 VNET_FEATURE_INIT (arp_proxy_feat_node, static) =
1645 {
1646   .arc_name = "arp",
1647   .node_name = "arp-proxy",
1648   .runs_after = VNET_FEATURES ("arp-reply"),
1649   .runs_before = VNET_FEATURES ("error-drop"),
1650 };
1651
1652 VNET_FEATURE_INIT (arp_drop_feat_node, static) =
1653 {
1654   .arc_name = "arp",
1655   .node_name = "error-drop",
1656 };
1657
1658 /* *INDENT-ON* */
1659
1660 static int
1661 ip4_arp_entry_sort (void *a1, void *a2)
1662 {
1663   ethernet_arp_ip4_entry_t *e1 = a1;
1664   ethernet_arp_ip4_entry_t *e2 = a2;
1665
1666   int cmp;
1667   vnet_main_t *vnm = vnet_get_main ();
1668
1669   cmp = vnet_sw_interface_compare (vnm, e1->sw_if_index, e2->sw_if_index);
1670   if (!cmp)
1671     cmp = ip4_address_compare (&e1->ip4_address, &e2->ip4_address);
1672   return cmp;
1673 }
1674
1675 ethernet_arp_ip4_entry_t *
1676 ip4_neighbors_pool (void)
1677 {
1678   ethernet_arp_main_t *am = &ethernet_arp_main;
1679   return am->ip4_entry_pool;
1680 }
1681
1682 ethernet_arp_ip4_entry_t *
1683 ip4_neighbor_entries (u32 sw_if_index)
1684 {
1685   ethernet_arp_main_t *am = &ethernet_arp_main;
1686   ethernet_arp_ip4_entry_t *n, *ns = 0;
1687
1688   /* *INDENT-OFF* */
1689   pool_foreach (n, am->ip4_entry_pool, ({
1690     if (sw_if_index != ~0 && n->sw_if_index != sw_if_index)
1691       continue;
1692     vec_add1 (ns, n[0]);
1693   }));
1694   /* *INDENT-ON* */
1695
1696   if (ns)
1697     vec_sort_with_function (ns, ip4_arp_entry_sort);
1698   return ns;
1699 }
1700
1701 static clib_error_t *
1702 show_ip4_arp (vlib_main_t * vm,
1703               unformat_input_t * input, vlib_cli_command_t * cmd)
1704 {
1705   vnet_main_t *vnm = vnet_get_main ();
1706   ethernet_arp_main_t *am = &ethernet_arp_main;
1707   ethernet_arp_ip4_entry_t *e, *es;
1708   ethernet_proxy_arp_t *pa;
1709   clib_error_t *error = 0;
1710   u32 sw_if_index;
1711
1712   /* Filter entries by interface if given. */
1713   sw_if_index = ~0;
1714   (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1715
1716   es = ip4_neighbor_entries (sw_if_index);
1717   if (es)
1718     {
1719       vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1720       vec_foreach (e, es)
1721       {
1722         vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1723       }
1724       vec_free (es);
1725     }
1726
1727   if (vec_len (am->proxy_arps))
1728     {
1729       vlib_cli_output (vm, "Proxy arps enabled for:");
1730       vec_foreach (pa, am->proxy_arps)
1731       {
1732         vlib_cli_output (vm, "Fib_index %d   %U - %U ",
1733                          pa->fib_index,
1734                          format_ip4_address, &pa->lo_addr,
1735                          format_ip4_address, &pa->hi_addr);
1736       }
1737     }
1738
1739   return error;
1740 }
1741
1742 /*?
1743  * Display all the IPv4 ARP entries.
1744  *
1745  * @cliexpar
1746  * Example of how to display the IPv4 ARP table:
1747  * @cliexstart{show ip arp}
1748  *    Time      FIB        IP4       Flags      Ethernet              Interface
1749  *    346.3028   0       6.1.1.3            de:ad:be:ef:ba:be   GigabitEthernet2/0/0
1750  *   3077.4271   0       6.1.1.4       S    de:ad:be:ef:ff:ff   GigabitEthernet2/0/0
1751  *   2998.6409   1       6.2.2.3            de:ad:be:ef:00:01   GigabitEthernet2/0/0
1752  * Proxy arps enabled for:
1753  * Fib_index 0   6.0.0.1 - 6.0.0.11
1754  * @cliexend
1755  ?*/
1756 /* *INDENT-OFF* */
1757 VLIB_CLI_COMMAND (show_ip4_arp_command, static) = {
1758   .path = "show ip arp",
1759   .function = show_ip4_arp,
1760   .short_help = "show ip arp",
1761 };
1762 /* *INDENT-ON* */
1763
1764 typedef struct
1765 {
1766   pg_edit_t l2_type, l3_type;
1767   pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1768   pg_edit_t opcode;
1769   struct
1770   {
1771     pg_edit_t mac;
1772     pg_edit_t ip4;
1773   } ip4_over_ethernet[2];
1774 } pg_ethernet_arp_header_t;
1775
1776 static inline void
1777 pg_ethernet_arp_header_init (pg_ethernet_arp_header_t * p)
1778 {
1779   /* Initialize fields that are not bit fields in the IP header. */
1780 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1781   _(l2_type);
1782   _(l3_type);
1783   _(n_l2_address_bytes);
1784   _(n_l3_address_bytes);
1785   _(opcode);
1786   _(ip4_over_ethernet[0].mac);
1787   _(ip4_over_ethernet[0].ip4);
1788   _(ip4_over_ethernet[1].mac);
1789   _(ip4_over_ethernet[1].ip4);
1790 #undef _
1791 }
1792
1793 uword
1794 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1795 {
1796   pg_stream_t *s = va_arg (*args, pg_stream_t *);
1797   pg_ethernet_arp_header_t *p;
1798   u32 group_index;
1799
1800   p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1801                             &group_index);
1802   pg_ethernet_arp_header_init (p);
1803
1804   /* Defaults. */
1805   pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1806   pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1807   pg_edit_set_fixed (&p->n_l2_address_bytes, 6);
1808   pg_edit_set_fixed (&p->n_l3_address_bytes, 4);
1809
1810   if (!unformat (input, "%U: %U/%U -> %U/%U",
1811                  unformat_pg_edit,
1812                  unformat_ethernet_arp_opcode_net_byte_order, &p->opcode,
1813                  unformat_pg_edit,
1814                  unformat_mac_address_t, &p->ip4_over_ethernet[0].mac,
1815                  unformat_pg_edit,
1816                  unformat_ip4_address, &p->ip4_over_ethernet[0].ip4,
1817                  unformat_pg_edit,
1818                  unformat_mac_address_t, &p->ip4_over_ethernet[1].mac,
1819                  unformat_pg_edit,
1820                  unformat_ip4_address, &p->ip4_over_ethernet[1].ip4))
1821     {
1822       /* Free up any edits we may have added. */
1823       pg_free_edit_group (s);
1824       return 0;
1825     }
1826   return 1;
1827 }
1828
1829 clib_error_t *
1830 ip4_set_arp_limit (u32 arp_limit)
1831 {
1832   ethernet_arp_main_t *am = &ethernet_arp_main;
1833
1834   am->limit_arp_cache_size = arp_limit;
1835   return 0;
1836 }
1837
1838 /**
1839  * @brief Control Plane hook to remove an ARP entry
1840  */
1841 int
1842 vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
1843                                   u32 sw_if_index,
1844                                   const
1845                                   ethernet_arp_ip4_over_ethernet_address_t *
1846                                   a)
1847 {
1848   vnet_arp_set_ip4_over_ethernet_rpc_args_t args = {
1849     .sw_if_index = sw_if_index,
1850     .flags = ETHERNET_ARP_ARGS_REMOVE,
1851     .ip4 = a->ip4,
1852     .mac = a->mac,
1853   };
1854
1855   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1856                                (u8 *) & args, sizeof (args));
1857   return 0;
1858 }
1859
1860 /**
1861  * @brief publish wildcard arp event
1862  * @param sw_if_index The interface on which the ARP entries are acted
1863  */
1864 static int
1865 vnet_arp_wc_publish (u32 sw_if_index,
1866                      const ethernet_arp_ip4_over_ethernet_address_t * a)
1867 {
1868   vnet_arp_set_ip4_over_ethernet_rpc_args_t args = {
1869     .flags = ETHERNET_ARP_ARGS_WC_PUB,
1870     .sw_if_index = sw_if_index,
1871     .ip4 = a->ip4,
1872     .mac = a->mac,
1873   };
1874
1875   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1876                                (u8 *) & args, sizeof (args));
1877   return 0;
1878 }
1879
1880 static void
1881 vnet_arp_wc_publish_internal (vnet_main_t * vnm,
1882                               vnet_arp_set_ip4_over_ethernet_rpc_args_t *
1883                               args)
1884 {
1885   vlib_main_t *vm = vlib_get_main ();
1886   ethernet_arp_main_t *am = &ethernet_arp_main;
1887   uword ni = am->wc_ip4_arp_publisher_node;
1888   uword et = am->wc_ip4_arp_publisher_et;
1889
1890   if (ni == (uword) ~ 0)
1891     return;
1892   wc_arp_report_t *r =
1893     vlib_process_signal_event_data (vm, ni, et, 1, sizeof *r);
1894   r->ip.as_u32 = args->ip4.as_u32;
1895   r->sw_if_index = args->sw_if_index;
1896   mac_address_copy (&r->mac, &args->mac);
1897 }
1898
1899 void
1900 wc_arp_set_publisher_node (uword node_index, uword event_type)
1901 {
1902   ethernet_arp_main_t *am = &ethernet_arp_main;
1903   am->wc_ip4_arp_publisher_node = node_index;
1904   am->wc_ip4_arp_publisher_et = event_type;
1905 }
1906
1907 static void
1908 arp_entry_free (ethernet_arp_interface_t * eai, ethernet_arp_ip4_entry_t * e);
1909
1910 static int
1911 vnet_arp_flush_ip4_over_ethernet_internal (vnet_main_t * vnm,
1912                                            vnet_arp_set_ip4_over_ethernet_rpc_args_t
1913                                            * args)
1914 {
1915   ethernet_arp_main_t *am = &ethernet_arp_main;
1916   ethernet_arp_ip4_entry_t *e;
1917   ethernet_arp_interface_t *eai;
1918
1919   if (vec_len (am->ethernet_arp_by_sw_if_index) <= args->sw_if_index)
1920     return 0;
1921
1922   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1923
1924   e = arp_entry_find (eai, &args->ip4);
1925
1926   if (NULL != e)
1927     {
1928       adj_nbr_walk_nh4 (e->sw_if_index,
1929                         &e->ip4_address, arp_mk_incomplete_walk, e);
1930
1931       /*
1932        * The difference between flush and unset, is that an unset
1933        * means delete for static and dynamic entries. A flush
1934        * means delete only for dynamic. Flushing is what the DP
1935        * does in response to interface events. unset is only done
1936        * by the control plane.
1937        */
1938       if (e->flags & IP_NEIGHBOR_FLAG_STATIC)
1939         {
1940           e->flags &= ~IP_NEIGHBOR_FLAG_DYNAMIC;
1941         }
1942       else if (e->flags & IP_NEIGHBOR_FLAG_DYNAMIC)
1943         {
1944           arp_entry_free (eai, e);
1945         }
1946     }
1947   return (0);
1948 }
1949
1950 /*
1951  * arp_add_del_interface_address
1952  *
1953  * callback when an interface address is added or deleted
1954  */
1955 static void
1956 arp_enable_disable_interface (ip4_main_t * im,
1957                               uword opaque, u32 sw_if_index, u32 is_enable)
1958 {
1959   ethernet_arp_main_t *am = &ethernet_arp_main;
1960
1961   if (is_enable)
1962     arp_enable (am, sw_if_index);
1963   else
1964     arp_disable (am, sw_if_index);
1965 }
1966
1967 /*
1968  * arp_add_del_interface_address
1969  *
1970  * callback when an interface address is added or deleted
1971  */
1972 static void
1973 arp_add_del_interface_address (ip4_main_t * im,
1974                                uword opaque,
1975                                u32 sw_if_index,
1976                                ip4_address_t * address,
1977                                u32 address_length,
1978                                u32 if_address_index, u32 is_del)
1979 {
1980   /*
1981    * Flush the ARP cache of all entries covered by the address
1982    * that is being removed.
1983    */
1984   ethernet_arp_main_t *am = &ethernet_arp_main;
1985   ethernet_arp_ip4_entry_t *e;
1986
1987   if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
1988     return;
1989
1990   if (is_del)
1991     {
1992       ethernet_arp_interface_t *eai;
1993       u32 i, *to_delete = 0;
1994       hash_pair_t *pair;
1995
1996       eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
1997
1998       /* *INDENT-OFF* */
1999       hash_foreach_pair (pair, eai->arp_entries,
2000       ({
2001         e = pool_elt_at_index(am->ip4_entry_pool,
2002                               pair->value[0]);
2003         if (ip4_destination_matches_route (im, &e->ip4_address,
2004                                            address, address_length))
2005           {
2006             vec_add1 (to_delete, e - am->ip4_entry_pool);
2007           }
2008       }));
2009       /* *INDENT-ON* */
2010
2011       for (i = 0; i < vec_len (to_delete); i++)
2012         {
2013           e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
2014
2015           vnet_arp_set_ip4_over_ethernet_rpc_args_t delme = {
2016             .ip4.as_u32 = e->ip4_address.as_u32,
2017             .sw_if_index = e->sw_if_index,
2018             .flags = ETHERNET_ARP_ARGS_FLUSH,
2019           };
2020           mac_address_copy (&delme.mac, &e->mac);
2021
2022           vnet_arp_flush_ip4_over_ethernet_internal (vnet_get_main (),
2023                                                      &delme);
2024         }
2025
2026       vec_free (to_delete);
2027     }
2028 }
2029
2030 static void
2031 arp_table_bind (ip4_main_t * im,
2032                 uword opaque,
2033                 u32 sw_if_index, u32 new_fib_index, u32 old_fib_index)
2034 {
2035   ethernet_arp_main_t *am = &ethernet_arp_main;
2036   ethernet_arp_interface_t *eai;
2037   ethernet_arp_ip4_entry_t *e;
2038   hash_pair_t *pair;
2039
2040   /*
2041    * the IP table that the interface is bound to has changed.
2042    * reinstall all the adj fibs.
2043    */
2044
2045   if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
2046     return;
2047
2048   eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
2049
2050   /* *INDENT-OFF* */
2051   hash_foreach_pair (pair, eai->arp_entries,
2052   ({
2053     e = pool_elt_at_index(am->ip4_entry_pool,
2054                           pair->value[0]);
2055     /*
2056      * remove the adj-fib from the old table and add to the new
2057      */
2058     arp_adj_fib_remove(e, old_fib_index);
2059     arp_adj_fib_add(e, new_fib_index);
2060   }));
2061   /* *INDENT-ON* */
2062
2063 }
2064
2065 static clib_error_t *
2066 ethernet_arp_init (vlib_main_t * vm)
2067 {
2068   ethernet_arp_main_t *am = &ethernet_arp_main;
2069   ip4_main_t *im = &ip4_main;
2070   pg_node_t *pn;
2071
2072   ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
2073
2074   pn = pg_get_node (arp_input_node.index);
2075   pn->unformat_edit = unformat_pg_arp_header;
2076
2077   am->opcode_by_name = hash_create_string (0, sizeof (uword));
2078 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
2079   foreach_ethernet_arp_opcode;
2080 #undef _
2081
2082   /* $$$ configurable */
2083   am->limit_arp_cache_size = 50000;
2084
2085   am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
2086   am->mac_changes_by_address = hash_create (0, sizeof (uword));
2087   am->wc_ip4_arp_publisher_node = (uword) ~ 0;
2088
2089   /* don't trace ARP error packets */
2090   {
2091     vlib_node_runtime_t *rt =
2092       vlib_node_get_runtime (vm, arp_input_node.index);
2093
2094 #define _(a,b)                                  \
2095     vnet_pcap_drop_trace_filter_add_del         \
2096         (rt->errors[ETHERNET_ARP_ERROR_##a],    \
2097          1 /* is_add */);
2098     foreach_ethernet_arp_error
2099 #undef _
2100   }
2101
2102   ip4_add_del_interface_address_callback_t cb;
2103   cb.function = arp_add_del_interface_address;
2104   cb.function_opaque = 0;
2105   vec_add1 (im->add_del_interface_address_callbacks, cb);
2106
2107   ip4_enable_disable_interface_callback_t cbe;
2108   cbe.function = arp_enable_disable_interface;
2109   cbe.function_opaque = 0;
2110   vec_add1 (im->enable_disable_interface_callbacks, cbe);
2111
2112   ip4_table_bind_callback_t cbt;
2113   cbt.function = arp_table_bind;
2114   cbt.function_opaque = 0;
2115   vec_add1 (im->table_bind_callbacks, cbt);
2116
2117   return 0;
2118 }
2119 /* *INDENT-OFF* */
2120 VLIB_INIT_FUNCTION (ethernet_arp_init) =
2121 {
2122   .runs_after = VLIB_INITS("ethernet_init"),
2123 };
2124 /* *INDENT-ON* */
2125
2126 static void
2127 arp_entry_free (ethernet_arp_interface_t * eai, ethernet_arp_ip4_entry_t * e)
2128 {
2129   ethernet_arp_main_t *am = &ethernet_arp_main;
2130
2131   arp_adj_fib_remove
2132     (e, ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index));
2133   hash_unset (eai->arp_entries, e->ip4_address.as_u32);
2134   pool_put (am->ip4_entry_pool, e);
2135 }
2136
2137 static inline int
2138 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
2139                                            vnet_arp_set_ip4_over_ethernet_rpc_args_t
2140                                            * args)
2141 {
2142   ethernet_arp_main_t *am = &ethernet_arp_main;
2143   ethernet_arp_ip4_entry_t *e;
2144   ethernet_arp_interface_t *eai;
2145
2146   if (vec_len (am->ethernet_arp_by_sw_if_index) <= args->sw_if_index)
2147     return 0;
2148
2149   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
2150
2151   e = arp_entry_find (eai, &args->ip4);
2152
2153   if (NULL != e)
2154     {
2155       adj_nbr_walk_nh4 (e->sw_if_index,
2156                         &e->ip4_address, arp_mk_incomplete_walk, e);
2157       arp_entry_free (eai, e);
2158     }
2159
2160   return 0;
2161 }
2162
2163
2164 static int
2165 vnet_arp_populate_ip4_over_ethernet_internal (vnet_main_t * vnm,
2166                                               vnet_arp_set_ip4_over_ethernet_rpc_args_t
2167                                               * args)
2168 {
2169   ethernet_arp_main_t *am = &ethernet_arp_main;
2170   ethernet_arp_ip4_entry_t *e;
2171   ethernet_arp_interface_t *eai;
2172
2173   arp_enable (am, args->sw_if_index);
2174   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
2175
2176   e = arp_entry_find (eai, &args->ip4);
2177
2178   if (NULL != e)
2179     {
2180       adj_nbr_walk_nh4 (e->sw_if_index,
2181                         &e->ip4_address, arp_mk_complete_walk, e);
2182     }
2183   return (0);
2184 }
2185
2186 static void
2187 set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t
2188                                     * a)
2189 {
2190   vnet_main_t *vm = vnet_get_main ();
2191   ASSERT (vlib_get_thread_index () == 0);
2192
2193   if (a->flags & ETHERNET_ARP_ARGS_REMOVE)
2194     vnet_arp_unset_ip4_over_ethernet_internal (vm, a);
2195   else if (a->flags & ETHERNET_ARP_ARGS_FLUSH)
2196     vnet_arp_flush_ip4_over_ethernet_internal (vm, a);
2197   else if (a->flags & ETHERNET_ARP_ARGS_POPULATE)
2198     vnet_arp_populate_ip4_over_ethernet_internal (vm, a);
2199   else if (a->flags & ETHERNET_ARP_ARGS_WC_PUB)
2200     vnet_arp_wc_publish_internal (vm, a);
2201   else
2202     vnet_arp_set_ip4_over_ethernet_internal (vm, a);
2203 }
2204
2205 /**
2206  * @brief Invoked when the interface's admin state changes
2207  */
2208 static clib_error_t *
2209 ethernet_arp_sw_interface_up_down (vnet_main_t * vnm,
2210                                    u32 sw_if_index, u32 flags)
2211 {
2212   ethernet_arp_main_t *am = &ethernet_arp_main;
2213   ethernet_arp_ip4_entry_t *e;
2214   u32 i, *to_update = 0;
2215
2216   /* *INDENT-OFF* */
2217   pool_foreach (e, am->ip4_entry_pool,
2218   ({
2219     if (e->sw_if_index == sw_if_index)
2220       vec_add1 (to_update,
2221                 e - am->ip4_entry_pool);
2222   }));
2223   /* *INDENT-ON* */
2224
2225   for (i = 0; i < vec_len (to_update); i++)
2226     {
2227       e = pool_elt_at_index (am->ip4_entry_pool, to_update[i]);
2228
2229       vnet_arp_set_ip4_over_ethernet_rpc_args_t update_me = {
2230         .ip4.as_u32 = e->ip4_address.as_u32,
2231         .sw_if_index = e->sw_if_index,
2232       };
2233       mac_address_copy (&update_me.mac, &e->mac);
2234
2235       if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
2236         {
2237           update_me.flags = ETHERNET_ARP_ARGS_POPULATE;
2238           vnet_arp_populate_ip4_over_ethernet_internal (vnm, &update_me);
2239         }
2240       else
2241         {
2242           update_me.flags = ETHERNET_ARP_ARGS_FLUSH;
2243           vnet_arp_flush_ip4_over_ethernet_internal (vnm, &update_me);
2244         }
2245     }
2246   vec_free (to_update);
2247
2248   return 0;
2249 }
2250
2251 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_arp_sw_interface_up_down);
2252
2253 static void
2254 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t * a)
2255 {
2256   u8 old;
2257   int i;
2258
2259   for (i = 3; i >= 0; i--)
2260     {
2261       old = a->ip4.as_u8[i];
2262       a->ip4.as_u8[i] += 1;
2263       if (old < a->ip4.as_u8[i])
2264         break;
2265     }
2266
2267   for (i = 5; i >= 0; i--)
2268     {
2269       old = a->mac.bytes[i];
2270       a->mac.bytes[i] += 1;
2271       if (old < a->mac.bytes[i])
2272         break;
2273     }
2274 }
2275
2276 int
2277 vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
2278                                 u32 sw_if_index,
2279                                 const ethernet_arp_ip4_over_ethernet_address_t
2280                                 * a, ip_neighbor_flags_t flags)
2281 {
2282   vnet_arp_set_ip4_over_ethernet_rpc_args_t args = {
2283     .sw_if_index = sw_if_index,
2284     .nbr_flags = flags,
2285     .flags = 0,
2286     .ip4.as_u32 = a->ip4.as_u32,
2287     .mac = a->mac,
2288   };
2289
2290   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
2291                                (u8 *) & args, sizeof (args));
2292   return 0;
2293 }
2294
2295 void
2296 proxy_arp_walk (proxy_arp_walk_t cb, void *data)
2297 {
2298   ethernet_arp_main_t *am = &ethernet_arp_main;
2299   ethernet_proxy_arp_t *pa;
2300
2301   vec_foreach (pa, am->proxy_arps)
2302   {
2303     if (!cb (&pa->lo_addr, &pa->hi_addr, pa->fib_index, data))
2304       break;
2305   }
2306 }
2307
2308 int
2309 vnet_proxy_arp_enable_disable (vnet_main_t * vnm, u32 sw_if_index, u8 enable)
2310 {
2311   ethernet_arp_main_t *am = &ethernet_arp_main;
2312   ethernet_arp_interface_t *eai;
2313
2314   vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index);
2315
2316   eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
2317
2318   if (enable)
2319     {
2320       if (!eai->proxy_enabled)
2321         {
2322           vnet_feature_enable_disable ("arp", "arp-proxy",
2323                                        sw_if_index, 1, NULL, 0);
2324         }
2325       eai->proxy_enabled = 1;
2326     }
2327   else
2328     {
2329       if (eai->proxy_enabled)
2330         {
2331           vnet_feature_enable_disable ("arp", "arp-proxy",
2332                                        sw_if_index, 0, NULL, 0);
2333         }
2334       eai->proxy_enabled = 0;
2335     }
2336
2337   return (0);
2338 }
2339
2340 int
2341 vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
2342                         ip4_address_t * hi_addr, u32 fib_index, int is_del)
2343 {
2344   ethernet_arp_main_t *am = &ethernet_arp_main;
2345   ethernet_proxy_arp_t *pa;
2346   u32 found_at_index = ~0;
2347
2348   vec_foreach (pa, am->proxy_arps)
2349   {
2350     if (pa->lo_addr.as_u32 == lo_addr->as_u32 &&
2351         pa->hi_addr.as_u32 == hi_addr->as_u32 && pa->fib_index == fib_index)
2352       {
2353         found_at_index = pa - am->proxy_arps;
2354         break;
2355       }
2356   }
2357
2358   if (found_at_index != ~0)
2359     {
2360       /* Delete, otherwise it's already in the table */
2361       if (is_del)
2362         vec_delete (am->proxy_arps, 1, found_at_index);
2363       return 0;
2364     }
2365   /* delete, no such entry */
2366   if (is_del)
2367     return VNET_API_ERROR_NO_SUCH_ENTRY;
2368
2369   /* add, not in table */
2370   vec_add2 (am->proxy_arps, pa, 1);
2371   pa->lo_addr.as_u32 = lo_addr->as_u32;
2372   pa->hi_addr.as_u32 = hi_addr->as_u32;
2373   pa->fib_index = fib_index;
2374   return 0;
2375 }
2376
2377 void
2378 proxy_arp_intfc_walk (proxy_arp_intf_walk_t cb, void *data)
2379 {
2380   ethernet_arp_main_t *am = &ethernet_arp_main;
2381   ethernet_arp_interface_t *eai;
2382
2383   vec_foreach (eai, am->ethernet_arp_by_sw_if_index)
2384   {
2385     if (eai->proxy_enabled)
2386       cb (eai - am->ethernet_arp_by_sw_if_index, data);
2387   }
2388 }
2389
2390 /*
2391  * Remove any proxy arp entries associated with the
2392  * specified fib.
2393  */
2394 int
2395 vnet_proxy_arp_fib_reset (u32 fib_id)
2396 {
2397   ethernet_arp_main_t *am = &ethernet_arp_main;
2398   ethernet_proxy_arp_t *pa;
2399   u32 *entries_to_delete = 0;
2400   u32 fib_index;
2401   int i;
2402
2403   fib_index = fib_table_find (FIB_PROTOCOL_IP4, fib_id);
2404   if (~0 == fib_index)
2405     return VNET_API_ERROR_NO_SUCH_ENTRY;
2406
2407   vec_foreach (pa, am->proxy_arps)
2408   {
2409     if (pa->fib_index == fib_index)
2410       {
2411         vec_add1 (entries_to_delete, pa - am->proxy_arps);
2412       }
2413   }
2414
2415   for (i = 0; i < vec_len (entries_to_delete); i++)
2416     {
2417       vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
2418     }
2419
2420   vec_free (entries_to_delete);
2421
2422   return 0;
2423 }
2424
2425 static clib_error_t *
2426 ip_arp_add_del_command_fn (vlib_main_t * vm,
2427                            unformat_input_t * input, vlib_cli_command_t * cmd)
2428 {
2429   vnet_main_t *vnm = vnet_get_main ();
2430   u32 sw_if_index;
2431   ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
2432   int addr_valid = 0;
2433   int is_del = 0;
2434   int count = 1;
2435   u32 fib_index = 0;
2436   u32 fib_id;
2437   int is_proxy = 0;
2438   ip_neighbor_flags_t flags;
2439
2440   flags = IP_NEIGHBOR_FLAG_NONE;
2441
2442   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2443     {
2444       /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
2445       if (unformat (input, "%U %U %U",
2446                     unformat_vnet_sw_interface, vnm, &sw_if_index,
2447                     unformat_ip4_address, &addr.ip4,
2448                     unformat_mac_address_t, &addr.mac))
2449         addr_valid = 1;
2450
2451       else if (unformat (input, "delete") || unformat (input, "del"))
2452         is_del = 1;
2453
2454       else if (unformat (input, "static"))
2455         flags |= IP_NEIGHBOR_FLAG_STATIC;
2456
2457       else if (unformat (input, "no-fib-entry"))
2458         flags |= IP_NEIGHBOR_FLAG_NO_FIB_ENTRY;
2459
2460       else if (unformat (input, "count %d", &count))
2461         ;
2462
2463       else if (unformat (input, "fib-id %d", &fib_id))
2464         {
2465           fib_index = fib_table_find (FIB_PROTOCOL_IP4, fib_id);
2466
2467           if (~0 == fib_index)
2468             return clib_error_return (0, "fib ID %d doesn't exist\n", fib_id);
2469         }
2470
2471       else if (unformat (input, "proxy %U - %U",
2472                          unformat_ip4_address, &lo_addr.ip4,
2473                          unformat_ip4_address, &hi_addr.ip4))
2474         is_proxy = 1;
2475       else
2476         break;
2477     }
2478
2479   if (is_proxy)
2480     {
2481       (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4,
2482                                      fib_index, is_del);
2483       return 0;
2484     }
2485
2486   if (addr_valid)
2487     {
2488       int i;
2489
2490       for (i = 0; i < count; i++)
2491         {
2492           if (is_del == 0)
2493             {
2494               uword event_type, *event_data = 0;
2495
2496               /* Park the debug CLI until the arp entry is installed */
2497               vnet_register_ip4_arp_resolution_event
2498                 (vnm, &addr.ip4, vlib_current_process (vm),
2499                  1 /* type */ , 0 /* data */ );
2500
2501               vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index, &addr, flags);
2502
2503               vlib_process_wait_for_event (vm);
2504               event_type = vlib_process_get_events (vm, &event_data);
2505               vec_reset_length (event_data);
2506               if (event_type != 1)
2507                 clib_warning ("event type %d unexpected", event_type);
2508             }
2509           else
2510             vnet_arp_unset_ip4_over_ethernet (vnm, sw_if_index, &addr);
2511
2512           increment_ip4_and_mac_address (&addr);
2513         }
2514     }
2515   else
2516     {
2517       return clib_error_return (0, "unknown input `%U'",
2518                                 format_unformat_error, input);
2519     }
2520
2521   return 0;
2522 }
2523
2524 /* *INDENT-OFF* */
2525 /*?
2526  * Add or delete IPv4 ARP cache entries.
2527  *
2528  * @note 'set ip arp' options (e.g. delete, static, 'fib-id <id>',
2529  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
2530  * any order and combination.
2531  *
2532  * @cliexpar
2533  * @parblock
2534  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
2535  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
2536  * @cliexcmd{set ip arp GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2537  * @cliexcmd{set ip arp delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
2538  *
2539  * To add or delete an IPv4 ARP cache entry to or from a specific fib
2540  * table:
2541  * @cliexcmd{set ip arp fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2542  * @cliexcmd{set ip arp fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2543  *
2544  * Add or delete IPv4 static ARP cache entries as follows:
2545  * @cliexcmd{set ip arp static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2546  * @cliexcmd{set ip arp static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2547  *
2548  * For testing / debugging purposes, the 'set ip arp' command can add or
2549  * delete multiple entries. Supply the 'count N' parameter:
2550  * @cliexcmd{set ip arp count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2551  * @endparblock
2552  ?*/
2553 VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = {
2554   .path = "set ip arp",
2555   .short_help =
2556   "set ip arp [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
2557   .function = ip_arp_add_del_command_fn,
2558 };
2559 /* *INDENT-ON* */
2560
2561 static clib_error_t *
2562 set_int_proxy_arp_command_fn (vlib_main_t * vm,
2563                               unformat_input_t *
2564                               input, vlib_cli_command_t * cmd)
2565 {
2566   vnet_main_t *vnm = vnet_get_main ();
2567   u32 sw_if_index;
2568   int enable = 0;
2569
2570   sw_if_index = ~0;
2571
2572   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2573     {
2574       if (unformat (input, "%U", unformat_vnet_sw_interface,
2575                     vnm, &sw_if_index))
2576         ;
2577       else if (unformat (input, "enable") || unformat (input, "on"))
2578         enable = 1;
2579       else if (unformat (input, "disable") || unformat (input, "off"))
2580         enable = 0;
2581       else
2582         break;
2583     }
2584
2585   if (~0 == sw_if_index)
2586     return clib_error_return (0, "unknown input '%U'",
2587                               format_unformat_error, input);
2588
2589   vnet_proxy_arp_enable_disable (vnm, sw_if_index, enable);
2590
2591   return 0;
2592 }
2593
2594 /* *INDENT-OFF* */
2595 /*?
2596  * Enable proxy-arp on an interface. The vpp stack will answer ARP
2597  * requests for the indicated address range. Multiple proxy-arp
2598  * ranges may be provisioned.
2599  *
2600  * @note Proxy ARP as a technology is infamous for blackholing traffic.
2601  * Also, the underlying implementation has not been performance-tuned.
2602  * Avoid creating an unnecessarily large set of ranges.
2603  *
2604  * @cliexpar
2605  * To enable proxy arp on a range of addresses, use:
2606  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11}
2607  * Append 'del' to delete a range of proxy ARP addresses:
2608  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11 del}
2609  * You must then specifically enable proxy arp on individual interfaces:
2610  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 enable}
2611  * To disable proxy arp on an individual interface:
2612  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 disable}
2613  ?*/
2614 VLIB_CLI_COMMAND (set_int_proxy_enable_command, static) = {
2615   .path = "set interface proxy-arp",
2616   .short_help =
2617   "set interface proxy-arp <intfc> [enable|disable]",
2618   .function = set_int_proxy_arp_command_fn,
2619 };
2620 /* *INDENT-ON* */
2621
2622
2623 /*
2624  * ARP/ND Termination in a L2 Bridge Domain based on IP4/IP6 to MAC
2625  * hash tables mac_by_ip4 and mac_by_ip6 for each BD.
2626  */
2627 typedef enum
2628 {
2629   ARP_TERM_NEXT_L2_OUTPUT,
2630   ARP_TERM_NEXT_DROP,
2631   ARP_TERM_N_NEXT,
2632 } arp_term_next_t;
2633
2634 u32 arp_term_next_node_index[32];
2635
2636 static uword
2637 arp_term_l2bd (vlib_main_t * vm,
2638                vlib_node_runtime_t * node, vlib_frame_t * frame)
2639 {
2640   l2input_main_t *l2im = &l2input_main;
2641   u32 n_left_from, next_index, *from, *to_next;
2642   u32 n_replies_sent = 0;
2643   u16 last_bd_index = ~0;
2644   l2_bridge_domain_t *last_bd_config = 0;
2645   l2_input_config_t *cfg0;
2646
2647   from = vlib_frame_vector_args (frame);
2648   n_left_from = frame->n_vectors;
2649   next_index = node->cached_next_index;
2650
2651   while (n_left_from > 0)
2652     {
2653       u32 n_left_to_next;
2654
2655       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2656
2657       while (n_left_from > 0 && n_left_to_next > 0)
2658         {
2659           vlib_buffer_t *p0;
2660           ethernet_header_t *eth0;
2661           ethernet_arp_header_t *arp0;
2662           ip6_header_t *iph0;
2663           u8 *l3h0;
2664           u32 pi0, error0, next0, sw_if_index0;
2665           u16 ethertype0;
2666           u16 bd_index0;
2667           u32 ip0;
2668           u8 *macp0;
2669
2670           pi0 = from[0];
2671           to_next[0] = pi0;
2672           from += 1;
2673           to_next += 1;
2674           n_left_from -= 1;
2675           n_left_to_next -= 1;
2676
2677           p0 = vlib_get_buffer (vm, pi0);
2678           // Terminate only local (SHG == 0) ARP
2679           if (vnet_buffer (p0)->l2.shg != 0)
2680             goto next_l2_feature;
2681
2682           eth0 = vlib_buffer_get_current (p0);
2683           l3h0 = (u8 *) eth0 + vnet_buffer (p0)->l2.l2_len;
2684           ethertype0 = clib_net_to_host_u16 (*(u16 *) (l3h0 - 2));
2685           arp0 = (ethernet_arp_header_t *) l3h0;
2686
2687           if (ethertype0 != ETHERNET_TYPE_ARP)
2688             goto check_ip6_nd;
2689
2690           if ((arp0->opcode !=
2691                clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request)) &&
2692               (arp0->opcode !=
2693                clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply)))
2694             goto check_ip6_nd;
2695
2696           /* Must be ARP request/reply packet here */
2697           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
2698                              (p0->flags & VLIB_BUFFER_IS_TRACED)))
2699             {
2700               u8 *t0 = vlib_add_trace (vm, node, p0,
2701                                        sizeof (ethernet_arp_input_trace_t));
2702               clib_memcpy_fast (t0, l3h0,
2703                                 sizeof (ethernet_arp_input_trace_t));
2704             }
2705
2706           error0 = 0;
2707           error0 =
2708             (arp0->l2_type !=
2709              clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
2710              ? ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
2711           error0 =
2712             (arp0->l3_type !=
2713              clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
2714              ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
2715
2716           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2717
2718           if (error0)
2719             goto drop;
2720
2721           /* Trash ARP packets whose ARP-level source addresses do not
2722              match, or if requester address is mcast */
2723           if (PREDICT_FALSE
2724               (!ethernet_mac_address_equal (eth0->src_address,
2725                                             arp0->ip4_over_ethernet[0].
2726                                             mac.bytes))
2727               || ethernet_address_cast (arp0->ip4_over_ethernet[0].mac.bytes))
2728             {
2729               /* VRRP virtual MAC may be different to SMAC in ARP reply */
2730               if (!ethernet_mac_address_equal
2731                   (arp0->ip4_over_ethernet[0].mac.bytes, vrrp_prefix))
2732                 {
2733                   error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
2734                   goto drop;
2735                 }
2736             }
2737           if (PREDICT_FALSE
2738               (ip4_address_is_multicast (&arp0->ip4_over_ethernet[0].ip4)))
2739             {
2740               error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
2741               goto drop;
2742             }
2743
2744           /* Check if anyone want ARP request events for L2 BDs */
2745           {
2746             ethernet_arp_main_t *am = &ethernet_arp_main;
2747             if (am->wc_ip4_arp_publisher_node != (uword) ~ 0)
2748               vnet_arp_wc_publish (sw_if_index0, &arp0->ip4_over_ethernet[0]);
2749           }
2750
2751           /* lookup BD mac_by_ip4 hash table for MAC entry */
2752           ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
2753           bd_index0 = vnet_buffer (p0)->l2.bd_index;
2754           if (PREDICT_FALSE ((bd_index0 != last_bd_index)
2755                              || (last_bd_index == (u16) ~ 0)))
2756             {
2757               last_bd_index = bd_index0;
2758               last_bd_config = vec_elt_at_index (l2im->bd_configs, bd_index0);
2759             }
2760           macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
2761
2762           if (PREDICT_FALSE (!macp0))
2763             goto next_l2_feature;       /* MAC not found */
2764           if (PREDICT_FALSE (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
2765                              arp0->ip4_over_ethernet[1].ip4.as_u32))
2766             goto next_l2_feature;       /* GARP */
2767
2768           /* MAC found, send ARP reply -
2769              Convert ARP request packet to ARP reply */
2770           arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
2771           arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
2772           arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
2773           mac_address_from_bytes (&arp0->ip4_over_ethernet[0].mac, macp0);
2774           clib_memcpy_fast (eth0->dst_address, eth0->src_address, 6);
2775           clib_memcpy_fast (eth0->src_address, macp0, 6);
2776           n_replies_sent += 1;
2777
2778         output_response:
2779           /* For BVI, need to use l2-fwd node to send ARP reply as
2780              l2-output node cannot output packet to BVI properly */
2781           cfg0 = vec_elt_at_index (l2im->configs, sw_if_index0);
2782           if (PREDICT_FALSE (cfg0->bvi))
2783             {
2784               vnet_buffer (p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
2785               vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
2786               goto next_l2_feature;
2787             }
2788
2789           /* Send ARP/ND reply back out input interface through l2-output */
2790           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2791           next0 = ARP_TERM_NEXT_L2_OUTPUT;
2792           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2793                                            to_next, n_left_to_next, pi0,
2794                                            next0);
2795           continue;
2796
2797         check_ip6_nd:
2798           /* IP6 ND event notification or solicitation handling to generate
2799              local response instead of flooding */
2800           iph0 = (ip6_header_t *) l3h0;
2801           if (PREDICT_FALSE (ethertype0 == ETHERNET_TYPE_IP6 &&
2802                              iph0->protocol == IP_PROTOCOL_ICMP6 &&
2803                              !ip6_address_is_unspecified
2804                              (&iph0->src_address)))
2805             {
2806               sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2807               if (vnet_ip6_nd_term
2808                   (vm, node, p0, eth0, iph0, sw_if_index0,
2809                    vnet_buffer (p0)->l2.bd_index))
2810                 goto output_response;
2811             }
2812
2813         next_l2_feature:
2814           {
2815             next0 = vnet_l2_feature_next (p0, arp_term_next_node_index,
2816                                           L2INPUT_FEAT_ARP_TERM);
2817             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2818                                              to_next, n_left_to_next,
2819                                              pi0, next0);
2820             continue;
2821           }
2822
2823         drop:
2824           if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
2825               (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
2826                arp0->ip4_over_ethernet[1].ip4.as_u32))
2827             {
2828               error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
2829             }
2830           next0 = ARP_TERM_NEXT_DROP;
2831           p0->error = node->errors[error0];
2832
2833           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2834                                            to_next, n_left_to_next, pi0,
2835                                            next0);
2836         }
2837
2838       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2839     }
2840
2841   vlib_error_count (vm, node->node_index,
2842                     ETHERNET_ARP_ERROR_replies_sent, n_replies_sent);
2843   return frame->n_vectors;
2844 }
2845
2846 /* *INDENT-OFF* */
2847 VLIB_REGISTER_NODE (arp_term_l2bd_node, static) = {
2848   .function = arp_term_l2bd,
2849   .name = "arp-term-l2bd",
2850   .vector_size = sizeof (u32),
2851   .n_errors = ETHERNET_ARP_N_ERROR,
2852   .error_strings = ethernet_arp_error_strings,
2853   .n_next_nodes = ARP_TERM_N_NEXT,
2854   .next_nodes = {
2855     [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
2856     [ARP_TERM_NEXT_DROP] = "error-drop",
2857   },
2858   .format_buffer = format_ethernet_arp_header,
2859   .format_trace = format_arp_term_input_trace,
2860 };
2861 /* *INDENT-ON* */
2862
2863 clib_error_t *
2864 arp_term_init (vlib_main_t * vm)
2865 {
2866   // Initialize the feature next-node indexes
2867   feat_bitmap_init_next_nodes (vm,
2868                                arp_term_l2bd_node.index,
2869                                L2INPUT_N_FEAT,
2870                                l2input_get_feat_names (),
2871                                arp_term_next_node_index);
2872   return 0;
2873 }
2874
2875 VLIB_INIT_FUNCTION (arp_term_init);
2876
2877 void
2878 change_arp_mac (u32 sw_if_index, ethernet_arp_ip4_entry_t * e)
2879 {
2880   if (e->sw_if_index == sw_if_index)
2881     {
2882       adj_nbr_walk_nh4 (e->sw_if_index,
2883                         &e->ip4_address, arp_mk_complete_walk, e);
2884     }
2885 }
2886
2887 void
2888 ethernet_arp_change_mac (u32 sw_if_index)
2889 {
2890   ethernet_arp_main_t *am = &ethernet_arp_main;
2891   ethernet_arp_ip4_entry_t *e;
2892   adj_index_t ai;
2893
2894   /* *INDENT-OFF* */
2895   pool_foreach (e, am->ip4_entry_pool,
2896   ({
2897     change_arp_mac (sw_if_index, e);
2898   }));
2899   /* *INDENT-ON* */
2900
2901   ai = adj_glean_get (FIB_PROTOCOL_IP4, sw_if_index);
2902
2903   if (ADJ_INDEX_INVALID != ai)
2904     adj_glean_update_rewrite (ai);
2905 }
2906
2907 void
2908 send_ip4_garp (vlib_main_t * vm, u32 sw_if_index)
2909 {
2910   ip4_main_t *i4m = &ip4_main;
2911   ip4_address_t *ip4_addr = ip4_interface_first_address (i4m, sw_if_index, 0);
2912
2913   send_ip4_garp_w_addr (vm, ip4_addr, sw_if_index);
2914 }
2915
2916 void
2917 send_ip4_garp_w_addr (vlib_main_t * vm,
2918                       const ip4_address_t * ip4_addr, u32 sw_if_index)
2919 {
2920   ip4_main_t *i4m = &ip4_main;
2921   vnet_main_t *vnm = vnet_get_main ();
2922   u8 *rewrite, rewrite_len;
2923   vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
2924
2925   if (ip4_addr)
2926     {
2927       clib_warning ("Sending GARP for IP4 address %U on sw_if_idex %d",
2928                     format_ip4_address, ip4_addr, sw_if_index);
2929
2930       /* Form GARP packet for output - Gratuitous ARP is an ARP request packet
2931          where the interface IP/MAC pair is used for both source and request
2932          MAC/IP pairs in the request */
2933       u32 bi = 0;
2934       ethernet_arp_header_t *h = vlib_packet_template_get_packet
2935         (vm, &i4m->ip4_arp_request_packet_template, &bi);
2936
2937       if (!h)
2938         return;
2939
2940       mac_address_from_bytes (&h->ip4_over_ethernet[0].mac, hi->hw_address);
2941       mac_address_from_bytes (&h->ip4_over_ethernet[1].mac, hi->hw_address);
2942       h->ip4_over_ethernet[0].ip4 = ip4_addr[0];
2943       h->ip4_over_ethernet[1].ip4 = ip4_addr[0];
2944
2945       /* Setup MAC header with ARP Etype and broadcast DMAC */
2946       vlib_buffer_t *b = vlib_get_buffer (vm, bi);
2947       rewrite =
2948         ethernet_build_rewrite (vnm, sw_if_index, VNET_LINK_ARP,
2949                                 VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST);
2950       rewrite_len = vec_len (rewrite);
2951       vlib_buffer_advance (b, -rewrite_len);
2952       ethernet_header_t *e = vlib_buffer_get_current (b);
2953       clib_memcpy_fast (e->dst_address, rewrite, rewrite_len);
2954       vec_free (rewrite);
2955
2956       /* Send GARP packet out the specified interface */
2957       vnet_buffer (b)->sw_if_index[VLIB_RX] =
2958         vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
2959       vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index);
2960       u32 *to_next = vlib_frame_vector_args (f);
2961       to_next[0] = bi;
2962       f->n_vectors = 1;
2963       vlib_put_frame_to_node (vm, hi->output_node_index, f);
2964     }
2965 }
2966
2967 /*
2968  * Remove any arp entries associated with the specified interface
2969  */
2970 static clib_error_t *
2971 vnet_arp_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
2972 {
2973   if (!is_add && sw_if_index != ~0)
2974     {
2975       ethernet_arp_main_t *am = &ethernet_arp_main;
2976       ethernet_arp_ip4_entry_t *e;
2977       /* *INDENT-OFF* */
2978       pool_foreach (e, am->ip4_entry_pool, ({
2979         if (e->sw_if_index != sw_if_index)
2980           continue;
2981         vnet_arp_set_ip4_over_ethernet_rpc_args_t args = {
2982           .sw_if_index = sw_if_index,
2983           .ip4 = e->ip4_address,
2984         };
2985         vnet_arp_unset_ip4_over_ethernet_internal (vnm, &args);
2986       }));
2987       /* *INDENT-ON* */
2988     }
2989
2990   return (NULL);
2991 }
2992
2993 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (vnet_arp_delete_sw_interface);
2994
2995 /*
2996  * fd.io coding-style-patch-verification: ON
2997  *
2998  * Local Variables:
2999  * eval: (c-set-style "gnu")
3000  * End:
3001  */