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