Initial commit of vpp code.
[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/ethernet/ethernet.h>
20 #include <vnet/ethernet/arp_packet.h>
21 #include <vnet/l2/l2_input.h>
22 #include <vppinfra/mhash.h>
23
24 typedef struct {
25   u32 sw_if_index;
26   u32 fib_index;
27   ip4_address_t ip4_address;
28 } ethernet_arp_ip4_key_t;
29
30 typedef struct {
31   ethernet_arp_ip4_key_t key;
32   u8 ethernet_address[6];
33
34   u16 flags;
35 #define ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC (1 << 0)
36
37   u64 cpu_time_last_updated;
38 } ethernet_arp_ip4_entry_t;
39
40 typedef struct {
41   u32 lo_addr;
42   u32 hi_addr;
43   u32 fib_index;
44 } ethernet_proxy_arp_t;
45
46 typedef struct {
47   u32 next_index;
48   uword node_index;
49   uword type_opaque;
50   uword data;
51   /* Used for arp event notification only */
52   void * data_callback;
53   u32 pid;
54 } pending_resolution_t;
55
56 typedef struct {
57   /* Hash tables mapping name to opcode. */
58   uword * opcode_by_name;
59
60   /* lite beer "glean" adjacency handling */
61   uword * pending_resolutions_by_address;
62   pending_resolution_t * pending_resolutions;
63
64   /* Mac address change notification */
65   uword * mac_changes_by_address;
66   pending_resolution_t * mac_changes;
67
68   u32 * arp_input_next_index_by_hw_if_index;
69
70   ethernet_arp_ip4_entry_t * ip4_entry_pool;
71
72   mhash_t ip4_entry_by_key;
73     
74   /* ARP attack mitigation */
75   u32 arp_delete_rotor;
76   u32 limit_arp_cache_size;
77
78   /* Proxy arp vector */
79   ethernet_proxy_arp_t * proxy_arps;
80 } ethernet_arp_main_t;
81
82 static ethernet_arp_main_t ethernet_arp_main;
83
84 static u8 * format_ethernet_arp_hardware_type (u8 * s, va_list * va)
85 {
86   ethernet_arp_hardware_type_t h = va_arg (*va, ethernet_arp_hardware_type_t);
87   char * t = 0;
88   switch (h)
89     {
90 #define _(n,f) case n: t = #f; break;
91       foreach_ethernet_arp_hardware_type;
92 #undef _
93
94     default:
95       return format (s, "unknown 0x%x", h);
96     }
97
98   return format (s, "%s", t);
99 }
100
101 static u8 * format_ethernet_arp_opcode (u8 * s, va_list * va)
102 {
103   ethernet_arp_opcode_t o = va_arg (*va, ethernet_arp_opcode_t);
104   char * t = 0;
105   switch (o)
106     {
107 #define _(f) case ETHERNET_ARP_OPCODE_##f: t = #f; break;
108       foreach_ethernet_arp_opcode;
109 #undef _
110
111     default:
112       return format (s, "unknown 0x%x", o);
113     }
114
115   return format (s, "%s", t);
116 }
117
118 static uword
119 unformat_ethernet_arp_opcode_host_byte_order (unformat_input_t * input,
120                                               va_list * args)
121 {
122   int * result = va_arg (*args, int *);
123   ethernet_arp_main_t * am = &ethernet_arp_main;
124   int x, i;
125
126   /* Numeric opcode. */
127   if (unformat (input, "0x%x", &x)
128       || unformat (input, "%d", &x))
129     {
130       if (x >= (1 << 16))
131         return 0;
132       *result = x;
133       return 1;
134     }
135
136   /* Named type. */
137   if (unformat_user (input, unformat_vlib_number_by_name,
138                      am->opcode_by_name, &i))
139     {
140       *result = i;
141       return 1;
142     }
143
144   return 0;
145 }
146
147 static uword
148 unformat_ethernet_arp_opcode_net_byte_order (unformat_input_t * input,
149                                              va_list * args)
150 {
151   int * result = va_arg (*args, int *);
152   if (! unformat_user (input, unformat_ethernet_arp_opcode_host_byte_order, result))
153     return 0;
154
155   *result = clib_host_to_net_u16 ((u16) *result);
156   return 1;
157 }
158
159 static u8 * format_ethernet_arp_header (u8 * s, va_list * va)
160 {
161   ethernet_arp_header_t * a = va_arg (*va, ethernet_arp_header_t *);
162   u32 max_header_bytes = va_arg (*va, u32);
163   uword indent;
164   u16 l2_type, l3_type;
165
166   if (max_header_bytes != 0 && sizeof (a[0]) > max_header_bytes)
167     return format (s, "ARP header truncated");
168
169   l2_type = clib_net_to_host_u16 (a->l2_type);
170   l3_type = clib_net_to_host_u16 (a->l3_type);
171
172   indent = format_get_indent (s);
173
174   s = format (s, "%U, type %U/%U, address size %d/%d",
175               format_ethernet_arp_opcode, clib_net_to_host_u16 (a->opcode),
176               format_ethernet_arp_hardware_type, l2_type,
177               format_ethernet_type, l3_type,
178               a->n_l2_address_bytes, a->n_l3_address_bytes);
179               
180   if (l2_type == ETHERNET_ARP_HARDWARE_TYPE_ethernet
181       && l3_type == ETHERNET_TYPE_IP4)
182     {
183       s = format (s, "\n%U%U/%U -> %U/%U",
184                   format_white_space, indent,
185                   format_ethernet_address, a->ip4_over_ethernet[0].ethernet,
186                   format_ip4_address, &a->ip4_over_ethernet[0].ip4,
187                   format_ethernet_address, a->ip4_over_ethernet[1].ethernet,
188                   format_ip4_address, &a->ip4_over_ethernet[1].ip4);
189     }
190   else
191     {
192       uword n2 = a->n_l2_address_bytes;
193       uword n3 = a->n_l3_address_bytes;
194       s = format (s, "\n%U%U/%U -> %U/%U",
195                   format_white_space, indent,
196                   format_hex_bytes, a->data + 0*n2 + 0*n3, n2,
197                   format_hex_bytes, a->data + 1*n2 + 0*n3, n3,
198                   format_hex_bytes, a->data + 1*n2 + 1*n3, n2,
199                   format_hex_bytes, a->data + 2*n2 + 1*n3, n3);
200     }
201
202   return s;
203 }
204
205 static u8 * format_ethernet_arp_ip4_entry (u8 * s, va_list * va)
206 {
207   vnet_main_t * vnm = va_arg (*va, vnet_main_t *);
208   ethernet_arp_ip4_entry_t * e = va_arg (*va, ethernet_arp_ip4_entry_t *);
209   vnet_sw_interface_t * si;
210   ip4_fib_t * fib;
211
212   if (! e)
213     return format (s, "%=12s%=6s%=16s%=4s%=20s%=24s", "Time", "FIB", "IP4", 
214                    "Static", "Ethernet", "Interface");
215
216   fib = find_ip4_fib_by_table_index_or_id (&ip4_main, e->key.fib_index,
217                                            IP4_ROUTE_FLAG_FIB_INDEX);
218   si = vnet_get_sw_interface (vnm, e->key.sw_if_index);
219   s = format (s, "%=12U%=6u%=16U%=4s%=20U%=25U",
220               format_vlib_cpu_time, vnm->vlib_main, e->cpu_time_last_updated,
221               fib->table_id,
222               format_ip4_address, &e->key.ip4_address,
223               (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) ? "S" : "",
224               format_ethernet_address, e->ethernet_address,
225               format_vnet_sw_interface_name, vnm, si);
226
227   return s;
228 }
229
230 typedef struct {
231   u8 packet_data[64];
232 } ethernet_arp_input_trace_t;
233
234 static u8 * format_ethernet_arp_input_trace (u8 * s, va_list * va)
235 {
236   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
237   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
238   ethernet_arp_input_trace_t * t = va_arg (*va, ethernet_arp_input_trace_t *);
239
240   s = format (s, "%U",
241               format_ethernet_arp_header,
242               t->packet_data, sizeof (t->packet_data));
243
244   return s;
245 }
246
247 clib_error_t *
248 ethernet_arp_sw_interface_up_down (vnet_main_t * vnm,
249                                    u32 sw_if_index,
250                                    u32 flags)
251 {
252   ethernet_arp_main_t * am = &ethernet_arp_main;
253   ethernet_arp_ip4_entry_t * e;
254
255   if (! (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
256     {
257       u32 i, * to_delete = 0;
258
259       pool_foreach (e, am->ip4_entry_pool, ({
260         if (e->key.sw_if_index == sw_if_index)
261           vec_add1 (to_delete, e - am->ip4_entry_pool);
262       }));
263
264       for (i = 0; i < vec_len (to_delete); i++)
265         {
266           ethernet_arp_ip4_over_ethernet_address_t delme;
267           e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
268
269           memcpy (&delme.ethernet, e->ethernet_address, 6);
270           delme.ip4.as_u32 = e->key.ip4_address.as_u32;
271
272           vnet_arp_unset_ip4_over_ethernet (vnm, e->key.sw_if_index,
273                                             e->key.fib_index, &delme);
274         }
275
276       vec_free (to_delete);
277     }
278
279   return 0;
280 }
281
282 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_arp_sw_interface_up_down);
283
284 static int
285 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
286                                          u32 sw_if_index,
287                                          u32 fib_index,
288                                          void * a_arg,
289                                          int is_static);
290
291 static int
292 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
293                                            u32 sw_if_index,
294                                            u32 fib_index,
295                                            void * a_arg);
296
297 typedef struct {
298   u32 sw_if_index;
299   u32 fib_index;
300   ethernet_arp_ip4_over_ethernet_address_t a;
301   int is_static;
302   int is_remove; /* set is_remove=1 to clear arp entry */
303 } vnet_arp_set_ip4_over_ethernet_rpc_args_t;
304
305 static void set_ip4_over_ethernet_rpc_callback 
306 ( vnet_arp_set_ip4_over_ethernet_rpc_args_t * a)
307 {
308   vnet_main_t * vm = vnet_get_main();
309   ASSERT(os_get_cpu_number() == 0);
310
311   if (a->is_remove)
312     vnet_arp_unset_ip4_over_ethernet_internal(vm, 
313                                               a->sw_if_index, 
314                                               a->fib_index,
315                                               &(a->a));
316   else
317     vnet_arp_set_ip4_over_ethernet_internal (vm,
318                                              a->sw_if_index,
319                                              a->fib_index,
320                                              &(a->a),
321                                              a->is_static);
322 }
323
324 int
325 vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
326                                 u32 sw_if_index,
327                                 u32 fib_index,
328                                 void * a_arg,
329                                 int is_static)
330 {
331   ethernet_arp_ip4_over_ethernet_address_t * a = a_arg;
332   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
333
334   args.sw_if_index = sw_if_index;
335   args.fib_index = fib_index;
336   args.is_static = is_static;
337   args.is_remove = 0;
338   memcpy (&args.a, a, sizeof (*a));
339
340   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback, 
341                                (u8 *) &args, sizeof (args));
342   return 0;
343 }
344
345 int
346 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
347                                          u32 sw_if_index,
348                                          u32 fib_index,
349                                          void * a_arg,
350                                          int is_static)
351 {
352   ethernet_arp_ip4_key_t k;
353   ethernet_arp_ip4_entry_t * e = 0;
354   ethernet_arp_main_t * am = &ethernet_arp_main;
355   ethernet_arp_ip4_over_ethernet_address_t * a = a_arg;
356   vlib_main_t * vm = vlib_get_main();
357   ip4_main_t * im = &ip4_main;
358   int make_new_arp_cache_entry=1;
359   uword * p;
360   ip4_add_del_route_args_t args;
361   ip_adjacency_t adj;
362   pending_resolution_t * pr, * mc;
363   
364   u32 next_index;
365
366   fib_index = (fib_index != (u32)~0) 
367     ? fib_index : im->fib_index_by_sw_if_index[sw_if_index];
368
369   k.sw_if_index = sw_if_index;
370   k.ip4_address = a->ip4;
371   k.fib_index = fib_index;
372
373   p = mhash_get (&am->ip4_entry_by_key, &k);
374   if (p)
375     {
376       e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
377
378       /* Refuse to over-write static arp. */
379       if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
380         return -2;
381       make_new_arp_cache_entry = 0;
382     }
383
384   /* Note: always install the route. It might have been deleted */
385   memset(&adj, 0, sizeof(adj));
386   adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
387
388   vnet_rewrite_for_sw_interface
389     (vnm,
390      VNET_L3_PACKET_TYPE_IP4,
391      sw_if_index,
392      ip4_rewrite_node.index,
393      a->ethernet,               /* destination address */
394      &adj.rewrite_header,
395      sizeof (adj.rewrite_data));
396
397   args.table_index_or_table_id = fib_index;
398   args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_ADD | IP4_ROUTE_FLAG_NEIGHBOR;
399   args.dst_address = a->ip4;
400   args.dst_address_length = 32;
401   args.adj_index = ~0;
402   args.add_adj = &adj;
403   args.n_add_adj = 1;
404
405   ip4_add_del_route (im, &args);
406   if (make_new_arp_cache_entry)
407     {
408       pool_get (am->ip4_entry_pool, e);
409       mhash_set (&am->ip4_entry_by_key, &k,
410                  e - am->ip4_entry_pool,
411                  /* old value */ 0);
412       e->key = k;
413     }
414
415   /* Update time stamp and ethernet address. */
416   memcpy (e->ethernet_address, a->ethernet, sizeof (e->ethernet_address));
417   e->cpu_time_last_updated = clib_cpu_time_now ();
418   if (is_static)
419     e->flags |= ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC;
420
421   /* Customer(s) waiting for this address to be resolved? */
422   p = hash_get (am->pending_resolutions_by_address, a->ip4.as_u32);
423   if (p)
424     {
425       next_index = p[0];
426
427       while (next_index != (u32)~0)
428         {
429           pr = pool_elt_at_index (am->pending_resolutions, next_index);
430           vlib_process_signal_event (vm, pr->node_index,
431                                      pr->type_opaque, 
432                                      pr->data);
433           next_index = pr->next_index;
434           pool_put (am->pending_resolutions, pr);
435         }
436       
437       hash_unset (am->pending_resolutions_by_address, a->ip4.as_u32);
438     }
439
440   /* Customer(s) requesting ARP event for this address? */
441   p = hash_get (am->mac_changes_by_address, a->ip4.as_u32);
442   if (p)
443     {
444       next_index = p[0];
445
446       while (next_index != (u32)~0)
447         {
448           int (*fp)(u32, u8 *, u32, u32);
449           int rv = 1;
450           mc = pool_elt_at_index (am->mac_changes, next_index);
451           fp = mc->data_callback;
452
453           /* Call the user's data callback, return 1 to suppress dup events */
454           if (fp)
455             rv = (*fp)(mc->data, a->ethernet, sw_if_index, 0);
456           
457           /* 
458            * Signal the resolver process, as long as the user
459            * says they want to be notified
460            */
461           if (rv == 0)
462             vlib_process_signal_event (vm, mc->node_index,
463                                        mc->type_opaque, 
464                                        mc->data);
465           next_index = mc->next_index;
466         }
467     }
468
469   return 0;
470 }
471
472 void vnet_register_ip4_arp_resolution_event (vnet_main_t * vnm, 
473                                              void * address_arg,
474                                              uword node_index,
475                                              uword type_opaque,
476                                              uword data)
477 {
478   ethernet_arp_main_t * am = &ethernet_arp_main;
479   ip4_address_t * address = address_arg;
480   uword * p;
481   pending_resolution_t * pr;
482   
483   pool_get (am->pending_resolutions, pr);
484
485   pr->next_index = ~0;
486   pr->node_index = node_index;
487   pr->type_opaque = type_opaque;
488   pr->data = data;
489   pr->data_callback = 0;
490
491   p = hash_get (am->pending_resolutions_by_address, address->as_u32);
492   if (p)
493     {
494       /* Insert new resolution at the head of the list */
495       pr->next_index = p[0];
496       hash_unset (am->pending_resolutions_by_address, address->as_u32);
497     }
498   
499   hash_set (am->pending_resolutions_by_address, address->as_u32, 
500             pr - am->pending_resolutions);
501 }
502
503 int vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm, 
504                                        void * data_callback,
505                                        u32 pid,
506                                        void * address_arg,
507                                        uword node_index,
508                                        uword type_opaque,
509                                        uword data, int is_add)
510 {
511   ethernet_arp_main_t * am = &ethernet_arp_main;
512   ip4_address_t * address = address_arg;
513   uword * p;
514   pending_resolution_t * mc;
515   void (*fp)(u32, u8 *) = data_callback;
516   
517   if (is_add)
518     {
519       pool_get (am->mac_changes, mc);
520
521       mc->next_index = ~0;
522       mc->node_index = node_index;
523       mc->type_opaque = type_opaque;
524       mc->data = data;
525       mc->data_callback = data_callback;
526       mc->pid = pid;
527       
528       p = hash_get (am->mac_changes_by_address, address->as_u32);
529       if (p)
530         {
531           /* Insert new resolution at the head of the list */
532           mc->next_index = p[0];
533           hash_unset (am->mac_changes_by_address, address->as_u32);
534         }
535       
536       hash_set (am->mac_changes_by_address, address->as_u32, 
537                 mc - am->mac_changes);
538       return 0;
539     }
540   else
541     {
542       u32 index;
543       pending_resolution_t * mc_last = 0;
544
545       p = hash_get (am->mac_changes_by_address, address->as_u32);
546       if (p == 0)
547         return VNET_API_ERROR_NO_SUCH_ENTRY;
548
549       index = p[0];
550
551       while (index != (u32)~0)
552         {
553           mc = pool_elt_at_index (am->mac_changes, index);
554           if (mc->node_index == node_index &&
555               mc->type_opaque == type_opaque &&
556               mc->pid == pid)
557             {
558               /* Clients may need to clean up pool entries, too */
559               if (fp)
560                 (*fp)(mc->data, 0 /* no new mac addrs */);
561               if (index == p[0])
562                 {
563                   hash_unset (am->mac_changes_by_address, address->as_u32);
564                   if (mc->next_index != ~0)
565                     hash_set (am->mac_changes_by_address, address->as_u32,
566                               mc->next_index);
567                   pool_put (am->mac_changes, mc);
568                   return 0;
569                 }
570               else
571                 {
572                   ASSERT(mc_last);
573                   mc_last->next_index = mc->next_index;
574                   pool_put (am->mac_changes, mc);
575                   return 0;
576                 }
577             }
578           mc_last = mc;
579           index = mc->next_index;
580         }
581       
582       return VNET_API_ERROR_NO_SUCH_ENTRY;
583     }
584 }
585
586 /* Either we drop the packet or we send a reply to the sender. */
587 typedef enum {
588   ARP_INPUT_NEXT_DROP,
589   ARP_INPUT_N_NEXT,
590 } arp_input_next_t;
591
592 #define foreach_ethernet_arp_error                                      \
593   _ (replies_sent, "ARP replies sent")                                  \
594   _ (l2_type_not_ethernet, "L2 type not ethernet")                      \
595   _ (l3_type_not_ip4, "L3 type not IP4")                                \
596   _ (l3_src_address_not_local, "IP4 source address not local to subnet") \
597   _ (l3_dst_address_not_local, "IP4 destination address not local to subnet") \
598   _ (l3_src_address_is_local, "IP4 source address matches local interface") \
599   _ (l3_src_address_learned, "ARP request IP4 source address learned")  \
600   _ (replies_received, "ARP replies received")                          \
601   _ (opcode_not_request, "ARP opcode not request")                      \
602   _ (proxy_arp_replies_sent, "Proxy ARP replies sent")                  \
603   _ (l2_address_mismatch, "ARP hw addr does not match L2 frame src addr") \
604   _ (missing_interface_address, "ARP missing interface address") \
605   _ (gratuitous_arp, "ARP probe or announcement dropped") \
606
607 typedef enum {
608 #define _(sym,string) ETHERNET_ARP_ERROR_##sym,
609   foreach_ethernet_arp_error
610 #undef _
611   ETHERNET_ARP_N_ERROR,
612 } ethernet_arp_input_error_t;
613
614 /* get first interface address */
615 ip4_address_t *
616 ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index,
617                              ip_interface_address_t ** result_ia)
618 {
619   ip_lookup_main_t * lm = &im->lookup_main;
620   ip_interface_address_t * ia = 0;
621   ip4_address_t * result = 0;
622
623   foreach_ip_interface_address (lm, ia, sw_if_index, 
624                                 1 /* honor unnumbered */,
625   ({
626     ip4_address_t * a = ip_interface_address_get_address (lm, ia);
627     result = a;
628     break;
629   }));
630   if (result_ia)
631     *result_ia = result ? ia : 0;
632   return result;
633 }
634
635 static void unset_random_arp_entry (void)
636 {
637   ethernet_arp_main_t * am = &ethernet_arp_main;
638   ethernet_arp_ip4_entry_t * e;
639   vnet_main_t * vnm = vnet_get_main();
640   ethernet_arp_ip4_over_ethernet_address_t delme;  
641   u32 index;
642
643   index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
644   am->arp_delete_rotor = index;
645
646   /* Try again from elt 0, could happen if an intfc goes down */
647   if (index == ~0)
648     {
649       index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
650       am->arp_delete_rotor = index;
651     }
652
653   /* Nothing left in the pool */
654   if (index == ~0)
655     return;
656
657   e = pool_elt_at_index (am->ip4_entry_pool, index);
658   
659   memcpy (&delme.ethernet, e->ethernet_address, 6);
660   delme.ip4.as_u32 = e->key.ip4_address.as_u32;
661   
662   vnet_arp_unset_ip4_over_ethernet (vnm, e->key.sw_if_index,
663                                     e->key.fib_index, &delme);
664 }
665   
666 static u32 arp_unnumbered (vlib_buffer_t * p0, 
667                            u32 pi0,
668                            ethernet_header_t * eth0,
669                            ip_interface_address_t * ifa0)
670 {
671   ethernet_arp_main_t * am = &ethernet_arp_main;
672   vlib_main_t * vm = vlib_get_main();
673   vnet_main_t * vnm = vnet_get_main();
674   vnet_interface_main_t * vim = &vnm->interface_main;
675   vnet_sw_interface_t * si;
676   vnet_hw_interface_t * hi;
677   u32 unnum_src_sw_if_index;
678   u32 * broadcast_swifs = 0;
679   u32 * buffers = 0;
680   u32 n_alloc = 0;
681   vlib_buffer_t * b0;
682   int i;
683   u8 dst_mac_address[6];
684   i16 header_size;
685   ethernet_arp_header_t * arp0;
686
687   /* Save the dst mac address */
688   memcpy(dst_mac_address, eth0->dst_address, sizeof (dst_mac_address));
689
690   /* Figure out which sw_if_index supplied the address */
691   unnum_src_sw_if_index = ifa0->sw_if_index;
692
693   /* Track down all users of the unnumbered source */
694   pool_foreach (si, vim->sw_interfaces, 
695   ({
696     if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
697         (si->unnumbered_sw_if_index == unnum_src_sw_if_index))
698       {
699         vec_add1 (broadcast_swifs, si->sw_if_index);
700       }
701   }));
702           
703
704   ASSERT (vec_len(broadcast_swifs));
705
706   /* Allocate buffering if we need it */
707   if (vec_len(broadcast_swifs) > 1)
708     {
709       vec_validate (buffers, vec_len(broadcast_swifs)-2);
710       n_alloc = vlib_buffer_alloc (vm, buffers, vec_len(buffers));
711       _vec_len (buffers) = n_alloc;
712       for (i = 0; i < n_alloc; i++)
713         {
714           b0 = vlib_get_buffer (vm, buffers[i]);
715
716           /* xerox (partially built) ARP pkt */
717           memcpy (b0->data, p0->data, p0->current_length + p0->current_data);
718           b0->current_data = p0->current_data;
719           b0->current_length = p0->current_length;
720           vnet_buffer(b0)->sw_if_index[VLIB_RX] =
721             vnet_buffer(p0)->sw_if_index[VLIB_RX];
722         }
723     }
724
725   vec_insert (buffers, 1, 0);
726   buffers[0] = pi0;
727   
728   for (i = 0; i < vec_len(buffers); i++)
729     {
730       b0 = vlib_get_buffer(vm, buffers[i]);
731       arp0 = vlib_buffer_get_current (b0);
732
733       hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[i]);
734       si = vnet_get_sw_interface (vnm, broadcast_swifs[i]);
735
736       /* For decoration, most likely */
737       vnet_buffer(b0)->sw_if_index[VLIB_TX] = hi->sw_if_index;
738
739       /* Fix ARP pkt src address */
740       memcpy (arp0->ip4_over_ethernet[0].ethernet, hi->hw_address, 6);
741
742       /* Build L2 encaps for this swif */
743       header_size = sizeof (ethernet_header_t);
744       if (si->sub.eth.flags.one_tag) 
745         header_size += 4;
746       else if (si->sub.eth.flags.two_tags)
747         header_size += 8;
748       
749       vlib_buffer_advance (b0, -header_size);
750       eth0 = vlib_buffer_get_current (b0);
751
752       if (si->sub.eth.flags.one_tag) {
753         ethernet_vlan_header_t * outer = (void *) (eth0 + 1);
754         
755         eth0->type = si->sub.eth.flags.dot1ad ?
756           clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
757           clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
758         outer->priority_cfi_and_id = 
759           clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
760         outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
761         
762       } else if (si->sub.eth.flags.two_tags) {
763         ethernet_vlan_header_t * outer = (void *) (eth0 + 1);
764         ethernet_vlan_header_t * inner = (void *) (outer + 1);
765         
766         eth0->type = si->sub.eth.flags.dot1ad ?
767           clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
768           clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
769         outer->priority_cfi_and_id = 
770           clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
771         outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
772         inner->priority_cfi_and_id = 
773           clib_host_to_net_u16 (si->sub.eth.inner_vlan_id);
774         inner->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
775         
776       } else {
777         eth0->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
778       }
779       
780       /* Restore the original dst address, set src address */
781       memcpy (eth0->dst_address, dst_mac_address, sizeof (eth0->dst_address));
782       memcpy (eth0->src_address, hi->hw_address, sizeof (eth0->src_address));
783       
784       /* Transmit replicas */
785       if (i > 0)
786         {
787           vlib_frame_t * f = vlib_get_frame_to_node (vm, hi->output_node_index);
788           u32 * to_next = vlib_frame_vector_args (f);
789           to_next[0] = buffers[i];
790           f->n_vectors = 1;
791           vlib_put_frame_to_node (vm, hi->output_node_index, f);
792         }
793     }
794
795   hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[0]);
796
797   vec_free (broadcast_swifs);
798   vec_free (buffers);
799
800   /* The regular path outputs the original pkt.. */
801   return vec_elt (am->arp_input_next_index_by_hw_if_index, hi->hw_if_index);
802 }
803
804 static uword
805 arp_input (vlib_main_t * vm,
806            vlib_node_runtime_t * node,
807            vlib_frame_t * frame)
808 {
809   ethernet_arp_main_t * am = &ethernet_arp_main;
810   vnet_main_t * vnm = vnet_get_main();
811   ip4_main_t * im4 = &ip4_main;
812   u32 n_left_from, next_index, * from, * to_next;
813   u32 n_replies_sent = 0, n_proxy_arp_replies_sent = 0;
814
815   from = vlib_frame_vector_args (frame);
816   n_left_from = frame->n_vectors;
817   next_index = node->cached_next_index;
818
819   if (node->flags & VLIB_NODE_FLAG_TRACE)
820     vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
821                                    /* stride */ 1,
822                                    sizeof (ethernet_arp_input_trace_t));
823
824   while (n_left_from > 0)
825     {
826       u32 n_left_to_next;
827
828       vlib_get_next_frame (vm, node, next_index,
829                            to_next, n_left_to_next);
830
831       while (n_left_from > 0 && n_left_to_next > 0)
832         {
833           vlib_buffer_t * p0;
834           vnet_hw_interface_t * hw_if0;
835           ethernet_arp_header_t * arp0;
836           ethernet_header_t * eth0;
837           ip_interface_address_t * ifa0;
838           ip_adjacency_t * adj0;
839           ip4_address_t * if_addr0;
840           ip4_address_t proxy_src;
841           u32 pi0, error0, next0, sw_if_index0;
842           u8 is_request0, src_is_local0, dst_is_local0, is_unnum0;
843           ethernet_proxy_arp_t * pa;
844
845           pi0 = from[0];
846           to_next[0] = pi0;
847           from += 1;
848           to_next += 1;
849           n_left_from -= 1;
850           n_left_to_next -= 1;
851
852           p0 = vlib_get_buffer (vm, pi0);
853           arp0 = vlib_buffer_get_current (p0);
854
855           is_request0 = arp0->opcode 
856               == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
857
858           error0 = ETHERNET_ARP_ERROR_replies_sent;
859
860           error0 = (arp0->l2_type != clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
861                     ? ETHERNET_ARP_ERROR_l2_type_not_ethernet
862                     : error0);
863           error0 = (arp0->l3_type != clib_net_to_host_u16 (ETHERNET_TYPE_IP4)
864                     ? ETHERNET_ARP_ERROR_l3_type_not_ip4
865                     : error0);
866
867           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
868
869           if (error0)
870             goto drop1;
871
872           /* Check that IP address is local and matches incoming interface. */
873           if_addr0 = ip4_interface_address_matching_destination (im4,
874                                                                  &arp0->ip4_over_ethernet[1].ip4,
875                                                                  sw_if_index0,
876                                                                  &ifa0);
877           if (! if_addr0)
878             {
879               error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
880               goto drop1;
881             }
882
883           /* Honor unnumbered interface, if any */
884           is_unnum0 = sw_if_index0 != ifa0->sw_if_index;
885
886           /* Source must also be local to subnet of matching interface address. */
887           if (! ip4_destination_matches_interface (im4, &arp0->ip4_over_ethernet[0].ip4, ifa0))
888             {
889               error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
890               goto drop1;
891             }
892
893           /* Reject requests/replies with our local interface address. */
894           src_is_local0 = if_addr0->as_u32 == arp0->ip4_over_ethernet[0].ip4.as_u32;
895           if (src_is_local0)
896             {
897               error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
898               goto drop1;
899             }
900
901           dst_is_local0 = if_addr0->as_u32 == arp0->ip4_over_ethernet[1].ip4.as_u32;
902
903           /* Fill in ethernet header. */
904           eth0 = ethernet_buffer_get_header (p0);
905
906           /* Trash ARP packets whose ARP-level source addresses do not
907              match their L2-frame-level source addresses */
908           if (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
909                       sizeof (eth0->src_address)))
910             {
911               error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
912               goto drop2;
913             }
914
915           /* Learn or update sender's mapping only for requests or unicasts
916              that don't match local interface address. */
917           if (ethernet_address_cast (eth0->dst_address) == ETHERNET_ADDRESS_UNICAST
918               || is_request0)
919             {
920               if (am->limit_arp_cache_size && 
921                   pool_elts (am->ip4_entry_pool) >= am->limit_arp_cache_size)
922                 unset_random_arp_entry();
923
924               vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index0, 
925                                               (u32)~0 /* default fib */,
926                                               &arp0->ip4_over_ethernet[0], 
927                                               0 /* is_static */);
928               error0 = ETHERNET_ARP_ERROR_l3_src_address_learned;
929              }
930
931           /* Only send a reply for requests sent which match a local interface. */
932           if (! (is_request0 && dst_is_local0))
933             {
934               error0 = (arp0->opcode == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply)
935                         ? ETHERNET_ARP_ERROR_replies_received : error0);
936               goto drop1;
937             }
938
939           /* Send a reply. */
940         send_reply:
941           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
942           hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
943
944           /* Can happen in a multi-core env. */
945           if (PREDICT_FALSE(hw_if0->hw_if_index >= vec_len (am->arp_input_next_index_by_hw_if_index)))
946             {
947               error0 = ETHERNET_ARP_ERROR_missing_interface_address;
948               goto drop2;
949             }
950
951           next0 = vec_elt (am->arp_input_next_index_by_hw_if_index, hw_if0->hw_if_index);
952
953           arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
954
955           arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
956
957           memcpy (arp0->ip4_over_ethernet[0].ethernet, hw_if0->hw_address, 6);
958           clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) = if_addr0->data_u32;
959
960           /* Hardware must be ethernet-like. */
961           ASSERT (vec_len (hw_if0->hw_address) == 6);
962
963           memcpy (eth0->dst_address, eth0->src_address, 6);
964           memcpy (eth0->src_address, hw_if0->hw_address, 6);
965
966           /* Figure out how much to rewind current data from adjacency. */
967           if (ifa0)
968             {
969               adj0 = ip_get_adjacency (&ip4_main.lookup_main, 
970                                        ifa0->neighbor_probe_adj_index);
971               if (adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP)
972                 {
973                   error0 = ETHERNET_ARP_ERROR_missing_interface_address;
974                   goto drop2;
975                 }
976               if (is_unnum0)
977                 next0 = arp_unnumbered (p0, pi0, eth0, ifa0);
978               else
979                 vlib_buffer_advance (p0, -adj0->rewrite_header.data_bytes);
980             }
981
982           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
983                                            n_left_to_next,pi0,next0);
984
985           n_replies_sent += 1;
986           continue;
987
988         drop1:
989           if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
990               (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
991                arp0->ip4_over_ethernet[1].ip4.as_u32))
992             {
993               error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
994               goto drop2;
995             }
996           /* See if proxy arp is configured for the address */
997           if (is_request0) 
998             {
999               vnet_sw_interface_t * si;
1000               u32 this_addr = clib_net_to_host_u32 
1001                 (arp0->ip4_over_ethernet[1].ip4.as_u32);
1002               u32 fib_index0;
1003
1004               si = vnet_get_sw_interface (vnm, sw_if_index0);
1005               
1006               if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP))
1007                 goto drop2;
1008
1009               fib_index0 = vec_elt (im4->fib_index_by_sw_if_index, 
1010                                     sw_if_index0);
1011
1012               vec_foreach (pa, am->proxy_arps)
1013                 {
1014                   u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
1015                   u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
1016
1017                    /* an ARP request hit in the proxy-arp table? */
1018                    if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1019                        (fib_index0 == pa->fib_index))
1020                     {
1021                       eth0 = ethernet_buffer_get_header (p0);
1022                       proxy_src.as_u32 = 
1023                         arp0->ip4_over_ethernet[1].ip4.data_u32;
1024
1025                       /* 
1026                        * Rewind buffer, direct code above not to
1027                        * think too hard about it. 
1028                        * $$$ is the answer ever anything other than
1029                        * vlib_buffer_reset(..)?
1030                        */
1031                       ifa0 = 0;
1032                       if_addr0 = &proxy_src;
1033                       vlib_buffer_reset (p0);
1034                       n_proxy_arp_replies_sent++;
1035                       goto send_reply;
1036                     }
1037                 }
1038             }
1039           
1040         drop2:
1041
1042           next0 = ARP_INPUT_NEXT_DROP;
1043           p0->error = node->errors[error0];
1044
1045           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1046                                            n_left_to_next,pi0,next0);
1047         }
1048
1049       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1050     }
1051
1052   vlib_error_count (vm, node->node_index,
1053                     ETHERNET_ARP_ERROR_replies_sent, 
1054                     n_replies_sent - n_proxy_arp_replies_sent);
1055   
1056   vlib_error_count (vm, node->node_index,
1057                     ETHERNET_ARP_ERROR_proxy_arp_replies_sent, 
1058                     n_proxy_arp_replies_sent);
1059   return frame->n_vectors;
1060 }
1061
1062 static char * ethernet_arp_error_strings[] = {
1063 #define _(sym,string) string,
1064   foreach_ethernet_arp_error
1065 #undef _
1066 };
1067
1068 VLIB_REGISTER_NODE (arp_input_node,static) = {
1069   .function = arp_input,
1070   .name = "arp-input",
1071   .vector_size = sizeof (u32),
1072
1073   .n_errors = ETHERNET_ARP_N_ERROR,
1074   .error_strings = ethernet_arp_error_strings,
1075
1076   .n_next_nodes = ARP_INPUT_N_NEXT,
1077   .next_nodes = {
1078     [ARP_INPUT_NEXT_DROP] = "error-drop",
1079   },
1080
1081   .format_buffer = format_ethernet_arp_header,
1082   .format_trace = format_ethernet_arp_input_trace,
1083 };
1084
1085 clib_error_t *
1086 ethernet_arp_hw_interface_link_up_down (vnet_main_t * vnm,
1087                                         u32 hw_if_index,
1088                                         u32 flags)
1089 {
1090   ethernet_arp_main_t * am = &ethernet_arp_main;
1091   vnet_hw_interface_t * hw_if;
1092
1093   hw_if = vnet_get_hw_interface (vnm, hw_if_index);
1094
1095   /* Fill in lookup tables with default table (0). */
1096   vec_validate_init_empty (am->arp_input_next_index_by_hw_if_index, hw_if_index, ~0);
1097   am->arp_input_next_index_by_hw_if_index[hw_if_index]
1098     = vlib_node_add_next (vnm->vlib_main, arp_input_node.index, hw_if->output_node_index);
1099
1100   return 0;
1101 }
1102
1103 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (ethernet_arp_hw_interface_link_up_down);
1104
1105 static int
1106 ip4_arp_entry_sort (void *a1, void *a2)
1107 {
1108   ethernet_arp_ip4_entry_t * e1 = a1;
1109   ethernet_arp_ip4_entry_t * e2 = a2;
1110
1111   int cmp;
1112   vnet_main_t * vnm = vnet_get_main();
1113
1114   cmp = vnet_sw_interface_compare 
1115     (vnm, e1->key.sw_if_index, e2->key.sw_if_index);
1116   if (! cmp)
1117     cmp = ip4_address_compare (&e1->key.ip4_address, &e2->key.ip4_address);
1118   return cmp;
1119 }
1120
1121 static clib_error_t *
1122 show_ip4_arp (vlib_main_t * vm,
1123               unformat_input_t * input,
1124               vlib_cli_command_t * cmd)
1125 {
1126   vnet_main_t * vnm = vnet_get_main();
1127   ethernet_arp_main_t * am = &ethernet_arp_main;
1128   ethernet_arp_ip4_entry_t * e, * es;
1129   ethernet_proxy_arp_t * pa;
1130   clib_error_t * error = 0;
1131   u32 sw_if_index;
1132
1133   /* Filter entries by interface if given. */
1134   sw_if_index = ~0;
1135   (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1136
1137   es = 0;
1138   pool_foreach (e, am->ip4_entry_pool, ({ vec_add1 (es, e[0]); }));
1139   vec_sort_with_function (es, ip4_arp_entry_sort);
1140   vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1141   vec_foreach (e, es) {
1142     if (sw_if_index != ~0 && e->key.sw_if_index != sw_if_index)
1143       continue;
1144     vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1145   }
1146   vec_free (es);
1147
1148   if (vec_len (am->proxy_arps))
1149     {
1150       vlib_cli_output (vm, "Proxy arps enabled for:");
1151       vec_foreach(pa, am->proxy_arps)
1152         {
1153           vlib_cli_output (vm, "Fib_index %d   %U - %U ", 
1154                            pa->fib_index,
1155                            format_ip4_address, &pa->lo_addr, 
1156                            format_ip4_address, &pa->hi_addr);
1157         }
1158     }
1159       
1160   return error;
1161 }
1162
1163 VLIB_CLI_COMMAND (show_ip4_arp_command, static) = {
1164   .path = "show ip arp",
1165   .function = show_ip4_arp,
1166   .short_help = "Show ARP table",
1167 };
1168
1169 typedef struct {
1170   pg_edit_t l2_type, l3_type;
1171   pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1172   pg_edit_t opcode;
1173   struct {
1174     pg_edit_t ethernet;
1175     pg_edit_t ip4;
1176   } ip4_over_ethernet[2];
1177 } pg_ethernet_arp_header_t;
1178
1179 static inline void
1180 pg_ethernet_arp_header_init (pg_ethernet_arp_header_t * p)
1181 {
1182   /* Initialize fields that are not bit fields in the IP header. */
1183 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1184   _ (l2_type);
1185   _ (l3_type);
1186   _ (n_l2_address_bytes);
1187   _ (n_l3_address_bytes);
1188   _ (opcode);
1189   _ (ip4_over_ethernet[0].ethernet);
1190   _ (ip4_over_ethernet[0].ip4);
1191   _ (ip4_over_ethernet[1].ethernet);
1192   _ (ip4_over_ethernet[1].ip4);
1193 #undef _
1194 }
1195
1196 uword
1197 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1198 {
1199   pg_stream_t * s = va_arg (*args, pg_stream_t *);
1200   pg_ethernet_arp_header_t * p;
1201   u32 group_index;
1202   
1203   p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1204                             &group_index);
1205   pg_ethernet_arp_header_init (p);
1206
1207   /* Defaults. */
1208   pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1209   pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1210   pg_edit_set_fixed (&p->n_l2_address_bytes, 6);
1211   pg_edit_set_fixed (&p->n_l3_address_bytes, 4);
1212
1213   if (! unformat (input, "%U: %U/%U -> %U/%U",
1214                   unformat_pg_edit,
1215                   unformat_ethernet_arp_opcode_net_byte_order, &p->opcode,
1216                   unformat_pg_edit,
1217                   unformat_ethernet_address, &p->ip4_over_ethernet[0].ethernet,
1218                   unformat_pg_edit,
1219                   unformat_ip4_address, &p->ip4_over_ethernet[0].ip4,
1220                   unformat_pg_edit,
1221                   unformat_ethernet_address, &p->ip4_over_ethernet[1].ethernet,
1222                   unformat_pg_edit,
1223                   unformat_ip4_address, &p->ip4_over_ethernet[1].ip4))
1224     {
1225       /* Free up any edits we may have added. */
1226       pg_free_edit_group (s);
1227       return 0;
1228     }
1229   return 1;
1230 }
1231
1232 clib_error_t *ip4_set_arp_limit (u32 arp_limit)
1233 {
1234   ethernet_arp_main_t * am = &ethernet_arp_main;
1235
1236   am->limit_arp_cache_size = arp_limit;
1237   return 0;
1238 }
1239
1240 static clib_error_t * ethernet_arp_init (vlib_main_t * vm)
1241 {
1242   ethernet_arp_main_t * am = &ethernet_arp_main;
1243   pg_node_t * pn;
1244
1245   ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
1246
1247   pn = pg_get_node (arp_input_node.index);
1248   pn->unformat_edit = unformat_pg_arp_header;
1249
1250   am->opcode_by_name = hash_create_string (0, sizeof (uword));
1251 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
1252   foreach_ethernet_arp_opcode;
1253 #undef _
1254
1255   mhash_init (&am->ip4_entry_by_key,
1256               /* value size */ sizeof (uword),
1257               /* key size */ sizeof (ethernet_arp_ip4_key_t));
1258
1259   /* $$$ configurable */
1260   am->limit_arp_cache_size = 50000;
1261
1262   am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
1263   am->mac_changes_by_address = hash_create (0, sizeof (uword));
1264
1265   /* don't trace ARP error packets */
1266   {
1267     vlib_node_runtime_t *rt = 
1268       vlib_node_get_runtime (vm, arp_input_node.index);
1269
1270 #define _(a,b)                                  \
1271     vnet_pcap_drop_trace_filter_add_del         \
1272         (rt->errors[ETHERNET_ARP_ERROR_##a],    \
1273          1 /* is_add */);
1274     foreach_ethernet_arp_error
1275 #undef _
1276   }
1277   
1278   return 0;
1279 }
1280
1281 VLIB_INIT_FUNCTION (ethernet_arp_init);
1282
1283 int 
1284 vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
1285                                   u32 sw_if_index, u32 fib_index,
1286                                   void * a_arg)
1287 {
1288   ethernet_arp_ip4_over_ethernet_address_t * a = a_arg;
1289   vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1290
1291   args.sw_if_index = sw_if_index;
1292   args.fib_index = fib_index;
1293   args.is_remove = 1;
1294   memcpy (&args.a, a, sizeof (*a));
1295
1296   vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback, 
1297                                (u8 *) &args, sizeof (args));
1298   return 0;
1299 }
1300
1301 static inline int 
1302 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
1303                                            u32 sw_if_index, 
1304                                            u32 fib_index,
1305                                            void * a_arg)
1306 {
1307   ethernet_arp_ip4_entry_t * e;
1308   ethernet_arp_main_t * am = &ethernet_arp_main;
1309   ethernet_arp_ip4_over_ethernet_address_t * a = a_arg;
1310   ethernet_arp_ip4_key_t k;
1311   uword * p;
1312   ip4_add_del_route_args_t args;
1313   ip4_main_t * im = &ip4_main;
1314   ip_lookup_main_t * lm = &im->lookup_main;
1315   u32 adj_index;
1316   ip_adjacency_t * adj;
1317
1318   k.sw_if_index = sw_if_index;
1319   k.ip4_address = a->ip4;
1320   k.fib_index = fib_index;
1321   p = mhash_get (&am->ip4_entry_by_key, &k);
1322   if (! p)
1323     return -1;
1324
1325   memset(&args, 0, sizeof(args));
1326
1327   /* 
1328    * Make sure that the route actually exists before we try to delete it,
1329    * and make sure that it's a rewrite adjacency.
1330    *
1331    * If we point 1-N unnumbered interfaces at a loopback interface and 
1332    * shut down the loopback before shutting down 1-N unnumbered 
1333    * interfaces, the ARP cache will still have an entry, 
1334    * but the route will have disappeared.
1335    * 
1336    * See also ip4_del_interface_routes (...) 
1337    *            -> ip4_delete_matching_routes (...).
1338    */
1339   
1340   adj_index = ip4_fib_lookup_with_table 
1341       (im, fib_index, &a->ip4, 1 /* disable default route */);
1342
1343   /* Miss adj? Forget it... */
1344   if (adj_index != lm->miss_adj_index) {
1345       adj = ip_get_adjacency (lm, adj_index);
1346       /* 
1347        * Stupid control-plane trick:
1348        * admin down an interface (removes arp routes from fib),
1349        * bring the interface back up (does not reinstall them)
1350        * then remove the arp cache entry (yuck). When that happens,
1351        * the adj we find here will be the interface subnet ARP adj.
1352        */
1353       if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE) {
1354           args.table_index_or_table_id = fib_index;
1355           args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL 
1356               | IP4_ROUTE_FLAG_NEIGHBOR;
1357           args.dst_address = a->ip4;
1358           args.dst_address_length = 32;
1359           ip4_add_del_route (im, &args);
1360           ip4_maybe_remap_adjacencies (im, fib_index, args.flags);
1361       }
1362   }
1363
1364   e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
1365   mhash_unset (&am->ip4_entry_by_key, &e->key, 0);
1366   pool_put (am->ip4_entry_pool, e);
1367   return 0;
1368 }
1369
1370 static void 
1371 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t *a)
1372 {
1373   u8 old;
1374   int i;
1375
1376   for (i = 3; i >= 0; i--) 
1377     {
1378       old = a->ip4.as_u8[i];
1379       a->ip4.as_u8[i] += 1;
1380       if (old < a->ip4.as_u8[i])
1381         break;
1382     }
1383
1384   for (i = 5; i >= 0; i--)
1385     {
1386       old = a->ethernet[i];
1387       a->ethernet[i] += 1;
1388       if (old < a->ethernet[i])
1389         break;
1390     }
1391 }
1392
1393 int vnet_proxy_arp_add_del (ip4_address_t *lo_addr,
1394                             ip4_address_t *hi_addr,
1395                             u32 fib_index, int is_del)
1396 {
1397   ethernet_arp_main_t *am = &ethernet_arp_main;
1398   ethernet_proxy_arp_t *pa;
1399   u32 found_at_index = ~0;
1400
1401   vec_foreach (pa, am->proxy_arps)
1402     {
1403       if (pa->lo_addr == lo_addr->as_u32 
1404           && pa->hi_addr == hi_addr->as_u32
1405           && pa->fib_index == fib_index)
1406         {
1407           found_at_index = pa - am->proxy_arps;
1408           break;
1409         }
1410     }
1411
1412   if (found_at_index != ~0)
1413     {
1414       /* Delete, otherwise it's already in the table */
1415       if (is_del)
1416         vec_delete (am->proxy_arps, 1, found_at_index);
1417       return 0;
1418     }
1419   /* delete, no such entry */
1420   if (is_del)
1421     return VNET_API_ERROR_NO_SUCH_ENTRY;
1422
1423   /* add, not in table */
1424   vec_add2 (am->proxy_arps, pa, 1);
1425   pa->lo_addr = lo_addr->as_u32;
1426   pa->hi_addr = hi_addr->as_u32;
1427   pa->fib_index = fib_index;
1428   return 0;
1429 }
1430
1431 /*
1432  * Remove any proxy arp entries asdociated with the 
1433  * specificed fib.
1434  */
1435 int vnet_proxy_arp_fib_reset (u32 fib_id)
1436 {
1437   ip4_main_t * im = &ip4_main;
1438   ethernet_arp_main_t *am = &ethernet_arp_main;
1439   ethernet_proxy_arp_t *pa;
1440   u32 * entries_to_delete = 0;
1441   u32 fib_index;
1442   uword * p;
1443   int i;
1444
1445   p = hash_get (im->fib_index_by_table_id, fib_id);
1446   if (! p)
1447       return VNET_API_ERROR_NO_SUCH_ENTRY;
1448   fib_index = p[0];
1449
1450   vec_foreach (pa, am->proxy_arps)
1451     {
1452       if (pa->fib_index == fib_index)
1453         {
1454           vec_add1 (entries_to_delete, pa - am->proxy_arps);
1455         }
1456     }
1457
1458   for (i = 0; i < vec_len(entries_to_delete); i++)
1459     {
1460        vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
1461     } 
1462
1463   vec_free (entries_to_delete);
1464
1465    return 0;
1466 }
1467
1468 static clib_error_t *
1469 ip_arp_add_del_command_fn (vlib_main_t * vm,
1470                  unformat_input_t * input,
1471                  vlib_cli_command_t * cmd)
1472 {
1473   vnet_main_t * vnm = vnet_get_main();
1474   u32 sw_if_index;
1475   ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
1476   int addr_valid = 0;
1477   int is_del = 0;
1478   int count = 1;
1479   u32 fib_index = 0;
1480   u32 fib_id;
1481   int is_static = 0;
1482   int is_proxy = 0;
1483
1484   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
1485     {
1486       /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
1487       if (unformat (input, "%U %U %U",
1488                     unformat_vnet_sw_interface, vnm, &sw_if_index,
1489                     unformat_ip4_address, &addr.ip4, 
1490                     unformat_ethernet_address, &addr.ethernet))
1491         addr_valid = 1;
1492
1493       else if (unformat (input, "delete") || unformat (input, "del"))
1494         is_del = 1;
1495
1496       else if (unformat (input, "static"))
1497         is_static = 1;
1498
1499       else if (unformat (input, "count %d", &count))
1500         ;
1501
1502       else if (unformat (input, "fib-id %d", &fib_id))
1503         {
1504           ip4_main_t * im = &ip4_main;
1505           uword * p = hash_get (im->fib_index_by_table_id, fib_id);
1506           if (! p)
1507             return clib_error_return (0, "fib ID %d doesn't exist\n",
1508                                       fib_id);
1509           fib_index = p[0];
1510         }
1511
1512       else if (unformat (input, "proxy %U - %U", 
1513                          unformat_ip4_address, &lo_addr.ip4, 
1514                          unformat_ip4_address, &hi_addr.ip4))
1515         is_proxy = 1;
1516       else
1517         break;
1518     }
1519   
1520   if (is_proxy)
1521     {
1522       (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4, 
1523                                      fib_index, is_del);
1524       return 0;
1525     }
1526
1527   if (addr_valid) 
1528     {
1529       int i;
1530
1531       for (i = 0; i < count; i++) 
1532         {
1533           if (is_del == 0) 
1534             {
1535               uword event_type, * event_data = 0;
1536
1537               /* Park the debug CLI until the arp entry is installed */
1538               vnet_register_ip4_arp_resolution_event 
1539                 (vnm, &addr.ip4, vlib_current_process(vm),
1540                  1 /* type */, 0 /* data */);
1541               
1542               vnet_arp_set_ip4_over_ethernet
1543                 (vnm, sw_if_index, fib_index, &addr, is_static);
1544               
1545               vlib_process_wait_for_event (vm);
1546               event_type = vlib_process_get_events (vm, &event_data);
1547               vec_reset_length(event_data);
1548               if (event_type != 1)
1549                 clib_warning ("event type %d unexpected", event_type);
1550             }
1551           else
1552             vnet_arp_unset_ip4_over_ethernet
1553                 (vnm, sw_if_index, fib_index, &addr);
1554
1555           increment_ip4_and_mac_address (&addr);
1556         }
1557     }
1558   else
1559     {
1560       return clib_error_return (0, "unknown input `%U'",
1561                                 format_unformat_error, input);
1562     }
1563   
1564   return 0;
1565 }
1566
1567 VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = {
1568     .path = "set ip arp",
1569     .short_help = "set ip arp [del] <intfc> <ip-address> <mac-address>",
1570     .function = ip_arp_add_del_command_fn,
1571 };
1572
1573 static clib_error_t *
1574 set_int_proxy_arp_command_fn (vlib_main_t * vm,
1575                               unformat_input_t * input,
1576                               vlib_cli_command_t * cmd)
1577 {
1578   vnet_main_t * vnm = vnet_get_main();
1579   u32 sw_if_index;
1580   vnet_sw_interface_t * si;
1581   int enable = 0;
1582   int intfc_set = 0;
1583
1584   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) 
1585     {
1586       if (unformat (input, "%U", unformat_vnet_sw_interface, 
1587                     vnm, &sw_if_index))
1588         intfc_set = 1;
1589       else if (unformat (input, "enable") || unformat (input, "on"))
1590         enable = 1;
1591       else if (unformat (input, "disable") || unformat (input, "off"))
1592         enable = 0;
1593       else
1594         break;
1595     }
1596
1597   if (intfc_set == 0)
1598     return clib_error_return (0, "unknown input '%U'",
1599                               format_unformat_error, input);
1600
1601   si = vnet_get_sw_interface (vnm, sw_if_index);
1602   ASSERT(si);
1603   if (enable)
1604     si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1605   else 
1606     si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1607   
1608   return 0;
1609 }
1610
1611 VLIB_CLI_COMMAND (set_int_proxy_enable_command, static) = {
1612     .path = "set interface proxy-arp",
1613     .short_help = "set interface proxy-arp <intfc> [enable|disable]",
1614     .function = set_int_proxy_arp_command_fn,
1615 };
1616
1617
1618 /*
1619  * ARP Termination in a L2 Bridge Domain based on an
1620  * IP4 to MAC hash table mac_by_ip4 for each BD.
1621  */
1622 typedef enum {
1623   ARP_TERM_NEXT_L2_OUTPUT,
1624   ARP_TERM_NEXT_DROP,
1625   ARP_TERM_N_NEXT,
1626 } arp_term_next_t;
1627
1628 u32 arp_term_next_node_index[32];
1629
1630 static uword
1631 arp_term_l2bd (vlib_main_t * vm,
1632                vlib_node_runtime_t * node,
1633                vlib_frame_t * frame)
1634 {
1635   l2input_main_t * l2im = &l2input_main;
1636   u32 n_left_from, next_index, * from, * to_next;
1637   u32 n_replies_sent = 0;
1638   u16 last_bd_index = ~0;
1639   l2_bridge_domain_t * last_bd_config = 0;
1640   l2_input_config_t * cfg0;
1641
1642   from = vlib_frame_vector_args (frame);
1643   n_left_from = frame->n_vectors;
1644   next_index = node->cached_next_index;
1645
1646   while (n_left_from > 0)
1647     {
1648       u32 n_left_to_next;
1649
1650       vlib_get_next_frame (vm, node, next_index,
1651                            to_next, n_left_to_next);
1652
1653       while (n_left_from > 0 && n_left_to_next > 0)
1654         {
1655           vlib_buffer_t * p0;
1656           ethernet_header_t * eth0;
1657           ethernet_arp_header_t * arp0;
1658           u8 * l3h0;
1659           u32 pi0, error0, next0, sw_if_index0;
1660           u16 ethertype0;
1661           u16 bd_index0;
1662           u32 ip0;
1663           u8 * macp0;
1664
1665           pi0 = from[0];
1666           to_next[0] = pi0;
1667           from += 1;
1668           to_next += 1;
1669           n_left_from -= 1;
1670           n_left_to_next -= 1;
1671
1672           p0 = vlib_get_buffer (vm, pi0);
1673           eth0 = vlib_buffer_get_current (p0);
1674           l3h0 = (u8 *)eth0 + vnet_buffer(p0)->l2.l2_len;
1675           ethertype0 = clib_net_to_host_u16(*(u16 *)(l3h0 - 2));
1676           arp0 = (ethernet_arp_header_t *) l3h0;
1677
1678           if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
1679                              (p0->flags & VLIB_BUFFER_IS_TRACED)))
1680             {
1681               u8 *t0 = vlib_add_trace (
1682                   vm, node, p0, sizeof(ethernet_arp_input_trace_t));
1683               memcpy (t0, l3h0, sizeof(ethernet_arp_input_trace_t));
1684             }
1685
1686           if (PREDICT_FALSE  (
1687             (ethertype0 != ETHERNET_TYPE_ARP) ||
1688             (arp0->opcode != clib_host_to_net_u16(ETHERNET_ARP_OPCODE_request))))
1689             goto next_l2_feature;
1690
1691           error0 = ETHERNET_ARP_ERROR_replies_sent;
1692           error0 = (arp0->l2_type != clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
1693                     ? ETHERNET_ARP_ERROR_l2_type_not_ethernet
1694                     : error0);
1695           error0 = (arp0->l3_type != clib_net_to_host_u16 (ETHERNET_TYPE_IP4)
1696                     ? ETHERNET_ARP_ERROR_l3_type_not_ip4
1697                     : error0);
1698
1699           sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1700
1701           if (error0)
1702             goto drop;
1703
1704           // Trash ARP packets whose ARP-level source addresses do not
1705           // match their L2-frame-level source addresses */
1706           if (PREDICT_FALSE (
1707             memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
1708                     sizeof (eth0->src_address))))
1709             {
1710               error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1711               goto drop;
1712             }
1713
1714           // Check if anyone want ARP request events for L2 BDs
1715           {
1716           pending_resolution_t * mc;
1717           ethernet_arp_main_t * am = &ethernet_arp_main;
1718           uword *p = hash_get (am->mac_changes_by_address, 0);
1719           if (p && (vnet_buffer(p0)->l2.shg == 0))
1720             { // Only SHG 0 interface which is more likely local
1721               u32 next_index = p[0];
1722               while (next_index != (u32)~0)
1723                 {
1724                   int (*fp)(u32, u8 *, u32, u32);
1725                   int rv = 1;
1726                   mc = pool_elt_at_index (am->mac_changes, next_index);
1727                   fp = mc->data_callback;
1728                   // Call the callback, return 1 to suppress dup events */
1729                   if (fp) rv = (*fp)(mc->data, 
1730                                      arp0->ip4_over_ethernet[0].ethernet, 
1731                                      sw_if_index0, 
1732                                      arp0->ip4_over_ethernet[0].ip4.as_u32);
1733                   // Signal the resolver process
1734                   if (rv == 0)
1735                     vlib_process_signal_event (vm, mc->node_index,
1736                                                mc->type_opaque, 
1737                                                mc->data);
1738                   next_index = mc->next_index;
1739                 }
1740             }
1741           }
1742
1743           // lookup BD mac_by_ip4 hash table for MAC entry
1744           ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
1745           bd_index0 = vnet_buffer(p0)->l2.bd_index;
1746           if (PREDICT_FALSE (
1747             (bd_index0 != last_bd_index) || (last_bd_index == ~0)))
1748             {
1749               last_bd_index = bd_index0;
1750               last_bd_config = vec_elt_at_index(l2im->bd_configs, bd_index0);
1751             }
1752           macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
1753
1754           if (PREDICT_FALSE(!macp0)) 
1755               goto next_l2_feature;     // MAC not found 
1756
1757           // MAC found, send ARP reply -
1758           // Convert ARP request packet to ARP reply
1759           arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1760           arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1761           arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
1762           memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
1763           memcpy (eth0->dst_address, eth0->src_address, 6);
1764           memcpy (eth0->src_address, macp0, 6);
1765           n_replies_sent += 1;
1766
1767           // For BVI, need to use l2-fwd node to send ARP reply as 
1768           // l2-output node cannot output packet to BVI properly
1769           cfg0 = vec_elt_at_index(l2im->configs, sw_if_index0);
1770           if (PREDICT_FALSE (cfg0->bvi))
1771             {
1772               vnet_buffer(p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
1773               vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
1774               goto next_l2_feature;
1775             }
1776
1777           // Send ARP reply back out input interface through l2-output
1778           vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1779           next0 = ARP_TERM_NEXT_L2_OUTPUT;
1780           // Note that output to VXLAN tunnel will fail due to SHG which
1781           // is probably desireable since ARP termination is not intended
1782           // for ARP requests from other hosts. If output to VXLAN tunnel is
1783           // required, however, can just clear the SHG in packet as follows:
1784           //   vnet_buffer(p0)->l2.shg = 0;
1785
1786           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1787                                            n_left_to_next,pi0,next0);
1788           continue;
1789
1790         next_l2_feature:
1791           {
1792             u32 feature_bitmap0 =
1793                 vnet_buffer(p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM;
1794             vnet_buffer(p0)->l2.feature_bitmap = feature_bitmap0;
1795             next0 = feat_bitmap_get_next_node_index(arp_term_next_node_index,
1796                                                     feature_bitmap0);
1797             vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1798                                              n_left_to_next,pi0,next0);
1799             continue;
1800           }
1801
1802         drop:
1803           if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1804               (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1805                arp0->ip4_over_ethernet[1].ip4.as_u32))
1806             {
1807               error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1808             }
1809           next0 = ARP_TERM_NEXT_DROP;
1810           p0->error = node->errors[error0];
1811
1812           vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1813                                            n_left_to_next,pi0,next0);
1814         }
1815
1816       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1817     }
1818
1819   vlib_error_count (vm, node->node_index,
1820                     ETHERNET_ARP_ERROR_replies_sent, 
1821                     n_replies_sent);
1822   return frame->n_vectors;
1823 }
1824
1825 VLIB_REGISTER_NODE (arp_term_l2bd_node,static) = {
1826   .function = arp_term_l2bd,
1827   .name = "arp-term-l2bd",
1828   .vector_size = sizeof (u32),
1829
1830   .n_errors = ETHERNET_ARP_N_ERROR,
1831   .error_strings = ethernet_arp_error_strings,
1832
1833   .n_next_nodes = ARP_TERM_N_NEXT,
1834   .next_nodes = {
1835     [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
1836     [ARP_TERM_NEXT_DROP] = "error-drop",
1837   },
1838
1839   .format_buffer = format_ethernet_arp_header,
1840   .format_trace = format_ethernet_arp_input_trace,
1841 };
1842
1843 clib_error_t *arp_term_init (vlib_main_t *vm)
1844 { // Initialize the feature next-node indexes 
1845   feat_bitmap_init_next_nodes(vm,
1846                               arp_term_l2bd_node.index,
1847                               L2INPUT_N_FEAT,
1848                               l2input_get_feat_names(),
1849                               arp_term_next_node_index);
1850   return 0;
1851 }
1852
1853 VLIB_INIT_FUNCTION (arp_term_init);