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