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