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