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