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