Attached hosts
[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           ip4_address_t *if_addr0, proxy_src;
1020           u32 pi0, error0, next0, sw_if_index0, conn_sw_if_index0, fib_index0;
1021           u8 is_request0, dst_is_local0, is_unnum0;
1022           ethernet_proxy_arp_t *pa;
1023           fib_node_index_t dst_fei, src_fei;
1024           fib_prefix_t pfx0;
1025           fib_entry_flag_t src_flags, dst_flags;
1026
1027           pi0 = from[0];
1028           to_next[0] = pi0;
1029           from += 1;
1030           to_next += 1;
1031           n_left_from -= 1;
1032           n_left_to_next -= 1;
1033           pa = 0;
1034
1035           p0 = vlib_get_buffer (vm, pi0);
1036           arp0 = vlib_buffer_get_current (p0);
1037
1038           is_request0 = arp0->opcode
1039             == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
1040
1041           error0 = ETHERNET_ARP_ERROR_replies_sent;
1042
1043           error0 =
1044             (arp0->l2_type !=
1045              clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ?
1046              ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
1047           error0 =
1048             (arp0->l3_type !=
1049              clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
1050              ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
1051
1052           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1053
1054           /* not playing the ARP game if the interface is not IPv4 enabled */
1055           error0 =
1056             (im4->ip_enabled_by_sw_if_index[sw_if_index0] == 0 ?
1057              ETHERNET_ARP_ERROR_interface_not_ip_enabled : error0);
1058
1059           if (error0)
1060             goto drop2;
1061
1062           /* Check that IP address is local and matches incoming interface. */
1063           fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
1064           if (~0 == fib_index0)
1065             {
1066               error0 = ETHERNET_ARP_ERROR_interface_no_table;
1067               goto drop2;
1068
1069             }
1070           dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1071                                           &arp0->ip4_over_ethernet[1].ip4,
1072                                           32);
1073           dst_flags = fib_entry_get_flags (dst_fei);
1074
1075           src_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1076                                           &arp0->ip4_over_ethernet[0].ip4,
1077                                           32);
1078           src_flags = fib_entry_get_flags (src_fei);
1079
1080           conn_sw_if_index0 = fib_entry_get_resolving_interface (dst_fei);
1081
1082           if (!(FIB_ENTRY_FLAG_CONNECTED & dst_flags))
1083             {
1084               error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
1085               goto drop1;
1086             }
1087
1088           /* Honor unnumbered interface, if any */
1089           is_unnum0 = sw_if_index0 != conn_sw_if_index0;
1090
1091           /* Source must also be local to subnet of matching interface address. */
1092           if (!((FIB_ENTRY_FLAG_ATTACHED & src_flags) ||
1093                 (FIB_ENTRY_FLAG_CONNECTED & src_flags)))
1094             {
1095               /*
1096                * The packet was sent from an address that is not connected nor attached
1097                * i.e. it is not from an address that is covered by a link's sub-net,
1098                * nor is it a already learned host resp.
1099                */
1100               error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
1101               goto drop2;
1102             }
1103           if (sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
1104             {
1105               /*
1106                * The interface the ARP was received on is not the interface
1107                * on which the covering prefix is configured. Maybe this is a case
1108                * for unnumbered.
1109                */
1110               is_unnum0 = 1;
1111             }
1112
1113           /* Reject requests/replies with our local interface address. */
1114           if (FIB_ENTRY_FLAG_LOCAL & src_flags)
1115             {
1116               error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
1117               goto drop2;
1118             }
1119
1120           dst_is_local0 = (FIB_ENTRY_FLAG_LOCAL & dst_flags);
1121           fib_entry_get_prefix (dst_fei, &pfx0);
1122           if_addr0 = &pfx0.fp_addr.ip4;
1123
1124           /* Fill in ethernet header. */
1125           eth0 = ethernet_buffer_get_header (p0);
1126
1127           /* Trash ARP packets whose ARP-level source addresses do not
1128              match their L2-frame-level source addresses */
1129           if (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
1130                       sizeof (eth0->src_address)))
1131             {
1132               error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1133               goto drop2;
1134             }
1135
1136           /* Learn or update sender's mapping only for requests or unicasts
1137              that don't match local interface address. */
1138           if (ethernet_address_cast (eth0->dst_address) ==
1139               ETHERNET_ADDRESS_UNICAST || is_request0)
1140             {
1141               if (am->limit_arp_cache_size &&
1142                   pool_elts (am->ip4_entry_pool) >= am->limit_arp_cache_size)
1143                 unset_random_arp_entry ();
1144
1145               vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index0,
1146                                               &arp0->ip4_over_ethernet[0],
1147                                               0 /* is_static */ , 0);
1148               error0 = ETHERNET_ARP_ERROR_l3_src_address_learned;
1149             }
1150
1151           /* Only send a reply for requests sent which match a local interface. */
1152           if (!(is_request0 && dst_is_local0))
1153             {
1154               error0 =
1155                 (arp0->opcode ==
1156                  clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply) ?
1157                  ETHERNET_ARP_ERROR_replies_received : error0);
1158               goto drop1;
1159             }
1160
1161           /* Send a reply. */
1162         send_reply:
1163           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1164           hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1165
1166           /* Send reply back through input interface */
1167           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1168           next0 = ARP_INPUT_NEXT_REPLY_TX;
1169
1170           arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1171
1172           arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1173
1174           clib_memcpy (arp0->ip4_over_ethernet[0].ethernet,
1175                        hw_if0->hw_address, 6);
1176           clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) =
1177             if_addr0->data_u32;
1178
1179           /* Hardware must be ethernet-like. */
1180           ASSERT (vec_len (hw_if0->hw_address) == 6);
1181
1182           clib_memcpy (eth0->dst_address, eth0->src_address, 6);
1183           clib_memcpy (eth0->src_address, hw_if0->hw_address, 6);
1184
1185           /* Figure out how much to rewind current data from adjacency. */
1186           /* get the adj from the destination's covering connected */
1187           if (NULL == pa)
1188             {
1189               if (is_unnum0)
1190                 {
1191                   if (!arp_unnumbered (p0, pi0, eth0, conn_sw_if_index0))
1192                     goto drop2;
1193                 }
1194               else
1195                 {
1196                   ip_adjacency_t *adj0 = NULL;
1197                   adj_index_t ai;
1198
1199                   if (FIB_ENTRY_FLAG_ATTACHED & src_flags)
1200                     {
1201                       /*
1202                        * If the source is attached use the adj from that source.
1203                        */
1204                       ai = fib_entry_get_adj (src_fei);
1205                       if (ADJ_INDEX_INVALID != ai)
1206                         {
1207                           adj0 = adj_get (ai);
1208                         }
1209                     }
1210                   else
1211                     {
1212                       /*
1213                        * Get the glean adj from the cover. This is presumably interface
1214                        * sourced, and therefre needs to be a glean adj.
1215                        */
1216                       ai = fib_entry_get_adj_for_source
1217                         (ip4_fib_table_lookup
1218                          (ip4_fib_get (fib_index0),
1219                           &arp0->ip4_over_ethernet[1].ip4, 31),
1220                          FIB_SOURCE_INTERFACE);
1221
1222                       if (ADJ_INDEX_INVALID != ai)
1223                         {
1224                           adj0 = adj_get (ai);
1225
1226                           if (adj0->lookup_next_index == IP_LOOKUP_NEXT_GLEAN)
1227                             {
1228                               adj0 = NULL;
1229                             }
1230                         }
1231                     }
1232                   if (NULL != adj0)
1233                     {
1234                       vlib_buffer_advance (p0,
1235                                            -adj0->rewrite_header.data_bytes);
1236                     }
1237                   else
1238                     {
1239                       error0 = ETHERNET_ARP_ERROR_missing_interface_address;
1240                       goto drop2;
1241                     }
1242                 }
1243             }
1244
1245           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1246                                            n_left_to_next, pi0, next0);
1247
1248           n_replies_sent += 1;
1249           continue;
1250
1251         drop1:
1252           if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1253               (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1254                arp0->ip4_over_ethernet[1].ip4.as_u32))
1255             {
1256               error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1257               goto drop2;
1258             }
1259           /* See if proxy arp is configured for the address */
1260           if (is_request0)
1261             {
1262               vnet_sw_interface_t *si;
1263               u32 this_addr = clib_net_to_host_u32
1264                 (arp0->ip4_over_ethernet[1].ip4.as_u32);
1265               u32 fib_index0;
1266
1267               si = vnet_get_sw_interface (vnm, sw_if_index0);
1268
1269               if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP))
1270                 goto drop2;
1271
1272               fib_index0 = vec_elt (im4->fib_index_by_sw_if_index,
1273                                     sw_if_index0);
1274
1275               vec_foreach (pa, am->proxy_arps)
1276               {
1277                 u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
1278                 u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
1279
1280                 /* an ARP request hit in the proxy-arp table? */
1281                 if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1282                     (fib_index0 == pa->fib_index))
1283                   {
1284                     eth0 = ethernet_buffer_get_header (p0);
1285                     proxy_src.as_u32 =
1286                       arp0->ip4_over_ethernet[1].ip4.data_u32;
1287
1288                     /*
1289                      * Rewind buffer, direct code above not to
1290                      * think too hard about it.
1291                      */
1292                     if_addr0 = &proxy_src;
1293                     is_unnum0 = 0;
1294                     i32 ethernet_start =
1295                       vnet_buffer (p0)->ethernet.start_of_ethernet_header;
1296                     i32 rewind = p0->current_data - ethernet_start;
1297                     vlib_buffer_advance (p0, -rewind);
1298                     n_proxy_arp_replies_sent++;
1299                     goto send_reply;
1300                   }
1301               }
1302             }
1303
1304         drop2:
1305
1306           next0 = ARP_INPUT_NEXT_DROP;
1307           p0->error = node->errors[error0];
1308
1309           vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1310                                            n_left_to_next, pi0, next0);
1311         }
1312
1313       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1314     }
1315
1316   vlib_error_count (vm, node->node_index,
1317                     ETHERNET_ARP_ERROR_replies_sent,
1318                     n_replies_sent - n_proxy_arp_replies_sent);
1319
1320   vlib_error_count (vm, node->node_index,
1321                     ETHERNET_ARP_ERROR_proxy_arp_replies_sent,
1322                     n_proxy_arp_replies_sent);
1323   return frame->n_vectors;
1324 }
1325
1326 static char *ethernet_arp_error_strings[] = {
1327 #define _(sym,string) string,
1328   foreach_ethernet_arp_error
1329 #undef _
1330 };
1331
1332 /* *INDENT-OFF* */
1333 VLIB_REGISTER_NODE (arp_input_node, static) =
1334 {
1335   .function = arp_input,
1336   .name = "arp-input",
1337   .vector_size = sizeof (u32),
1338   .n_errors = ETHERNET_ARP_N_ERROR,
1339   .error_strings = ethernet_arp_error_strings,
1340   .n_next_nodes = ARP_INPUT_N_NEXT,
1341   .next_nodes = {
1342     [ARP_INPUT_NEXT_DROP] = "error-drop",
1343     [ARP_INPUT_NEXT_REPLY_TX] = "interface-output",
1344   },
1345   .format_buffer = format_ethernet_arp_header,
1346   .format_trace = format_ethernet_arp_input_trace,
1347 };
1348 /* *INDENT-ON* */
1349
1350 static int
1351 ip4_arp_entry_sort (void *a1, void *a2)
1352 {
1353   ethernet_arp_ip4_entry_t *e1 = a1;
1354   ethernet_arp_ip4_entry_t *e2 = a2;
1355
1356   int cmp;
1357   vnet_main_t *vnm = vnet_get_main ();
1358
1359   cmp = vnet_sw_interface_compare (vnm, e1->sw_if_index, e2->sw_if_index);
1360   if (!cmp)
1361     cmp = ip4_address_compare (&e1->ip4_address, &e2->ip4_address);
1362   return cmp;
1363 }
1364
1365 ethernet_arp_ip4_entry_t *
1366 ip4_neighbor_entries (u32 sw_if_index)
1367 {
1368   ethernet_arp_main_t *am = &ethernet_arp_main;
1369   ethernet_arp_ip4_entry_t *n, *ns = 0;
1370
1371   /* *INDENT-OFF* */
1372   pool_foreach (n, am->ip4_entry_pool, ({
1373     if (sw_if_index != ~0 && n->sw_if_index != sw_if_index)
1374       continue;
1375     vec_add1 (ns, n[0]);
1376   }));
1377   /* *INDENT-ON* */
1378
1379   if (ns)
1380     vec_sort_with_function (ns, ip4_arp_entry_sort);
1381   return ns;
1382 }
1383
1384 static clib_error_t *
1385 show_ip4_arp (vlib_main_t * vm,
1386               unformat_input_t * input, vlib_cli_command_t * cmd)
1387 {
1388   vnet_main_t *vnm = vnet_get_main ();
1389   ethernet_arp_main_t *am = &ethernet_arp_main;
1390   ethernet_arp_ip4_entry_t *e, *es;
1391   ethernet_proxy_arp_t *pa;
1392   clib_error_t *error = 0;
1393   u32 sw_if_index;
1394
1395   /* Filter entries by interface if given. */
1396   sw_if_index = ~0;
1397   (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1398
1399   es = ip4_neighbor_entries (sw_if_index);
1400   if (es)
1401     {
1402       vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1403       vec_foreach (e, es)
1404       {
1405         vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1406       }
1407       vec_free (es);
1408     }
1409
1410   if (vec_len (am->proxy_arps))
1411     {
1412       vlib_cli_output (vm, "Proxy arps enabled for:");
1413       vec_foreach (pa, am->proxy_arps)
1414       {
1415         vlib_cli_output (vm, "Fib_index %d   %U - %U ",
1416                          pa->fib_index,
1417                          format_ip4_address, &pa->lo_addr,
1418                          format_ip4_address, &pa->hi_addr);
1419       }
1420     }
1421
1422   return error;
1423 }
1424
1425 /*?
1426  * Display all the IPv4 ARP entries.
1427  *
1428  * @cliexpar
1429  * Example of how to display the IPv4 ARP table:
1430  * @cliexstart{show ip arp}
1431  *    Time      FIB        IP4       Flags      Ethernet              Interface
1432  *    346.3028   0       6.1.1.3            de:ad:be:ef:ba:be   GigabitEthernet2/0/0
1433  *   3077.4271   0       6.1.1.4       S    de:ad:be:ef:ff:ff   GigabitEthernet2/0/0
1434  *   2998.6409   1       6.2.2.3            de:ad:be:ef:00:01   GigabitEthernet2/0/0
1435  * Proxy arps enabled for:
1436  * Fib_index 0   6.0.0.1 - 6.0.0.11
1437  * @cliexend
1438  ?*/
1439 /* *INDENT-OFF* */
1440 VLIB_CLI_COMMAND (show_ip4_arp_command, static) = {
1441   .path = "show ip arp",
1442   .function = show_ip4_arp,
1443   .short_help = "show ip arp",
1444 };
1445 /* *INDENT-ON* */
1446
1447 typedef struct
1448 {
1449   pg_edit_t l2_type, l3_type;
1450   pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1451   pg_edit_t opcode;
1452   struct
1453   {
1454     pg_edit_t ethernet;
1455     pg_edit_t ip4;
1456   } ip4_over_ethernet[2];
1457 } pg_ethernet_arp_header_t;
1458
1459 static inline void
1460 pg_ethernet_arp_header_init (pg_ethernet_arp_header_t * p)
1461 {
1462   /* Initialize fields that are not bit fields in the IP header. */
1463 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1464   _(l2_type);
1465   _(l3_type);
1466   _(n_l2_address_bytes);
1467   _(n_l3_address_bytes);
1468   _(opcode);
1469   _(ip4_over_ethernet[0].ethernet);
1470   _(ip4_over_ethernet[0].ip4);
1471   _(ip4_over_ethernet[1].ethernet);
1472   _(ip4_over_ethernet[1].ip4);
1473 #undef _
1474 }
1475
1476 uword
1477 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1478 {
1479   pg_stream_t *s = va_arg (*args, pg_stream_t *);
1480   pg_ethernet_arp_header_t *p;
1481   u32 group_index;
1482
1483   p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1484                             &group_index);
1485   pg_ethernet_arp_header_init (p);
1486
1487   /* Defaults. */
1488   pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1489   pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1490   pg_edit_set_fixed (&p->n_l2_address_bytes, 6);
1491   pg_edit_set_fixed (&p->n_l3_address_bytes, 4);
1492
1493   if (!unformat (input, "%U: %U/%U -> %U/%U",
1494                  unformat_pg_edit,
1495                  unformat_ethernet_arp_opcode_net_byte_order, &p->opcode,
1496                  unformat_pg_edit,
1497                  unformat_ethernet_address, &p->ip4_over_ethernet[0].ethernet,
1498                  unformat_pg_edit,
1499                  unformat_ip4_address, &p->ip4_over_ethernet[0].ip4,
1500                  unformat_pg_edit,
1501                  unformat_ethernet_address, &p->ip4_over_ethernet[1].ethernet,
1502                  unformat_pg_edit,
1503                  unformat_ip4_address, &p->ip4_over_ethernet[1].ip4))
1504     {
1505       /* Free up any edits we may have added. */
1506       pg_free_edit_group (s);
1507       return 0;
1508     }
1509   return 1;
1510 }
1511
1512 clib_error_t *
1513 ip4_set_arp_limit (u32 arp_limit)
1514 {
1515   ethernet_arp_main_t *am = &ethernet_arp_main;
1516
1517   am->limit_arp_cache_size = arp_limit;
1518   return 0;
1519 }
1520
1521 /**
1522  * @brief Control Plane hook to remove an ARP entry
1523  */
1524 int
1525 vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
1526                                   u32 sw_if_index, void *a_arg)
1527 {
1528   ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1529   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1530
1531   args.sw_if_index = sw_if_index;
1532   args.flags = ETHERNET_ARP_ARGS_REMOVE;
1533   clib_memcpy (&args.a, a, sizeof (*a));
1534
1535   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1536                                (u8 *) & args, sizeof (args));
1537   return 0;
1538 }
1539
1540 /**
1541  * @brief Internally generated event to flush the ARP cache on an
1542  * interface state change event.
1543  * A flush will remove dynamic ARP entries, and for statics remove the MAC
1544  * address from the corresponding adjacencies.
1545  */
1546 static int
1547 vnet_arp_flush_ip4_over_ethernet (vnet_main_t * vnm,
1548                                   u32 sw_if_index, void *a_arg)
1549 {
1550   ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1551   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1552
1553   args.sw_if_index = sw_if_index;
1554   args.flags = ETHERNET_ARP_ARGS_FLUSH;
1555   clib_memcpy (&args.a, a, sizeof (*a));
1556
1557   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1558                                (u8 *) & args, sizeof (args));
1559   return 0;
1560 }
1561
1562 /**
1563  * @brief Internally generated event to populate the ARP cache on an
1564  * interface state change event.
1565  * For static entries this will re-source the adjacencies.
1566  *
1567  * @param sw_if_index The interface on which the ARP entires are acted
1568  */
1569 static int
1570 vnet_arp_populate_ip4_over_ethernet (vnet_main_t * vnm,
1571                                      u32 sw_if_index, void *a_arg)
1572 {
1573   ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1574   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1575
1576   args.sw_if_index = sw_if_index;
1577   args.flags = ETHERNET_ARP_ARGS_POPULATE;
1578   clib_memcpy (&args.a, a, sizeof (*a));
1579
1580   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1581                                (u8 *) & args, sizeof (args));
1582   return 0;
1583 }
1584
1585 /*
1586  * arp_add_del_interface_address
1587  *
1588  * callback when an interface address is added or deleted
1589  */
1590 static void
1591 arp_add_del_interface_address (ip4_main_t * im,
1592                                uword opaque,
1593                                u32 sw_if_index,
1594                                ip4_address_t * address,
1595                                u32 address_length,
1596                                u32 if_address_index, u32 is_del)
1597 {
1598   /*
1599    * Flush the ARP cache of all entries covered by the address
1600    * that is being removed.
1601    */
1602   ethernet_arp_main_t *am = &ethernet_arp_main;
1603   ethernet_arp_ip4_entry_t *e;
1604
1605   if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
1606     return;
1607
1608   if (is_del)
1609     {
1610       ethernet_arp_interface_t *eai;
1611       u32 i, *to_delete = 0;
1612       hash_pair_t *pair;
1613
1614       eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
1615
1616       /* *INDENT-OFF* */
1617       hash_foreach_pair (pair, eai->arp_entries,
1618       ({
1619         e = pool_elt_at_index(am->ip4_entry_pool,
1620                               pair->value[0]);
1621         if (ip4_destination_matches_route (im, &e->ip4_address,
1622                                            address, address_length))
1623           {
1624             vec_add1 (to_delete, e - am->ip4_entry_pool);
1625           }
1626       }));
1627       /* *INDENT-ON* */
1628
1629       for (i = 0; i < vec_len (to_delete); i++)
1630         {
1631           ethernet_arp_ip4_over_ethernet_address_t delme;
1632           e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1633
1634           clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1635           delme.ip4.as_u32 = e->ip4_address.as_u32;
1636
1637           vnet_arp_flush_ip4_over_ethernet (vnet_get_main (),
1638                                             e->sw_if_index, &delme);
1639         }
1640
1641       vec_free (to_delete);
1642     }
1643 }
1644
1645 static clib_error_t *
1646 ethernet_arp_init (vlib_main_t * vm)
1647 {
1648   ethernet_arp_main_t *am = &ethernet_arp_main;
1649   ip4_main_t *im = &ip4_main;
1650   clib_error_t *error;
1651   pg_node_t *pn;
1652
1653   if ((error = vlib_call_init_function (vm, ethernet_init)))
1654     return error;
1655
1656   ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
1657
1658   pn = pg_get_node (arp_input_node.index);
1659   pn->unformat_edit = unformat_pg_arp_header;
1660
1661   am->opcode_by_name = hash_create_string (0, sizeof (uword));
1662 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
1663   foreach_ethernet_arp_opcode;
1664 #undef _
1665
1666   /* $$$ configurable */
1667   am->limit_arp_cache_size = 50000;
1668
1669   am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
1670   am->mac_changes_by_address = hash_create (0, sizeof (uword));
1671
1672   /* don't trace ARP error packets */
1673   {
1674     vlib_node_runtime_t *rt =
1675       vlib_node_get_runtime (vm, arp_input_node.index);
1676
1677 #define _(a,b)                                  \
1678     vnet_pcap_drop_trace_filter_add_del         \
1679         (rt->errors[ETHERNET_ARP_ERROR_##a],    \
1680          1 /* is_add */);
1681     foreach_ethernet_arp_error
1682 #undef _
1683   }
1684
1685   ip4_add_del_interface_address_callback_t cb;
1686   cb.function = arp_add_del_interface_address;
1687   cb.function_opaque = 0;
1688   vec_add1 (im->add_del_interface_address_callbacks, cb);
1689
1690   return 0;
1691 }
1692
1693 VLIB_INIT_FUNCTION (ethernet_arp_init);
1694
1695 static void
1696 arp_entry_free (ethernet_arp_interface_t * eai, ethernet_arp_ip4_entry_t * e)
1697 {
1698   ethernet_arp_main_t *am = &ethernet_arp_main;
1699
1700   /* it's safe to delete the ADJ source on the FIB entry, even if it
1701    * was added */
1702   fib_table_entry_delete_index (e->fib_entry_index, FIB_SOURCE_ADJ);
1703   hash_unset (eai->arp_entries, e->ip4_address.as_u32);
1704   pool_put (am->ip4_entry_pool, e);
1705 }
1706
1707 static inline int
1708 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
1709                                            vnet_arp_set_ip4_over_ethernet_rpc_args_t
1710                                            * args)
1711 {
1712   ethernet_arp_main_t *am = &ethernet_arp_main;
1713   ethernet_arp_ip4_entry_t *e;
1714   ethernet_arp_interface_t *eai;
1715
1716   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1717
1718   e = arp_entry_find (eai, &args->a.ip4);
1719
1720   if (NULL != e)
1721     {
1722       arp_entry_free (eai, e);
1723
1724       adj_nbr_walk_nh4 (e->sw_if_index,
1725                         &e->ip4_address, arp_mk_incomplete_walk, NULL);
1726     }
1727
1728   return 0;
1729 }
1730
1731 static int
1732 vnet_arp_flush_ip4_over_ethernet_internal (vnet_main_t * vnm,
1733                                            vnet_arp_set_ip4_over_ethernet_rpc_args_t
1734                                            * args)
1735 {
1736   ethernet_arp_main_t *am = &ethernet_arp_main;
1737   ethernet_arp_ip4_entry_t *e;
1738   ethernet_arp_interface_t *eai;
1739
1740   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1741
1742   e = arp_entry_find (eai, &args->a.ip4);
1743
1744   if (NULL != e)
1745     {
1746       adj_nbr_walk_nh4 (e->sw_if_index,
1747                         &e->ip4_address, arp_mk_incomplete_walk, e);
1748
1749       /*
1750        * The difference between flush and unset, is that an unset
1751        * means delete for static and dynamic entries. A flush
1752        * means delete only for dynamic. Flushing is what the DP
1753        * does in response to interface events. unset is only done
1754        * by the control plane.
1755        */
1756       if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC)
1757         {
1758           arp_entry_free (eai, e);
1759         }
1760     }
1761   return (0);
1762 }
1763
1764 static int
1765 vnet_arp_populate_ip4_over_ethernet_internal (vnet_main_t * vnm,
1766                                               vnet_arp_set_ip4_over_ethernet_rpc_args_t
1767                                               * args)
1768 {
1769   ethernet_arp_main_t *am = &ethernet_arp_main;
1770   ethernet_arp_ip4_entry_t *e;
1771   ethernet_arp_interface_t *eai;
1772
1773   eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1774
1775   e = arp_entry_find (eai, &args->a.ip4);
1776
1777   if (NULL != e)
1778     {
1779       adj_nbr_walk_nh4 (e->sw_if_index,
1780                         &e->ip4_address, arp_mk_complete_walk, e);
1781     }
1782   return (0);
1783 }
1784
1785 static void
1786 set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t
1787                                     * a)
1788 {
1789   vnet_main_t *vm = vnet_get_main ();
1790   ASSERT (os_get_cpu_number () == 0);
1791
1792   if (a->flags & ETHERNET_ARP_ARGS_REMOVE)
1793     vnet_arp_unset_ip4_over_ethernet_internal (vm, a);
1794   else if (a->flags & ETHERNET_ARP_ARGS_FLUSH)
1795     vnet_arp_flush_ip4_over_ethernet_internal (vm, a);
1796   else if (a->flags & ETHERNET_ARP_ARGS_POPULATE)
1797     vnet_arp_populate_ip4_over_ethernet_internal (vm, a);
1798   else
1799     vnet_arp_set_ip4_over_ethernet_internal (vm, a);
1800 }
1801
1802 /**
1803  * @brief Invoked when the interface's admin state changes
1804  */
1805 static clib_error_t *
1806 ethernet_arp_sw_interface_up_down (vnet_main_t * vnm,
1807                                    u32 sw_if_index, u32 flags)
1808 {
1809   ethernet_arp_main_t *am = &ethernet_arp_main;
1810   ethernet_arp_ip4_entry_t *e;
1811   u32 i, *to_delete = 0;
1812
1813   /* *INDENT-OFF* */
1814   pool_foreach (e, am->ip4_entry_pool,
1815   ({
1816     if (e->sw_if_index == sw_if_index)
1817       vec_add1 (to_delete,
1818                 e - am->ip4_entry_pool);
1819   }));
1820   /* *INDENT-ON* */
1821
1822   for (i = 0; i < vec_len (to_delete); i++)
1823     {
1824       ethernet_arp_ip4_over_ethernet_address_t delme;
1825       e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1826
1827       clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1828       delme.ip4.as_u32 = e->ip4_address.as_u32;
1829
1830       if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1831         {
1832           vnet_arp_populate_ip4_over_ethernet (vnm, e->sw_if_index, &delme);
1833         }
1834       else
1835         {
1836           vnet_arp_flush_ip4_over_ethernet (vnm, e->sw_if_index, &delme);
1837         }
1838
1839     }
1840   vec_free (to_delete);
1841
1842   return 0;
1843 }
1844
1845 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_arp_sw_interface_up_down);
1846
1847 static void
1848 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t * a)
1849 {
1850   u8 old;
1851   int i;
1852
1853   for (i = 3; i >= 0; i--)
1854     {
1855       old = a->ip4.as_u8[i];
1856       a->ip4.as_u8[i] += 1;
1857       if (old < a->ip4.as_u8[i])
1858         break;
1859     }
1860
1861   for (i = 5; i >= 0; i--)
1862     {
1863       old = a->ethernet[i];
1864       a->ethernet[i] += 1;
1865       if (old < a->ethernet[i])
1866         break;
1867     }
1868 }
1869
1870 int
1871 vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
1872                                 u32 sw_if_index, void *a_arg,
1873                                 int is_static, int is_no_fib_entry)
1874 {
1875   ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1876   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1877
1878   args.sw_if_index = sw_if_index;
1879   args.is_static = is_static;
1880   args.is_no_fib_entry = is_no_fib_entry;
1881   args.flags = 0;
1882   clib_memcpy (&args.a, a, sizeof (*a));
1883
1884   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1885                                (u8 *) & args, sizeof (args));
1886   return 0;
1887 }
1888
1889 int
1890 vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
1891                         ip4_address_t * hi_addr, u32 fib_index, int is_del)
1892 {
1893   ethernet_arp_main_t *am = &ethernet_arp_main;
1894   ethernet_proxy_arp_t *pa;
1895   u32 found_at_index = ~0;
1896
1897   vec_foreach (pa, am->proxy_arps)
1898   {
1899     if (pa->lo_addr == lo_addr->as_u32
1900         && pa->hi_addr == hi_addr->as_u32 && pa->fib_index == fib_index)
1901       {
1902         found_at_index = pa - am->proxy_arps;
1903         break;
1904       }
1905   }
1906
1907   if (found_at_index != ~0)
1908     {
1909       /* Delete, otherwise it's already in the table */
1910       if (is_del)
1911         vec_delete (am->proxy_arps, 1, found_at_index);
1912       return 0;
1913     }
1914   /* delete, no such entry */
1915   if (is_del)
1916     return VNET_API_ERROR_NO_SUCH_ENTRY;
1917
1918   /* add, not in table */
1919   vec_add2 (am->proxy_arps, pa, 1);
1920   pa->lo_addr = lo_addr->as_u32;
1921   pa->hi_addr = hi_addr->as_u32;
1922   pa->fib_index = fib_index;
1923   return 0;
1924 }
1925
1926 /*
1927  * Remove any proxy arp entries asdociated with the
1928  * specificed fib.
1929  */
1930 int
1931 vnet_proxy_arp_fib_reset (u32 fib_id)
1932 {
1933   ip4_main_t *im = &ip4_main;
1934   ethernet_arp_main_t *am = &ethernet_arp_main;
1935   ethernet_proxy_arp_t *pa;
1936   u32 *entries_to_delete = 0;
1937   u32 fib_index;
1938   uword *p;
1939   int i;
1940
1941   p = hash_get (im->fib_index_by_table_id, fib_id);
1942   if (!p)
1943     return VNET_API_ERROR_NO_SUCH_ENTRY;
1944   fib_index = p[0];
1945
1946   vec_foreach (pa, am->proxy_arps)
1947   {
1948     if (pa->fib_index == fib_index)
1949       {
1950         vec_add1 (entries_to_delete, pa - am->proxy_arps);
1951       }
1952   }
1953
1954   for (i = 0; i < vec_len (entries_to_delete); i++)
1955     {
1956       vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
1957     }
1958
1959   vec_free (entries_to_delete);
1960
1961   return 0;
1962 }
1963
1964 static clib_error_t *
1965 ip_arp_add_del_command_fn (vlib_main_t * vm,
1966                            unformat_input_t * input, vlib_cli_command_t * cmd)
1967 {
1968   vnet_main_t *vnm = vnet_get_main ();
1969   u32 sw_if_index;
1970   ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
1971   int addr_valid = 0;
1972   int is_del = 0;
1973   int count = 1;
1974   u32 fib_index = 0;
1975   u32 fib_id;
1976   int is_static = 0;
1977   int is_no_fib_entry = 0;
1978   int is_proxy = 0;
1979
1980   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1981     {
1982       /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
1983       if (unformat (input, "%U %U %U",
1984                     unformat_vnet_sw_interface, vnm, &sw_if_index,
1985                     unformat_ip4_address, &addr.ip4,
1986                     unformat_ethernet_address, &addr.ethernet))
1987         addr_valid = 1;
1988
1989       else if (unformat (input, "delete") || unformat (input, "del"))
1990         is_del = 1;
1991
1992       else if (unformat (input, "static"))
1993         is_static = 1;
1994
1995       else if (unformat (input, "no-fib-entry"))
1996         is_no_fib_entry = 1;
1997
1998       else if (unformat (input, "count %d", &count))
1999         ;
2000
2001       else if (unformat (input, "fib-id %d", &fib_id))
2002         {
2003           ip4_main_t *im = &ip4_main;
2004           uword *p = hash_get (im->fib_index_by_table_id, fib_id);
2005           if (!p)
2006             return clib_error_return (0, "fib ID %d doesn't exist\n", fib_id);
2007           fib_index = p[0];
2008         }
2009
2010       else if (unformat (input, "proxy %U - %U",
2011                          unformat_ip4_address, &lo_addr.ip4,
2012                          unformat_ip4_address, &hi_addr.ip4))
2013         is_proxy = 1;
2014       else
2015         break;
2016     }
2017
2018   if (is_proxy)
2019     {
2020       (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4,
2021                                      fib_index, is_del);
2022       return 0;
2023     }
2024
2025   if (addr_valid)
2026     {
2027       int i;
2028
2029       for (i = 0; i < count; i++)
2030         {
2031           if (is_del == 0)
2032             {
2033               uword event_type, *event_data = 0;
2034
2035               /* Park the debug CLI until the arp entry is installed */
2036               vnet_register_ip4_arp_resolution_event
2037                 (vnm, &addr.ip4, vlib_current_process (vm),
2038                  1 /* type */ , 0 /* data */ );
2039
2040               vnet_arp_set_ip4_over_ethernet
2041                 (vnm, sw_if_index, &addr, is_static, is_no_fib_entry);
2042
2043               vlib_process_wait_for_event (vm);
2044               event_type = vlib_process_get_events (vm, &event_data);
2045               vec_reset_length (event_data);
2046               if (event_type != 1)
2047                 clib_warning ("event type %d unexpected", event_type);
2048             }
2049           else
2050             vnet_arp_unset_ip4_over_ethernet (vnm, sw_if_index, &addr);
2051
2052           increment_ip4_and_mac_address (&addr);
2053         }
2054     }
2055   else
2056     {
2057       return clib_error_return (0, "unknown input `%U'",
2058                                 format_unformat_error, input);
2059     }
2060
2061   return 0;
2062 }
2063
2064 /* *INDENT-OFF* */
2065 /*?
2066  * Add or delete IPv4 ARP cache entries.
2067  *
2068  * @note 'set ip arp' options (e.g. delete, static, 'fib-id <id>',
2069  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
2070  * any order and combination.
2071  *
2072  * @cliexpar
2073  * @parblock
2074  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
2075  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
2076  * @cliexcmd{set ip arp GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2077  * @cliexcmd{set ip arp delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
2078  *
2079  * To add or delete an IPv4 ARP cache entry to or from a specific fib
2080  * table:
2081  * @cliexcmd{set ip arp fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2082  * @cliexcmd{set ip arp fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2083  *
2084  * Add or delete IPv4 static ARP cache entries as follows:
2085  * @cliexcmd{set ip arp static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2086  * @cliexcmd{set ip arp static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2087  *
2088  * For testing / debugging purposes, the 'set ip arp' command can add or
2089  * delete multiple entries. Supply the 'count N' parameter:
2090  * @cliexcmd{set ip arp count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2091  * @endparblock
2092  ?*/
2093 VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = {
2094   .path = "set ip arp",
2095   .short_help =
2096   "set ip arp [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
2097   .function = ip_arp_add_del_command_fn,
2098 };
2099 /* *INDENT-ON* */
2100
2101 static clib_error_t *
2102 set_int_proxy_arp_command_fn (vlib_main_t * vm,
2103                               unformat_input_t *
2104                               input, vlib_cli_command_t * cmd)
2105 {
2106   vnet_main_t *vnm = vnet_get_main ();
2107   u32 sw_if_index;
2108   vnet_sw_interface_t *si;
2109   int enable = 0;
2110   int intfc_set = 0;
2111
2112   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2113     {
2114       if (unformat (input, "%U", unformat_vnet_sw_interface,
2115                     vnm, &sw_if_index))
2116         intfc_set = 1;
2117       else if (unformat (input, "enable") || unformat (input, "on"))
2118         enable = 1;
2119       else if (unformat (input, "disable") || unformat (input, "off"))
2120         enable = 0;
2121       else
2122         break;
2123     }
2124
2125   if (intfc_set == 0)
2126     return clib_error_return (0, "unknown input '%U'",
2127                               format_unformat_error, input);
2128
2129   si = vnet_get_sw_interface (vnm, sw_if_index);
2130   ASSERT (si);
2131   if (enable)
2132     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2133   else
2134     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
2135
2136   return 0;
2137 }
2138
2139 /* *INDENT-OFF* */
2140 /*?
2141  * Enable proxy-arp on an interface. The vpp stack will answer ARP
2142  * requests for the indicated address range. Multiple proxy-arp
2143  * ranges may be provisioned.
2144  *
2145  * @note Proxy ARP as a technology is infamous for blackholing traffic.
2146  * Also, the underlying implementation has not been performance-tuned.
2147  * Avoid creating an unnecessarily large set of ranges.
2148  *
2149  * @cliexpar
2150  * To enable proxy arp on a range of addresses, use:
2151  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11}
2152  * Append 'del' to delete a range of proxy ARP addresses:
2153  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11 del}
2154  * You must then specifically enable proxy arp on individual interfaces:
2155  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 enable}
2156  * To disable proxy arp on an individual interface:
2157  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 disable}
2158  ?*/
2159 VLIB_CLI_COMMAND (set_int_proxy_enable_command, static) = {
2160   .path = "set interface proxy-arp",
2161   .short_help =
2162   "set interface proxy-arp <intfc> [enable|disable]",
2163   .function = set_int_proxy_arp_command_fn,
2164 };
2165 /* *INDENT-ON* */
2166
2167
2168 /*
2169  * ARP/ND Termination in a L2 Bridge Domain based on IP4/IP6 to MAC
2170  * hash tables mac_by_ip4 and mac_by_ip6 for each BD.
2171  */
2172 typedef enum
2173 {
2174   ARP_TERM_NEXT_L2_OUTPUT,
2175   ARP_TERM_NEXT_DROP,
2176   ARP_TERM_N_NEXT,
2177 } arp_term_next_t;
2178
2179 u32 arp_term_next_node_index[32];
2180
2181 static uword
2182 arp_term_l2bd (vlib_main_t * vm,
2183                vlib_node_runtime_t * node, vlib_frame_t * frame)
2184 {
2185   l2input_main_t *l2im = &l2input_main;
2186   u32 n_left_from, next_index, *from, *to_next;
2187   u32 n_replies_sent = 0;
2188   u16 last_bd_index = ~0;
2189   l2_bridge_domain_t *last_bd_config = 0;
2190   l2_input_config_t *cfg0;
2191
2192   from = vlib_frame_vector_args (frame);
2193   n_left_from = frame->n_vectors;
2194   next_index = node->cached_next_index;
2195
2196   while (n_left_from > 0)
2197     {
2198       u32 n_left_to_next;
2199
2200       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2201
2202       while (n_left_from > 0 && n_left_to_next > 0)
2203         {
2204           vlib_buffer_t *p0;
2205           ethernet_header_t *eth0;
2206           ethernet_arp_header_t *arp0;
2207           ip6_header_t *iph0;
2208           u8 *l3h0;
2209           u32 pi0, error0, next0, sw_if_index0;
2210           u16 ethertype0;
2211           u16 bd_index0;
2212           u32 ip0;
2213           u8 *macp0;
2214
2215           pi0 = from[0];
2216           to_next[0] = pi0;
2217           from += 1;
2218           to_next += 1;
2219           n_left_from -= 1;
2220           n_left_to_next -= 1;
2221
2222           p0 = vlib_get_buffer (vm, pi0);
2223           eth0 = vlib_buffer_get_current (p0);
2224           l3h0 = (u8 *) eth0 + vnet_buffer (p0)->l2.l2_len;
2225           ethertype0 = clib_net_to_host_u16 (*(u16 *) (l3h0 - 2));
2226           arp0 = (ethernet_arp_header_t *) l3h0;
2227
2228           if (PREDICT_FALSE ((ethertype0 != ETHERNET_TYPE_ARP) ||
2229                              (arp0->opcode !=
2230                               clib_host_to_net_u16
2231                               (ETHERNET_ARP_OPCODE_request))))
2232             goto check_ip6_nd;
2233
2234           /* Must be ARP request packet here */
2235           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
2236                              (p0->flags & VLIB_BUFFER_IS_TRACED)))
2237             {
2238               u8 *t0 = vlib_add_trace (vm, node, p0,
2239                                        sizeof (ethernet_arp_input_trace_t));
2240               clib_memcpy (t0, l3h0, sizeof (ethernet_arp_input_trace_t));
2241             }
2242
2243           error0 = ETHERNET_ARP_ERROR_replies_sent;
2244           error0 =
2245             (arp0->l2_type !=
2246              clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
2247              ? ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
2248           error0 =
2249             (arp0->l3_type !=
2250              clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
2251              ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
2252
2253           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2254
2255           if (error0)
2256             goto drop;
2257
2258           /* Trash ARP packets whose ARP-level source addresses do not
2259              match their L2-frame-level source addresses  */
2260           if (PREDICT_FALSE
2261               (memcmp
2262                (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
2263                 sizeof (eth0->src_address))))
2264             {
2265               error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
2266               goto drop;
2267             }
2268
2269           /* Check if anyone want ARP request events for L2 BDs */
2270           {
2271             pending_resolution_t *mc;
2272             ethernet_arp_main_t *am = &ethernet_arp_main;
2273             uword *p = hash_get (am->mac_changes_by_address, 0);
2274             if (p && (vnet_buffer (p0)->l2.shg == 0))
2275               {                 // Only SHG 0 interface which is more likely local
2276                 u32 next_index = p[0];
2277                 while (next_index != (u32) ~ 0)
2278                   {
2279                     int (*fp) (u32, u8 *, u32, u32);
2280                     int rv = 1;
2281                     mc = pool_elt_at_index (am->mac_changes, next_index);
2282                     fp = mc->data_callback;
2283                     /* Call the callback, return 1 to suppress dup events */
2284                     if (fp)
2285                       rv = (*fp) (mc->data,
2286                                   arp0->ip4_over_ethernet[0].ethernet,
2287                                   sw_if_index0,
2288                                   arp0->ip4_over_ethernet[0].ip4.as_u32);
2289                     /* Signal the resolver process */
2290                     if (rv == 0)
2291                       vlib_process_signal_event (vm, mc->node_index,
2292                                                  mc->type_opaque, mc->data);
2293                     next_index = mc->next_index;
2294                   }
2295               }
2296           }
2297
2298           /* lookup BD mac_by_ip4 hash table for MAC entry */
2299           ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
2300           bd_index0 = vnet_buffer (p0)->l2.bd_index;
2301           if (PREDICT_FALSE ((bd_index0 != last_bd_index)
2302                              || (last_bd_index == (u16) ~ 0)))
2303             {
2304               last_bd_index = bd_index0;
2305               last_bd_config = vec_elt_at_index (l2im->bd_configs, bd_index0);
2306             }
2307           macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
2308
2309           if (PREDICT_FALSE (!macp0))
2310             goto next_l2_feature;       /* MAC not found */
2311
2312           /* MAC found, send ARP reply -
2313              Convert ARP request packet to ARP reply */
2314           arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
2315           arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
2316           arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
2317           clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
2318           clib_memcpy (eth0->dst_address, eth0->src_address, 6);
2319           clib_memcpy (eth0->src_address, macp0, 6);
2320           n_replies_sent += 1;
2321
2322         output_response:
2323           /* For BVI, need to use l2-fwd node to send ARP reply as
2324              l2-output node cannot output packet to BVI properly */
2325           cfg0 = vec_elt_at_index (l2im->configs, sw_if_index0);
2326           if (PREDICT_FALSE (cfg0->bvi))
2327             {
2328               vnet_buffer (p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
2329               vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
2330               goto next_l2_feature;
2331             }
2332
2333           /* Send ARP/ND reply back out input interface through l2-output */
2334           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2335           next0 = ARP_TERM_NEXT_L2_OUTPUT;
2336           /* Note that output to VXLAN tunnel will fail due to SHG which
2337              is probably desireable since ARP termination is not intended
2338              for ARP requests from other hosts. If output to VXLAN tunnel is
2339              required, however, can just clear the SHG in packet as follows:
2340              vnet_buffer(p0)->l2.shg = 0;         */
2341           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2342                                            to_next, n_left_to_next, pi0,
2343                                            next0);
2344           continue;
2345
2346         check_ip6_nd:
2347           /* IP6 ND event notification or solicitation handling to generate
2348              local response instead of flooding */
2349           iph0 = (ip6_header_t *) l3h0;
2350           if (PREDICT_FALSE (ethertype0 == ETHERNET_TYPE_IP6 &&
2351                              iph0->protocol == IP_PROTOCOL_ICMP6 &&
2352                              !ip6_address_is_unspecified
2353                              (&iph0->src_address)))
2354             {
2355               sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2356               if (vnet_ip6_nd_term
2357                   (vm, node, p0, eth0, iph0, sw_if_index0,
2358                    vnet_buffer (p0)->l2.bd_index, vnet_buffer (p0)->l2.shg))
2359                 goto output_response;
2360             }
2361
2362         next_l2_feature:
2363           {
2364             u32 feature_bitmap0 =
2365               vnet_buffer (p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM;
2366             vnet_buffer (p0)->l2.feature_bitmap = feature_bitmap0;
2367             next0 =
2368               feat_bitmap_get_next_node_index (arp_term_next_node_index,
2369                                                feature_bitmap0);
2370             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2371                                              to_next, n_left_to_next,
2372                                              pi0, next0);
2373             continue;
2374           }
2375
2376         drop:
2377           if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
2378               (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
2379                arp0->ip4_over_ethernet[1].ip4.as_u32))
2380             {
2381               error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
2382             }
2383           next0 = ARP_TERM_NEXT_DROP;
2384           p0->error = node->errors[error0];
2385
2386           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2387                                            to_next, n_left_to_next, pi0,
2388                                            next0);
2389         }
2390
2391       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2392     }
2393
2394   vlib_error_count (vm, node->node_index,
2395                     ETHERNET_ARP_ERROR_replies_sent, n_replies_sent);
2396   return frame->n_vectors;
2397 }
2398
2399 /* *INDENT-OFF* */
2400 VLIB_REGISTER_NODE (arp_term_l2bd_node, static) = {
2401   .function = arp_term_l2bd,
2402   .name = "arp-term-l2bd",
2403   .vector_size = sizeof (u32),
2404   .n_errors = ETHERNET_ARP_N_ERROR,
2405   .error_strings = ethernet_arp_error_strings,
2406   .n_next_nodes = ARP_TERM_N_NEXT,
2407   .next_nodes = {
2408     [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
2409     [ARP_TERM_NEXT_DROP] = "error-drop",
2410   },
2411   .format_buffer = format_ethernet_arp_header,
2412   .format_trace = format_arp_term_input_trace,
2413 };
2414 /* *INDENT-ON* */
2415
2416 clib_error_t *
2417 arp_term_init (vlib_main_t * vm)
2418 {
2419   // Initialize the feature next-node indexes
2420   feat_bitmap_init_next_nodes (vm,
2421                                arp_term_l2bd_node.index,
2422                                L2INPUT_N_FEAT,
2423                                l2input_get_feat_names (),
2424                                arp_term_next_node_index);
2425   return 0;
2426 }
2427
2428 VLIB_INIT_FUNCTION (arp_term_init);
2429
2430 void
2431 change_arp_mac (u32 sw_if_index, ethernet_arp_ip4_entry_t * e)
2432 {
2433   if (e->sw_if_index == sw_if_index)
2434     {
2435       adj_nbr_walk_nh4 (e->sw_if_index,
2436                         &e->ip4_address, arp_mk_complete_walk, e);
2437     }
2438 }
2439
2440 void
2441 ethernet_arp_change_mac (u32 sw_if_index)
2442 {
2443   ethernet_arp_main_t *am = &ethernet_arp_main;
2444   ethernet_arp_ip4_entry_t *e;
2445
2446   /* *INDENT-OFF* */
2447   pool_foreach (e, am->ip4_entry_pool,
2448   ({
2449     change_arp_mac (sw_if_index, e);
2450   }));
2451   /* *INDENT-ON* */
2452 }
2453
2454 /*
2455  * fd.io coding-style-patch-verification: ON
2456  *
2457  * Local Variables:
2458  * eval: (c-set-style "gnu")
2459  * End:
2460  */