IMplementation for option to not create a FIB table entry when adding a neighbor...
[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/ip6.h>
20 #include <vnet/ethernet/ethernet.h>
21 #include <vnet/ethernet/arp_packet.h>
22 #include <vnet/l2/l2_input.h>
23 #include <vppinfra/mhash.h>
24 #include <vnet/fib/ip4_fib.h>
25 #include <vnet/adj/adj_nbr.h>
26 #include <vnet/adj/adj_mcast.h>
27 #include <vnet/mpls/mpls.h>
28
29 /**
30  * @file
31  * @brief IPv4 ARP.
32  *
33  * This file contains code to manage the IPv4 ARP tables (IP Address
34  * to MAC Address lookup).
35  */
36
37
38 void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
39
40 /**
41  * @brief Per-interface ARP configuration and state
42  */
43 typedef struct ethernet_arp_interface_t_
44 {
45   /**
46    * Hash table of ARP entries.
47    * Since this hash table is per-interface, the key is only the IPv4 address.
48    */
49   uword *arp_entries;
50 } ethernet_arp_interface_t;
51
52 typedef struct
53 {
54   u32 lo_addr;
55   u32 hi_addr;
56   u32 fib_index;
57 } ethernet_proxy_arp_t;
58
59 typedef struct
60 {
61   u32 next_index;
62   uword node_index;
63   uword type_opaque;
64   uword data;
65   /* Used for arp event notification only */
66   void *data_callback;
67   u32 pid;
68 } pending_resolution_t;
69
70 typedef struct
71 {
72   /* Hash tables mapping name to opcode. */
73   uword *opcode_by_name;
74
75   /* lite beer "glean" adjacency handling */
76   uword *pending_resolutions_by_address;
77   pending_resolution_t *pending_resolutions;
78
79   /* Mac address change notification */
80   uword *mac_changes_by_address;
81   pending_resolution_t *mac_changes;
82
83   ethernet_arp_ip4_entry_t *ip4_entry_pool;
84
85   /* ARP attack mitigation */
86   u32 arp_delete_rotor;
87   u32 limit_arp_cache_size;
88
89   /** Per interface state */
90   ethernet_arp_interface_t *ethernet_arp_by_sw_if_index;
91
92   /* Proxy arp vector */
93   ethernet_proxy_arp_t *proxy_arps;
94 } ethernet_arp_main_t;
95
96 static ethernet_arp_main_t ethernet_arp_main;
97
98 typedef struct
99 {
100   u32 sw_if_index;
101   ethernet_arp_ip4_over_ethernet_address_t a;
102   int is_static;
103   int is_no_fib_entry;
104   int flags;
105 #define ETHERNET_ARP_ARGS_REMOVE (1<<0)
106 #define ETHERNET_ARP_ARGS_FLUSH  (1<<1)
107 #define ETHERNET_ARP_ARGS_POPULATE  (1<<2)
108 } vnet_arp_set_ip4_over_ethernet_rpc_args_t;
109
110 static void
111 set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t
112                                     * a);
113
114 static u8 *
115 format_ethernet_arp_hardware_type (u8 * s, va_list * va)
116 {
117   ethernet_arp_hardware_type_t h = va_arg (*va, ethernet_arp_hardware_type_t);
118   char *t = 0;
119   switch (h)
120     {
121 #define _(n,f) case n: t = #f; break;
122       foreach_ethernet_arp_hardware_type;
123 #undef _
124
125     default:
126       return format (s, "unknown 0x%x", h);
127     }
128
129   return format (s, "%s", t);
130 }
131
132 static u8 *
133 format_ethernet_arp_opcode (u8 * s, va_list * va)
134 {
135   ethernet_arp_opcode_t o = va_arg (*va, ethernet_arp_opcode_t);
136   char *t = 0;
137   switch (o)
138     {
139 #define _(f) case ETHERNET_ARP_OPCODE_##f: t = #f; break;
140       foreach_ethernet_arp_opcode;
141 #undef _
142
143     default:
144       return format (s, "unknown 0x%x", o);
145     }
146
147   return format (s, "%s", t);
148 }
149
150 static uword
151 unformat_ethernet_arp_opcode_host_byte_order (unformat_input_t * input,
152                                               va_list * args)
153 {
154   int *result = va_arg (*args, int *);
155   ethernet_arp_main_t *am = &ethernet_arp_main;
156   int x, i;
157
158   /* Numeric opcode. */
159   if (unformat (input, "0x%x", &x) || unformat (input, "%d", &x))
160     {
161       if (x >= (1 << 16))
162         return 0;
163       *result = x;
164       return 1;
165     }
166
167   /* Named type. */
168   if (unformat_user (input, unformat_vlib_number_by_name,
169                      am->opcode_by_name, &i))
170     {
171       *result = i;
172       return 1;
173     }
174
175   return 0;
176 }
177
178 static uword
179 unformat_ethernet_arp_opcode_net_byte_order (unformat_input_t * input,
180                                              va_list * args)
181 {
182   int *result = va_arg (*args, int *);
183   if (!unformat_user
184       (input, unformat_ethernet_arp_opcode_host_byte_order, result))
185     return 0;
186
187   *result = clib_host_to_net_u16 ((u16) * result);
188   return 1;
189 }
190
191 static u8 *
192 format_ethernet_arp_header (u8 * s, va_list * va)
193 {
194   ethernet_arp_header_t *a = va_arg (*va, ethernet_arp_header_t *);
195   u32 max_header_bytes = va_arg (*va, u32);
196   uword indent;
197   u16 l2_type, l3_type;
198
199   if (max_header_bytes != 0 && sizeof (a[0]) > max_header_bytes)
200     return format (s, "ARP header truncated");
201
202   l2_type = clib_net_to_host_u16 (a->l2_type);
203   l3_type = clib_net_to_host_u16 (a->l3_type);
204
205   indent = format_get_indent (s);
206
207   s = format (s, "%U, type %U/%U, address size %d/%d",
208               format_ethernet_arp_opcode, clib_net_to_host_u16 (a->opcode),
209               format_ethernet_arp_hardware_type, l2_type,
210               format_ethernet_type, l3_type,
211               a->n_l2_address_bytes, a->n_l3_address_bytes);
212
213   if (l2_type == ETHERNET_ARP_HARDWARE_TYPE_ethernet
214       && l3_type == ETHERNET_TYPE_IP4)
215     {
216       s = format (s, "\n%U%U/%U -> %U/%U",
217                   format_white_space, indent,
218                   format_ethernet_address, a->ip4_over_ethernet[0].ethernet,
219                   format_ip4_address, &a->ip4_over_ethernet[0].ip4,
220                   format_ethernet_address, a->ip4_over_ethernet[1].ethernet,
221                   format_ip4_address, &a->ip4_over_ethernet[1].ip4);
222     }
223   else
224     {
225       uword n2 = a->n_l2_address_bytes;
226       uword n3 = a->n_l3_address_bytes;
227       s = format (s, "\n%U%U/%U -> %U/%U",
228                   format_white_space, indent,
229                   format_hex_bytes, a->data + 0 * n2 + 0 * n3, n2,
230                   format_hex_bytes, a->data + 1 * n2 + 0 * n3, n3,
231                   format_hex_bytes, a->data + 1 * n2 + 1 * n3, n2,
232                   format_hex_bytes, a->data + 2 * n2 + 1 * n3, n3);
233     }
234
235   return s;
236 }
237
238 u8 *
239 format_ethernet_arp_ip4_entry (u8 * s, va_list * va)
240 {
241   vnet_main_t *vnm = va_arg (*va, vnet_main_t *);
242   ethernet_arp_ip4_entry_t *e = va_arg (*va, ethernet_arp_ip4_entry_t *);
243   vnet_sw_interface_t *si;
244   u8 *flags = 0;
245
246   if (!e)
247     return format (s, "%=12s%=16s%=6s%=20s%=24s", "Time", "IP4",
248                    "Flags", "Ethernet", "Interface");
249
250   si = vnet_get_sw_interface (vnm, e->sw_if_index);
251
252   if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
253     flags = format (flags, "S");
254
255   if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC)
256     flags = format (flags, "D");
257
258   if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_NO_FIB_ENTRY)
259     flags = format (flags, "N");
260
261   s = format (s, "%=12U%=16U%=6s%=20U%=24U",
262               format_vlib_cpu_time, vnm->vlib_main, e->cpu_time_last_updated,
263               format_ip4_address, &e->ip4_address,
264               flags ? (char *) flags : "",
265               format_ethernet_address, e->ethernet_address,
266               format_vnet_sw_interface_name, vnm, si);
267
268   vec_free (flags);
269   return s;
270 }
271
272 typedef struct
273 {
274   u8 packet_data[64];
275 } ethernet_arp_input_trace_t;
276
277 static u8 *
278 format_ethernet_arp_input_trace (u8 * s, va_list * va)
279 {
280   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
281   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
282   ethernet_arp_input_trace_t *t = va_arg (*va, ethernet_arp_input_trace_t *);
283
284   s = format (s, "%U",
285               format_ethernet_arp_header,
286               t->packet_data, sizeof (t->packet_data));
287
288   return s;
289 }
290
291 static u8 *
292 format_arp_term_input_trace (u8 * s, va_list * va)
293 {
294   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
295   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
296   ethernet_arp_input_trace_t *t = va_arg (*va, ethernet_arp_input_trace_t *);
297
298   /* arp-term trace data saved is either arp or ip6/icmp6 packet:
299      - for arp, the 1st 16-bit field is hw type of value of 0x0001.
300      - for ip6, the first nibble has value of 6. */
301   s = format (s, "%U", t->packet_data[0] == 0 ?
302               format_ethernet_arp_header : format_ip6_header,
303               t->packet_data, sizeof (t->packet_data));
304
305   return s;
306 }
307
308 static void
309 arp_nbr_probe (ip_adjacency_t * adj)
310 {
311   vnet_main_t *vnm = vnet_get_main ();
312   ip4_main_t *im = &ip4_main;
313   ip_interface_address_t *ia;
314   ethernet_arp_header_t *h;
315   vnet_hw_interface_t *hi;
316   vnet_sw_interface_t *si;
317   ip4_address_t *src;
318   vlib_buffer_t *b;
319   vlib_main_t *vm;
320   u32 bi = 0;
321
322   vm = vlib_get_main ();
323
324   si = vnet_get_sw_interface (vnm, adj->rewrite_header.sw_if_index);
325
326   if (!(si->flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
327     {
328       return;
329     }
330
331   src =
332     ip4_interface_address_matching_destination (im,
333                                                 &adj->sub_type.nbr.next_hop.
334                                                 ip4,
335                                                 adj->rewrite_header.
336                                                 sw_if_index, &ia);
337   if (!src)
338     {
339       return;
340     }
341
342   h =
343     vlib_packet_template_get_packet (vm, &im->ip4_arp_request_packet_template,
344                                      &bi);
345
346   hi = vnet_get_sup_hw_interface (vnm, adj->rewrite_header.sw_if_index);
347
348   clib_memcpy (h->ip4_over_ethernet[0].ethernet,
349                hi->hw_address, sizeof (h->ip4_over_ethernet[0].ethernet));
350
351   h->ip4_over_ethernet[0].ip4 = src[0];
352   h->ip4_over_ethernet[1].ip4 = adj->sub_type.nbr.next_hop.ip4;
353
354   b = vlib_get_buffer (vm, bi);
355   vnet_buffer (b)->sw_if_index[VLIB_RX] =
356     vnet_buffer (b)->sw_if_index[VLIB_TX] = adj->rewrite_header.sw_if_index;
357
358   /* Add encapsulation string for software interface (e.g. ethernet header). */
359   vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
360   vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
361
362   {
363     vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index);
364     u32 *to_next = vlib_frame_vector_args (f);
365     to_next[0] = bi;
366     f->n_vectors = 1;
367     vlib_put_frame_to_node (vm, hi->output_node_index, f);
368   }
369 }
370
371 static void
372 arp_mk_complete (adj_index_t ai, ethernet_arp_ip4_entry_t * e)
373 {
374   adj_nbr_update_rewrite
375     (ai, ADJ_NBR_REWRITE_FLAG_COMPLETE,
376      ethernet_build_rewrite (vnet_get_main (),
377                              e->sw_if_index,
378                              adj_get_link_type (ai), e->ethernet_address));
379 }
380
381 static void
382 arp_mk_incomplete (adj_index_t ai)
383 {
384   ip_adjacency_t *adj = adj_get (ai);
385
386   adj_nbr_update_rewrite
387     (ai,
388      ADJ_NBR_REWRITE_FLAG_INCOMPLETE,
389      ethernet_build_rewrite (vnet_get_main (),
390                              adj->rewrite_header.sw_if_index,
391                              VNET_LINK_ARP,
392                              VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
393 }
394
395 static ethernet_arp_ip4_entry_t *
396 arp_entry_find (ethernet_arp_interface_t * eai, const ip4_address_t * addr)
397 {
398   ethernet_arp_main_t *am = &ethernet_arp_main;
399   ethernet_arp_ip4_entry_t *e = NULL;
400   uword *p;
401
402   if (NULL != eai->arp_entries)
403     {
404       p = hash_get (eai->arp_entries, addr->as_u32);
405       if (!p)
406         return (NULL);
407
408       e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
409     }
410
411   return (e);
412 }
413
414 static adj_walk_rc_t
415 arp_mk_complete_walk (adj_index_t ai, void *ctx)
416 {
417   ethernet_arp_ip4_entry_t *e = ctx;
418
419   arp_mk_complete (ai, e);
420
421   return (ADJ_WALK_RC_CONTINUE);
422 }
423
424 static adj_walk_rc_t
425 arp_mk_incomplete_walk (adj_index_t ai, void *ctx)
426 {
427   arp_mk_incomplete (ai);
428
429   return (ADJ_WALK_RC_CONTINUE);
430 }
431
432 void
433 arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
434 {
435   ethernet_arp_main_t *am = &ethernet_arp_main;
436   ethernet_arp_interface_t *arp_int;
437   ethernet_arp_ip4_entry_t *e;
438   ip_adjacency_t *adj;
439
440   adj = adj_get (ai);
441
442   vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index);
443   arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
444   e = arp_entry_find (arp_int, &adj->sub_type.nbr.next_hop.ip4);
445
446   switch (adj->lookup_next_index)
447     {
448     case IP_LOOKUP_NEXT_ARP:
449     case IP_LOOKUP_NEXT_GLEAN:
450       if (NULL != e)
451         {
452           adj_nbr_walk_nh4 (sw_if_index,
453                             &e->ip4_address, arp_mk_complete_walk, e);
454         }
455       else
456         {
457           /*
458            * no matching ARP entry.
459            * construct the rewrite required to for an ARP packet, and stick
460            * that in the adj's pipe to smoke.
461            */
462           adj_nbr_update_rewrite
463             (ai,
464              ADJ_NBR_REWRITE_FLAG_INCOMPLETE,
465              ethernet_build_rewrite
466              (vnm,
467               sw_if_index,
468               VNET_LINK_ARP,
469               VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST));
470
471           /*
472            * since the FIB has added this adj for a route, it makes sense it
473            * may want to forward traffic sometime soon. Let's send a
474            * speculative ARP. just one. If we were to do periodically that
475            * wouldn't be bad either, but that's more code than i'm prepared to
476            * write at this time for relatively little reward.
477            */
478           arp_nbr_probe (adj);
479         }
480       break;
481     case IP_LOOKUP_NEXT_MCAST:
482       /*
483        * Construct a partial rewrite from the known ethernet mcast dest MAC
484        */
485       adj_mcast_update_rewrite
486         (ai,
487          ethernet_build_rewrite (vnm,
488                                  sw_if_index,
489                                  adj->ia_link,
490                                  ethernet_ip4_mcast_dst_addr ()));
491
492       /*
493        * Complete the remaining fields of the adj's rewrite to direct the
494        * complete of the rewrite at switch time by copying in the IP
495        * dst address's bytes.
496        * Ofset is 11 bytes from the end of the MAC header - which is three
497        * bytes into the desintation address. And we write 3 bytes.
498        */
499       adj->rewrite_header.dst_mcast_offset = 11;
500       adj->rewrite_header.dst_mcast_n_bytes = 3;
501
502       break;
503
504     case IP_LOOKUP_NEXT_DROP:
505     case IP_LOOKUP_NEXT_PUNT:
506     case IP_LOOKUP_NEXT_LOCAL:
507     case IP_LOOKUP_NEXT_REWRITE:
508     case IP_LOOKUP_NEXT_LOAD_BALANCE:
509     case IP_LOOKUP_NEXT_MIDCHAIN:
510     case IP_LOOKUP_NEXT_ICMP_ERROR:
511     case IP_LOOKUP_N_NEXT:
512       ASSERT (0);
513       break;
514     }
515 }
516
517 int
518 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
519                                          vnet_arp_set_ip4_over_ethernet_rpc_args_t
520                                          * args)
521 {
522   ethernet_arp_ip4_entry_t *e = 0;
523   ethernet_arp_main_t *am = &ethernet_arp_main;
524   ethernet_arp_ip4_over_ethernet_address_t *a = &args->a;
525   vlib_main_t *vm = vlib_get_main ();
526   int make_new_arp_cache_entry = 1;
527   uword *p;
528   pending_resolution_t *pr, *mc;
529   ethernet_arp_interface_t *arp_int;
530   int is_static = args->is_static;
531   u32 sw_if_index = args->sw_if_index;
532   int is_no_fib_entry = args->is_no_fib_entry;
533
534   vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index);
535
536   arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
537
538   if (NULL != arp_int->arp_entries)
539     {
540       p = hash_get (arp_int->arp_entries, a->ip4.as_u32);
541       if (p)
542         {
543           e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
544
545           /* Refuse to over-write static arp. */
546           if (!is_static && (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC))
547             return -2;
548           make_new_arp_cache_entry = 0;
549         }
550     }
551
552   if (make_new_arp_cache_entry)
553     {
554       pool_get (am->ip4_entry_pool, e);
555
556       if (NULL == arp_int->arp_entries)
557         {
558           arp_int->arp_entries = hash_create (0, sizeof (u32));
559         }
560
561       hash_set (arp_int->arp_entries, a->ip4.as_u32, e - am->ip4_entry_pool);
562
563       e->sw_if_index = sw_if_index;
564       e->ip4_address = a->ip4;
565       clib_memcpy (e->ethernet_address,
566                    a->ethernet, sizeof (e->ethernet_address));
567
568       if (!is_no_fib_entry)
569         {
570           fib_prefix_t pfx = {
571             .fp_len = 32,
572             .fp_proto = FIB_PROTOCOL_IP4,
573             .fp_addr.ip4 = a->ip4,
574           };
575           u32 fib_index;
576
577           fib_index =
578             ip4_fib_table_get_index_for_sw_if_index (e->sw_if_index);
579           e->fib_entry_index =
580             fib_table_entry_update_one_path (fib_index, &pfx, FIB_SOURCE_ADJ,
581                                              FIB_ENTRY_FLAG_ATTACHED,
582                                              FIB_PROTOCOL_IP4, &pfx.fp_addr,
583                                              e->sw_if_index, ~0, 1, NULL,
584                                              FIB_ROUTE_PATH_FLAG_NONE);
585           e->flags |= ETHERNET_ARP_IP4_ENTRY_FLAG_NO_FIB_ENTRY;
586         }
587     }
588   else
589     {
590       /*
591        * prevent a DoS attack from the data-plane that
592        * spams us with no-op updates to the MAC address
593        */
594       if (0 == memcmp (e->ethernet_address,
595                        a->ethernet, sizeof (e->ethernet_address)))
596         return -1;
597
598       /* Update time stamp and ethernet address. */
599       clib_memcpy (e->ethernet_address, a->ethernet,
600                    sizeof (e->ethernet_address));
601     }
602
603   e->cpu_time_last_updated = clib_cpu_time_now ();
604   if (is_static)
605     e->flags |= ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC;
606   else
607     e->flags |= ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC;
608
609   adj_nbr_walk_nh4 (sw_if_index, &e->ip4_address, arp_mk_complete_walk, e);
610
611   /* Customer(s) waiting for this address to be resolved? */
612   p = hash_get (am->pending_resolutions_by_address, a->ip4.as_u32);
613   if (p)
614     {
615       u32 next_index;
616       next_index = p[0];
617
618       while (next_index != (u32) ~ 0)
619         {
620           pr = pool_elt_at_index (am->pending_resolutions, next_index);
621           vlib_process_signal_event (vm, pr->node_index,
622                                      pr->type_opaque, pr->data);
623           next_index = pr->next_index;
624           pool_put (am->pending_resolutions, pr);
625         }
626
627       hash_unset (am->pending_resolutions_by_address, a->ip4.as_u32);
628     }
629
630   /* Customer(s) requesting ARP event for this address? */
631   p = hash_get (am->mac_changes_by_address, a->ip4.as_u32);
632   if (p)
633     {
634       u32 next_index;
635       next_index = p[0];
636
637       while (next_index != (u32) ~ 0)
638         {
639           int (*fp) (u32, u8 *, u32, u32);
640           int rv = 1;
641           mc = pool_elt_at_index (am->mac_changes, next_index);
642           fp = mc->data_callback;
643
644           /* Call the user's data callback, return 1 to suppress dup events */
645           if (fp)
646             rv = (*fp) (mc->data, a->ethernet, sw_if_index, 0);
647
648           /*
649            * Signal the resolver process, as long as the user
650            * says they want to be notified
651            */
652           if (rv == 0)
653             vlib_process_signal_event (vm, mc->node_index,
654                                        mc->type_opaque, mc->data);
655           next_index = mc->next_index;
656         }
657     }
658
659   return 0;
660 }
661
662 void
663 vnet_register_ip4_arp_resolution_event (vnet_main_t * vnm,
664                                         void *address_arg,
665                                         uword node_index,
666                                         uword type_opaque, uword data)
667 {
668   ethernet_arp_main_t *am = &ethernet_arp_main;
669   ip4_address_t *address = address_arg;
670   uword *p;
671   pending_resolution_t *pr;
672
673   pool_get (am->pending_resolutions, pr);
674
675   pr->next_index = ~0;
676   pr->node_index = node_index;
677   pr->type_opaque = type_opaque;
678   pr->data = data;
679   pr->data_callback = 0;
680
681   p = hash_get (am->pending_resolutions_by_address, address->as_u32);
682   if (p)
683     {
684       /* Insert new resolution at the head of the list */
685       pr->next_index = p[0];
686       hash_unset (am->pending_resolutions_by_address, address->as_u32);
687     }
688
689   hash_set (am->pending_resolutions_by_address, address->as_u32,
690             pr - am->pending_resolutions);
691 }
692
693 int
694 vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm,
695                                    void *data_callback,
696                                    u32 pid,
697                                    void *address_arg,
698                                    uword node_index,
699                                    uword type_opaque, uword data, int is_add)
700 {
701   ethernet_arp_main_t *am = &ethernet_arp_main;
702   ip4_address_t *address = address_arg;
703   uword *p;
704   pending_resolution_t *mc;
705   void (*fp) (u32, u8 *) = data_callback;
706
707   if (is_add)
708     {
709       pool_get (am->mac_changes, mc);
710
711       mc->next_index = ~0;
712       mc->node_index = node_index;
713       mc->type_opaque = type_opaque;
714       mc->data = data;
715       mc->data_callback = data_callback;
716       mc->pid = pid;
717
718       p = hash_get (am->mac_changes_by_address, address->as_u32);
719       if (p)
720         {
721           /* Insert new resolution at the head of the list */
722           mc->next_index = p[0];
723           hash_unset (am->mac_changes_by_address, address->as_u32);
724         }
725
726       hash_set (am->mac_changes_by_address, address->as_u32,
727                 mc - am->mac_changes);
728       return 0;
729     }
730   else
731     {
732       u32 index;
733       pending_resolution_t *mc_last = 0;
734
735       p = hash_get (am->mac_changes_by_address, address->as_u32);
736       if (p == 0)
737         return VNET_API_ERROR_NO_SUCH_ENTRY;
738
739       index = p[0];
740
741       while (index != (u32) ~ 0)
742         {
743           mc = pool_elt_at_index (am->mac_changes, index);
744           if (mc->node_index == node_index &&
745               mc->type_opaque == type_opaque && mc->pid == pid)
746             {
747               /* Clients may need to clean up pool entries, too */
748               if (fp)
749                 (*fp) (mc->data, 0 /* no new mac addrs */ );
750               if (index == p[0])
751                 {
752                   hash_unset (am->mac_changes_by_address, address->as_u32);
753                   if (mc->next_index != ~0)
754                     hash_set (am->mac_changes_by_address, address->as_u32,
755                               mc->next_index);
756                   pool_put (am->mac_changes, mc);
757                   return 0;
758                 }
759               else
760                 {
761                   ASSERT (mc_last);
762                   mc_last->next_index = mc->next_index;
763                   pool_put (am->mac_changes, mc);
764                   return 0;
765                 }
766             }
767           mc_last = mc;
768           index = mc->next_index;
769         }
770
771       return VNET_API_ERROR_NO_SUCH_ENTRY;
772     }
773 }
774
775 /* Either we drop the packet or we send a reply to the sender. */
776 typedef enum
777 {
778   ARP_INPUT_NEXT_DROP,
779   ARP_INPUT_NEXT_REPLY_TX,
780   ARP_INPUT_N_NEXT,
781 } arp_input_next_t;
782
783 #define foreach_ethernet_arp_error                                      \
784   _ (replies_sent, "ARP replies sent")                                  \
785   _ (l2_type_not_ethernet, "L2 type not ethernet")                      \
786   _ (l3_type_not_ip4, "L3 type not IP4")                                \
787   _ (l3_src_address_not_local, "IP4 source address not local to subnet") \
788   _ (l3_dst_address_not_local, "IP4 destination address not local to subnet") \
789   _ (l3_src_address_is_local, "IP4 source address matches local interface") \
790   _ (l3_src_address_learned, "ARP request IP4 source address learned")  \
791   _ (replies_received, "ARP replies received")                          \
792   _ (opcode_not_request, "ARP opcode not request")                      \
793   _ (proxy_arp_replies_sent, "Proxy ARP replies sent")                  \
794   _ (l2_address_mismatch, "ARP hw addr does not match L2 frame src addr") \
795   _ (missing_interface_address, "ARP missing interface address") \
796   _ (gratuitous_arp, "ARP probe or announcement dropped") \
797   _ (interface_no_table, "Interface is not mapped to an IP table") \
798   _ (interface_not_ip_enabled, "Interface is not IP enabled") \
799
800 typedef enum
801 {
802 #define _(sym,string) ETHERNET_ARP_ERROR_##sym,
803   foreach_ethernet_arp_error
804 #undef _
805     ETHERNET_ARP_N_ERROR,
806 } ethernet_arp_input_error_t;
807
808
809 static void
810 unset_random_arp_entry (void)
811 {
812   ethernet_arp_main_t *am = &ethernet_arp_main;
813   ethernet_arp_ip4_entry_t *e;
814   vnet_main_t *vnm = vnet_get_main ();
815   ethernet_arp_ip4_over_ethernet_address_t delme;
816   u32 index;
817
818   index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
819   am->arp_delete_rotor = index;
820
821   /* Try again from elt 0, could happen if an intfc goes down */
822   if (index == ~0)
823     {
824       index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
825       am->arp_delete_rotor = index;
826     }
827
828   /* Nothing left in the pool */
829   if (index == ~0)
830     return;
831
832   e = pool_elt_at_index (am->ip4_entry_pool, index);
833
834   clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
835   delme.ip4.as_u32 = e->ip4_address.as_u32;
836
837   vnet_arp_unset_ip4_over_ethernet (vnm, e->sw_if_index, &delme);
838 }
839
840 static int
841 arp_unnumbered (vlib_buffer_t * p0,
842                 u32 pi0, ethernet_header_t * eth0, u32 sw_if_index)
843 {
844   vlib_main_t *vm = vlib_get_main ();
845   vnet_main_t *vnm = vnet_get_main ();
846   vnet_interface_main_t *vim = &vnm->interface_main;
847   vnet_sw_interface_t *si;
848   vnet_hw_interface_t *hi;
849   u32 unnum_src_sw_if_index;
850   u32 *broadcast_swifs = 0;
851   u32 *buffers = 0;
852   u32 n_alloc = 0;
853   vlib_buffer_t *b0;
854   int i;
855   u8 dst_mac_address[6];
856   i16 header_size;
857   ethernet_arp_header_t *arp0;
858
859   /* Save the dst mac address */
860   clib_memcpy (dst_mac_address, eth0->dst_address, sizeof (dst_mac_address));
861
862   /* Figure out which sw_if_index supplied the address */
863   unnum_src_sw_if_index = sw_if_index;
864
865   /* Track down all users of the unnumbered source */
866   /* *INDENT-OFF* */
867   pool_foreach (si, vim->sw_interfaces,
868   ({
869     if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
870         (si->unnumbered_sw_if_index == unnum_src_sw_if_index))
871       {
872         vec_add1 (broadcast_swifs, si->sw_if_index);
873       }
874   }));
875   /* *INDENT-ON* */
876
877   /* If there are no interfaces un-unmbered to this interface,
878      we are done  here. */
879   if (0 == vec_len (broadcast_swifs))
880     return 0;
881
882   /* Allocate buffering if we need it */
883   if (vec_len (broadcast_swifs) > 1)
884     {
885       vec_validate (buffers, vec_len (broadcast_swifs) - 2);
886       n_alloc = vlib_buffer_alloc (vm, buffers, vec_len (buffers));
887       _vec_len (buffers) = n_alloc;
888       for (i = 0; i < n_alloc; i++)
889         {
890           b0 = vlib_get_buffer (vm, buffers[i]);
891
892           /* xerox (partially built) ARP pkt */
893           clib_memcpy (b0->data, p0->data,
894                        p0->current_length + p0->current_data);
895           b0->current_data = p0->current_data;
896           b0->current_length = p0->current_length;
897           vnet_buffer (b0)->sw_if_index[VLIB_RX] =
898             vnet_buffer (p0)->sw_if_index[VLIB_RX];
899         }
900     }
901
902   vec_insert (buffers, 1, 0);
903   buffers[0] = pi0;
904
905   for (i = 0; i < vec_len (buffers); i++)
906     {
907       b0 = vlib_get_buffer (vm, buffers[i]);
908       arp0 = vlib_buffer_get_current (b0);
909
910       hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[i]);
911       si = vnet_get_sw_interface (vnm, broadcast_swifs[i]);
912
913       /* For decoration, most likely */
914       vnet_buffer (b0)->sw_if_index[VLIB_TX] = hi->sw_if_index;
915
916       /* Fix ARP pkt src address */
917       clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, hi->hw_address, 6);
918
919       /* Build L2 encaps for this swif */
920       header_size = sizeof (ethernet_header_t);
921       if (si->sub.eth.flags.one_tag)
922         header_size += 4;
923       else if (si->sub.eth.flags.two_tags)
924         header_size += 8;
925
926       vlib_buffer_advance (b0, -header_size);
927       eth0 = vlib_buffer_get_current (b0);
928
929       if (si->sub.eth.flags.one_tag)
930         {
931           ethernet_vlan_header_t *outer = (void *) (eth0 + 1);
932
933           eth0->type = si->sub.eth.flags.dot1ad ?
934             clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
935             clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
936           outer->priority_cfi_and_id =
937             clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
938           outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
939
940         }
941       else if (si->sub.eth.flags.two_tags)
942         {
943           ethernet_vlan_header_t *outer = (void *) (eth0 + 1);
944           ethernet_vlan_header_t *inner = (void *) (outer + 1);
945
946           eth0->type = si->sub.eth.flags.dot1ad ?
947             clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
948             clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
949           outer->priority_cfi_and_id =
950             clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
951           outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
952           inner->priority_cfi_and_id =
953             clib_host_to_net_u16 (si->sub.eth.inner_vlan_id);
954           inner->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
955
956         }
957       else
958         {
959           eth0->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
960         }
961
962       /* Restore the original dst address, set src address */
963       clib_memcpy (eth0->dst_address, dst_mac_address,
964                    sizeof (eth0->dst_address));
965       clib_memcpy (eth0->src_address, hi->hw_address,
966                    sizeof (eth0->src_address));
967
968       /* Transmit replicas */
969       if (i > 0)
970         {
971           vlib_frame_t *f =
972             vlib_get_frame_to_node (vm, hi->output_node_index);
973           u32 *to_next = vlib_frame_vector_args (f);
974           to_next[0] = buffers[i];
975           f->n_vectors = 1;
976           vlib_put_frame_to_node (vm, hi->output_node_index, f);
977         }
978     }
979
980   /* The regular path outputs the original pkt.. */
981   vnet_buffer (p0)->sw_if_index[VLIB_TX] = broadcast_swifs[0];
982
983   vec_free (broadcast_swifs);
984   vec_free (buffers);
985
986   return !0;
987 }
988
989 static uword
990 arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
991 {
992   ethernet_arp_main_t *am = &ethernet_arp_main;
993   vnet_main_t *vnm = vnet_get_main ();
994   ip4_main_t *im4 = &ip4_main;
995   u32 n_left_from, next_index, *from, *to_next;
996   u32 n_replies_sent = 0, n_proxy_arp_replies_sent = 0;
997
998   from = vlib_frame_vector_args (frame);
999   n_left_from = frame->n_vectors;
1000   next_index = node->cached_next_index;
1001
1002   if (node->flags & VLIB_NODE_FLAG_TRACE)
1003     vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
1004                                    /* stride */ 1,
1005                                    sizeof (ethernet_arp_input_trace_t));
1006
1007   while (n_left_from > 0)
1008     {
1009       u32 n_left_to_next;
1010
1011       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1012
1013       while (n_left_from > 0 && n_left_to_next > 0)
1014         {
1015           vlib_buffer_t *p0;
1016           vnet_hw_interface_t *hw_if0;
1017           ethernet_arp_header_t *arp0;
1018           ethernet_header_t *eth0;
1019           ip_adjacency_t *adj0;
1020           ip4_address_t *if_addr0, proxy_src;
1021           u32 pi0, error0, next0, sw_if_index0, conn_sw_if_index0, fib_index0;
1022           u8 is_request0, dst_is_local0, is_unnum0;
1023           ethernet_proxy_arp_t *pa;
1024           fib_node_index_t dst_fei, src_fei;
1025           fib_prefix_t pfx0;
1026           fib_entry_flag_t src_flags, dst_flags;
1027
1028           pi0 = from[0];
1029           to_next[0] = pi0;
1030           from += 1;
1031           to_next += 1;
1032           n_left_from -= 1;
1033           n_left_to_next -= 1;
1034           pa = 0;
1035
1036           p0 = vlib_get_buffer (vm, pi0);
1037           arp0 = vlib_buffer_get_current (p0);
1038
1039           is_request0 = arp0->opcode
1040             == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
1041
1042           error0 = ETHERNET_ARP_ERROR_replies_sent;
1043
1044           error0 =
1045             (arp0->l2_type !=
1046              clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ?
1047              ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
1048           error0 =
1049             (arp0->l3_type !=
1050              clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
1051              ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
1052
1053           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1054
1055           /* not playing the ARP game if the interface is not IPv4 enabled */
1056           error0 =
1057             (im4->ip_enabled_by_sw_if_index[sw_if_index0] == 0 ?
1058              ETHERNET_ARP_ERROR_interface_not_ip_enabled : error0);
1059
1060           if (error0)
1061             goto drop2;
1062
1063           /* Check that IP address is local and matches incoming interface. */
1064           fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
1065           if (~0 == fib_index0)
1066             {
1067               error0 = ETHERNET_ARP_ERROR_interface_no_table;
1068               goto drop2;
1069
1070             }
1071           dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1072                                           &arp0->ip4_over_ethernet[1].ip4,
1073                                           32);
1074           dst_flags = fib_entry_get_flags (dst_fei);
1075
1076           conn_sw_if_index0 = fib_entry_get_resolving_interface (dst_fei);
1077
1078           if (!(FIB_ENTRY_FLAG_CONNECTED & dst_flags))
1079             {
1080               error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
1081               goto drop1;
1082             }
1083
1084           /* Honor unnumbered interface, if any */
1085           is_unnum0 = sw_if_index0 != conn_sw_if_index0;
1086
1087           /* Source must also be local to subnet of matching interface address. */
1088           src_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1089                                           &arp0->ip4_over_ethernet[0].ip4,
1090                                           32);
1091           src_flags = fib_entry_get_flags (src_fei);
1092
1093           if (!((FIB_ENTRY_FLAG_ATTACHED & src_flags) ||
1094                 (FIB_ENTRY_FLAG_CONNECTED & src_flags)))
1095             {
1096               /*
1097                * The packet was sent from an address that is not connected nor attached
1098                * i.e. it is not from an address that is covered by a link's sub-net,
1099                * nor is it a already learned host resp.
1100                */
1101               error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
1102               goto drop2;
1103             }
1104           if (sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
1105             {
1106               /*
1107                * The interface the ARP was received on is not the interface
1108                * on which the covering prefix is configured. Maybe this is a case
1109                * for unnumbered.
1110                */
1111               is_unnum0 = 1;
1112             }
1113
1114           /* Reject requests/replies with our local interface address. */
1115           if (FIB_ENTRY_FLAG_LOCAL & src_flags)
1116             {
1117               error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
1118               goto drop2;
1119             }
1120
1121           dst_is_local0 = (FIB_ENTRY_FLAG_LOCAL & dst_flags);
1122           fib_entry_get_prefix (dst_fei, &pfx0);
1123           if_addr0 = &pfx0.fp_addr.ip4;
1124
1125           /* Fill in ethernet header. */
1126           eth0 = ethernet_buffer_get_header (p0);
1127
1128           /* Trash ARP packets whose ARP-level source addresses do not
1129              match their L2-frame-level source addresses */
1130           if (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
1131                       sizeof (eth0->src_address)))
1132             {
1133               error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1134               goto drop2;
1135             }
1136
1137           /* Learn or update sender's mapping only for requests or unicasts
1138              that don't match local interface address. */
1139           if (ethernet_address_cast (eth0->dst_address) ==
1140               ETHERNET_ADDRESS_UNICAST || is_request0)
1141             {
1142               if (am->limit_arp_cache_size &&
1143                   pool_elts (am->ip4_entry_pool) >= am->limit_arp_cache_size)
1144                 unset_random_arp_entry ();
1145
1146               vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index0,
1147                                               &arp0->ip4_over_ethernet[0],
1148                                               0 /* is_static */ , 0);
1149               error0 = ETHERNET_ARP_ERROR_l3_src_address_learned;
1150             }
1151
1152           /* Only send a reply for requests sent which match a local interface. */
1153           if (!(is_request0 && dst_is_local0))
1154             {
1155               error0 =
1156                 (arp0->opcode ==
1157                  clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply) ?
1158                  ETHERNET_ARP_ERROR_replies_received : error0);
1159               goto drop1;
1160             }
1161
1162           /* Send a reply. */
1163         send_reply:
1164           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1165           hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1166
1167           /* Send reply back through input interface */
1168           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1169           next0 = ARP_INPUT_NEXT_REPLY_TX;
1170
1171           arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1172
1173           arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1174
1175           clib_memcpy (arp0->ip4_over_ethernet[0].ethernet,
1176                        hw_if0->hw_address, 6);
1177           clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) =
1178             if_addr0->data_u32;
1179
1180           /* Hardware must be ethernet-like. */
1181           ASSERT (vec_len (hw_if0->hw_address) == 6);
1182
1183           clib_memcpy (eth0->dst_address, eth0->src_address, 6);
1184           clib_memcpy (eth0->src_address, hw_if0->hw_address, 6);
1185
1186           /* Figure out how much to rewind current data from adjacency. */
1187           /* get the adj from the destination's covering connected */
1188           if (NULL == pa)
1189             {
1190               adj0 =
1191                 adj_get (fib_entry_get_adj_for_source
1192                          (ip4_fib_table_lookup
1193                           (ip4_fib_get (fib_index0),
1194                            &arp0->ip4_over_ethernet[1].ip4, 31),
1195                           FIB_SOURCE_INTERFACE));
1196               if (adj0->lookup_next_index != IP_LOOKUP_NEXT_GLEAN)
1197                 {
1198                   error0 = ETHERNET_ARP_ERROR_missing_interface_address;
1199                   goto drop2;
1200                 }
1201               if (is_unnum0)
1202                 {
1203                   if (!arp_unnumbered (p0, pi0, eth0, conn_sw_if_index0))
1204                     goto drop2;
1205                 }
1206               else
1207                 vlib_buffer_advance (p0, -adj0->rewrite_header.data_bytes);
1208             }
1209           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1210                                            n_left_to_next, pi0, next0);
1211
1212           n_replies_sent += 1;
1213           continue;
1214
1215         drop1:
1216           if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1217               (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1218                arp0->ip4_over_ethernet[1].ip4.as_u32))
1219             {
1220               error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1221               goto drop2;
1222             }
1223           /* See if proxy arp is configured for the address */
1224           if (is_request0)
1225             {
1226               vnet_sw_interface_t *si;
1227               u32 this_addr = clib_net_to_host_u32
1228                 (arp0->ip4_over_ethernet[1].ip4.as_u32);
1229               u32 fib_index0;
1230
1231               si = vnet_get_sw_interface (vnm, sw_if_index0);
1232
1233               if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP))
1234                 goto drop2;
1235
1236               fib_index0 = vec_elt (im4->fib_index_by_sw_if_index,
1237                                     sw_if_index0);
1238
1239               vec_foreach (pa, am->proxy_arps)
1240               {
1241                 u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
1242                 u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
1243
1244                 /* an ARP request hit in the proxy-arp table? */
1245                 if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1246                     (fib_index0 == pa->fib_index))
1247                   {
1248                     eth0 = ethernet_buffer_get_header (p0);
1249                     proxy_src.as_u32 =
1250                       arp0->ip4_over_ethernet[1].ip4.data_u32;
1251
1252                     /*
1253                      * Rewind buffer, direct code above not to
1254                      * think too hard about it.
1255                      */
1256                     if_addr0 = &proxy_src;
1257                     is_unnum0 = 0;
1258                     i32 ethernet_start =
1259                       vnet_buffer (p0)->ethernet.start_of_ethernet_header;
1260                     i32 rewind = p0->current_data - ethernet_start;
1261                     vlib_buffer_advance (p0, -rewind);
1262                     n_proxy_arp_replies_sent++;
1263                     goto send_reply;
1264                   }
1265               }
1266             }
1267
1268         drop2:
1269
1270           next0 = ARP_INPUT_NEXT_DROP;
1271           p0->error = node->errors[error0];
1272
1273           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1274                                            n_left_to_next, pi0, next0);
1275         }
1276
1277       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1278     }
1279
1280   vlib_error_count (vm, node->node_index,
1281                     ETHERNET_ARP_ERROR_replies_sent,
1282                     n_replies_sent - n_proxy_arp_replies_sent);
1283
1284   vlib_error_count (vm, node->node_index,
1285                     ETHERNET_ARP_ERROR_proxy_arp_replies_sent,
1286                     n_proxy_arp_replies_sent);
1287   return frame->n_vectors;
1288 }
1289
1290 static char *ethernet_arp_error_strings[] = {
1291 #define _(sym,string) string,
1292   foreach_ethernet_arp_error
1293 #undef _
1294 };
1295
1296 /* *INDENT-OFF* */
1297 VLIB_REGISTER_NODE (arp_input_node, static) =
1298 {
1299   .function = arp_input,
1300   .name = "arp-input",
1301   .vector_size = sizeof (u32),
1302   .n_errors = ETHERNET_ARP_N_ERROR,
1303   .error_strings = ethernet_arp_error_strings,
1304   .n_next_nodes = ARP_INPUT_N_NEXT,
1305   .next_nodes = {
1306     [ARP_INPUT_NEXT_DROP] = "error-drop",
1307     [ARP_INPUT_NEXT_REPLY_TX] = "interface-output",
1308   },
1309   .format_buffer = format_ethernet_arp_header,
1310   .format_trace = format_ethernet_arp_input_trace,
1311 };
1312 /* *INDENT-ON* */
1313
1314 static int
1315 ip4_arp_entry_sort (void *a1, void *a2)
1316 {
1317   ethernet_arp_ip4_entry_t *e1 = a1;
1318   ethernet_arp_ip4_entry_t *e2 = a2;
1319
1320   int cmp;
1321   vnet_main_t *vnm = vnet_get_main ();
1322
1323   cmp = vnet_sw_interface_compare (vnm, e1->sw_if_index, e2->sw_if_index);
1324   if (!cmp)
1325     cmp = ip4_address_compare (&e1->ip4_address, &e2->ip4_address);
1326   return cmp;
1327 }
1328
1329 ethernet_arp_ip4_entry_t *
1330 ip4_neighbor_entries (u32 sw_if_index)
1331 {
1332   ethernet_arp_main_t *am = &ethernet_arp_main;
1333   ethernet_arp_ip4_entry_t *n, *ns = 0;
1334
1335   /* *INDENT-OFF* */
1336   pool_foreach (n, am->ip4_entry_pool, ({
1337     if (sw_if_index != ~0 && n->sw_if_index != sw_if_index)
1338       continue;
1339     vec_add1 (ns, n[0]);
1340   }));
1341   /* *INDENT-ON* */
1342
1343   if (ns)
1344     vec_sort_with_function (ns, ip4_arp_entry_sort);
1345   return ns;
1346 }
1347
1348 static clib_error_t *
1349 show_ip4_arp (vlib_main_t * vm,
1350               unformat_input_t * input, vlib_cli_command_t * cmd)
1351 {
1352   vnet_main_t *vnm = vnet_get_main ();
1353   ethernet_arp_main_t *am = &ethernet_arp_main;
1354   ethernet_arp_ip4_entry_t *e, *es;
1355   ethernet_proxy_arp_t *pa;
1356   clib_error_t *error = 0;
1357   u32 sw_if_index;
1358
1359   /* Filter entries by interface if given. */
1360   sw_if_index = ~0;
1361   (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1362
1363   es = ip4_neighbor_entries (sw_if_index);
1364   if (es)
1365     {
1366       vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1367       vec_foreach (e, es)
1368       {
1369         vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1370       }
1371       vec_free (es);
1372     }
1373
1374   if (vec_len (am->proxy_arps))
1375     {
1376       vlib_cli_output (vm, "Proxy arps enabled for:");
1377       vec_foreach (pa, am->proxy_arps)
1378       {
1379         vlib_cli_output (vm, "Fib_index %d   %U - %U ",
1380                          pa->fib_index,
1381                          format_ip4_address, &pa->lo_addr,
1382                          format_ip4_address, &pa->hi_addr);
1383       }
1384     }
1385
1386   return error;
1387 }
1388
1389 /*?
1390  * Display all the IPv4 ARP entries.
1391  *
1392  * @cliexpar
1393  * Example of how to display the IPv4 ARP table:
1394  * @cliexstart{show ip arp}
1395  *    Time      FIB        IP4       Flags      Ethernet              Interface
1396  *    346.3028   0       6.1.1.3            de:ad:be:ef:ba:be   GigabitEthernet2/0/0
1397  *   3077.4271   0       6.1.1.4       S    de:ad:be:ef:ff:ff   GigabitEthernet2/0/0
1398  *   2998.6409   1       6.2.2.3            de:ad:be:ef:00:01   GigabitEthernet2/0/0
1399  * Proxy arps enabled for:
1400  * Fib_index 0   6.0.0.1 - 6.0.0.11
1401  * @cliexend
1402  ?*/
1403 /* *INDENT-OFF* */
1404 VLIB_CLI_COMMAND (show_ip4_arp_command, static) = {
1405   .path = "show ip arp",
1406   .function = show_ip4_arp,
1407   .short_help = "show ip arp",
1408 };
1409 /* *INDENT-ON* */
1410
1411 typedef struct
1412 {
1413   pg_edit_t l2_type, l3_type;
1414   pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1415   pg_edit_t opcode;
1416   struct
1417   {
1418     pg_edit_t ethernet;
1419     pg_edit_t ip4;
1420   } ip4_over_ethernet[2];
1421 } pg_ethernet_arp_header_t;
1422
1423 static inline void
1424 pg_ethernet_arp_header_init (pg_ethernet_arp_header_t * p)
1425 {
1426   /* Initialize fields that are not bit fields in the IP header. */
1427 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1428   _(l2_type);
1429   _(l3_type);
1430   _(n_l2_address_bytes);
1431   _(n_l3_address_bytes);
1432   _(opcode);
1433   _(ip4_over_ethernet[0].ethernet);
1434   _(ip4_over_ethernet[0].ip4);
1435   _(ip4_over_ethernet[1].ethernet);
1436   _(ip4_over_ethernet[1].ip4);
1437 #undef _
1438 }
1439
1440 uword
1441 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1442 {
1443   pg_stream_t *s = va_arg (*args, pg_stream_t *);
1444   pg_ethernet_arp_header_t *p;
1445   u32 group_index;
1446
1447   p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1448                             &group_index);
1449   pg_ethernet_arp_header_init (p);
1450
1451   /* Defaults. */
1452   pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1453   pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1454   pg_edit_set_fixed (&p->n_l2_address_bytes, 6);
1455   pg_edit_set_fixed (&p->n_l3_address_bytes, 4);
1456
1457   if (!unformat (input, "%U: %U/%U -> %U/%U",
1458                  unformat_pg_edit,
1459                  unformat_ethernet_arp_opcode_net_byte_order, &p->opcode,
1460                  unformat_pg_edit,
1461                  unformat_ethernet_address, &p->ip4_over_ethernet[0].ethernet,
1462                  unformat_pg_edit,
1463                  unformat_ip4_address, &p->ip4_over_ethernet[0].ip4,
1464                  unformat_pg_edit,
1465                  unformat_ethernet_address, &p->ip4_over_ethernet[1].ethernet,
1466                  unformat_pg_edit,
1467                  unformat_ip4_address, &p->ip4_over_ethernet[1].ip4))
1468     {
1469       /* Free up any edits we may have added. */
1470       pg_free_edit_group (s);
1471       return 0;
1472     }
1473   return 1;
1474 }
1475
1476 clib_error_t *
1477 ip4_set_arp_limit (u32 arp_limit)
1478 {
1479   ethernet_arp_main_t *am = &ethernet_arp_main;
1480
1481   am->limit_arp_cache_size = arp_limit;
1482   return 0;
1483 }
1484
1485 /**
1486  * @brief Control Plane hook to remove an ARP entry
1487  */
1488 int
1489 vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
1490                                   u32 sw_if_index, void *a_arg)
1491 {
1492   ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1493   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1494
1495   args.sw_if_index = sw_if_index;
1496   args.flags = ETHERNET_ARP_ARGS_REMOVE;
1497   clib_memcpy (&args.a, a, sizeof (*a));
1498
1499   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1500                                (u8 *) & args, sizeof (args));
1501   return 0;
1502 }
1503
1504 /**
1505  * @brief Internally generated event to flush the ARP cache on an
1506  * interface state change event.
1507  * A flush will remove dynamic ARP entries, and for statics remove the MAC
1508  * address from the corresponding adjacencies.
1509  */
1510 static int
1511 vnet_arp_flush_ip4_over_ethernet (vnet_main_t * vnm,
1512                                   u32 sw_if_index, void *a_arg)
1513 {
1514   ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1515   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1516
1517   args.sw_if_index = sw_if_index;
1518   args.flags = ETHERNET_ARP_ARGS_FLUSH;
1519   clib_memcpy (&args.a, a, sizeof (*a));
1520
1521   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1522                                (u8 *) & args, sizeof (args));
1523   return 0;
1524 }
1525
1526 /**
1527  * @brief Internally generated event to populate the ARP cache on an
1528  * interface state change event.
1529  * For static entries this will re-source the adjacencies.
1530  *
1531  * @param sw_if_index The interface on which the ARP entires are acted
1532  */
1533 static int
1534 vnet_arp_populate_ip4_over_ethernet (vnet_main_t * vnm,
1535                                      u32 sw_if_index, void *a_arg)
1536 {
1537   ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1538   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1539
1540   args.sw_if_index = sw_if_index;
1541   args.flags = ETHERNET_ARP_ARGS_POPULATE;
1542   clib_memcpy (&args.a, a, sizeof (*a));
1543
1544   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1545                                (u8 *) & args, sizeof (args));
1546   return 0;
1547 }
1548
1549 /*
1550  * arp_add_del_interface_address
1551  *
1552  * callback when an interface address is added or deleted
1553  */
1554 static void
1555 arp_add_del_interface_address (ip4_main_t * im,
1556                                uword opaque,
1557                                u32 sw_if_index,
1558                                ip4_address_t * address,
1559                                u32 address_length,
1560                                u32 if_address_index, u32 is_del)
1561 {
1562   /*
1563    * Flush the ARP cache of all entries covered by the address
1564    * that is being removed.
1565    */
1566   ethernet_arp_main_t *am = &ethernet_arp_main;
1567   ethernet_arp_ip4_entry_t *e;
1568
1569   if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
1570     return;
1571
1572   if (is_del)
1573     {
1574       ethernet_arp_interface_t *eai;
1575       u32 i, *to_delete = 0;
1576       hash_pair_t *pair;
1577
1578       eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
1579
1580       /* *INDENT-OFF* */
1581       hash_foreach_pair (pair, eai->arp_entries,
1582       ({
1583         e = pool_elt_at_index(am->ip4_entry_pool,
1584                               pair->value[0]);
1585         if (ip4_destination_matches_route (im, &e->ip4_address,
1586                                            address, address_length))
1587           {
1588             vec_add1 (to_delete, e - am->ip4_entry_pool);
1589           }
1590       }));
1591       /* *INDENT-ON* */
1592
1593       for (i = 0; i < vec_len (to_delete); i++)
1594         {
1595           ethernet_arp_ip4_over_ethernet_address_t delme;
1596           e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1597
1598           clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1599           delme.ip4.as_u32 = e->ip4_address.as_u32;
1600
1601           vnet_arp_flush_ip4_over_ethernet (vnet_get_main (),
1602                                             e->sw_if_index, &delme);
1603         }
1604
1605       vec_free (to_delete);
1606     }
1607 }
1608
1609 static clib_error_t *
1610 ethernet_arp_init (vlib_main_t * vm)
1611 {
1612   ethernet_arp_main_t *am = &ethernet_arp_main;
1613   ip4_main_t *im = &ip4_main;
1614   clib_error_t *error;
1615   pg_node_t *pn;
1616
1617   if ((error = vlib_call_init_function (vm, ethernet_init)))
1618     return error;
1619
1620   ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
1621
1622   pn = pg_get_node (arp_input_node.index);
1623   pn->unformat_edit = unformat_pg_arp_header;
1624
1625   am->opcode_by_name = hash_create_string (0, sizeof (uword));
1626 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
1627   foreach_ethernet_arp_opcode;
1628 #undef _
1629
1630   /* $$$ configurable */
1631   am->limit_arp_cache_size = 50000;
1632
1633   am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
1634   am->mac_changes_by_address = hash_create (0, sizeof (uword));
1635
1636   /* don't trace ARP error packets */
1637   {
1638     vlib_node_runtime_t *rt =
1639       vlib_node_get_runtime (vm, arp_input_node.index);
1640
1641 #define _(a,b)                                  \
1642     vnet_pcap_drop_trace_filter_add_del         \
1643         (rt->errors[ETHERNET_ARP_ERROR_##a],    \
1644          1 /* is_add */);
1645     foreach_ethernet_arp_error
1646 #undef _
1647   }
1648
1649   ip4_add_del_interface_address_callback_t cb;
1650   cb.function = arp_add_del_interface_address;
1651   cb.function_opaque = 0;
1652   vec_add1 (im->add_del_interface_address_callbacks, cb);
1653
1654   return 0;
1655 }
1656
1657 VLIB_INIT_FUNCTION (ethernet_arp_init);
1658
1659 static void
1660 arp_entry_free (ethernet_arp_interface_t * eai, ethernet_arp_ip4_entry_t * e)
1661 {
1662   ethernet_arp_main_t *am = &ethernet_arp_main;
1663
1664   /* it's safe to delete the ADJ source on the FIB entry, even if it
1665    * was added */
1666   fib_table_entry_delete_index (e->fib_entry_index, FIB_SOURCE_ADJ);
1667   hash_unset (eai->arp_entries, e->ip4_address.as_u32);
1668   pool_put (am->ip4_entry_pool, e);
1669 }
1670
1671 static inline int
1672 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
1673                                            vnet_arp_set_ip4_over_ethernet_rpc_args_t
1674                                            * args)
1675 {
1676   ethernet_arp_main_t *am = &ethernet_arp_main;
1677   ethernet_arp_ip4_entry_t *e;
1678   ethernet_arp_interface_t *eai;
1679
1680   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1681
1682   e = arp_entry_find (eai, &args->a.ip4);
1683
1684   if (NULL != e)
1685     {
1686       arp_entry_free (eai, e);
1687
1688       adj_nbr_walk_nh4 (e->sw_if_index,
1689                         &e->ip4_address, arp_mk_incomplete_walk, NULL);
1690     }
1691
1692   return 0;
1693 }
1694
1695 static int
1696 vnet_arp_flush_ip4_over_ethernet_internal (vnet_main_t * vnm,
1697                                            vnet_arp_set_ip4_over_ethernet_rpc_args_t
1698                                            * args)
1699 {
1700   ethernet_arp_main_t *am = &ethernet_arp_main;
1701   ethernet_arp_ip4_entry_t *e;
1702   ethernet_arp_interface_t *eai;
1703
1704   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1705
1706   e = arp_entry_find (eai, &args->a.ip4);
1707
1708   if (NULL != e)
1709     {
1710       adj_nbr_walk_nh4 (e->sw_if_index,
1711                         &e->ip4_address, arp_mk_incomplete_walk, e);
1712
1713       /*
1714        * The difference between flush and unset, is that an unset
1715        * means delete for static and dynamic entries. A flush
1716        * means delete only for dynamic. Flushing is what the DP
1717        * does in response to interface events. unset is only done
1718        * by the control plane.
1719        */
1720       if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC)
1721         {
1722           arp_entry_free (eai, e);
1723         }
1724     }
1725   return (0);
1726 }
1727
1728 static int
1729 vnet_arp_populate_ip4_over_ethernet_internal (vnet_main_t * vnm,
1730                                               vnet_arp_set_ip4_over_ethernet_rpc_args_t
1731                                               * args)
1732 {
1733   ethernet_arp_main_t *am = &ethernet_arp_main;
1734   ethernet_arp_ip4_entry_t *e;
1735   ethernet_arp_interface_t *eai;
1736
1737   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1738
1739   e = arp_entry_find (eai, &args->a.ip4);
1740
1741   if (NULL != e)
1742     {
1743       adj_nbr_walk_nh4 (e->sw_if_index,
1744                         &e->ip4_address, arp_mk_complete_walk, e);
1745     }
1746   return (0);
1747 }
1748
1749 static void
1750 set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t
1751                                     * a)
1752 {
1753   vnet_main_t *vm = vnet_get_main ();
1754   ASSERT (os_get_cpu_number () == 0);
1755
1756   if (a->flags & ETHERNET_ARP_ARGS_REMOVE)
1757     vnet_arp_unset_ip4_over_ethernet_internal (vm, a);
1758   else if (a->flags & ETHERNET_ARP_ARGS_FLUSH)
1759     vnet_arp_flush_ip4_over_ethernet_internal (vm, a);
1760   else if (a->flags & ETHERNET_ARP_ARGS_POPULATE)
1761     vnet_arp_populate_ip4_over_ethernet_internal (vm, a);
1762   else
1763     vnet_arp_set_ip4_over_ethernet_internal (vm, a);
1764 }
1765
1766 /**
1767  * @brief Invoked when the interface's admin state changes
1768  */
1769 static clib_error_t *
1770 ethernet_arp_sw_interface_up_down (vnet_main_t * vnm,
1771                                    u32 sw_if_index, u32 flags)
1772 {
1773   ethernet_arp_main_t *am = &ethernet_arp_main;
1774   ethernet_arp_ip4_entry_t *e;
1775   u32 i, *to_delete = 0;
1776
1777   /* *INDENT-OFF* */
1778   pool_foreach (e, am->ip4_entry_pool,
1779   ({
1780     if (e->sw_if_index == sw_if_index)
1781       vec_add1 (to_delete,
1782                 e - am->ip4_entry_pool);
1783   }));
1784   /* *INDENT-ON* */
1785
1786   for (i = 0; i < vec_len (to_delete); i++)
1787     {
1788       ethernet_arp_ip4_over_ethernet_address_t delme;
1789       e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1790
1791       clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1792       delme.ip4.as_u32 = e->ip4_address.as_u32;
1793
1794       if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1795         {
1796           vnet_arp_populate_ip4_over_ethernet (vnm, e->sw_if_index, &delme);
1797         }
1798       else
1799         {
1800           vnet_arp_flush_ip4_over_ethernet (vnm, e->sw_if_index, &delme);
1801         }
1802
1803     }
1804   vec_free (to_delete);
1805
1806   return 0;
1807 }
1808
1809 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_arp_sw_interface_up_down);
1810
1811 static void
1812 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t * a)
1813 {
1814   u8 old;
1815   int i;
1816
1817   for (i = 3; i >= 0; i--)
1818     {
1819       old = a->ip4.as_u8[i];
1820       a->ip4.as_u8[i] += 1;
1821       if (old < a->ip4.as_u8[i])
1822         break;
1823     }
1824
1825   for (i = 5; i >= 0; i--)
1826     {
1827       old = a->ethernet[i];
1828       a->ethernet[i] += 1;
1829       if (old < a->ethernet[i])
1830         break;
1831     }
1832 }
1833
1834 int
1835 vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
1836                                 u32 sw_if_index, void *a_arg,
1837                                 int is_static, int is_no_fib_entry)
1838 {
1839   ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1840   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1841
1842   args.sw_if_index = sw_if_index;
1843   args.is_static = is_static;
1844   args.is_no_fib_entry = is_no_fib_entry;
1845   args.flags = 0;
1846   clib_memcpy (&args.a, a, sizeof (*a));
1847
1848   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1849                                (u8 *) & args, sizeof (args));
1850   return 0;
1851 }
1852
1853 int
1854 vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
1855                         ip4_address_t * hi_addr, u32 fib_index, int is_del)
1856 {
1857   ethernet_arp_main_t *am = &ethernet_arp_main;
1858   ethernet_proxy_arp_t *pa;
1859   u32 found_at_index = ~0;
1860
1861   vec_foreach (pa, am->proxy_arps)
1862   {
1863     if (pa->lo_addr == lo_addr->as_u32
1864         && pa->hi_addr == hi_addr->as_u32 && pa->fib_index == fib_index)
1865       {
1866         found_at_index = pa - am->proxy_arps;
1867         break;
1868       }
1869   }
1870
1871   if (found_at_index != ~0)
1872     {
1873       /* Delete, otherwise it's already in the table */
1874       if (is_del)
1875         vec_delete (am->proxy_arps, 1, found_at_index);
1876       return 0;
1877     }
1878   /* delete, no such entry */
1879   if (is_del)
1880     return VNET_API_ERROR_NO_SUCH_ENTRY;
1881
1882   /* add, not in table */
1883   vec_add2 (am->proxy_arps, pa, 1);
1884   pa->lo_addr = lo_addr->as_u32;
1885   pa->hi_addr = hi_addr->as_u32;
1886   pa->fib_index = fib_index;
1887   return 0;
1888 }
1889
1890 /*
1891  * Remove any proxy arp entries asdociated with the
1892  * specificed fib.
1893  */
1894 int
1895 vnet_proxy_arp_fib_reset (u32 fib_id)
1896 {
1897   ip4_main_t *im = &ip4_main;
1898   ethernet_arp_main_t *am = &ethernet_arp_main;
1899   ethernet_proxy_arp_t *pa;
1900   u32 *entries_to_delete = 0;
1901   u32 fib_index;
1902   uword *p;
1903   int i;
1904
1905   p = hash_get (im->fib_index_by_table_id, fib_id);
1906   if (!p)
1907     return VNET_API_ERROR_NO_SUCH_ENTRY;
1908   fib_index = p[0];
1909
1910   vec_foreach (pa, am->proxy_arps)
1911   {
1912     if (pa->fib_index == fib_index)
1913       {
1914         vec_add1 (entries_to_delete, pa - am->proxy_arps);
1915       }
1916   }
1917
1918   for (i = 0; i < vec_len (entries_to_delete); i++)
1919     {
1920       vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
1921     }
1922
1923   vec_free (entries_to_delete);
1924
1925   return 0;
1926 }
1927
1928 static clib_error_t *
1929 ip_arp_add_del_command_fn (vlib_main_t * vm,
1930                            unformat_input_t * input, vlib_cli_command_t * cmd)
1931 {
1932   vnet_main_t *vnm = vnet_get_main ();
1933   u32 sw_if_index;
1934   ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
1935   int addr_valid = 0;
1936   int is_del = 0;
1937   int count = 1;
1938   u32 fib_index = 0;
1939   u32 fib_id;
1940   int is_static = 0;
1941   int is_no_fib_entry = 0;
1942   int is_proxy = 0;
1943
1944   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1945     {
1946       /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
1947       if (unformat (input, "%U %U %U",
1948                     unformat_vnet_sw_interface, vnm, &sw_if_index,
1949                     unformat_ip4_address, &addr.ip4,
1950                     unformat_ethernet_address, &addr.ethernet))
1951         addr_valid = 1;
1952
1953       else if (unformat (input, "delete") || unformat (input, "del"))
1954         is_del = 1;
1955
1956       else if (unformat (input, "static"))
1957         is_static = 1;
1958
1959       else if (unformat (input, "no-fib-entry"))
1960         is_no_fib_entry = 1;
1961
1962       else if (unformat (input, "count %d", &count))
1963         ;
1964
1965       else if (unformat (input, "fib-id %d", &fib_id))
1966         {
1967           ip4_main_t *im = &ip4_main;
1968           uword *p = hash_get (im->fib_index_by_table_id, fib_id);
1969           if (!p)
1970             return clib_error_return (0, "fib ID %d doesn't exist\n", fib_id);
1971           fib_index = p[0];
1972         }
1973
1974       else if (unformat (input, "proxy %U - %U",
1975                          unformat_ip4_address, &lo_addr.ip4,
1976                          unformat_ip4_address, &hi_addr.ip4))
1977         is_proxy = 1;
1978       else
1979         break;
1980     }
1981
1982   if (is_proxy)
1983     {
1984       (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4,
1985                                      fib_index, is_del);
1986       return 0;
1987     }
1988
1989   if (addr_valid)
1990     {
1991       int i;
1992
1993       for (i = 0; i < count; i++)
1994         {
1995           if (is_del == 0)
1996             {
1997               uword event_type, *event_data = 0;
1998
1999               /* Park the debug CLI until the arp entry is installed */
2000               vnet_register_ip4_arp_resolution_event
2001                 (vnm, &addr.ip4, vlib_current_process (vm),
2002                  1 /* type */ , 0 /* data */ );
2003
2004               vnet_arp_set_ip4_over_ethernet
2005                 (vnm, sw_if_index, &addr, is_static, is_no_fib_entry);
2006
2007               vlib_process_wait_for_event (vm);
2008               event_type = vlib_process_get_events (vm, &event_data);
2009               vec_reset_length (event_data);
2010               if (event_type != 1)
2011                 clib_warning ("event type %d unexpected", event_type);
2012             }
2013           else
2014             vnet_arp_unset_ip4_over_ethernet (vnm, sw_if_index, &addr);
2015
2016           increment_ip4_and_mac_address (&addr);
2017         }
2018     }
2019   else
2020     {
2021       return clib_error_return (0, "unknown input `%U'",
2022                                 format_unformat_error, input);
2023     }
2024
2025   return 0;
2026 }
2027
2028 /* *INDENT-OFF* */
2029 /*?
2030  * Add or delete IPv4 ARP cache entries.
2031  *
2032  * @note 'set ip arp' options (e.g. delete, static, 'fib-id <id>',
2033  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
2034  * any order and combination.
2035  *
2036  * @cliexpar
2037  * @parblock
2038  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
2039  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
2040  * @cliexcmd{set ip arp GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2041  * @cliexcmd{set ip arp delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
2042  *
2043  * To add or delete an IPv4 ARP cache entry to or from a specific fib
2044  * table:
2045  * @cliexcmd{set ip arp fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2046  * @cliexcmd{set ip arp fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2047  *
2048  * Add or delete IPv4 static ARP cache entries as follows:
2049  * @cliexcmd{set ip arp static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2050  * @cliexcmd{set ip arp static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2051  *
2052  * For testing / debugging purposes, the 'set ip arp' command can add or
2053  * delete multiple entries. Supply the 'count N' parameter:
2054  * @cliexcmd{set ip arp count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2055  * @endparblock
2056  ?*/
2057 VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = {
2058   .path = "set ip arp",
2059   .short_help =
2060   "set ip arp [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
2061   .function = ip_arp_add_del_command_fn,
2062 };
2063 /* *INDENT-ON* */
2064
2065 static clib_error_t *
2066 set_int_proxy_arp_command_fn (vlib_main_t * vm,
2067                               unformat_input_t *
2068                               input, vlib_cli_command_t * cmd)
2069 {
2070   vnet_main_t *vnm = vnet_get_main ();
2071   u32 sw_if_index;
2072   vnet_sw_interface_t *si;
2073   int enable = 0;
2074   int intfc_set = 0;
2075
2076   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2077     {
2078       if (unformat (input, "%U", unformat_vnet_sw_interface,
2079                     vnm, &sw_if_index))
2080         intfc_set = 1;
2081       else if (unformat (input, "enable") || unformat (input, "on"))
2082         enable = 1;
2083       else if (unformat (input, "disable") || unformat (input, "off"))
2084         enable = 0;
2085       else
2086         break;
2087     }
2088
2089   if (intfc_set == 0)
2090     return clib_error_return (0, "unknown input '%U'",
2091                               format_unformat_error, input);
2092
2093   si = vnet_get_sw_interface (vnm, sw_if_index);
2094   ASSERT (si);
2095   if (enable)
2096     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2097   else
2098     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2099
2100   return 0;
2101 }
2102
2103 /* *INDENT-OFF* */
2104 /*?
2105  * Enable proxy-arp on an interface. The vpp stack will answer ARP
2106  * requests for the indicated address range. Multiple proxy-arp
2107  * ranges may be provisioned.
2108  *
2109  * @note Proxy ARP as a technology is infamous for blackholing traffic.
2110  * Also, the underlying implementation has not been performance-tuned.
2111  * Avoid creating an unnecessarily large set of ranges.
2112  *
2113  * @cliexpar
2114  * To enable proxy arp on a range of addresses, use:
2115  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11}
2116  * Append 'del' to delete a range of proxy ARP addresses:
2117  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11 del}
2118  * You must then specifically enable proxy arp on individual interfaces:
2119  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 enable}
2120  * To disable proxy arp on an individual interface:
2121  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 disable}
2122  ?*/
2123 VLIB_CLI_COMMAND (set_int_proxy_enable_command, static) = {
2124   .path = "set interface proxy-arp",
2125   .short_help =
2126   "set interface proxy-arp <intfc> [enable|disable]",
2127   .function = set_int_proxy_arp_command_fn,
2128 };
2129 /* *INDENT-ON* */
2130
2131
2132 /*
2133  * ARP/ND Termination in a L2 Bridge Domain based on IP4/IP6 to MAC
2134  * hash tables mac_by_ip4 and mac_by_ip6 for each BD.
2135  */
2136 typedef enum
2137 {
2138   ARP_TERM_NEXT_L2_OUTPUT,
2139   ARP_TERM_NEXT_DROP,
2140   ARP_TERM_N_NEXT,
2141 } arp_term_next_t;
2142
2143 u32 arp_term_next_node_index[32];
2144
2145 static uword
2146 arp_term_l2bd (vlib_main_t * vm,
2147                vlib_node_runtime_t * node, vlib_frame_t * frame)
2148 {
2149   l2input_main_t *l2im = &l2input_main;
2150   u32 n_left_from, next_index, *from, *to_next;
2151   u32 n_replies_sent = 0;
2152   u16 last_bd_index = ~0;
2153   l2_bridge_domain_t *last_bd_config = 0;
2154   l2_input_config_t *cfg0;
2155
2156   from = vlib_frame_vector_args (frame);
2157   n_left_from = frame->n_vectors;
2158   next_index = node->cached_next_index;
2159
2160   while (n_left_from > 0)
2161     {
2162       u32 n_left_to_next;
2163
2164       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2165
2166       while (n_left_from > 0 && n_left_to_next > 0)
2167         {
2168           vlib_buffer_t *p0;
2169           ethernet_header_t *eth0;
2170           ethernet_arp_header_t *arp0;
2171           ip6_header_t *iph0;
2172           u8 *l3h0;
2173           u32 pi0, error0, next0, sw_if_index0;
2174           u16 ethertype0;
2175           u16 bd_index0;
2176           u32 ip0;
2177           u8 *macp0;
2178
2179           pi0 = from[0];
2180           to_next[0] = pi0;
2181           from += 1;
2182           to_next += 1;
2183           n_left_from -= 1;
2184           n_left_to_next -= 1;
2185
2186           p0 = vlib_get_buffer (vm, pi0);
2187           eth0 = vlib_buffer_get_current (p0);
2188           l3h0 = (u8 *) eth0 + vnet_buffer (p0)->l2.l2_len;
2189           ethertype0 = clib_net_to_host_u16 (*(u16 *) (l3h0 - 2));
2190           arp0 = (ethernet_arp_header_t *) l3h0;
2191
2192           if (PREDICT_FALSE ((ethertype0 != ETHERNET_TYPE_ARP) ||
2193                              (arp0->opcode !=
2194                               clib_host_to_net_u16
2195                               (ETHERNET_ARP_OPCODE_request))))
2196             goto check_ip6_nd;
2197
2198           /* Must be ARP request packet here */
2199           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
2200                              (p0->flags & VLIB_BUFFER_IS_TRACED)))
2201             {
2202               u8 *t0 = vlib_add_trace (vm, node, p0,
2203                                        sizeof (ethernet_arp_input_trace_t));
2204               clib_memcpy (t0, l3h0, sizeof (ethernet_arp_input_trace_t));
2205             }
2206
2207           error0 = ETHERNET_ARP_ERROR_replies_sent;
2208           error0 =
2209             (arp0->l2_type !=
2210              clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
2211              ? ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
2212           error0 =
2213             (arp0->l3_type !=
2214              clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
2215              ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
2216
2217           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2218
2219           if (error0)
2220             goto drop;
2221
2222           /* Trash ARP packets whose ARP-level source addresses do not
2223              match their L2-frame-level source addresses  */
2224           if (PREDICT_FALSE
2225               (memcmp
2226                (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
2227                 sizeof (eth0->src_address))))
2228             {
2229               error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
2230               goto drop;
2231             }
2232
2233           /* Check if anyone want ARP request events for L2 BDs */
2234           {
2235             pending_resolution_t *mc;
2236             ethernet_arp_main_t *am = &ethernet_arp_main;
2237             uword *p = hash_get (am->mac_changes_by_address, 0);
2238             if (p && (vnet_buffer (p0)->l2.shg == 0))
2239               {                 // Only SHG 0 interface which is more likely local
2240                 u32 next_index = p[0];
2241                 while (next_index != (u32) ~ 0)
2242                   {
2243                     int (*fp) (u32, u8 *, u32, u32);
2244                     int rv = 1;
2245                     mc = pool_elt_at_index (am->mac_changes, next_index);
2246                     fp = mc->data_callback;
2247                     /* Call the callback, return 1 to suppress dup events */
2248                     if (fp)
2249                       rv = (*fp) (mc->data,
2250                                   arp0->ip4_over_ethernet[0].ethernet,
2251                                   sw_if_index0,
2252                                   arp0->ip4_over_ethernet[0].ip4.as_u32);
2253                     /* Signal the resolver process */
2254                     if (rv == 0)
2255                       vlib_process_signal_event (vm, mc->node_index,
2256                                                  mc->type_opaque, mc->data);
2257                     next_index = mc->next_index;
2258                   }
2259               }
2260           }
2261
2262           /* lookup BD mac_by_ip4 hash table for MAC entry */
2263           ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
2264           bd_index0 = vnet_buffer (p0)->l2.bd_index;
2265           if (PREDICT_FALSE ((bd_index0 != last_bd_index)
2266                              || (last_bd_index == (u16) ~ 0)))
2267             {
2268               last_bd_index = bd_index0;
2269               last_bd_config = vec_elt_at_index (l2im->bd_configs, bd_index0);
2270             }
2271           macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
2272
2273           if (PREDICT_FALSE (!macp0))
2274             goto next_l2_feature;       /* MAC not found */
2275
2276           /* MAC found, send ARP reply -
2277              Convert ARP request packet to ARP reply */
2278           arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
2279           arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
2280           arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
2281           clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
2282           clib_memcpy (eth0->dst_address, eth0->src_address, 6);
2283           clib_memcpy (eth0->src_address, macp0, 6);
2284           n_replies_sent += 1;
2285
2286         output_response:
2287           /* For BVI, need to use l2-fwd node to send ARP reply as
2288              l2-output node cannot output packet to BVI properly */
2289           cfg0 = vec_elt_at_index (l2im->configs, sw_if_index0);
2290           if (PREDICT_FALSE (cfg0->bvi))
2291             {
2292               vnet_buffer (p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
2293               vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
2294               goto next_l2_feature;
2295             }
2296
2297           /* Send ARP/ND reply back out input interface through l2-output */
2298           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2299           next0 = ARP_TERM_NEXT_L2_OUTPUT;
2300           /* Note that output to VXLAN tunnel will fail due to SHG which
2301              is probably desireable since ARP termination is not intended
2302              for ARP requests from other hosts. If output to VXLAN tunnel is
2303              required, however, can just clear the SHG in packet as follows:
2304              vnet_buffer(p0)->l2.shg = 0;         */
2305           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2306                                            to_next, n_left_to_next, pi0,
2307                                            next0);
2308           continue;
2309
2310         check_ip6_nd:
2311           /* IP6 ND event notification or solicitation handling to generate
2312              local response instead of flooding */
2313           iph0 = (ip6_header_t *) l3h0;
2314           if (PREDICT_FALSE (ethertype0 == ETHERNET_TYPE_IP6 &&
2315                              iph0->protocol == IP_PROTOCOL_ICMP6 &&
2316                              !ip6_address_is_unspecified
2317                              (&iph0->src_address)))
2318             {
2319               sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2320               if (vnet_ip6_nd_term
2321                   (vm, node, p0, eth0, iph0, sw_if_index0,
2322                    vnet_buffer (p0)->l2.bd_index, vnet_buffer (p0)->l2.shg))
2323                 goto output_response;
2324             }
2325
2326         next_l2_feature:
2327           {
2328             u32 feature_bitmap0 =
2329               vnet_buffer (p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM;
2330             vnet_buffer (p0)->l2.feature_bitmap = feature_bitmap0;
2331             next0 =
2332               feat_bitmap_get_next_node_index (arp_term_next_node_index,
2333                                                feature_bitmap0);
2334             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2335                                              to_next, n_left_to_next,
2336                                              pi0, next0);
2337             continue;
2338           }
2339
2340         drop:
2341           if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
2342               (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
2343                arp0->ip4_over_ethernet[1].ip4.as_u32))
2344             {
2345               error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
2346             }
2347           next0 = ARP_TERM_NEXT_DROP;
2348           p0->error = node->errors[error0];
2349
2350           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2351                                            to_next, n_left_to_next, pi0,
2352                                            next0);
2353         }
2354
2355       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2356     }
2357
2358   vlib_error_count (vm, node->node_index,
2359                     ETHERNET_ARP_ERROR_replies_sent, n_replies_sent);
2360   return frame->n_vectors;
2361 }
2362
2363 /* *INDENT-OFF* */
2364 VLIB_REGISTER_NODE (arp_term_l2bd_node, static) = {
2365   .function = arp_term_l2bd,
2366   .name = "arp-term-l2bd",
2367   .vector_size = sizeof (u32),
2368   .n_errors = ETHERNET_ARP_N_ERROR,
2369   .error_strings = ethernet_arp_error_strings,
2370   .n_next_nodes = ARP_TERM_N_NEXT,
2371   .next_nodes = {
2372     [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
2373     [ARP_TERM_NEXT_DROP] = "error-drop",
2374   },
2375   .format_buffer = format_ethernet_arp_header,
2376   .format_trace = format_arp_term_input_trace,
2377 };
2378 /* *INDENT-ON* */
2379
2380 clib_error_t *
2381 arp_term_init (vlib_main_t * vm)
2382 {
2383   // Initialize the feature next-node indexes
2384   feat_bitmap_init_next_nodes (vm,
2385                                arp_term_l2bd_node.index,
2386                                L2INPUT_N_FEAT,
2387                                l2input_get_feat_names (),
2388                                arp_term_next_node_index);
2389   return 0;
2390 }
2391
2392 VLIB_INIT_FUNCTION (arp_term_init);
2393
2394 void
2395 change_arp_mac (u32 sw_if_index, ethernet_arp_ip4_entry_t * e)
2396 {
2397   if (e->sw_if_index == sw_if_index)
2398     {
2399       adj_nbr_walk_nh4 (e->sw_if_index,
2400                         &e->ip4_address, arp_mk_complete_walk, e);
2401     }
2402 }
2403
2404 void
2405 ethernet_arp_change_mac (u32 sw_if_index)
2406 {
2407   ethernet_arp_main_t *am = &ethernet_arp_main;
2408   ethernet_arp_ip4_entry_t *e;
2409
2410   /* *INDENT-OFF* */
2411   pool_foreach (e, am->ip4_entry_pool,
2412   ({
2413     change_arp_mac (sw_if_index, e);
2414   }));
2415   /* *INDENT-ON* */
2416 }
2417
2418 /*
2419  * fd.io coding-style-patch-verification: ON
2420  *
2421  * Local Variables:
2422  * eval: (c-set-style "gnu")
2423  * End:
2424  */