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