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