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