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