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