FD.io VPP  v17.07.01-10-g3be13f0
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/ip/ip6.h>
20 #include <vnet/ethernet/ethernet.h>
22 #include <vnet/l2/l2_input.h>
23 #include <vppinfra/mhash.h>
24 #include <vnet/fib/ip4_fib.h>
25 #include <vnet/fib/fib_entry_src.h>
26 #include <vnet/adj/adj_nbr.h>
27 #include <vnet/adj/adj_mcast.h>
28 #include <vnet/mpls/mpls.h>
29 
30 /**
31  * @file
32  * @brief IPv4 ARP.
33  *
34  * This file contains code to manage the IPv4 ARP tables (IP Address
35  * to MAC Address lookup).
36  */
37 
38 
39 void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
40 
41 /**
42  * @brief Per-interface ARP configuration and state
43  */
45 {
46  /**
47  * Hash table of ARP entries.
48  * Since this hash table is per-interface, the key is only the IPv4 address.
49  */
52 
53 typedef struct
54 {
59 
60 typedef struct
61 {
66  /* Used for arp event notification only */
70 
71 typedef struct
72 {
73  /* Hash tables mapping name to opcode. */
75 
76  /* lite beer "glean" adjacency handling */
79 
80  /* Mac address change notification */
83 
85 
86  /* ARP attack mitigation */
89 
90  /** Per interface state */
92 
93  /* Proxy arp vector */
96 
98 
99 typedef struct
100 {
102  ethernet_arp_ip4_over_ethernet_address_t a;
105  int flags;
106 #define ETHERNET_ARP_ARGS_REMOVE (1<<0)
107 #define ETHERNET_ARP_ARGS_FLUSH (1<<1)
108 #define ETHERNET_ARP_ARGS_POPULATE (1<<2)
110 
111 static const u8 vrrp_prefix[] = { 0x00, 0x00, 0x5E, 0x00, 0x01 };
112 
113 /* Node index for send_garp_na_process */
115 
116 static void
118  * a);
119 
120 static u8 *
122 {
124  char *t = 0;
125  switch (h)
126  {
127 #define _(n,f) case n: t = #f; break;
129 #undef _
130 
131  default:
132  return format (s, "unknown 0x%x", h);
133  }
134 
135  return format (s, "%s", t);
136 }
137 
138 static u8 *
139 format_ethernet_arp_opcode (u8 * s, va_list * va)
140 {
142  char *t = 0;
143  switch (o)
144  {
145 #define _(f) case ETHERNET_ARP_OPCODE_##f: t = #f; break;
147 #undef _
148 
149  default:
150  return format (s, "unknown 0x%x", o);
151  }
152 
153  return format (s, "%s", t);
154 }
155 
156 static uword
158  va_list * args)
159 {
160  int *result = va_arg (*args, int *);
162  int x, i;
163 
164  /* Numeric opcode. */
165  if (unformat (input, "0x%x", &x) || unformat (input, "%d", &x))
166  {
167  if (x >= (1 << 16))
168  return 0;
169  *result = x;
170  return 1;
171  }
172 
173  /* Named type. */
175  am->opcode_by_name, &i))
176  {
177  *result = i;
178  return 1;
179  }
180 
181  return 0;
182 }
183 
184 static uword
186  va_list * args)
187 {
188  int *result = va_arg (*args, int *);
189  if (!unformat_user
191  return 0;
192 
193  *result = clib_host_to_net_u16 ((u16) * result);
194  return 1;
195 }
196 
197 static u8 *
198 format_ethernet_arp_header (u8 * s, va_list * va)
199 {
200  ethernet_arp_header_t *a = va_arg (*va, ethernet_arp_header_t *);
201  u32 max_header_bytes = va_arg (*va, u32);
202  uword indent;
203  u16 l2_type, l3_type;
204 
205  if (max_header_bytes != 0 && sizeof (a[0]) > max_header_bytes)
206  return format (s, "ARP header truncated");
207 
208  l2_type = clib_net_to_host_u16 (a->l2_type);
209  l3_type = clib_net_to_host_u16 (a->l3_type);
210 
211  indent = format_get_indent (s);
212 
213  s = format (s, "%U, type %U/%U, address size %d/%d",
214  format_ethernet_arp_opcode, clib_net_to_host_u16 (a->opcode),
216  format_ethernet_type, l3_type,
218 
219  if (l2_type == ETHERNET_ARP_HARDWARE_TYPE_ethernet
220  && l3_type == ETHERNET_TYPE_IP4)
221  {
222  s = format (s, "\n%U%U/%U -> %U/%U",
223  format_white_space, indent,
228  }
229  else
230  {
231  uword n2 = a->n_l2_address_bytes;
232  uword n3 = a->n_l3_address_bytes;
233  s = format (s, "\n%U%U/%U -> %U/%U",
234  format_white_space, indent,
235  format_hex_bytes, a->data + 0 * n2 + 0 * n3, n2,
236  format_hex_bytes, a->data + 1 * n2 + 0 * n3, n3,
237  format_hex_bytes, a->data + 1 * n2 + 1 * n3, n2,
238  format_hex_bytes, a->data + 2 * n2 + 1 * n3, n3);
239  }
240 
241  return s;
242 }
243 
244 u8 *
246 {
247  vnet_main_t *vnm = va_arg (*va, vnet_main_t *);
250  u8 *flags = 0;
251 
252  if (!e)
253  return format (s, "%=12s%=16s%=6s%=20s%=24s", "Time", "IP4",
254  "Flags", "Ethernet", "Interface");
255 
256  si = vnet_get_sw_interface (vnm, e->sw_if_index);
257 
259  flags = format (flags, "S");
260 
262  flags = format (flags, "D");
263 
265  flags = format (flags, "N");
266 
267  s = format (s, "%=12U%=16U%=6s%=20U%=24U",
270  flags ? (char *) flags : "",
273 
274  vec_free (flags);
275  return s;
276 }
277 
278 typedef struct
279 {
280  u8 packet_data[64];
282 
283 static u8 *
285 {
286  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
287  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
289 
290  s = format (s, "%U",
292  t->packet_data, sizeof (t->packet_data));
293 
294  return s;
295 }
296 
297 static u8 *
298 format_arp_term_input_trace (u8 * s, va_list * va)
299 {
300  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
301  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
303 
304  /* arp-term trace data saved is either arp or ip6/icmp6 packet:
305  - for arp, the 1st 16-bit field is hw type of value of 0x0001.
306  - for ip6, the first nibble has value of 6. */
307  s = format (s, "%U", t->packet_data[0] == 0 ?
309  t->packet_data, sizeof (t->packet_data));
310 
311  return s;
312 }
313 
314 static void
316 {
317  vnet_main_t *vnm = vnet_get_main ();
318  ip4_main_t *im = &ip4_main;
323  ip4_address_t *src;
324  vlib_buffer_t *b;
325  vlib_main_t *vm;
326  u32 bi = 0;
327 
328  vm = vlib_get_main ();
329 
330  si = vnet_get_sw_interface (vnm, adj->rewrite_header.sw_if_index);
331 
333  {
334  return;
335  }
336 
337  src =
339  &adj->sub_type.nbr.next_hop.
340  ip4,
341  adj->rewrite_header.
342  sw_if_index, &ia);
343  if (!src)
344  {
345  return;
346  }
347 
348  h =
350  &bi);
351 
352  hi = vnet_get_sup_hw_interface (vnm, adj->rewrite_header.sw_if_index);
353 
354  clib_memcpy (h->ip4_over_ethernet[0].ethernet,
355  hi->hw_address, sizeof (h->ip4_over_ethernet[0].ethernet));
356 
357  h->ip4_over_ethernet[0].ip4 = src[0];
358  h->ip4_over_ethernet[1].ip4 = adj->sub_type.nbr.next_hop.ip4;
359 
360  b = vlib_get_buffer (vm, bi);
361  vnet_buffer (b)->sw_if_index[VLIB_RX] =
362  vnet_buffer (b)->sw_if_index[VLIB_TX] = adj->rewrite_header.sw_if_index;
363 
364  /* Add encapsulation string for software interface (e.g. ethernet header). */
365  vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
366  vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
367 
368  {
370  u32 *to_next = vlib_frame_vector_args (f);
371  to_next[0] = bi;
372  f->n_vectors = 1;
374  }
375 }
376 
377 static void
379 {
383  e->sw_if_index,
385 }
386 
387 static void
389 {
390  ip_adjacency_t *adj = adj_get (ai);
391 
393  (ai,
396  adj->rewrite_header.sw_if_index,
399 }
400 
403 {
406  uword *p;
407 
408  if (NULL != eai->arp_entries)
409  {
410  p = hash_get (eai->arp_entries, addr->as_u32);
411  if (!p)
412  return (NULL);
413 
414  e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
415  }
416 
417  return (e);
418 }
419 
420 static adj_walk_rc_t
422 {
423  ethernet_arp_ip4_entry_t *e = ctx;
424 
425  arp_mk_complete (ai, e);
426 
427  return (ADJ_WALK_RC_CONTINUE);
428 }
429 
430 static adj_walk_rc_t
432 {
433  arp_mk_incomplete (ai);
434 
435  return (ADJ_WALK_RC_CONTINUE);
436 }
437 
438 void
439 arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
440 {
442  ethernet_arp_interface_t *arp_int;
444  ip_adjacency_t *adj;
445 
446  adj = adj_get (ai);
447 
448  vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index);
449  arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
450  e = arp_entry_find (arp_int, &adj->sub_type.nbr.next_hop.ip4);
451 
452  switch (adj->lookup_next_index)
453  {
454  case IP_LOOKUP_NEXT_ARP:
456  if (NULL != e)
457  {
458  adj_nbr_walk_nh4 (sw_if_index,
460  }
461  else
462  {
463  /*
464  * no matching ARP entry.
465  * construct the rewrite required to for an ARP packet, and stick
466  * that in the adj's pipe to smoke.
467  */
469  (ai,
472  (vnm,
473  sw_if_index,
476 
477  /*
478  * since the FIB has added this adj for a route, it makes sense it
479  * may want to forward traffic sometime soon. Let's send a
480  * speculative ARP. just one. If we were to do periodically that
481  * wouldn't be bad either, but that's more code than i'm prepared to
482  * write at this time for relatively little reward.
483  */
484  arp_nbr_probe (adj);
485  }
486  break;
488  {
489  /*
490  * Construct a partial rewrite from the known ethernet mcast dest MAC
491  */
492  u8 *rewrite;
493  u8 offset;
494 
495  rewrite = ethernet_build_rewrite (vnm,
496  sw_if_index,
497  adj->ia_link,
499  offset = vec_len (rewrite) - 2;
500 
501  /*
502  * Complete the remaining fields of the adj's rewrite to direct the
503  * complete of the rewrite at switch time by copying in the IP
504  * dst address's bytes.
505  * Ofset is 2 bytes into the MAC desintation address. And we copy 23 bits
506  * from the address.
507  */
508  adj_mcast_update_rewrite (ai, rewrite, offset, 0x007fffff);
509 
510  break;
511  }
512  case IP_LOOKUP_NEXT_DROP:
513  case IP_LOOKUP_NEXT_PUNT:
519  case IP_LOOKUP_N_NEXT:
520  ASSERT (0);
521  break;
522  }
523 }
524 
525 int
528  * args)
529 {
532  ethernet_arp_ip4_over_ethernet_address_t *a = &args->a;
533  vlib_main_t *vm = vlib_get_main ();
534  int make_new_arp_cache_entry = 1;
535  uword *p;
536  pending_resolution_t *pr, *mc;
537  ethernet_arp_interface_t *arp_int;
538  int is_static = args->is_static;
539  u32 sw_if_index = args->sw_if_index;
540  int is_no_fib_entry = args->is_no_fib_entry;
541 
542  vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index);
543 
544  arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
545 
546  if (NULL != arp_int->arp_entries)
547  {
548  p = hash_get (arp_int->arp_entries, a->ip4.as_u32);
549  if (p)
550  {
551  e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
552 
553  /* Refuse to over-write static arp. */
554  if (!is_static && (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC))
555  return -2;
556  make_new_arp_cache_entry = 0;
557  }
558  }
559 
560  if (make_new_arp_cache_entry)
561  {
562  pool_get (am->ip4_entry_pool, e);
563 
564  if (NULL == arp_int->arp_entries)
565  {
566  arp_int->arp_entries = hash_create (0, sizeof (u32));
567  }
568 
569  hash_set (arp_int->arp_entries, a->ip4.as_u32, e - am->ip4_entry_pool);
570 
571  e->sw_if_index = sw_if_index;
572  e->ip4_address = a->ip4;
575  a->ethernet, sizeof (e->ethernet_address));
576 
577  if (!is_no_fib_entry)
578  {
579  fib_prefix_t pfx = {
580  .fp_len = 32,
581  .fp_proto = FIB_PROTOCOL_IP4,
582  .fp_addr.ip4 = a->ip4,
583  };
584  u32 fib_index;
585 
586  fib_index =
588  e->fib_entry_index =
589  fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
592  e->sw_if_index, ~0, 1, NULL,
594  }
595  else
596  {
598  }
599  }
600  else
601  {
602  /*
603  * prevent a DoS attack from the data-plane that
604  * spams us with no-op updates to the MAC address
605  */
606  if (0 == memcmp (e->ethernet_address,
607  a->ethernet, sizeof (e->ethernet_address)))
608  return -1;
609 
610  /* Update time stamp and ethernet address. */
611  clib_memcpy (e->ethernet_address, a->ethernet,
612  sizeof (e->ethernet_address));
613  }
614 
616  if (is_static)
618  else
620 
621  adj_nbr_walk_nh4 (sw_if_index, &e->ip4_address, arp_mk_complete_walk, e);
622 
623  /* Customer(s) waiting for this address to be resolved? */
624  p = hash_get (am->pending_resolutions_by_address, a->ip4.as_u32);
625  if (p)
626  {
627  u32 next_index;
628  next_index = p[0];
629 
630  while (next_index != (u32) ~ 0)
631  {
632  pr = pool_elt_at_index (am->pending_resolutions, next_index);
634  pr->type_opaque, pr->data);
635  next_index = pr->next_index;
636  pool_put (am->pending_resolutions, pr);
637  }
638 
639  hash_unset (am->pending_resolutions_by_address, a->ip4.as_u32);
640  }
641 
642  /* Customer(s) requesting ARP event for this address? */
643  p = hash_get (am->mac_changes_by_address, a->ip4.as_u32);
644  if (p)
645  {
646  u32 next_index;
647  next_index = p[0];
648 
649  while (next_index != (u32) ~ 0)
650  {
651  int (*fp) (u32, u8 *, u32, u32);
652  int rv = 1;
653  mc = pool_elt_at_index (am->mac_changes, next_index);
654  fp = mc->data_callback;
655 
656  /* Call the user's data callback, return 1 to suppress dup events */
657  if (fp)
658  rv = (*fp) (mc->data, a->ethernet, sw_if_index, 0);
659 
660  /*
661  * Signal the resolver process, as long as the user
662  * says they want to be notified
663  */
664  if (rv == 0)
666  mc->type_opaque, mc->data);
667  next_index = mc->next_index;
668  }
669  }
670 
671  return 0;
672 }
673 
674 void
676  void *address_arg,
677  uword node_index,
678  uword type_opaque, uword data)
679 {
681  ip4_address_t *address = address_arg;
682  uword *p;
684 
685  pool_get (am->pending_resolutions, pr);
686 
687  pr->next_index = ~0;
688  pr->node_index = node_index;
689  pr->type_opaque = type_opaque;
690  pr->data = data;
691  pr->data_callback = 0;
692 
693  p = hash_get (am->pending_resolutions_by_address, address->as_u32);
694  if (p)
695  {
696  /* Insert new resolution at the head of the list */
697  pr->next_index = p[0];
699  }
700 
702  pr - am->pending_resolutions);
703 }
704 
705 int
707  void *data_callback,
708  u32 pid,
709  void *address_arg,
710  uword node_index,
711  uword type_opaque, uword data, int is_add)
712 {
714  ip4_address_t *address = address_arg;
715 
716  /* Try to find an existing entry */
717  u32 *first = (u32 *) hash_get (am->mac_changes_by_address, address->as_u32);
718  u32 *p = first;
720  while (p && *p != ~0)
721  {
722  mc = pool_elt_at_index (am->mac_changes, *p);
723  if (mc->node_index == node_index && mc->type_opaque == type_opaque
724  && mc->pid == pid)
725  break;
726  p = &mc->next_index;
727  }
728 
729  int found = p && *p != ~0;
730  if (is_add)
731  {
732  if (found)
733  return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
734 
735  pool_get (am->mac_changes, mc);
736  *mc = (pending_resolution_t)
737  {
738  .next_index = ~0,.node_index = node_index,.type_opaque =
739  type_opaque,.data = data,.data_callback = data_callback,.pid =
740  pid,};
741 
742  /* Insert new resolution at the end of the list */
743  u32 new_idx = mc - am->mac_changes;
744  if (p)
745  p[0] = new_idx;
746  else
747  hash_set (am->mac_changes_by_address, address->as_u32, new_idx);
748  }
749  else
750  {
751  if (!found)
752  return VNET_API_ERROR_NO_SUCH_ENTRY;
753 
754  /* Clients may need to clean up pool entries, too */
755  void (*fp) (u32, u8 *) = data_callback;
756  if (fp)
757  (*fp) (mc->data, 0 /* no new mac addrs */ );
758 
759  /* Remove the entry from the list and delete the entry */
760  *p = mc->next_index;
761  pool_put (am->mac_changes, mc);
762 
763  /* Remove from hash if we deleted the last entry */
764  if (*p == ~0 && p == first)
765  hash_unset (am->mac_changes_by_address, address->as_u32);
766  }
767  return 0;
768 }
769 
770 /* Either we drop the packet or we send a reply to the sender. */
771 typedef enum
772 {
777 
778 #define foreach_ethernet_arp_error \
779  _ (replies_sent, "ARP replies sent") \
780  _ (l2_type_not_ethernet, "L2 type not ethernet") \
781  _ (l3_type_not_ip4, "L3 type not IP4") \
782  _ (l3_src_address_not_local, "IP4 source address not local to subnet") \
783  _ (l3_dst_address_not_local, "IP4 destination address not local to subnet") \
784  _ (l3_src_address_is_local, "IP4 source address matches local interface") \
785  _ (l3_src_address_learned, "ARP request IP4 source address learned") \
786  _ (replies_received, "ARP replies received") \
787  _ (opcode_not_request, "ARP opcode not request") \
788  _ (proxy_arp_replies_sent, "Proxy ARP replies sent") \
789  _ (l2_address_mismatch, "ARP hw addr does not match L2 frame src addr") \
790  _ (missing_interface_address, "ARP missing interface address") \
791  _ (gratuitous_arp, "ARP probe or announcement dropped") \
792  _ (interface_no_table, "Interface is not mapped to an IP table") \
793  _ (interface_not_ip_enabled, "Interface is not IP enabled") \
794 
795 typedef enum
796 {
797 #define _(sym,string) ETHERNET_ARP_ERROR_##sym,
799 #undef _
802 
803 
804 static void
806 {
809  vnet_main_t *vnm = vnet_get_main ();
810  ethernet_arp_ip4_over_ethernet_address_t delme;
811  u32 index;
812 
814  am->arp_delete_rotor = index;
815 
816  /* Try again from elt 0, could happen if an intfc goes down */
817  if (index == ~0)
818  {
820  am->arp_delete_rotor = index;
821  }
822 
823  /* Nothing left in the pool */
824  if (index == ~0)
825  return;
826 
827  e = pool_elt_at_index (am->ip4_entry_pool, index);
828 
829  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
830  delme.ip4.as_u32 = e->ip4_address.as_u32;
831 
833 }
834 
835 static int
837  u32 input_sw_if_index, u32 conn_sw_if_index)
838 {
839  vnet_main_t *vnm = vnet_get_main ();
842 
843  /* verify that the input interface is unnumbered to the connected.
844  * the connected interface is the interface on which the subnet is
845  * configured */
846  si = &vim->sw_interfaces[input_sw_if_index];
847 
849  (si->unnumbered_sw_if_index == conn_sw_if_index)))
850  {
851  /* the input interface is not unnumbered to the interface on which
852  * the sub-net is configured that covers the ARP request.
853  * So this is not the case for unnumbered.. */
854  return 0;
855  }
856 
857  return !0;
858 }
859 
860 static u32
862  ethernet_arp_main_t * am, u32 sw_if_index, void *addr)
863 {
864  if (am->limit_arp_cache_size &&
867 
868  vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index, addr, 0, 0);
869  return (ETHERNET_ARP_ERROR_l3_src_address_learned);
870 }
871 
872 static uword
874 {
876  vnet_main_t *vnm = vnet_get_main ();
877  ip4_main_t *im4 = &ip4_main;
878  u32 n_left_from, next_index, *from, *to_next;
879  u32 n_replies_sent = 0, n_proxy_arp_replies_sent = 0;
880 
881  from = vlib_frame_vector_args (frame);
882  n_left_from = frame->n_vectors;
883  next_index = node->cached_next_index;
884 
885  if (node->flags & VLIB_NODE_FLAG_TRACE)
886  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
887  /* stride */ 1,
888  sizeof (ethernet_arp_input_trace_t));
889 
890  while (n_left_from > 0)
891  {
892  u32 n_left_to_next;
893 
894  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
895 
896  while (n_left_from > 0 && n_left_to_next > 0)
897  {
898  vlib_buffer_t *p0;
899  vnet_hw_interface_t *hw_if0;
900  ethernet_arp_header_t *arp0;
901  ethernet_header_t *eth_rx, *eth_tx;
902  ip4_address_t *if_addr0, proxy_src;
903  u32 pi0, error0, next0, sw_if_index0, conn_sw_if_index0, fib_index0;
904  u8 is_request0, dst_is_local0, is_unnum0, is_vrrp_reply0;
906  fib_node_index_t dst_fei, src_fei;
907  fib_prefix_t pfx0;
908  fib_entry_flag_t src_flags, dst_flags;
909  ip_adjacency_t *adj0 = NULL;
910  adj_index_t ai;
911 
912  pi0 = from[0];
913  to_next[0] = pi0;
914  from += 1;
915  to_next += 1;
916  n_left_from -= 1;
917  n_left_to_next -= 1;
918  pa = 0;
919 
920  p0 = vlib_get_buffer (vm, pi0);
921  arp0 = vlib_buffer_get_current (p0);
922  /* Fill in ethernet header. */
923  eth_rx = ethernet_buffer_get_header (p0);
924 
925  is_request0 = arp0->opcode
926  == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
927 
928  error0 = ETHERNET_ARP_ERROR_replies_sent;
929 
930  error0 =
931  (arp0->l2_type !=
932  clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ?
933  ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
934  error0 =
935  (arp0->l3_type !=
936  clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
937  ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
938 
939  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
940 
941  /* not playing the ARP game if the interface is not IPv4 enabled */
942  error0 =
943  (im4->ip_enabled_by_sw_if_index[sw_if_index0] == 0 ?
944  ETHERNET_ARP_ERROR_interface_not_ip_enabled : error0);
945 
946  if (error0)
947  goto drop2;
948 
949  /* Check that IP address is local and matches incoming interface. */
950  fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
951  if (~0 == fib_index0)
952  {
953  error0 = ETHERNET_ARP_ERROR_interface_no_table;
954  goto drop2;
955 
956  }
957  dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
958  &arp0->ip4_over_ethernet[1].ip4,
959  32);
960  dst_flags = fib_entry_get_flags (dst_fei);
961 
962  conn_sw_if_index0 = fib_entry_get_resolving_interface (dst_fei);
963 
964  /* Honor unnumbered interface, if any */
965  is_unnum0 = sw_if_index0 != conn_sw_if_index0;
966 
967  {
968  /*
969  * we're looking for FIB entries that indicate the source
970  * is attached. There may be more specific non-attached
971  * routes tht match the source, but these do not influence
972  * whether we respond to an ARP request, i.e. they do not
973  * influence whether we are the correct way for the sender
974  * to reach us, they only affect how we reach the sender.
975  */
976  fib_entry_t *src_fib_entry;
977  fib_entry_src_t *src;
978  fib_source_t source;
979  fib_prefix_t pfx;
980  int attached;
981  int mask;
982 
983  mask = 32;
984  attached = 0;
985 
986  do
987  {
988  src_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
989  &arp0->
990  ip4_over_ethernet[0].ip4,
991  mask);
992  src_fib_entry = fib_entry_get (src_fei);
993 
994  /*
995  * It's possible that the source that provides the
996  * flags we need, or the flags we must not have,
997  * is not the best source, so check then all.
998  */
999  /* *INDENT-OFF* */
1000  FOR_EACH_SRC_ADDED(src_fib_entry, src, source,
1001  ({
1002  src_flags = fib_entry_get_flags_for_source (src_fei, source);
1003 
1004  /* Reject requests/replies with our local interface
1005  address. */
1006  if (FIB_ENTRY_FLAG_LOCAL & src_flags)
1007  {
1008  error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
1009  goto drop2;
1010  }
1011  /* A Source must also be local to subnet of matching
1012  * interface address. */
1013  if ((FIB_ENTRY_FLAG_ATTACHED & src_flags) ||
1014  (FIB_ENTRY_FLAG_CONNECTED & src_flags))
1015  {
1016  attached = 1;
1017  break;
1018  }
1019  /*
1020  * else
1021  * The packet was sent from an address that is not
1022  * connected nor attached i.e. it is not from an
1023  * address that is covered by a link's sub-net,
1024  * nor is it a already learned host resp.
1025  */
1026  }));
1027  /* *INDENT-ON* */
1028 
1029  /*
1030  * shorter mask lookup for the next iteration.
1031  */
1032  fib_entry_get_prefix (src_fei, &pfx);
1033  mask = pfx.fp_len - 1;
1034 
1035  /*
1036  * continue until we hit the default route or we find
1037  * the attached we are looking for. The most likely
1038  * outcome is we find the attached with the first source
1039  * on the first lookup.
1040  */
1041  }
1042  while (!attached &&
1044 
1045  if (!attached)
1046  {
1047  /*
1048  * the matching route is a not attached, i.e. it was
1049  * added as a result of routing, rather than interface/ARP
1050  * configuration. If the matching route is not a host route
1051  * (i.e. a /32)
1052  */
1053  error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
1054  goto drop2;
1055  }
1056  }
1057 
1058  if (!(FIB_ENTRY_FLAG_CONNECTED & dst_flags))
1059  {
1060  error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
1061  goto drop1;
1062  }
1063 
1064  if (sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
1065  {
1066  /*
1067  * The interface the ARP was received on is not the interface
1068  * on which the covering prefix is configured. Maybe this is a
1069  * case for unnumbered.
1070  */
1071  is_unnum0 = 1;
1072  }
1073 
1074  dst_is_local0 = (FIB_ENTRY_FLAG_LOCAL & dst_flags);
1075  fib_entry_get_prefix (dst_fei, &pfx0);
1076  if_addr0 = &pfx0.fp_addr.ip4;
1077 
1078  is_vrrp_reply0 =
1079  ((arp0->opcode ==
1080  clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply))
1081  &&
1082  (!memcmp
1083  (arp0->ip4_over_ethernet[0].ethernet, vrrp_prefix,
1084  sizeof (vrrp_prefix))));
1085 
1086  /* Trash ARP packets whose ARP-level source addresses do not
1087  match their L2-frame-level source addresses, unless it's
1088  a reply from a VRRP virtual router */
1089  if (memcmp
1090  (eth_rx->src_address, arp0->ip4_over_ethernet[0].ethernet,
1091  sizeof (eth_rx->src_address)) && !is_vrrp_reply0)
1092  {
1093  error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1094  goto drop2;
1095  }
1096 
1097  /* Learn or update sender's mapping only for replies to addresses
1098  * that are local to the subnet */
1099  if (arp0->opcode ==
1100  clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply) &&
1101  dst_is_local0)
1102  {
1103  error0 = arp_learn (vnm, am, sw_if_index0,
1104  &arp0->ip4_over_ethernet[0]);
1105  goto drop1;
1106  }
1107 
1108  /* Send a reply. */
1109  send_reply:
1110  ai = fib_entry_get_adj (src_fei);
1111  if (ADJ_INDEX_INVALID != ai)
1112  {
1113  adj0 = adj_get (ai);
1114  }
1115  else
1116  {
1117  error0 = ETHERNET_ARP_ERROR_missing_interface_address;
1118  goto drop2;
1119  }
1120  /* Figure out how much to rewind current data from adjacency. */
1121  vlib_buffer_advance (p0, -adj0->rewrite_header.data_bytes);
1122  eth_tx = vlib_buffer_get_current (p0);
1123 
1124  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1125  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1126 
1127  /* Send reply back through input interface */
1128  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1129  next0 = ARP_INPUT_NEXT_REPLY_TX;
1130 
1131  arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1132 
1133  arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1134 
1135  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet,
1136  hw_if0->hw_address, 6);
1137  clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) =
1138  if_addr0->data_u32;
1139 
1140  /* Hardware must be ethernet-like. */
1141  ASSERT (vec_len (hw_if0->hw_address) == 6);
1142 
1143  /* the rx nd tx ethernet headers wil overlap in the case
1144  * when we received a tagged VLAN=0 packet, but we are sending
1145  * back untagged */
1146  memmove (eth_tx->dst_address, eth_rx->src_address, 6);
1147  clib_memcpy (eth_tx->src_address, hw_if0->hw_address, 6);
1148 
1149  if (NULL == pa)
1150  {
1151  if (is_unnum0)
1152  {
1153  if (!arp_unnumbered (p0, sw_if_index0, conn_sw_if_index0))
1154  goto drop2;
1155  }
1156  }
1157 
1158  /* We are going to reply to this request, so learn the sender */
1159  error0 = arp_learn (vnm, am, sw_if_index0,
1160  &arp0->ip4_over_ethernet[1]);
1161 
1162  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1163  n_left_to_next, pi0, next0);
1164 
1165  n_replies_sent += 1;
1166  continue;
1167 
1168  drop1:
1169  if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1170  (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1171  arp0->ip4_over_ethernet[1].ip4.as_u32))
1172  {
1173  error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1174  goto drop2;
1175  }
1176  /* See if proxy arp is configured for the address */
1177  if (is_request0)
1178  {
1179  vnet_sw_interface_t *si;
1180  u32 this_addr = clib_net_to_host_u32
1181  (arp0->ip4_over_ethernet[1].ip4.as_u32);
1182  u32 fib_index0;
1183 
1184  si = vnet_get_sw_interface (vnm, sw_if_index0);
1185 
1187  goto drop2;
1188 
1189  fib_index0 = vec_elt (im4->fib_index_by_sw_if_index,
1190  sw_if_index0);
1191 
1192  vec_foreach (pa, am->proxy_arps)
1193  {
1194  u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
1195  u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
1196 
1197  /* an ARP request hit in the proxy-arp table? */
1198  if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1199  (fib_index0 == pa->fib_index))
1200  {
1201  proxy_src.as_u32 =
1202  arp0->ip4_over_ethernet[1].ip4.data_u32;
1203 
1204  /*
1205  * change the interface address to the proxied
1206  */
1207  if_addr0 = &proxy_src;
1208  is_unnum0 = 0;
1209  n_proxy_arp_replies_sent++;
1210  goto send_reply;
1211  }
1212  }
1213  }
1214 
1215  drop2:
1216 
1217  next0 = ARP_INPUT_NEXT_DROP;
1218  p0->error = node->errors[error0];
1219 
1220  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1221  n_left_to_next, pi0, next0);
1222  }
1223 
1224  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1225  }
1226 
1227  vlib_error_count (vm, node->node_index,
1228  ETHERNET_ARP_ERROR_replies_sent,
1229  n_replies_sent - n_proxy_arp_replies_sent);
1230 
1231  vlib_error_count (vm, node->node_index,
1232  ETHERNET_ARP_ERROR_proxy_arp_replies_sent,
1233  n_proxy_arp_replies_sent);
1234  return frame->n_vectors;
1235 }
1236 
1237 static char *ethernet_arp_error_strings[] = {
1238 #define _(sym,string) string,
1240 #undef _
1241 };
1242 
1243 /* *INDENT-OFF* */
1245 {
1246  .function = arp_input,
1247  .name = "arp-input",
1248  .vector_size = sizeof (u32),
1249  .n_errors = ETHERNET_ARP_N_ERROR,
1250  .error_strings = ethernet_arp_error_strings,
1251  .n_next_nodes = ARP_INPUT_N_NEXT,
1252  .next_nodes = {
1253  [ARP_INPUT_NEXT_DROP] = "error-drop",
1254  [ARP_INPUT_NEXT_REPLY_TX] = "interface-output",
1255  },
1256  .format_buffer = format_ethernet_arp_header,
1257  .format_trace = format_ethernet_arp_input_trace,
1258 };
1259 /* *INDENT-ON* */
1260 
1261 static int
1262 ip4_arp_entry_sort (void *a1, void *a2)
1263 {
1264  ethernet_arp_ip4_entry_t *e1 = a1;
1265  ethernet_arp_ip4_entry_t *e2 = a2;
1266 
1267  int cmp;
1268  vnet_main_t *vnm = vnet_get_main ();
1269 
1270  cmp = vnet_sw_interface_compare (vnm, e1->sw_if_index, e2->sw_if_index);
1271  if (!cmp)
1272  cmp = ip4_address_compare (&e1->ip4_address, &e2->ip4_address);
1273  return cmp;
1274 }
1275 
1278 {
1280  ethernet_arp_ip4_entry_t *n, *ns = 0;
1281 
1282  /* *INDENT-OFF* */
1283  pool_foreach (n, am->ip4_entry_pool, ({
1284  if (sw_if_index != ~0 && n->sw_if_index != sw_if_index)
1285  continue;
1286  vec_add1 (ns, n[0]);
1287  }));
1288  /* *INDENT-ON* */
1289 
1290  if (ns)
1292  return ns;
1293 }
1294 
1295 static clib_error_t *
1297  unformat_input_t * input, vlib_cli_command_t * cmd)
1298 {
1299  vnet_main_t *vnm = vnet_get_main ();
1301  ethernet_arp_ip4_entry_t *e, *es;
1303  clib_error_t *error = 0;
1304  u32 sw_if_index;
1305 
1306  /* Filter entries by interface if given. */
1307  sw_if_index = ~0;
1308  (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1309 
1310  es = ip4_neighbor_entries (sw_if_index);
1311  if (es)
1312  {
1313  vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1314  vec_foreach (e, es)
1315  {
1316  vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1317  }
1318  vec_free (es);
1319  }
1320 
1321  if (vec_len (am->proxy_arps))
1322  {
1323  vlib_cli_output (vm, "Proxy arps enabled for:");
1324  vec_foreach (pa, am->proxy_arps)
1325  {
1326  vlib_cli_output (vm, "Fib_index %d %U - %U ",
1327  pa->fib_index,
1329  format_ip4_address, &pa->hi_addr);
1330  }
1331  }
1332 
1333  return error;
1334 }
1335 
1336 /*?
1337  * Display all the IPv4 ARP entries.
1338  *
1339  * @cliexpar
1340  * Example of how to display the IPv4 ARP table:
1341  * @cliexstart{show ip arp}
1342  * Time FIB IP4 Flags Ethernet Interface
1343  * 346.3028 0 6.1.1.3 de:ad:be:ef:ba:be GigabitEthernet2/0/0
1344  * 3077.4271 0 6.1.1.4 S de:ad:be:ef:ff:ff GigabitEthernet2/0/0
1345  * 2998.6409 1 6.2.2.3 de:ad:be:ef:00:01 GigabitEthernet2/0/0
1346  * Proxy arps enabled for:
1347  * Fib_index 0 6.0.0.1 - 6.0.0.11
1348  * @cliexend
1349  ?*/
1350 /* *INDENT-OFF* */
1351 VLIB_CLI_COMMAND (show_ip4_arp_command, static) = {
1352  .path = "show ip arp",
1353  .function = show_ip4_arp,
1354  .short_help = "show ip arp",
1355 };
1356 /* *INDENT-ON* */
1357 
1358 typedef struct
1359 {
1360  pg_edit_t l2_type, l3_type;
1361  pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1363  struct
1364  {
1367  } ip4_over_ethernet[2];
1369 
1370 static inline void
1372 {
1373  /* Initialize fields that are not bit fields in the IP header. */
1374 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1375  _(l2_type);
1376  _(l3_type);
1377  _(n_l2_address_bytes);
1378  _(n_l3_address_bytes);
1379  _(opcode);
1380  _(ip4_over_ethernet[0].ethernet);
1381  _(ip4_over_ethernet[0].ip4);
1382  _(ip4_over_ethernet[1].ethernet);
1383  _(ip4_over_ethernet[1].ip4);
1384 #undef _
1385 }
1386 
1387 uword
1388 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1389 {
1390  pg_stream_t *s = va_arg (*args, pg_stream_t *);
1392  u32 group_index;
1393 
1394  p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1395  &group_index);
1397 
1398  /* Defaults. */
1399  pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1400  pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1403 
1404  if (!unformat (input, "%U: %U/%U -> %U/%U",
1415  {
1416  /* Free up any edits we may have added. */
1417  pg_free_edit_group (s);
1418  return 0;
1419  }
1420  return 1;
1421 }
1422 
1423 clib_error_t *
1425 {
1427 
1428  am->limit_arp_cache_size = arp_limit;
1429  return 0;
1430 }
1431 
1432 /**
1433  * @brief Control Plane hook to remove an ARP entry
1434  */
1435 int
1437  u32 sw_if_index, void *a_arg)
1438 {
1439  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1441 
1442  args.sw_if_index = sw_if_index;
1444  clib_memcpy (&args.a, a, sizeof (*a));
1445 
1447  (u8 *) & args, sizeof (args));
1448  return 0;
1449 }
1450 
1451 /**
1452  * @brief Internally generated event to flush the ARP cache on an
1453  * interface state change event.
1454  * A flush will remove dynamic ARP entries, and for statics remove the MAC
1455  * address from the corresponding adjacencies.
1456  */
1457 static int
1459  u32 sw_if_index, void *a_arg)
1460 {
1461  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1463 
1464  args.sw_if_index = sw_if_index;
1466  clib_memcpy (&args.a, a, sizeof (*a));
1467 
1469  (u8 *) & args, sizeof (args));
1470  return 0;
1471 }
1472 
1473 /**
1474  * @brief Internally generated event to populate the ARP cache on an
1475  * interface state change event.
1476  * For static entries this will re-source the adjacencies.
1477  *
1478  * @param sw_if_index The interface on which the ARP entires are acted
1479  */
1480 static int
1482  u32 sw_if_index, void *a_arg)
1483 {
1484  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1486 
1487  args.sw_if_index = sw_if_index;
1489  clib_memcpy (&args.a, a, sizeof (*a));
1490 
1492  (u8 *) & args, sizeof (args));
1493  return 0;
1494 }
1495 
1496 /*
1497  * arp_add_del_interface_address
1498  *
1499  * callback when an interface address is added or deleted
1500  */
1501 static void
1503  uword opaque,
1504  u32 sw_if_index,
1505  ip4_address_t * address,
1506  u32 address_length,
1507  u32 if_address_index, u32 is_del)
1508 {
1509  /*
1510  * Flush the ARP cache of all entries covered by the address
1511  * that is being removed.
1512  */
1515 
1516  if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
1517  return;
1518 
1519  if (is_del)
1520  {
1522  u32 i, *to_delete = 0;
1523  hash_pair_t *pair;
1524 
1525  eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
1526 
1527  /* *INDENT-OFF* */
1528  hash_foreach_pair (pair, eai->arp_entries,
1529  ({
1530  e = pool_elt_at_index(am->ip4_entry_pool,
1531  pair->value[0]);
1532  if (ip4_destination_matches_route (im, &e->ip4_address,
1533  address, address_length))
1534  {
1535  vec_add1 (to_delete, e - am->ip4_entry_pool);
1536  }
1537  }));
1538  /* *INDENT-ON* */
1539 
1540  for (i = 0; i < vec_len (to_delete); i++)
1541  {
1542  ethernet_arp_ip4_over_ethernet_address_t delme;
1543  e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1544 
1545  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1546  delme.ip4.as_u32 = e->ip4_address.as_u32;
1547 
1549  e->sw_if_index, &delme);
1550  }
1551 
1552  vec_free (to_delete);
1553  }
1554 }
1555 
1556 static clib_error_t *
1558 {
1560  ip4_main_t *im = &ip4_main;
1561  clib_error_t *error;
1562  pg_node_t *pn;
1563 
1564  if ((error = vlib_call_init_function (vm, ethernet_init)))
1565  return error;
1566 
1567  ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
1568 
1569  pn = pg_get_node (arp_input_node.index);
1571 
1572  am->opcode_by_name = hash_create_string (0, sizeof (uword));
1573 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
1575 #undef _
1576 
1577  /* $$$ configurable */
1578  am->limit_arp_cache_size = 50000;
1579 
1580  am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
1581  am->mac_changes_by_address = hash_create (0, sizeof (uword));
1582 
1583  /* don't trace ARP error packets */
1584  {
1585  vlib_node_runtime_t *rt =
1587 
1588 #define _(a,b) \
1589  vnet_pcap_drop_trace_filter_add_del \
1590  (rt->errors[ETHERNET_ARP_ERROR_##a], \
1591  1 /* is_add */);
1593 #undef _
1594  }
1595 
1598  cb.function_opaque = 0;
1600 
1601  return 0;
1602 }
1603 
1605 
1606 static void
1608 {
1610 
1612  {
1613  fib_prefix_t pfx = {
1614  .fp_len = 32,
1615  .fp_proto = FIB_PROTOCOL_IP4,
1616  .fp_addr.ip4 = e->ip4_address,
1617  };
1618  u32 fib_index;
1619 
1621 
1622  fib_table_entry_path_remove (fib_index, &pfx,
1625  &pfx.fp_addr,
1626  e->sw_if_index, ~0, 1,
1628  }
1630  pool_put (am->ip4_entry_pool, e);
1631 }
1632 
1633 static inline int
1636  * args)
1637 {
1641 
1642  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1643 
1644  e = arp_entry_find (eai, &args->a.ip4);
1645 
1646  if (NULL != e)
1647  {
1648  arp_entry_free (eai, e);
1649 
1652  }
1653 
1654  return 0;
1655 }
1656 
1657 static int
1660  * args)
1661 {
1665 
1666  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1667 
1668  e = arp_entry_find (eai, &args->a.ip4);
1669 
1670  if (NULL != e)
1671  {
1674 
1675  /*
1676  * The difference between flush and unset, is that an unset
1677  * means delete for static and dynamic entries. A flush
1678  * means delete only for dynamic. Flushing is what the DP
1679  * does in response to interface events. unset is only done
1680  * by the control plane.
1681  */
1683  {
1684  arp_entry_free (eai, e);
1685  }
1686  }
1687  return (0);
1688 }
1689 
1690 static int
1693  * args)
1694 {
1698 
1699  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1700 
1701  e = arp_entry_find (eai, &args->a.ip4);
1702 
1703  if (NULL != e)
1704  {
1707  }
1708  return (0);
1709 }
1710 
1711 static void
1713  * a)
1714 {
1715  vnet_main_t *vm = vnet_get_main ();
1716  ASSERT (vlib_get_thread_index () == 0);
1717 
1720  else if (a->flags & ETHERNET_ARP_ARGS_FLUSH)
1722  else if (a->flags & ETHERNET_ARP_ARGS_POPULATE)
1724  else
1726 }
1727 
1728 /**
1729  * @brief Invoked when the interface's admin state changes
1730  */
1731 static clib_error_t *
1733  u32 sw_if_index, u32 flags)
1734 {
1737  u32 i, *to_delete = 0;
1738 
1739  /* *INDENT-OFF* */
1740  pool_foreach (e, am->ip4_entry_pool,
1741  ({
1742  if (e->sw_if_index == sw_if_index)
1743  vec_add1 (to_delete,
1744  e - am->ip4_entry_pool);
1745  }));
1746  /* *INDENT-ON* */
1747 
1748  for (i = 0; i < vec_len (to_delete); i++)
1749  {
1750  ethernet_arp_ip4_over_ethernet_address_t delme;
1751  e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1752 
1753  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1754  delme.ip4.as_u32 = e->ip4_address.as_u32;
1755 
1756  if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1757  {
1759  }
1760  else
1761  {
1763  }
1764 
1765  }
1766  vec_free (to_delete);
1767 
1768  return 0;
1769 }
1770 
1772 
1773 static void
1774 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t * a)
1775 {
1776  u8 old;
1777  int i;
1778 
1779  for (i = 3; i >= 0; i--)
1780  {
1781  old = a->ip4.as_u8[i];
1782  a->ip4.as_u8[i] += 1;
1783  if (old < a->ip4.as_u8[i])
1784  break;
1785  }
1786 
1787  for (i = 5; i >= 0; i--)
1788  {
1789  old = a->ethernet[i];
1790  a->ethernet[i] += 1;
1791  if (old < a->ethernet[i])
1792  break;
1793  }
1794 }
1795 
1796 int
1798  u32 sw_if_index, void *a_arg,
1799  int is_static, int is_no_fib_entry)
1800 {
1801  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1803 
1804  args.sw_if_index = sw_if_index;
1805  args.is_static = is_static;
1806  args.is_no_fib_entry = is_no_fib_entry;
1807  args.flags = 0;
1808  clib_memcpy (&args.a, a, sizeof (*a));
1809 
1811  (u8 *) & args, sizeof (args));
1812  return 0;
1813 }
1814 
1815 int
1817  ip4_address_t * hi_addr, u32 fib_index, int is_del)
1818 {
1821  u32 found_at_index = ~0;
1822 
1823  vec_foreach (pa, am->proxy_arps)
1824  {
1825  if (pa->lo_addr == lo_addr->as_u32
1826  && pa->hi_addr == hi_addr->as_u32 && pa->fib_index == fib_index)
1827  {
1828  found_at_index = pa - am->proxy_arps;
1829  break;
1830  }
1831  }
1832 
1833  if (found_at_index != ~0)
1834  {
1835  /* Delete, otherwise it's already in the table */
1836  if (is_del)
1837  vec_delete (am->proxy_arps, 1, found_at_index);
1838  return 0;
1839  }
1840  /* delete, no such entry */
1841  if (is_del)
1842  return VNET_API_ERROR_NO_SUCH_ENTRY;
1843 
1844  /* add, not in table */
1845  vec_add2 (am->proxy_arps, pa, 1);
1846  pa->lo_addr = lo_addr->as_u32;
1847  pa->hi_addr = hi_addr->as_u32;
1848  pa->fib_index = fib_index;
1849  return 0;
1850 }
1851 
1852 /*
1853  * Remove any proxy arp entries asdociated with the
1854  * specificed fib.
1855  */
1856 int
1858 {
1861  u32 *entries_to_delete = 0;
1862  u32 fib_index;
1863  int i;
1864 
1865  fib_index = fib_table_find (FIB_PROTOCOL_IP4, fib_id);
1866  if (~0 == fib_index)
1867  return VNET_API_ERROR_NO_SUCH_ENTRY;
1868 
1869  vec_foreach (pa, am->proxy_arps)
1870  {
1871  if (pa->fib_index == fib_index)
1872  {
1873  vec_add1 (entries_to_delete, pa - am->proxy_arps);
1874  }
1875  }
1876 
1877  for (i = 0; i < vec_len (entries_to_delete); i++)
1878  {
1879  vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
1880  }
1881 
1882  vec_free (entries_to_delete);
1883 
1884  return 0;
1885 }
1886 
1887 static clib_error_t *
1889  unformat_input_t * input, vlib_cli_command_t * cmd)
1890 {
1891  vnet_main_t *vnm = vnet_get_main ();
1892  u32 sw_if_index;
1893  ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
1894  int addr_valid = 0;
1895  int is_del = 0;
1896  int count = 1;
1897  u32 fib_index = 0;
1898  u32 fib_id;
1899  int is_static = 0;
1900  int is_no_fib_entry = 0;
1901  int is_proxy = 0;
1902 
1903  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1904  {
1905  /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
1906  if (unformat (input, "%U %U %U",
1907  unformat_vnet_sw_interface, vnm, &sw_if_index,
1908  unformat_ip4_address, &addr.ip4,
1909  unformat_ethernet_address, &addr.ethernet))
1910  addr_valid = 1;
1911 
1912  else if (unformat (input, "delete") || unformat (input, "del"))
1913  is_del = 1;
1914 
1915  else if (unformat (input, "static"))
1916  is_static = 1;
1917 
1918  else if (unformat (input, "no-fib-entry"))
1919  is_no_fib_entry = 1;
1920 
1921  else if (unformat (input, "count %d", &count))
1922  ;
1923 
1924  else if (unformat (input, "fib-id %d", &fib_id))
1925  {
1926  fib_index = fib_table_find (FIB_PROTOCOL_IP4, fib_id);
1927 
1928  if (~0 == fib_index)
1929  return clib_error_return (0, "fib ID %d doesn't exist\n", fib_id);
1930  }
1931 
1932  else if (unformat (input, "proxy %U - %U",
1933  unformat_ip4_address, &lo_addr.ip4,
1934  unformat_ip4_address, &hi_addr.ip4))
1935  is_proxy = 1;
1936  else
1937  break;
1938  }
1939 
1940  if (is_proxy)
1941  {
1942  (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4,
1943  fib_index, is_del);
1944  return 0;
1945  }
1946 
1947  if (addr_valid)
1948  {
1949  int i;
1950 
1951  for (i = 0; i < count; i++)
1952  {
1953  if (is_del == 0)
1954  {
1955  uword event_type, *event_data = 0;
1956 
1957  /* Park the debug CLI until the arp entry is installed */
1959  (vnm, &addr.ip4, vlib_current_process (vm),
1960  1 /* type */ , 0 /* data */ );
1961 
1963  (vnm, sw_if_index, &addr, is_static, is_no_fib_entry);
1964 
1966  event_type = vlib_process_get_events (vm, &event_data);
1967  vec_reset_length (event_data);
1968  if (event_type != 1)
1969  clib_warning ("event type %d unexpected", event_type);
1970  }
1971  else
1972  vnet_arp_unset_ip4_over_ethernet (vnm, sw_if_index, &addr);
1973 
1975  }
1976  }
1977  else
1978  {
1979  return clib_error_return (0, "unknown input `%U'",
1980  format_unformat_error, input);
1981  }
1982 
1983  return 0;
1984 }
1985 
1986 /* *INDENT-OFF* */
1987 /*?
1988  * Add or delete IPv4 ARP cache entries.
1989  *
1990  * @note 'set ip arp' options (e.g. delete, static, 'fib-id <id>',
1991  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
1992  * any order and combination.
1993  *
1994  * @cliexpar
1995  * @parblock
1996  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
1997  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
1998  * @cliexcmd{set ip arp GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1999  * @cliexcmd{set ip arp delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
2000  *
2001  * To add or delete an IPv4 ARP cache entry to or from a specific fib
2002  * table:
2003  * @cliexcmd{set ip arp fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2004  * @cliexcmd{set ip arp fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2005  *
2006  * Add or delete IPv4 static ARP cache entries as follows:
2007  * @cliexcmd{set ip arp static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2008  * @cliexcmd{set ip arp static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2009  *
2010  * For testing / debugging purposes, the 'set ip arp' command can add or
2011  * delete multiple entries. Supply the 'count N' parameter:
2012  * @cliexcmd{set ip arp count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2013  * @endparblock
2014  ?*/
2015 VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = {
2016  .path = "set ip arp",
2017  .short_help =
2018  "set ip arp [del] <intfc> <ip-address> <mac-address> [static] [no-fib-entry] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
2019  .function = ip_arp_add_del_command_fn,
2020 };
2021 /* *INDENT-ON* */
2022 
2023 static clib_error_t *
2026  input, vlib_cli_command_t * cmd)
2027 {
2028  vnet_main_t *vnm = vnet_get_main ();
2029  u32 sw_if_index;
2030  vnet_sw_interface_t *si;
2031  int enable = 0;
2032  int intfc_set = 0;
2033 
2034  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2035  {
2036  if (unformat (input, "%U", unformat_vnet_sw_interface,
2037  vnm, &sw_if_index))
2038  intfc_set = 1;
2039  else if (unformat (input, "enable") || unformat (input, "on"))
2040  enable = 1;
2041  else if (unformat (input, "disable") || unformat (input, "off"))
2042  enable = 0;
2043  else
2044  break;
2045  }
2046 
2047  if (intfc_set == 0)
2048  return clib_error_return (0, "unknown input '%U'",
2049  format_unformat_error, input);
2050 
2051  si = vnet_get_sw_interface (vnm, sw_if_index);
2052  ASSERT (si);
2053  if (enable)
2055  else
2057 
2058  return 0;
2059 }
2060 
2061 /* *INDENT-OFF* */
2062 /*?
2063  * Enable proxy-arp on an interface. The vpp stack will answer ARP
2064  * requests for the indicated address range. Multiple proxy-arp
2065  * ranges may be provisioned.
2066  *
2067  * @note Proxy ARP as a technology is infamous for blackholing traffic.
2068  * Also, the underlying implementation has not been performance-tuned.
2069  * Avoid creating an unnecessarily large set of ranges.
2070  *
2071  * @cliexpar
2072  * To enable proxy arp on a range of addresses, use:
2073  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11}
2074  * Append 'del' to delete a range of proxy ARP addresses:
2075  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11 del}
2076  * You must then specifically enable proxy arp on individual interfaces:
2077  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 enable}
2078  * To disable proxy arp on an individual interface:
2079  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 disable}
2080  ?*/
2081 VLIB_CLI_COMMAND (set_int_proxy_enable_command, static) = {
2082  .path = "set interface proxy-arp",
2083  .short_help =
2084  "set interface proxy-arp <intfc> [enable|disable]",
2085  .function = set_int_proxy_arp_command_fn,
2086 };
2087 /* *INDENT-ON* */
2088 
2089 
2090 /*
2091  * ARP/ND Termination in a L2 Bridge Domain based on IP4/IP6 to MAC
2092  * hash tables mac_by_ip4 and mac_by_ip6 for each BD.
2093  */
2094 typedef enum
2095 {
2099 } arp_term_next_t;
2100 
2102 
2103 static uword
2105  vlib_node_runtime_t * node, vlib_frame_t * frame)
2106 {
2107  l2input_main_t *l2im = &l2input_main;
2108  u32 n_left_from, next_index, *from, *to_next;
2109  u32 n_replies_sent = 0;
2110  u16 last_bd_index = ~0;
2111  l2_bridge_domain_t *last_bd_config = 0;
2112  l2_input_config_t *cfg0;
2113 
2114  from = vlib_frame_vector_args (frame);
2115  n_left_from = frame->n_vectors;
2116  next_index = node->cached_next_index;
2117 
2118  while (n_left_from > 0)
2119  {
2120  u32 n_left_to_next;
2121 
2122  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2123 
2124  while (n_left_from > 0 && n_left_to_next > 0)
2125  {
2126  vlib_buffer_t *p0;
2127  ethernet_header_t *eth0;
2128  ethernet_arp_header_t *arp0;
2129  ip6_header_t *iph0;
2130  u8 *l3h0;
2131  u32 pi0, error0, next0, sw_if_index0;
2132  u16 ethertype0;
2133  u16 bd_index0;
2134  u32 ip0;
2135  u8 *macp0;
2136  u8 is_vrrp_reply0;
2137 
2138  pi0 = from[0];
2139  to_next[0] = pi0;
2140  from += 1;
2141  to_next += 1;
2142  n_left_from -= 1;
2143  n_left_to_next -= 1;
2144 
2145  p0 = vlib_get_buffer (vm, pi0);
2146  // Terminate only local (SHG == 0) ARP
2147  if (vnet_buffer (p0)->l2.shg != 0)
2148  goto next_l2_feature;
2149 
2150  eth0 = vlib_buffer_get_current (p0);
2151  l3h0 = (u8 *) eth0 + vnet_buffer (p0)->l2.l2_len;
2152  ethertype0 = clib_net_to_host_u16 (*(u16 *) (l3h0 - 2));
2153  arp0 = (ethernet_arp_header_t *) l3h0;
2154 
2155  if (PREDICT_FALSE ((ethertype0 != ETHERNET_TYPE_ARP) ||
2156  (arp0->opcode !=
2157  clib_host_to_net_u16
2158  (ETHERNET_ARP_OPCODE_request))))
2159  goto check_ip6_nd;
2160 
2161  /* Must be ARP request packet here */
2162  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
2163  (p0->flags & VLIB_BUFFER_IS_TRACED)))
2164  {
2165  u8 *t0 = vlib_add_trace (vm, node, p0,
2166  sizeof (ethernet_arp_input_trace_t));
2167  clib_memcpy (t0, l3h0, sizeof (ethernet_arp_input_trace_t));
2168  }
2169 
2170  error0 = ETHERNET_ARP_ERROR_replies_sent;
2171  error0 =
2172  (arp0->l2_type !=
2173  clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
2174  ? ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
2175  error0 =
2176  (arp0->l3_type !=
2177  clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
2178  ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
2179 
2180  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2181 
2182  if (error0)
2183  goto drop;
2184 
2185  is_vrrp_reply0 =
2186  ((arp0->opcode ==
2187  clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply))
2188  &&
2189  (!memcmp
2190  (arp0->ip4_over_ethernet[0].ethernet, vrrp_prefix,
2191  sizeof (vrrp_prefix))));
2192 
2193  /* Trash ARP packets whose ARP-level source addresses do not
2194  match their L2-frame-level source addresses, unless it's
2195  a reply from a VRRP virtual router */
2196  if (PREDICT_FALSE
2197  (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
2198  sizeof (eth0->src_address)) && !is_vrrp_reply0))
2199  {
2200  error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
2201  goto drop;
2202  }
2203 
2204  /* Check if anyone want ARP request events for L2 BDs */
2205  {
2208  uword *p = hash_get (am->mac_changes_by_address, 0);
2209  if (p)
2210  {
2211  u32 next_index = p[0];
2212  while (next_index != (u32) ~ 0)
2213  {
2214  int (*fp) (u32, u8 *, u32, u32);
2215  int rv = 1;
2216  mc = pool_elt_at_index (am->mac_changes, next_index);
2217  fp = mc->data_callback;
2218  /* Call the callback, return 1 to suppress dup events */
2219  if (fp)
2220  rv = (*fp) (mc->data,
2221  arp0->ip4_over_ethernet[0].ethernet,
2222  sw_if_index0,
2223  arp0->ip4_over_ethernet[0].ip4.as_u32);
2224  /* Signal the resolver process */
2225  if (rv == 0)
2227  mc->type_opaque, mc->data);
2228  next_index = mc->next_index;
2229  }
2230  }
2231  }
2232 
2233  /* lookup BD mac_by_ip4 hash table for MAC entry */
2234  ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
2235  bd_index0 = vnet_buffer (p0)->l2.bd_index;
2236  if (PREDICT_FALSE ((bd_index0 != last_bd_index)
2237  || (last_bd_index == (u16) ~ 0)))
2238  {
2239  last_bd_index = bd_index0;
2240  last_bd_config = vec_elt_at_index (l2im->bd_configs, bd_index0);
2241  }
2242  macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
2243 
2244  if (PREDICT_FALSE (!macp0))
2245  goto next_l2_feature; /* MAC not found */
2246 
2247  /* MAC found, send ARP reply -
2248  Convert ARP request packet to ARP reply */
2249  arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
2250  arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
2251  arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
2252  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
2253  clib_memcpy (eth0->dst_address, eth0->src_address, 6);
2254  clib_memcpy (eth0->src_address, macp0, 6);
2255  n_replies_sent += 1;
2256 
2257  output_response:
2258  /* For BVI, need to use l2-fwd node to send ARP reply as
2259  l2-output node cannot output packet to BVI properly */
2260  cfg0 = vec_elt_at_index (l2im->configs, sw_if_index0);
2261  if (PREDICT_FALSE (cfg0->bvi))
2262  {
2263  vnet_buffer (p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
2264  vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
2265  goto next_l2_feature;
2266  }
2267 
2268  /* Send ARP/ND reply back out input interface through l2-output */
2269  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2270  next0 = ARP_TERM_NEXT_L2_OUTPUT;
2271  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2272  to_next, n_left_to_next, pi0,
2273  next0);
2274  continue;
2275 
2276  check_ip6_nd:
2277  /* IP6 ND event notification or solicitation handling to generate
2278  local response instead of flooding */
2279  iph0 = (ip6_header_t *) l3h0;
2280  if (PREDICT_FALSE (ethertype0 == ETHERNET_TYPE_IP6 &&
2281  iph0->protocol == IP_PROTOCOL_ICMP6 &&
2283  (&iph0->src_address)))
2284  {
2285  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2286  if (vnet_ip6_nd_term
2287  (vm, node, p0, eth0, iph0, sw_if_index0,
2288  vnet_buffer (p0)->l2.bd_index))
2289  goto output_response;
2290  }
2291 
2292  next_l2_feature:
2293  {
2294  u32 feature_bitmap0 =
2295  vnet_buffer (p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM;
2296  vnet_buffer (p0)->l2.feature_bitmap = feature_bitmap0;
2297  next0 =
2299  feature_bitmap0);
2300  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2301  to_next, n_left_to_next,
2302  pi0, next0);
2303  continue;
2304  }
2305 
2306  drop:
2307  if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
2308  (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
2309  arp0->ip4_over_ethernet[1].ip4.as_u32))
2310  {
2311  error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
2312  }
2313  next0 = ARP_TERM_NEXT_DROP;
2314  p0->error = node->errors[error0];
2315 
2316  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2317  to_next, n_left_to_next, pi0,
2318  next0);
2319  }
2320 
2321  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2322  }
2323 
2324  vlib_error_count (vm, node->node_index,
2325  ETHERNET_ARP_ERROR_replies_sent, n_replies_sent);
2326  return frame->n_vectors;
2327 }
2328 
2329 /* *INDENT-OFF* */
2331  .function = arp_term_l2bd,
2332  .name = "arp-term-l2bd",
2333  .vector_size = sizeof (u32),
2334  .n_errors = ETHERNET_ARP_N_ERROR,
2335  .error_strings = ethernet_arp_error_strings,
2336  .n_next_nodes = ARP_TERM_N_NEXT,
2337  .next_nodes = {
2338  [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
2339  [ARP_TERM_NEXT_DROP] = "error-drop",
2340  },
2341  .format_buffer = format_ethernet_arp_header,
2342  .format_trace = format_arp_term_input_trace,
2343 };
2344 /* *INDENT-ON* */
2345 
2346 clib_error_t *
2348 {
2349  // Initialize the feature next-node indexes
2351  arp_term_l2bd_node.index,
2355  return 0;
2356 }
2357 
2359 
2360 void
2362 {
2363  if (e->sw_if_index == sw_if_index)
2364  {
2367  }
2368 }
2369 
2370 void
2372 {
2375 
2376  /* *INDENT-OFF* */
2377  pool_foreach (e, am->ip4_entry_pool,
2378  ({
2379  change_arp_mac (sw_if_index, e);
2380  }));
2381  /* *INDENT-ON* */
2382 }
2383 
2384 void static
2386 {
2387  ip4_main_t *i4m = &ip4_main;
2388  u32 sw_if_index = hi->sw_if_index;
2389  ip4_address_t *ip4_addr = ip4_interface_first_address (i4m, sw_if_index, 0);
2390 
2391  if (ip4_addr)
2392  {
2393  clib_warning ("Sending GARP for IP4 address %U on sw_if_idex %d",
2394  format_ip4_address, ip4_addr, sw_if_index);
2395 
2396  /* Form GARP packet for output - Gratuitous ARP is an ARP request packet
2397  where the interface IP/MAC pair is used for both source and request
2398  MAC/IP pairs in the request */
2399  u32 bi = 0;
2401  (vm, &i4m->ip4_arp_request_packet_template, &bi);
2402  clib_memcpy (h->ip4_over_ethernet[0].ethernet, hi->hw_address,
2403  sizeof (h->ip4_over_ethernet[0].ethernet));
2404  clib_memcpy (h->ip4_over_ethernet[1].ethernet, hi->hw_address,
2405  sizeof (h->ip4_over_ethernet[1].ethernet));
2406  h->ip4_over_ethernet[0].ip4 = ip4_addr[0];
2407  h->ip4_over_ethernet[1].ip4 = ip4_addr[0];
2408 
2409  /* Setup MAC header with ARP Etype and broadcast DMAC */
2410  vlib_buffer_t *b = vlib_get_buffer (vm, bi);
2411  vlib_buffer_advance (b, -sizeof (ethernet_header_t));
2413  e->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
2414  clib_memcpy (e->src_address, hi->hw_address, sizeof (e->src_address));
2415  memset (e->dst_address, 0xff, sizeof (e->dst_address));
2416 
2417  /* Send GARP packet out the specified interface */
2418  vnet_buffer (b)->sw_if_index[VLIB_RX] =
2419  vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
2421  u32 *to_next = vlib_frame_vector_args (f);
2422  to_next[0] = bi;
2423  f->n_vectors = 1;
2425  }
2426 }
2427 
2429 
2430 static uword
2433 {
2434  vnet_main_t *vnm = vnet_get_main ();
2435  uword event_type, *event_data = 0;
2436 
2438 
2439  while (1)
2440  {
2442  event_type = vlib_process_get_events (vm, &event_data);
2443  if ((event_type == SEND_GARP_NA) && (vec_len (event_data) >= 1))
2444  {
2445  u32 hw_if_index = event_data[0];
2446  vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
2447  send_ip4_garp (vm, hi);
2448  send_ip6_na (vm, hi);
2449  }
2450  vec_reset_length (event_data);
2451  }
2452  return 0;
2453 }
2454 
2455 
2456 /* *INDENT-OFF* */
2458  .function = send_garp_na_process,
2459  .type = VLIB_NODE_TYPE_PROCESS,
2460  .name = "send-garp-na-process",
2461 };
2462 /* *INDENT-ON* */
2463 
2464 /*
2465  * fd.io coding-style-patch-verification: ON
2466  *
2467  * Local Variables:
2468  * eval: (c-set-style "gnu")
2469  * End:
2470  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:436
#define vnet_rewrite_one_header(rw0, p0, most_likely_size)
Definition: rewrite.h:281
Definition: edit.h:64
static void set_ip4_over_ethernet_rpc_callback(vnet_arp_set_ip4_over_ethernet_rpc_args_t *a)
Definition: arp.c:1712
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:567
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
vmrglw vmrglh hi
#define pool_next_index(P, I)
Return next occupied pool index after i, useful for safe iteration.
Definition: pool.h:405
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:313
static uword arp_term_l2bd(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: arp.c:2104
#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:337
An entry in a FIB table.
Definition: fib_entry.h:380
#define CLIB_UNUSED(x)
Definition: clib.h:79
u8 * format_ethernet_arp_ip4_entry(u8 *s, va_list *va)
Definition: arp.c:245
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:117
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
An indication that the rewrite is incomplete, i.e.
Definition: adj_nbr.h:90
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
Definition: node_funcs.h:619
uword unformat_pg_arp_header(unformat_input_t *input, va_list *args)
Definition: arp.c:1388
static void pg_ethernet_arp_header_init(pg_ethernet_arp_header_t *p)
Definition: arp.c:1371
static int vnet_arp_unset_ip4_over_ethernet_internal(vnet_main_t *vnm, vnet_arp_set_ip4_over_ethernet_rpc_args_t *args)
Definition: arp.c:1634
static void increment_ip4_and_mac_address(ethernet_arp_ip4_over_ethernet_address_t *a)
Definition: arp.c:1774
An indication that the rewrite is complete, i.e.
Definition: adj_nbr.h:98
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
struct ip_adjacency_t_::@37::@38 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
static uword vlib_current_process(vlib_main_t *vm)
Definition: node_funcs.h:426
static void arp_add_del_interface_address(ip4_main_t *im, uword opaque, u32 sw_if_index, ip4_address_t *address, u32 address_length, u32 if_address_index, u32 is_del)
Definition: arp.c:1502
static void pg_edit_set_fixed(pg_edit_t *e, u64 value)
Definition: edit.h:153
static clib_error_t * show_ip4_arp(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: arp.c:1296
vnet_interface_main_t interface_main
Definition: vnet.h:56
pending_resolution_t * pending_resolutions
Definition: arp.c:78
void fib_entry_get_prefix(fib_node_index_t fib_entry_index, fib_prefix_t *pfx)
Definition: fib_entry.c:1532
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:57
Multicast Adjacency.
Definition: adj.h:82
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:355
#define NULL
Definition: clib.h:55
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
Definition: ip4_forward.c:684
IP unicast adjacency.
Definition: adj.h:174
Information related to the source of a FIB entry.
Definition: fib_entry.h:289
struct ethernet_arp_interface_t_ ethernet_arp_interface_t
Per-interface ARP configuration and state.
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:459
void change_arp_mac(u32 sw_if_index, ethernet_arp_ip4_entry_t *e)
Definition: arp.c:2361
static u8 * format_ethernet_arp_header(u8 *s, va_list *va)
Definition: arp.c:198
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:2024
clib_error_t * ip4_set_arp_limit(u32 arp_limit)
Definition: arp.c:1424
static uword arp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: arp.c:873
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
This packet is to be rewritten and forwarded to the next processing node.
Definition: adj.h:73
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
word vnet_sw_interface_compare(vnet_main_t *vnm, uword sw_if_index0, uword sw_if_index1)
Definition: interface.c:1130
static u64 clib_cpu_time_now(void)
Definition: time.h:73
void arp_update_adjacency(vnet_main_t *vnm, u32 sw_if_index, u32 ai)
Definition: arp.c:439
struct _vlib_node_registration vlib_node_registration_t
static uword unformat_ethernet_arp_opcode_host_byte_order(unformat_input_t *input, va_list *args)
Definition: arp.c:157
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:561
void fib_table_entry_path_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_protocol_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, fib_route_path_flags_t path_flags)
remove one path to an entry (aka route) in the FIB.
Definition: fib_table.c:664
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:983
uword unformat_pg_edit(unformat_input_t *input, va_list *args)
Definition: edit.c:106
void adj_nbr_walk_nh4(u32 sw_if_index, const ip4_address_t *addr, adj_walk_cb_t cb, void *ctx)
Walk adjacencies on a link with a given v4 next-hop.
Definition: adj_nbr.c:614
pg_edit_t l2_type
Definition: arp.c:1360
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:99
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
uword * opcode_by_name
Definition: arp.c:74
format_function_t format_vlib_cpu_time
Definition: node_funcs.h:1125
unformat_function_t unformat_vnet_sw_interface
u64 cpu_time_last_updated
Definition: arp_packet.h:159
union ip_adjacency_t_::@37 sub_type
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1328
vlib_error_t * errors
Vector of errors for this node.
Definition: node.h:419
Definition: fib_entry.h:235
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
pg_edit_t ethernet
Definition: arp.c:1365
ip6_address_t src_address
Definition: ip6_packet.h:341
void * data_callback
Definition: arp.c:67
#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:350
vnet_link_t ia_link
link/ether-type 1 bytes
Definition: adj.h:195
static int vnet_arp_populate_ip4_over_ethernet_internal(vnet_main_t *vnm, vnet_arp_set_ip4_over_ethernet_rpc_args_t *args)
Definition: arp.c:1691
u32 send_garp_na_process_node_index
Definition: arp.c:114
Adjacency to punt this packet.
Definition: adj.h:55
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(ethernet_arp_sw_interface_up_down)
arp_input_next_t
Definition: arp.c:771
static const u8 vrrp_prefix[]
Definition: arp.c:111
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:221
format_function_t format_ip4_address
Definition: format.h:79
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:365
pg_edit_t n_l3_address_bytes
Definition: arp.c:1361
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define VNET_SW_INTERFACE_FLAG_PROXY_ARP
Definition: interface.h:565
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
unformat_function_t unformat_ip4_address
Definition: format.h:76
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
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:542
pending_resolution_t * mac_changes
Definition: arp.c:82
static uword format_get_indent(u8 *s)
Definition: format.h:72
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:1262
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
Aggregrate type for a prefix.
Definition: fib_types.h:160
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
#define clib_error_return(e, args...)
Definition: error.h:99
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:284
static int vnet_arp_flush_ip4_over_ethernet(vnet_main_t *vnm, u32 sw_if_index, void *a_arg)
Internally generated event to flush the ARP cache on an interface state change event.
Definition: arp.c:1458
#define foreach_ethernet_arp_opcode
Definition: arp_packet.h:61
uword * pending_resolutions_by_address
Definition: arp.c:77
static void * pg_create_edit_group(pg_stream_t *s, int n_edit_bytes, int n_packet_bytes, u32 *group_index)
Definition: pg.h:225
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1025
u16 fp_len
The mask length.
Definition: fib_types.h:164
#define vlib_call_init_function(vm, x)
Definition: init.h:162
static ethernet_arp_ip4_entry_t * arp_entry_find(ethernet_arp_interface_t *eai, const ip4_address_t *addr)
Definition: arp.c:402
int vnet_arp_unset_ip4_over_ethernet(vnet_main_t *vnm, u32 sw_if_index, void *a_arg)
Control Plane hook to remove an ARP entry.
Definition: arp.c:1436
#define hash_create_string(elts, value_bytes)
Definition: hash.h:652
adj_index_t fib_entry_get_adj(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:460
pg_edit_t l3_type
Definition: arp.c:1360
static adj_walk_rc_t arp_mk_complete_walk(adj_index_t ai, void *ctx)
Definition: arp.c:421
Per-interface ARP configuration and state.
Definition: arp.c:44
fib_node_index_t fib_table_entry_path_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_protocol_t next_hop_proto, const ip46_address_t *next_hop, u32 next_hop_sw_if_index, u32 next_hop_fib_index, u32 next_hop_weight, mpls_label_t *next_hop_labels, fib_route_path_flags_t path_flags)
Add one path to an entry (aka route) in the FIB.
Definition: fib_table.c:504
static heap_elt_t * first(heap_header_t *h)
Definition: heap.c:59
#define FOR_EACH_SRC_ADDED(_entry, _src, _source, action)
Definition: fib_entry.h:238
#define hash_get(h, key)
Definition: hash.h:248
format_function_t format_vnet_sw_interface_name
#define ADJ_INDEX_INVALID
Invalid ADJ index - used when no adj is known likewise blazoned capitals INVALID speak volumes where ...
Definition: adj_types.h:36
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
static ethernet_header_t * ethernet_buffer_get_header(vlib_buffer_t *b)
Definition: ethernet.h:345
#define foreach_ethernet_arp_error
Definition: arp.c:778
vlib_main_t * vlib_main
Definition: vnet.h:78
static void arp_mk_complete(adj_index_t ai, ethernet_arp_ip4_entry_t *e)
Definition: arp.c:378
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:946
Adjacency source.
Definition: fib_entry.h:92
enum fib_source_t_ fib_source_t
The different sources that can create a route.
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:183
uword type_opaque
Definition: arp.c:64
#define ETHERNET_ARP_ARGS_FLUSH
Definition: arp.c:107
ip4_address_t ip4_address
Definition: arp_packet.h:153
struct _unformat_input_t unformat_input_t
u32 sw_if_index
Definition: arp_packet.h:152
static u32 arp_learn(vnet_main_t *vnm, ethernet_arp_main_t *am, u32 sw_if_index, void *addr)
Definition: arp.c:861
u8 ethernet_address[6]
Definition: arp_packet.h:155
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:188
u8 * ip_enabled_by_sw_if_index
Definition: ip4.h:105
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
static void unset_random_arp_entry(void)
Definition: arp.c:805
#define PREDICT_FALSE(x)
Definition: clib.h:97
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: adj.h:68
ethernet_arp_interface_t * ethernet_arp_by_sw_if_index
Per interface state.
Definition: arp.c:91
int vnet_arp_set_ip4_over_ethernet_internal(vnet_main_t *vnm, vnet_arp_set_ip4_over_ethernet_rpc_args_t *args)
Definition: arp.c:526
u32 node_index
Node index.
Definition: node.h:441
static clib_error_t * ethernet_arp_init(vlib_main_t *vm)
Definition: arp.c:1557
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
#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:216
#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:366
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:113
static void send_ip4_garp(vlib_main_t *vm, vnet_hw_interface_t *hi)
Definition: arp.c:2385
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1338
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:1888
void send_ip6_na(vlib_main_t *vm, vnet_hw_interface_t *hi)
u8 * format_ethernet_type(u8 *s, va_list *args)
Definition: format.c:58
fib_node_index_t ip4_fib_table_lookup(const ip4_fib_t *fib, const ip4_address_t *addr, u32 len)
Definition: ip4_fib.c:288
struct pg_ethernet_arp_header_t::@97 ip4_over_ethernet[2]
ethernet_proxy_arp_t * proxy_arps
Definition: arp.c:94
This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite st...
Definition: adj.h:63
int fib_entry_is_sourced(fib_node_index_t fib_entry_index, fib_source_t source)
Adjacency to drop this packet.
Definition: adj.h:53
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
u16 n_vectors
Definition: node.h:345
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:185
static void arp_mk_incomplete(adj_index_t ai)
Definition: arp.c:388
int ip4_address_compare(ip4_address_t *a1, ip4_address_t *a2)
Definition: ip46_cli.c:51
pg_edit_t n_l2_address_bytes
Definition: arp.c:1361
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:340
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:70
static ethernet_arp_main_t ethernet_arp_main
Definition: arp.c:97
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_fib.h:105
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
Multicast Midchain Adjacency.
Definition: adj.h:86
static char * ethernet_arp_error_strings[]
Definition: arp.c:1237
#define ETHERNET_ARP_ARGS_POPULATE
Definition: arp.c:108
#define clib_warning(format, args...)
Definition: error.h:59
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:85
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:69
unformat_function_t * unformat_edit
Definition: pg.h:307
uword * mac_changes_by_address
Definition: arp.c:81
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
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:675
static clib_error_t * ethernet_arp_sw_interface_up_down(vnet_main_t *vnm, u32 sw_if_index, u32 flags)
Invoked when the interface&#39;s admin state changes.
Definition: arp.c:1732
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:58
fib_entry_t * fib_entry_get(fib_node_index_t index)
Definition: fib_entry.c:44
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:1816
enum fib_entry_flag_t_ fib_entry_flag_t
static u8 * format_ethernet_arp_opcode(u8 *s, va_list *va)
Definition: arp.c:139
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
This packets follow a mid-chain adjacency.
Definition: adj.h:76
clib_error_t * arp_term_init(vlib_main_t *vm)
Definition: arp.c:2347
vlib_packet_template_t ip4_arp_request_packet_template
Template used to generate IP4 ARP packets.
Definition: ip4.h:120
#define hash_create(elts, value_bytes)
Definition: hash.h:658
#define ETHERNET_ARP_ARGS_REMOVE
Definition: arp.c:106
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
Definition: node.h:460
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:560
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:227
#define ASSERT(truth)
u32 arp_term_next_node_index[32]
Definition: arp.c:2101
unsigned int u32
Definition: types.h:88
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:785
The default route source.
Definition: fib_entry.h:121
IPv4 main type.
Definition: ip4.h:83
uword unformat_vlib_number_by_name(unformat_input_t *input, va_list *args)
Definition: format.c:157
static void pg_free_edit_group(pg_stream_t *s)
Definition: pg.h:278
u32 arp_delete_rotor
Definition: arp.c:87
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:201
void adj_mcast_update_rewrite(adj_index_t adj_index, u8 *rewrite, u8 offset, u32 mask)
adj_mcast_update_rewrite
Definition: adj_mcast.c:102
#define VLIB_NODE_FLAG_TRACE
Definition: node.h:260
static vlib_node_registration_t send_garp_na_proc_node
(constructor) VLIB_REGISTER_NODE (send_garp_na_proc_node)
Definition: arp.c:2428
static uword send_garp_na_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: arp.c:2431
format_function_t format_ip6_header
Definition: format.h:98
ethernet_arp_entry_flags_t flags
Definition: arp_packet.h:157
static void arp_nbr_probe(ip_adjacency_t *adj)
Definition: arp.c:315
Definition: pg.h:96
ethernet_arp_ip4_over_ethernet_address_t a
Definition: arp.c:102
void ethernet_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Definition: node.c:1301
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
static vlib_node_registration_t arp_term_l2bd_node
(constructor) VLIB_REGISTER_NODE (arp_term_l2bd_node)
Definition: arp.c:2330
uword * arp_entries
Hash table of ARP entries.
Definition: arp.c:50
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.
fib_entry_flag_t fib_entry_get_flags_for_source(fib_node_index_t fib_entry_index, fib_source_t source)
This packets needs to go to ICMP error.
Definition: adj.h:79
This packet is for one of our own IP addresses.
Definition: adj.h:58
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:88
static vlib_node_registration_t arp_input_node
(constructor) VLIB_REGISTER_NODE (arp_input_node)
Definition: arp.c:1244
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
int vnet_proxy_arp_fib_reset(u32 fib_id)
Definition: arp.c:1857
fib_node_index_t fib_entry_index
The index of the adj-fib entry created.
Definition: arp_packet.h:164
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
ip_lookup_next_t lookup_next_index
Next hop after ip4-lookup.
Definition: adj.h:189
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
Definition: fib_entry.h:234
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:960
static u8 * format_arp_term_input_trace(u8 *s, va_list *va)
Definition: arp.c:298
static int vnet_arp_flush_ip4_over_ethernet_internal(vnet_main_t *vnm, vnet_arp_set_ip4_over_ethernet_rpc_args_t *args)
Definition: arp.c:1658
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:644
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:269
static clib_error_t * ethernet_init(vlib_main_t *vm)
Definition: init.c:82
static u8 * format_ethernet_arp_hardware_type(u8 *s, va_list *va)
Definition: arp.c:121
u8 * ethernet_build_rewrite(vnet_main_t *vnm, u32 sw_if_index, vnet_link_t link_type, const void *dst_address)
build a rewrite string to use for sending packets of type &#39;link_type&#39; to &#39;dst_address&#39; ...
Definition: interface.c:79
l2_bridge_domain_t * bd_configs
Definition: l2_input.h:69
static void arp_entry_free(ethernet_arp_interface_t *eai, ethernet_arp_ip4_entry_t *e)
Definition: arp.c:1607
pg_edit_t opcode
Definition: arp.c:1362
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
ethernet_arp_input_error_t
Definition: arp.c:795
arp_term_next_t
Definition: arp.c:2094
struct clib_bihash_value offset
template key/value backing page structure
u32 limit_arp_cache_size
Definition: arp.c:88
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
#define vnet_buffer(b)
Definition: buffer.h:304
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:144
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1168
uword node_index
Definition: arp.c:63
#define vec_foreach(var, vec)
Vector iterator.
static uword ip6_address_is_unspecified(ip6_address_t *a)
Definition: ip6_packet.h:277
uword * mac_by_ip4
Definition: l2_bd.h:82
u16 flags
Copy of main node flags.
Definition: node.h:454
static int arp_unnumbered(vlib_buffer_t *p0, u32 input_sw_if_index, u32 conn_sw_if_index)
Definition: arp.c:836
ethernet_arp_ip4_entry_t * ip4_neighbor_entries(u32 sw_if_index)
Definition: arp.c:1277
vhost_vring_addr_t addr
Definition: vhost-user.h:82
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
int vnet_arp_set_ip4_over_ethernet(vnet_main_t *vnm, u32 sw_if_index, void *a_arg, int is_static, int is_no_fib_entry)
Definition: arp.c:1797
static int vnet_arp_populate_ip4_over_ethernet(vnet_main_t *vnm, u32 sw_if_index, void *a_arg)
Internally generated event to populate the ARP cache on an interface state change event...
Definition: arp.c:1481
u32 flags
Definition: vhost-user.h:76
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
Definition: buffer.h:74
static uword unformat_ethernet_arp_opcode_net_byte_order(unformat_input_t *input, va_list *args)
Definition: arp.c:185
void adj_nbr_update_rewrite(adj_index_t adj_index, adj_nbr_rewrite_flag_t flags, u8 *rewrite)
adj_nbr_update_rewrite
Definition: adj_nbr.c:291
void ethernet_arp_change_mac(u32 sw_if_index)
Definition: arp.c:2371
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:680
ethernet_arp_ip4_entry_t * ip4_entry_pool
Definition: arp.c:84
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:706
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
Definition: buffer_funcs.h:57
Definition: pg.h:304
const u8 * ethernet_ip4_mcast_dst_addr(void)
Definition: interface.c:55
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
int vnet_ip6_nd_term(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *p0, ethernet_header_t *eth, ip6_header_t *ip, u32 sw_if_index, u16 bd_index)
Definition: defs.h:46
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
Definition: arp_packet.h:150
fib_entry_flag_t fib_entry_get_flags(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:252
static adj_walk_rc_t arp_mk_incomplete_walk(adj_index_t ai, void *ctx)
Definition: arp.c:431
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:203
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109