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