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