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