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