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