FD.io VPP  v17.01-9-ge7dcee4
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/adj/adj_nbr.h>
26 #include <vnet/mpls/mpls.h>
27 
28 /**
29  * @file
30  * @brief IPv4 ARP.
31  *
32  * This file contains code to manage the IPv4 ARP tables (IP Address
33  * to MAC Address lookup).
34  */
35 
36 
37 void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
38 
39 /**
40  * @brief Per-interface ARP configuration and state
41  */
43 {
44  /**
45  * Hash table of ARP entries.
46  * Since this hash table is per-interface, the key is only the IPv4 address.
47  */
50 
51 typedef struct
52 {
57 
58 typedef struct
59 {
64  /* Used for arp event notification only */
68 
69 typedef struct
70 {
71  /* Hash tables mapping name to opcode. */
73 
74  /* lite beer "glean" adjacency handling */
77 
78  /* Mac address change notification */
81 
83 
84  /* ARP attack mitigation */
87 
88  /** Per interface state */
90 
91  /* Proxy arp vector */
94 
96 
97 typedef struct
98 {
100  ethernet_arp_ip4_over_ethernet_address_t a;
102  int flags;
103 #define ETHERNET_ARP_ARGS_REMOVE (1<<0)
104 #define ETHERNET_ARP_ARGS_FLUSH (1<<1)
105 #define ETHERNET_ARP_ARGS_POPULATE (1<<2)
107 
108 static void
110  * a);
111 
112 static u8 *
114 {
116  char *t = 0;
117  switch (h)
118  {
119 #define _(n,f) case n: t = #f; break;
121 #undef _
122 
123  default:
124  return format (s, "unknown 0x%x", h);
125  }
126 
127  return format (s, "%s", t);
128 }
129 
130 static u8 *
131 format_ethernet_arp_opcode (u8 * s, va_list * va)
132 {
134  char *t = 0;
135  switch (o)
136  {
137 #define _(f) case ETHERNET_ARP_OPCODE_##f: t = #f; break;
139 #undef _
140 
141  default:
142  return format (s, "unknown 0x%x", o);
143  }
144 
145  return format (s, "%s", t);
146 }
147 
148 static uword
150  va_list * args)
151 {
152  int *result = va_arg (*args, int *);
154  int x, i;
155 
156  /* Numeric opcode. */
157  if (unformat (input, "0x%x", &x) || unformat (input, "%d", &x))
158  {
159  if (x >= (1 << 16))
160  return 0;
161  *result = x;
162  return 1;
163  }
164 
165  /* Named type. */
167  am->opcode_by_name, &i))
168  {
169  *result = i;
170  return 1;
171  }
172 
173  return 0;
174 }
175 
176 static uword
178  va_list * args)
179 {
180  int *result = va_arg (*args, int *);
181  if (!unformat_user
183  return 0;
184 
185  *result = clib_host_to_net_u16 ((u16) * result);
186  return 1;
187 }
188 
189 static u8 *
190 format_ethernet_arp_header (u8 * s, va_list * va)
191 {
192  ethernet_arp_header_t *a = va_arg (*va, ethernet_arp_header_t *);
193  u32 max_header_bytes = va_arg (*va, u32);
194  uword indent;
195  u16 l2_type, l3_type;
196 
197  if (max_header_bytes != 0 && sizeof (a[0]) > max_header_bytes)
198  return format (s, "ARP header truncated");
199 
200  l2_type = clib_net_to_host_u16 (a->l2_type);
201  l3_type = clib_net_to_host_u16 (a->l3_type);
202 
203  indent = format_get_indent (s);
204 
205  s = format (s, "%U, type %U/%U, address size %d/%d",
206  format_ethernet_arp_opcode, clib_net_to_host_u16 (a->opcode),
208  format_ethernet_type, l3_type,
210 
211  if (l2_type == ETHERNET_ARP_HARDWARE_TYPE_ethernet
212  && l3_type == ETHERNET_TYPE_IP4)
213  {
214  s = format (s, "\n%U%U/%U -> %U/%U",
215  format_white_space, indent,
220  }
221  else
222  {
223  uword n2 = a->n_l2_address_bytes;
224  uword n3 = a->n_l3_address_bytes;
225  s = format (s, "\n%U%U/%U -> %U/%U",
226  format_white_space, indent,
227  format_hex_bytes, a->data + 0 * n2 + 0 * n3, n2,
228  format_hex_bytes, a->data + 1 * n2 + 0 * n3, n3,
229  format_hex_bytes, a->data + 1 * n2 + 1 * n3, n2,
230  format_hex_bytes, a->data + 2 * n2 + 1 * n3, n3);
231  }
232 
233  return s;
234 }
235 
236 u8 *
238 {
239  vnet_main_t *vnm = va_arg (*va, vnet_main_t *);
242  u8 *flags = 0;
243 
244  if (!e)
245  return format (s, "%=12s%=16s%=6s%=20s%=24s", "Time", "IP4",
246  "Flags", "Ethernet", "Interface");
247 
248  si = vnet_get_sw_interface (vnm, e->sw_if_index);
249 
251  flags = format (flags, "S");
252 
254  flags = format (flags, "D");
255 
256  s = format (s, "%=12U%=16U%=6s%=20U%=24U",
259  flags ? (char *) flags : "",
262 
263  vec_free (flags);
264  return s;
265 }
266 
267 typedef struct
268 {
269  u8 packet_data[64];
271 
272 static u8 *
274 {
275  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
276  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
278 
279  s = format (s, "%U",
281  t->packet_data, sizeof (t->packet_data));
282 
283  return s;
284 }
285 
286 static u8 *
287 format_arp_term_input_trace (u8 * s, va_list * va)
288 {
289  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
290  CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
292 
293  /* arp-term trace data saved is either arp or ip6/icmp6 packet:
294  - for arp, the 1st 16-bit field is hw type of value of 0x0001.
295  - for ip6, the first nibble has value of 6. */
296  s = format (s, "%U", t->packet_data[0] == 0 ?
298  t->packet_data, sizeof (t->packet_data));
299 
300  return s;
301 }
302 
303 static void
305 {
306  vnet_main_t *vnm = vnet_get_main ();
307  ip4_main_t *im = &ip4_main;
312  ip4_address_t *src;
313  vlib_buffer_t *b;
314  vlib_main_t *vm;
315  u32 bi = 0;
316 
317  vm = vlib_get_main ();
318 
319  si = vnet_get_sw_interface (vnm, adj->rewrite_header.sw_if_index);
320 
322  {
323  return;
324  }
325 
326  src =
328  &adj->sub_type.nbr.next_hop.
329  ip4,
330  adj->rewrite_header.
331  sw_if_index, &ia);
332  if (!src)
333  {
334  return;
335  }
336 
337  h =
339  &bi);
340 
341  hi = vnet_get_sup_hw_interface (vnm, adj->rewrite_header.sw_if_index);
342 
343  clib_memcpy (h->ip4_over_ethernet[0].ethernet,
344  hi->hw_address, sizeof (h->ip4_over_ethernet[0].ethernet));
345 
346  h->ip4_over_ethernet[0].ip4 = src[0];
347  h->ip4_over_ethernet[1].ip4 = adj->sub_type.nbr.next_hop.ip4;
348 
349  b = vlib_get_buffer (vm, bi);
350  vnet_buffer (b)->sw_if_index[VLIB_RX] =
351  vnet_buffer (b)->sw_if_index[VLIB_TX] = adj->rewrite_header.sw_if_index;
352 
353  /* Add encapsulation string for software interface (e.g. ethernet header). */
354  vnet_rewrite_one_header (adj[0], h, sizeof (ethernet_header_t));
355  vlib_buffer_advance (b, -adj->rewrite_header.data_bytes);
356 
357  {
359  u32 *to_next = vlib_frame_vector_args (f);
360  to_next[0] = bi;
361  f->n_vectors = 1;
363  }
364 }
365 
366 static void
368 {
372  e->sw_if_index,
374 }
375 
376 static void
378 {
379  ip_adjacency_t *adj = adj_get (ai);
380 
382  (ai,
385  adj->rewrite_header.sw_if_index,
388 }
389 
392 {
395  uword *p;
396 
397  if (NULL != eai->arp_entries)
398  {
399  p = hash_get (eai->arp_entries, addr->as_u32);
400  if (!p)
401  return (NULL);
402 
403  e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
404  }
405 
406  return (e);
407 }
408 
409 static adj_walk_rc_t
411 {
412  ethernet_arp_ip4_entry_t *e = ctx;
413 
414  arp_mk_complete (ai, e);
415 
416  return (ADJ_WALK_RC_CONTINUE);
417 }
418 
419 static adj_walk_rc_t
421 {
422  arp_mk_incomplete (ai);
423 
424  return (ADJ_WALK_RC_CONTINUE);
425 }
426 
427 void
428 arp_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
429 {
431  ethernet_arp_interface_t *arp_int;
433  ip_adjacency_t *adj;
434 
435  adj = adj_get (ai);
436 
437  vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index);
438  arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
439  e = arp_entry_find (arp_int, &adj->sub_type.nbr.next_hop.ip4);
440 
441  if (NULL != e)
442  {
443  adj_nbr_walk_nh4 (sw_if_index,
445  }
446  else
447  {
448  /*
449  * no matching ARP entry.
450  * construct the rewire required to for an ARP packet, and stick
451  * that in the adj's pipe to smoke.
452  */
456  sw_if_index,
459 
460  /*
461  * since the FIB has added this adj for a route, it makes sense it may
462  * want to forward traffic sometime soon. Let's send a speculative ARP.
463  * just one. If we were to do periodically that wouldn't be bad either,
464  * but that's more code than i'm prepared to write at this time for
465  * relatively little reward.
466  */
467  arp_nbr_probe (adj);
468  }
469 }
470 
471 int
474  * args)
475 {
478  ethernet_arp_ip4_over_ethernet_address_t *a = &args->a;
479  vlib_main_t *vm = vlib_get_main ();
480  int make_new_arp_cache_entry = 1;
481  uword *p;
482  pending_resolution_t *pr, *mc;
483  ethernet_arp_interface_t *arp_int;
484  int is_static = args->is_static;
485  u32 sw_if_index = args->sw_if_index;
486 
487  vec_validate (am->ethernet_arp_by_sw_if_index, sw_if_index);
488 
489  arp_int = &am->ethernet_arp_by_sw_if_index[sw_if_index];
490 
491  if (NULL != arp_int->arp_entries)
492  {
493  p = hash_get (arp_int->arp_entries, a->ip4.as_u32);
494  if (p)
495  {
496  e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
497 
498  /* Refuse to over-write static arp. */
499  if (!is_static && (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC))
500  return -2;
501  make_new_arp_cache_entry = 0;
502  }
503  }
504 
505  if (make_new_arp_cache_entry)
506  {
507  fib_prefix_t pfx = {
508  .fp_len = 32,
509  .fp_proto = FIB_PROTOCOL_IP4,
510  .fp_addr = {
511  .ip4 = a->ip4,
512  }
513  ,
514  };
515  u32 fib_index;
516 
517  pool_get (am->ip4_entry_pool, e);
518 
519  if (NULL == arp_int->arp_entries)
520  {
521  arp_int->arp_entries = hash_create (0, sizeof (u32));
522  }
523 
524  hash_set (arp_int->arp_entries, a->ip4.as_u32, e - am->ip4_entry_pool);
525 
526  e->sw_if_index = sw_if_index;
527  e->ip4_address = a->ip4;
529  a->ethernet, sizeof (e->ethernet_address));
530 
532  e->fib_entry_index =
534  &pfx,
538  &pfx.fp_addr,
539  e->sw_if_index,
540  ~0,
542  }
543  else
544  {
545  /*
546  * prevent a DoS attack from the data-plane that
547  * spams us with no-op updates to the MAC address
548  */
549  if (0 == memcmp (e->ethernet_address,
550  a->ethernet, sizeof (e->ethernet_address)))
551  return -1;
552 
553  /* Update time stamp and ethernet address. */
554  clib_memcpy (e->ethernet_address, a->ethernet,
555  sizeof (e->ethernet_address));
556  }
557 
559  if (is_static)
561  else
563 
564  adj_nbr_walk_nh4 (sw_if_index, &e->ip4_address, arp_mk_complete_walk, e);
565 
566  /* Customer(s) waiting for this address to be resolved? */
567  p = hash_get (am->pending_resolutions_by_address, a->ip4.as_u32);
568  if (p)
569  {
570  u32 next_index;
571  next_index = p[0];
572 
573  while (next_index != (u32) ~ 0)
574  {
575  pr = pool_elt_at_index (am->pending_resolutions, next_index);
577  pr->type_opaque, pr->data);
578  next_index = pr->next_index;
579  pool_put (am->pending_resolutions, pr);
580  }
581 
582  hash_unset (am->pending_resolutions_by_address, a->ip4.as_u32);
583  }
584 
585  /* Customer(s) requesting ARP event for this address? */
586  p = hash_get (am->mac_changes_by_address, a->ip4.as_u32);
587  if (p)
588  {
589  u32 next_index;
590  next_index = p[0];
591 
592  while (next_index != (u32) ~ 0)
593  {
594  int (*fp) (u32, u8 *, u32, u32);
595  int rv = 1;
596  mc = pool_elt_at_index (am->mac_changes, next_index);
597  fp = mc->data_callback;
598 
599  /* Call the user's data callback, return 1 to suppress dup events */
600  if (fp)
601  rv = (*fp) (mc->data, a->ethernet, sw_if_index, 0);
602 
603  /*
604  * Signal the resolver process, as long as the user
605  * says they want to be notified
606  */
607  if (rv == 0)
609  mc->type_opaque, mc->data);
610  next_index = mc->next_index;
611  }
612  }
613 
614  return 0;
615 }
616 
617 void
619  void *address_arg,
620  uword node_index,
621  uword type_opaque, uword data)
622 {
624  ip4_address_t *address = address_arg;
625  uword *p;
627 
628  pool_get (am->pending_resolutions, pr);
629 
630  pr->next_index = ~0;
631  pr->node_index = node_index;
632  pr->type_opaque = type_opaque;
633  pr->data = data;
634  pr->data_callback = 0;
635 
636  p = hash_get (am->pending_resolutions_by_address, address->as_u32);
637  if (p)
638  {
639  /* Insert new resolution at the head of the list */
640  pr->next_index = p[0];
642  }
643 
645  pr - am->pending_resolutions);
646 }
647 
648 int
650  void *data_callback,
651  u32 pid,
652  void *address_arg,
653  uword node_index,
654  uword type_opaque, uword data, int is_add)
655 {
657  ip4_address_t *address = address_arg;
658  uword *p;
660  void (*fp) (u32, u8 *) = data_callback;
661 
662  if (is_add)
663  {
664  pool_get (am->mac_changes, mc);
665 
666  mc->next_index = ~0;
667  mc->node_index = node_index;
668  mc->type_opaque = type_opaque;
669  mc->data = data;
670  mc->data_callback = data_callback;
671  mc->pid = pid;
672 
673  p = hash_get (am->mac_changes_by_address, address->as_u32);
674  if (p)
675  {
676  /* Insert new resolution at the head of the list */
677  mc->next_index = p[0];
678  hash_unset (am->mac_changes_by_address, address->as_u32);
679  }
680 
681  hash_set (am->mac_changes_by_address, address->as_u32,
682  mc - am->mac_changes);
683  return 0;
684  }
685  else
686  {
687  u32 index;
688  pending_resolution_t *mc_last = 0;
689 
690  p = hash_get (am->mac_changes_by_address, address->as_u32);
691  if (p == 0)
692  return VNET_API_ERROR_NO_SUCH_ENTRY;
693 
694  index = p[0];
695 
696  while (index != (u32) ~ 0)
697  {
698  mc = pool_elt_at_index (am->mac_changes, index);
699  if (mc->node_index == node_index &&
700  mc->type_opaque == type_opaque && mc->pid == pid)
701  {
702  /* Clients may need to clean up pool entries, too */
703  if (fp)
704  (*fp) (mc->data, 0 /* no new mac addrs */ );
705  if (index == p[0])
706  {
707  hash_unset (am->mac_changes_by_address, address->as_u32);
708  if (mc->next_index != ~0)
709  hash_set (am->mac_changes_by_address, address->as_u32,
710  mc->next_index);
711  pool_put (am->mac_changes, mc);
712  return 0;
713  }
714  else
715  {
716  ASSERT (mc_last);
717  mc_last->next_index = mc->next_index;
718  pool_put (am->mac_changes, mc);
719  return 0;
720  }
721  }
722  mc_last = mc;
723  index = mc->next_index;
724  }
725 
726  return VNET_API_ERROR_NO_SUCH_ENTRY;
727  }
728 }
729 
730 /* Either we drop the packet or we send a reply to the sender. */
731 typedef enum
732 {
737 
738 #define foreach_ethernet_arp_error \
739  _ (replies_sent, "ARP replies sent") \
740  _ (l2_type_not_ethernet, "L2 type not ethernet") \
741  _ (l3_type_not_ip4, "L3 type not IP4") \
742  _ (l3_src_address_not_local, "IP4 source address not local to subnet") \
743  _ (l3_dst_address_not_local, "IP4 destination address not local to subnet") \
744  _ (l3_src_address_is_local, "IP4 source address matches local interface") \
745  _ (l3_src_address_learned, "ARP request IP4 source address learned") \
746  _ (replies_received, "ARP replies received") \
747  _ (opcode_not_request, "ARP opcode not request") \
748  _ (proxy_arp_replies_sent, "Proxy ARP replies sent") \
749  _ (l2_address_mismatch, "ARP hw addr does not match L2 frame src addr") \
750  _ (missing_interface_address, "ARP missing interface address") \
751  _ (gratuitous_arp, "ARP probe or announcement dropped") \
752  _ (interface_no_table, "Interface is not mapped to an IP table") \
753 
754 typedef enum
755 {
756 #define _(sym,string) ETHERNET_ARP_ERROR_##sym,
758 #undef _
761 
762 
763 static void
765 {
768  vnet_main_t *vnm = vnet_get_main ();
769  ethernet_arp_ip4_over_ethernet_address_t delme;
770  u32 index;
771 
773  am->arp_delete_rotor = index;
774 
775  /* Try again from elt 0, could happen if an intfc goes down */
776  if (index == ~0)
777  {
779  am->arp_delete_rotor = index;
780  }
781 
782  /* Nothing left in the pool */
783  if (index == ~0)
784  return;
785 
786  e = pool_elt_at_index (am->ip4_entry_pool, index);
787 
788  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
789  delme.ip4.as_u32 = e->ip4_address.as_u32;
790 
792 }
793 
794 static int
796  u32 pi0, ethernet_header_t * eth0, u32 sw_if_index)
797 {
798  vlib_main_t *vm = vlib_get_main ();
799  vnet_main_t *vnm = vnet_get_main ();
803  u32 unnum_src_sw_if_index;
804  u32 *broadcast_swifs = 0;
805  u32 *buffers = 0;
806  u32 n_alloc = 0;
807  vlib_buffer_t *b0;
808  int i;
809  u8 dst_mac_address[6];
810  i16 header_size;
811  ethernet_arp_header_t *arp0;
812 
813  /* Save the dst mac address */
814  clib_memcpy (dst_mac_address, eth0->dst_address, sizeof (dst_mac_address));
815 
816  /* Figure out which sw_if_index supplied the address */
817  unnum_src_sw_if_index = sw_if_index;
818 
819  /* Track down all users of the unnumbered source */
820  /* *INDENT-OFF* */
821  pool_foreach (si, vim->sw_interfaces,
822  ({
823  if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
824  (si->unnumbered_sw_if_index == unnum_src_sw_if_index))
825  {
826  vec_add1 (broadcast_swifs, si->sw_if_index);
827  }
828  }));
829  /* *INDENT-ON* */
830 
831  /* If there are no interfaces un-unmbered to this interface,
832  we are done here. */
833  if (0 == vec_len (broadcast_swifs))
834  return 0;
835 
836  /* Allocate buffering if we need it */
837  if (vec_len (broadcast_swifs) > 1)
838  {
839  vec_validate (buffers, vec_len (broadcast_swifs) - 2);
840  n_alloc = vlib_buffer_alloc (vm, buffers, vec_len (buffers));
841  _vec_len (buffers) = n_alloc;
842  for (i = 0; i < n_alloc; i++)
843  {
844  b0 = vlib_get_buffer (vm, buffers[i]);
845 
846  /* xerox (partially built) ARP pkt */
847  clib_memcpy (b0->data, p0->data,
848  p0->current_length + p0->current_data);
849  b0->current_data = p0->current_data;
850  b0->current_length = p0->current_length;
851  vnet_buffer (b0)->sw_if_index[VLIB_RX] =
852  vnet_buffer (p0)->sw_if_index[VLIB_RX];
853  }
854  }
855 
856  vec_insert (buffers, 1, 0);
857  buffers[0] = pi0;
858 
859  for (i = 0; i < vec_len (buffers); i++)
860  {
861  b0 = vlib_get_buffer (vm, buffers[i]);
862  arp0 = vlib_buffer_get_current (b0);
863 
864  hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[i]);
865  si = vnet_get_sw_interface (vnm, broadcast_swifs[i]);
866 
867  /* For decoration, most likely */
868  vnet_buffer (b0)->sw_if_index[VLIB_TX] = hi->sw_if_index;
869 
870  /* Fix ARP pkt src address */
871  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, hi->hw_address, 6);
872 
873  /* Build L2 encaps for this swif */
874  header_size = sizeof (ethernet_header_t);
875  if (si->sub.eth.flags.one_tag)
876  header_size += 4;
877  else if (si->sub.eth.flags.two_tags)
878  header_size += 8;
879 
880  vlib_buffer_advance (b0, -header_size);
881  eth0 = vlib_buffer_get_current (b0);
882 
883  if (si->sub.eth.flags.one_tag)
884  {
885  ethernet_vlan_header_t *outer = (void *) (eth0 + 1);
886 
887  eth0->type = si->sub.eth.flags.dot1ad ?
888  clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
889  clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
890  outer->priority_cfi_and_id =
891  clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
892  outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
893 
894  }
895  else if (si->sub.eth.flags.two_tags)
896  {
897  ethernet_vlan_header_t *outer = (void *) (eth0 + 1);
898  ethernet_vlan_header_t *inner = (void *) (outer + 1);
899 
900  eth0->type = si->sub.eth.flags.dot1ad ?
901  clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
902  clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
903  outer->priority_cfi_and_id =
904  clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
905  outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
906  inner->priority_cfi_and_id =
907  clib_host_to_net_u16 (si->sub.eth.inner_vlan_id);
908  inner->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
909 
910  }
911  else
912  {
913  eth0->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
914  }
915 
916  /* Restore the original dst address, set src address */
917  clib_memcpy (eth0->dst_address, dst_mac_address,
918  sizeof (eth0->dst_address));
919  clib_memcpy (eth0->src_address, hi->hw_address,
920  sizeof (eth0->src_address));
921 
922  /* Transmit replicas */
923  if (i > 0)
924  {
925  vlib_frame_t *f =
926  vlib_get_frame_to_node (vm, hi->output_node_index);
927  u32 *to_next = vlib_frame_vector_args (f);
928  to_next[0] = buffers[i];
929  f->n_vectors = 1;
930  vlib_put_frame_to_node (vm, hi->output_node_index, f);
931  }
932  }
933 
934  /* The regular path outputs the original pkt.. */
935  vnet_buffer (p0)->sw_if_index[VLIB_TX] = broadcast_swifs[0];
936 
937  vec_free (broadcast_swifs);
938  vec_free (buffers);
939 
940  return !0;
941 }
942 
943 static uword
945 {
947  vnet_main_t *vnm = vnet_get_main ();
948  ip4_main_t *im4 = &ip4_main;
949  u32 n_left_from, next_index, *from, *to_next;
950  u32 n_replies_sent = 0, n_proxy_arp_replies_sent = 0;
951 
952  from = vlib_frame_vector_args (frame);
953  n_left_from = frame->n_vectors;
954  next_index = node->cached_next_index;
955 
956  if (node->flags & VLIB_NODE_FLAG_TRACE)
957  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
958  /* stride */ 1,
959  sizeof (ethernet_arp_input_trace_t));
960 
961  while (n_left_from > 0)
962  {
963  u32 n_left_to_next;
964 
965  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
966 
967  while (n_left_from > 0 && n_left_to_next > 0)
968  {
969  vlib_buffer_t *p0;
970  vnet_hw_interface_t *hw_if0;
971  ethernet_arp_header_t *arp0;
972  ethernet_header_t *eth0;
973  ip_adjacency_t *adj0;
974  ip4_address_t *if_addr0, proxy_src;
975  u32 pi0, error0, next0, sw_if_index0, conn_sw_if_index0, fib_index0;
976  u8 is_request0, dst_is_local0, is_unnum0;
978  fib_node_index_t dst_fei, src_fei;
979  fib_prefix_t pfx0;
980  fib_entry_flag_t src_flags, dst_flags;
981 
982  pi0 = from[0];
983  to_next[0] = pi0;
984  from += 1;
985  to_next += 1;
986  n_left_from -= 1;
987  n_left_to_next -= 1;
988  pa = 0;
989 
990  p0 = vlib_get_buffer (vm, pi0);
991  arp0 = vlib_buffer_get_current (p0);
992 
993  is_request0 = arp0->opcode
994  == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
995 
996  error0 = ETHERNET_ARP_ERROR_replies_sent;
997 
998  error0 =
999  (arp0->l2_type !=
1000  clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ?
1001  ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
1002  error0 =
1003  (arp0->l3_type !=
1004  clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
1005  ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
1006 
1007  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1008 
1009  if (error0)
1010  goto drop2;
1011 
1012  /* Check that IP address is local and matches incoming interface. */
1013  fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
1014  if (~0 == fib_index0)
1015  {
1016  error0 = ETHERNET_ARP_ERROR_interface_no_table;
1017  goto drop2;
1018 
1019  }
1020  dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1021  &arp0->ip4_over_ethernet[1].ip4,
1022  32);
1023  dst_flags = fib_entry_get_flags_for_source (dst_fei,
1025 
1026  conn_sw_if_index0 =
1029 
1030  if (!(FIB_ENTRY_FLAG_CONNECTED & dst_flags))
1031  {
1032  error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
1033  goto drop1;
1034  }
1035 
1036  /* Honor unnumbered interface, if any */
1037  is_unnum0 = sw_if_index0 != conn_sw_if_index0;
1038 
1039  /* Source must also be local to subnet of matching interface address. */
1040  src_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1041  &arp0->ip4_over_ethernet[0].ip4,
1042  32);
1043  src_flags = fib_entry_get_flags (src_fei);
1044 
1045  if (!((FIB_ENTRY_FLAG_ATTACHED & src_flags) ||
1046  (FIB_ENTRY_FLAG_CONNECTED & src_flags)))
1047  {
1048  /*
1049  * The packet was sent from an address that is not connected nor attached
1050  * i.e. it is not from an address that is covered by a link's sub-net,
1051  * nor is it a already learned host resp.
1052  */
1053  error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
1054  goto drop2;
1055  }
1056  if (sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
1057  {
1058  /*
1059  * The interface the ARP was received on is not the interface
1060  * on which the covering prefix is configured. Maybe this is a case
1061  * for unnumbered.
1062  */
1063  is_unnum0 = 1;
1064  }
1065 
1066  /* Reject requests/replies with our local interface address. */
1067  if (FIB_ENTRY_FLAG_LOCAL & src_flags)
1068  {
1069  error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
1070  goto drop2;
1071  }
1072 
1073  dst_is_local0 = (FIB_ENTRY_FLAG_LOCAL & dst_flags);
1074  fib_entry_get_prefix (dst_fei, &pfx0);
1075  if_addr0 = &pfx0.fp_addr.ip4;
1076 
1077  /* Fill in ethernet header. */
1078  eth0 = ethernet_buffer_get_header (p0);
1079 
1080  /* Trash ARP packets whose ARP-level source addresses do not
1081  match their L2-frame-level source addresses */
1082  if (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
1083  sizeof (eth0->src_address)))
1084  {
1085  error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1086  goto drop2;
1087  }
1088 
1089  /* Learn or update sender's mapping only for requests or unicasts
1090  that don't match local interface address. */
1091  if (ethernet_address_cast (eth0->dst_address) ==
1092  ETHERNET_ADDRESS_UNICAST || is_request0)
1093  {
1094  if (am->limit_arp_cache_size &&
1097 
1098  vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index0,
1099  &arp0->ip4_over_ethernet[0],
1100  0 /* is_static */ );
1101  error0 = ETHERNET_ARP_ERROR_l3_src_address_learned;
1102  }
1103 
1104  /* Only send a reply for requests sent which match a local interface. */
1105  if (!(is_request0 && dst_is_local0))
1106  {
1107  error0 =
1108  (arp0->opcode ==
1109  clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply) ?
1110  ETHERNET_ARP_ERROR_replies_received : error0);
1111  goto drop1;
1112  }
1113 
1114  /* Send a reply. */
1115  send_reply:
1116  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1117  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1118 
1119  /* Send reply back through input interface */
1120  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1121  next0 = ARP_INPUT_NEXT_REPLY_TX;
1122 
1123  arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1124 
1125  arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1126 
1127  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet,
1128  hw_if0->hw_address, 6);
1129  clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) =
1130  if_addr0->data_u32;
1131 
1132  /* Hardware must be ethernet-like. */
1133  ASSERT (vec_len (hw_if0->hw_address) == 6);
1134 
1135  clib_memcpy (eth0->dst_address, eth0->src_address, 6);
1136  clib_memcpy (eth0->src_address, hw_if0->hw_address, 6);
1137 
1138  /* Figure out how much to rewind current data from adjacency. */
1139  /* get the adj from the destination's covering connected */
1140  if (NULL == pa)
1141  {
1142  adj0 =
1145  (ip4_fib_get (fib_index0),
1146  &arp0->ip4_over_ethernet[1].ip4, 31),
1149  {
1150  error0 = ETHERNET_ARP_ERROR_missing_interface_address;
1151  goto drop2;
1152  }
1153  if (is_unnum0)
1154  {
1155  if (!arp_unnumbered (p0, pi0, eth0, conn_sw_if_index0))
1156  goto drop2;
1157  }
1158  else
1159  vlib_buffer_advance (p0, -adj0->rewrite_header.data_bytes);
1160  }
1161  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1162  n_left_to_next, pi0, next0);
1163 
1164  n_replies_sent += 1;
1165  continue;
1166 
1167  drop1:
1168  if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1169  (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1170  arp0->ip4_over_ethernet[1].ip4.as_u32))
1171  {
1172  error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1173  goto drop2;
1174  }
1175  /* See if proxy arp is configured for the address */
1176  if (is_request0)
1177  {
1178  vnet_sw_interface_t *si;
1179  u32 this_addr = clib_net_to_host_u32
1180  (arp0->ip4_over_ethernet[1].ip4.as_u32);
1181  u32 fib_index0;
1182 
1183  si = vnet_get_sw_interface (vnm, sw_if_index0);
1184 
1186  goto drop2;
1187 
1188  fib_index0 = vec_elt (im4->fib_index_by_sw_if_index,
1189  sw_if_index0);
1190 
1191  vec_foreach (pa, am->proxy_arps)
1192  {
1193  u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
1194  u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
1195 
1196  /* an ARP request hit in the proxy-arp table? */
1197  if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1198  (fib_index0 == pa->fib_index))
1199  {
1200  eth0 = ethernet_buffer_get_header (p0);
1201  proxy_src.as_u32 =
1202  arp0->ip4_over_ethernet[1].ip4.data_u32;
1203 
1204  /*
1205  * Rewind buffer, direct code above not to
1206  * think too hard about it.
1207  */
1208  if_addr0 = &proxy_src;
1209  is_unnum0 = 0;
1210  i32 ethernet_start =
1211  vnet_buffer (p0)->ethernet.start_of_ethernet_header;
1212  i32 rewind = p0->current_data - ethernet_start;
1213  vlib_buffer_advance (p0, -rewind);
1214  n_proxy_arp_replies_sent++;
1215  goto send_reply;
1216  }
1217  }
1218  }
1219 
1220  drop2:
1221 
1222  next0 = ARP_INPUT_NEXT_DROP;
1223  p0->error = node->errors[error0];
1224 
1225  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1226  n_left_to_next, pi0, next0);
1227  }
1228 
1229  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1230  }
1231 
1232  vlib_error_count (vm, node->node_index,
1233  ETHERNET_ARP_ERROR_replies_sent,
1234  n_replies_sent - n_proxy_arp_replies_sent);
1235 
1236  vlib_error_count (vm, node->node_index,
1237  ETHERNET_ARP_ERROR_proxy_arp_replies_sent,
1238  n_proxy_arp_replies_sent);
1239  return frame->n_vectors;
1240 }
1241 
1242 static char *ethernet_arp_error_strings[] = {
1243 #define _(sym,string) string,
1245 #undef _
1246 };
1247 
1248 /* *INDENT-OFF* */
1250 {
1251  .function = arp_input,
1252  .name = "arp-input",
1253  .vector_size = sizeof (u32),
1254  .n_errors = ETHERNET_ARP_N_ERROR,
1255  .error_strings = ethernet_arp_error_strings,
1256  .n_next_nodes = ARP_INPUT_N_NEXT,
1257  .next_nodes = {
1258  [ARP_INPUT_NEXT_DROP] = "error-drop",
1259  [ARP_INPUT_NEXT_REPLY_TX] = "interface-output",
1260  },
1261  .format_buffer = format_ethernet_arp_header,
1262  .format_trace = format_ethernet_arp_input_trace,
1263 };
1264 /* *INDENT-ON* */
1265 
1266 static int
1267 ip4_arp_entry_sort (void *a1, void *a2)
1268 {
1269  ethernet_arp_ip4_entry_t *e1 = a1;
1270  ethernet_arp_ip4_entry_t *e2 = a2;
1271 
1272  int cmp;
1273  vnet_main_t *vnm = vnet_get_main ();
1274 
1275  cmp = vnet_sw_interface_compare (vnm, e1->sw_if_index, e2->sw_if_index);
1276  if (!cmp)
1277  cmp = ip4_address_compare (&e1->ip4_address, &e2->ip4_address);
1278  return cmp;
1279 }
1280 
1283 {
1285  ethernet_arp_ip4_entry_t *n, *ns = 0;
1286 
1287  /* *INDENT-OFF* */
1288  pool_foreach (n, am->ip4_entry_pool, ({
1289  if (sw_if_index != ~0 && n->sw_if_index != sw_if_index)
1290  continue;
1291  vec_add1 (ns, n[0]);
1292  }));
1293  /* *INDENT-ON* */
1294 
1295  if (ns)
1297  return ns;
1298 }
1299 
1300 static clib_error_t *
1302  unformat_input_t * input, vlib_cli_command_t * cmd)
1303 {
1304  vnet_main_t *vnm = vnet_get_main ();
1306  ethernet_arp_ip4_entry_t *e, *es;
1308  clib_error_t *error = 0;
1309  u32 sw_if_index;
1310 
1311  /* Filter entries by interface if given. */
1312  sw_if_index = ~0;
1313  (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1314 
1315  es = ip4_neighbor_entries (sw_if_index);
1316  if (es)
1317  {
1318  vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1319  vec_foreach (e, es)
1320  {
1321  vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1322  }
1323  vec_free (es);
1324  }
1325 
1326  if (vec_len (am->proxy_arps))
1327  {
1328  vlib_cli_output (vm, "Proxy arps enabled for:");
1329  vec_foreach (pa, am->proxy_arps)
1330  {
1331  vlib_cli_output (vm, "Fib_index %d %U - %U ",
1332  pa->fib_index,
1334  format_ip4_address, &pa->hi_addr);
1335  }
1336  }
1337 
1338  return error;
1339 }
1340 
1341 /*?
1342  * Display all the IPv4 ARP entries.
1343  *
1344  * @cliexpar
1345  * Example of how to display the IPv4 ARP table:
1346  * @cliexstart{show ip arp}
1347  * Time FIB IP4 Flags Ethernet Interface
1348  * 346.3028 0 6.1.1.3 de:ad:be:ef:ba:be GigabitEthernet2/0/0
1349  * 3077.4271 0 6.1.1.4 S de:ad:be:ef:ff:ff GigabitEthernet2/0/0
1350  * 2998.6409 1 6.2.2.3 de:ad:be:ef:00:01 GigabitEthernet2/0/0
1351  * Proxy arps enabled for:
1352  * Fib_index 0 6.0.0.1 - 6.0.0.11
1353  * @cliexend
1354  ?*/
1355 /* *INDENT-OFF* */
1357  .path = "show ip arp",
1358  .function = show_ip4_arp,
1359  .short_help = "show ip arp",
1360 };
1361 /* *INDENT-ON* */
1362 
1363 typedef struct
1364 {
1365  pg_edit_t l2_type, l3_type;
1366  pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1368  struct
1369  {
1372  } ip4_over_ethernet[2];
1374 
1375 static inline void
1377 {
1378  /* Initialize fields that are not bit fields in the IP header. */
1379 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1380  _(l2_type);
1381  _(l3_type);
1382  _(n_l2_address_bytes);
1383  _(n_l3_address_bytes);
1384  _(opcode);
1385  _(ip4_over_ethernet[0].ethernet);
1386  _(ip4_over_ethernet[0].ip4);
1387  _(ip4_over_ethernet[1].ethernet);
1388  _(ip4_over_ethernet[1].ip4);
1389 #undef _
1390 }
1391 
1392 uword
1393 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1394 {
1395  pg_stream_t *s = va_arg (*args, pg_stream_t *);
1397  u32 group_index;
1398 
1399  p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1400  &group_index);
1402 
1403  /* Defaults. */
1404  pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1405  pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1408 
1409  if (!unformat (input, "%U: %U/%U -> %U/%U",
1420  {
1421  /* Free up any edits we may have added. */
1422  pg_free_edit_group (s);
1423  return 0;
1424  }
1425  return 1;
1426 }
1427 
1428 clib_error_t *
1430 {
1432 
1433  am->limit_arp_cache_size = arp_limit;
1434  return 0;
1435 }
1436 
1437 /**
1438  * @brief Control Plane hook to remove an ARP entry
1439  */
1440 int
1442  u32 sw_if_index, void *a_arg)
1443 {
1444  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1446 
1447  args.sw_if_index = sw_if_index;
1449  clib_memcpy (&args.a, a, sizeof (*a));
1450 
1452  (u8 *) & args, sizeof (args));
1453  return 0;
1454 }
1455 
1456 /**
1457  * @brief Internally generated event to flush the ARP cache on an
1458  * interface state change event.
1459  * A flush will remove dynamic ARP entries, and for statics remove the MAC
1460  * address from the corresponding adjacencies.
1461  */
1462 static int
1464  u32 sw_if_index, void *a_arg)
1465 {
1466  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1468 
1469  args.sw_if_index = sw_if_index;
1471  clib_memcpy (&args.a, a, sizeof (*a));
1472 
1474  (u8 *) & args, sizeof (args));
1475  return 0;
1476 }
1477 
1478 /**
1479  * @brief Internally generated event to populate the ARP cache on an
1480  * interface state change event.
1481  * For static entries this will re-source the adjacencies.
1482  *
1483  * @param sw_if_index The interface on which the ARP entires are acted
1484  */
1485 static int
1487  u32 sw_if_index, void *a_arg)
1488 {
1489  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1491 
1492  args.sw_if_index = sw_if_index;
1494  clib_memcpy (&args.a, a, sizeof (*a));
1495 
1497  (u8 *) & args, sizeof (args));
1498  return 0;
1499 }
1500 
1501 /*
1502  * arp_add_del_interface_address
1503  *
1504  * callback when an interface address is added or deleted
1505  */
1506 static void
1508  uword opaque,
1509  u32 sw_if_index,
1510  ip4_address_t * address,
1511  u32 address_length,
1512  u32 if_address_index, u32 is_del)
1513 {
1514  /*
1515  * Flush the ARP cache of all entries covered by the address
1516  * that is being removed.
1517  */
1520 
1521  if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
1522  return;
1523 
1524  if (is_del)
1525  {
1527  u32 i, *to_delete = 0;
1528  hash_pair_t *pair;
1529 
1530  eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
1531 
1532  /* *INDENT-OFF* */
1533  hash_foreach_pair (pair, eai->arp_entries,
1534  ({
1535  e = pool_elt_at_index(am->ip4_entry_pool,
1536  pair->value[0]);
1537  if (ip4_destination_matches_route (im, &e->ip4_address,
1538  address, address_length))
1539  {
1540  vec_add1 (to_delete, e - am->ip4_entry_pool);
1541  }
1542  }));
1543  /* *INDENT-ON* */
1544 
1545  for (i = 0; i < vec_len (to_delete); i++)
1546  {
1547  ethernet_arp_ip4_over_ethernet_address_t delme;
1548  e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1549 
1550  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1551  delme.ip4.as_u32 = e->ip4_address.as_u32;
1552 
1554  e->sw_if_index, &delme);
1555  }
1556 
1557  vec_free (to_delete);
1558  }
1559 }
1560 
1561 static clib_error_t *
1563 {
1565  ip4_main_t *im = &ip4_main;
1566  clib_error_t *error;
1567  pg_node_t *pn;
1568 
1569  if ((error = vlib_call_init_function (vm, ethernet_init)))
1570  return error;
1571 
1572  ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
1573 
1574  pn = pg_get_node (arp_input_node.index);
1576 
1577  am->opcode_by_name = hash_create_string (0, sizeof (uword));
1578 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
1580 #undef _
1581 
1582  /* $$$ configurable */
1583  am->limit_arp_cache_size = 50000;
1584 
1585  am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
1586  am->mac_changes_by_address = hash_create (0, sizeof (uword));
1587 
1588  /* don't trace ARP error packets */
1589  {
1590  vlib_node_runtime_t *rt =
1592 
1593 #define _(a,b) \
1594  vnet_pcap_drop_trace_filter_add_del \
1595  (rt->errors[ETHERNET_ARP_ERROR_##a], \
1596  1 /* is_add */);
1598 #undef _
1599  }
1600 
1603  cb.function_opaque = 0;
1605 
1606  return 0;
1607 }
1608 
1610 
1611 static void
1613 {
1615 
1618  pool_put (am->ip4_entry_pool, e);
1619 }
1620 
1621 static inline int
1624  * args)
1625 {
1629 
1630  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1631 
1632  e = arp_entry_find (eai, &args->a.ip4);
1633 
1634  if (NULL != e)
1635  {
1636  arp_entry_free (eai, e);
1637 
1640  }
1641 
1642  return 0;
1643 }
1644 
1645 static int
1648  * args)
1649 {
1653 
1654  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1655 
1656  e = arp_entry_find (eai, &args->a.ip4);
1657 
1658  if (NULL != e)
1659  {
1662 
1663  /*
1664  * The difference between flush and unset, is that an unset
1665  * means delete for static and dynamic entries. A flush
1666  * means delete only for dynamic. Flushing is what the DP
1667  * does in response to interface events. unset is only done
1668  * by the control plane.
1669  */
1671  {
1672  arp_entry_free (eai, e);
1673  }
1674  }
1675  return (0);
1676 }
1677 
1678 static int
1681  * args)
1682 {
1686 
1687  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1688 
1689  e = arp_entry_find (eai, &args->a.ip4);
1690 
1691  if (NULL != e)
1692  {
1695  }
1696  return (0);
1697 }
1698 
1699 static void
1701  * a)
1702 {
1703  vnet_main_t *vm = vnet_get_main ();
1704  ASSERT (os_get_cpu_number () == 0);
1705 
1708  else if (a->flags & ETHERNET_ARP_ARGS_FLUSH)
1710  else if (a->flags & ETHERNET_ARP_ARGS_POPULATE)
1712  else
1714 }
1715 
1716 /**
1717  * @brief Invoked when the interface's admin state changes
1718  */
1719 static clib_error_t *
1721  u32 sw_if_index, u32 flags)
1722 {
1725  u32 i, *to_delete = 0;
1726 
1727  /* *INDENT-OFF* */
1728  pool_foreach (e, am->ip4_entry_pool,
1729  ({
1730  if (e->sw_if_index == sw_if_index)
1731  vec_add1 (to_delete,
1732  e - am->ip4_entry_pool);
1733  }));
1734  /* *INDENT-ON* */
1735 
1736  for (i = 0; i < vec_len (to_delete); i++)
1737  {
1738  ethernet_arp_ip4_over_ethernet_address_t delme;
1739  e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1740 
1741  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1742  delme.ip4.as_u32 = e->ip4_address.as_u32;
1743 
1744  if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1745  {
1747  }
1748  else
1749  {
1751  }
1752 
1753  }
1754  vec_free (to_delete);
1755 
1756  return 0;
1757 }
1758 
1760 
1761 static void
1762 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t * a)
1763 {
1764  u8 old;
1765  int i;
1766 
1767  for (i = 3; i >= 0; i--)
1768  {
1769  old = a->ip4.as_u8[i];
1770  a->ip4.as_u8[i] += 1;
1771  if (old < a->ip4.as_u8[i])
1772  break;
1773  }
1774 
1775  for (i = 5; i >= 0; i--)
1776  {
1777  old = a->ethernet[i];
1778  a->ethernet[i] += 1;
1779  if (old < a->ethernet[i])
1780  break;
1781  }
1782 }
1783 
1784 int
1786  u32 sw_if_index, void *a_arg, int is_static)
1787 {
1788  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1790 
1791  args.sw_if_index = sw_if_index;
1792  args.is_static = is_static;
1793  args.flags = 0;
1794  clib_memcpy (&args.a, a, sizeof (*a));
1795 
1797  (u8 *) & args, sizeof (args));
1798  return 0;
1799 }
1800 
1801 int
1803  ip4_address_t * hi_addr, u32 fib_index, int is_del)
1804 {
1807  u32 found_at_index = ~0;
1808 
1809  vec_foreach (pa, am->proxy_arps)
1810  {
1811  if (pa->lo_addr == lo_addr->as_u32
1812  && pa->hi_addr == hi_addr->as_u32 && pa->fib_index == fib_index)
1813  {
1814  found_at_index = pa - am->proxy_arps;
1815  break;
1816  }
1817  }
1818 
1819  if (found_at_index != ~0)
1820  {
1821  /* Delete, otherwise it's already in the table */
1822  if (is_del)
1823  vec_delete (am->proxy_arps, 1, found_at_index);
1824  return 0;
1825  }
1826  /* delete, no such entry */
1827  if (is_del)
1828  return VNET_API_ERROR_NO_SUCH_ENTRY;
1829 
1830  /* add, not in table */
1831  vec_add2 (am->proxy_arps, pa, 1);
1832  pa->lo_addr = lo_addr->as_u32;
1833  pa->hi_addr = hi_addr->as_u32;
1834  pa->fib_index = fib_index;
1835  return 0;
1836 }
1837 
1838 /*
1839  * Remove any proxy arp entries asdociated with the
1840  * specificed fib.
1841  */
1842 int
1844 {
1845  ip4_main_t *im = &ip4_main;
1848  u32 *entries_to_delete = 0;
1849  u32 fib_index;
1850  uword *p;
1851  int i;
1852 
1853  p = hash_get (im->fib_index_by_table_id, fib_id);
1854  if (!p)
1855  return VNET_API_ERROR_NO_SUCH_ENTRY;
1856  fib_index = p[0];
1857 
1858  vec_foreach (pa, am->proxy_arps)
1859  {
1860  if (pa->fib_index == fib_index)
1861  {
1862  vec_add1 (entries_to_delete, pa - am->proxy_arps);
1863  }
1864  }
1865 
1866  for (i = 0; i < vec_len (entries_to_delete); i++)
1867  {
1868  vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
1869  }
1870 
1871  vec_free (entries_to_delete);
1872 
1873  return 0;
1874 }
1875 
1876 static clib_error_t *
1878  unformat_input_t * input, vlib_cli_command_t * cmd)
1879 {
1880  vnet_main_t *vnm = vnet_get_main ();
1881  u32 sw_if_index;
1882  ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
1883  int addr_valid = 0;
1884  int is_del = 0;
1885  int count = 1;
1886  u32 fib_index = 0;
1887  u32 fib_id;
1888  int is_static = 0;
1889  int is_proxy = 0;
1890 
1891  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1892  {
1893  /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
1894  if (unformat (input, "%U %U %U",
1895  unformat_vnet_sw_interface, vnm, &sw_if_index,
1896  unformat_ip4_address, &addr.ip4,
1897  unformat_ethernet_address, &addr.ethernet))
1898  addr_valid = 1;
1899 
1900  else if (unformat (input, "delete") || unformat (input, "del"))
1901  is_del = 1;
1902 
1903  else if (unformat (input, "static"))
1904  is_static = 1;
1905 
1906  else if (unformat (input, "count %d", &count))
1907  ;
1908 
1909  else if (unformat (input, "fib-id %d", &fib_id))
1910  {
1911  ip4_main_t *im = &ip4_main;
1912  uword *p = hash_get (im->fib_index_by_table_id, fib_id);
1913  if (!p)
1914  return clib_error_return (0, "fib ID %d doesn't exist\n", fib_id);
1915  fib_index = p[0];
1916  }
1917 
1918  else if (unformat (input, "proxy %U - %U",
1919  unformat_ip4_address, &lo_addr.ip4,
1920  unformat_ip4_address, &hi_addr.ip4))
1921  is_proxy = 1;
1922  else
1923  break;
1924  }
1925 
1926  if (is_proxy)
1927  {
1928  (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4,
1929  fib_index, is_del);
1930  return 0;
1931  }
1932 
1933  if (addr_valid)
1934  {
1935  int i;
1936 
1937  for (i = 0; i < count; i++)
1938  {
1939  if (is_del == 0)
1940  {
1941  uword event_type, *event_data = 0;
1942 
1943  /* Park the debug CLI until the arp entry is installed */
1945  (vnm, &addr.ip4, vlib_current_process (vm),
1946  1 /* type */ , 0 /* data */ );
1947 
1949  (vnm, sw_if_index, &addr, is_static);
1950 
1952  event_type = vlib_process_get_events (vm, &event_data);
1953  vec_reset_length (event_data);
1954  if (event_type != 1)
1955  clib_warning ("event type %d unexpected", event_type);
1956  }
1957  else
1958  vnet_arp_unset_ip4_over_ethernet (vnm, sw_if_index, &addr);
1959 
1961  }
1962  }
1963  else
1964  {
1965  return clib_error_return (0, "unknown input `%U'",
1966  format_unformat_error, input);
1967  }
1968 
1969  return 0;
1970 }
1971 
1972 /* *INDENT-OFF* */
1973 /*?
1974  * Add or delete IPv4 ARP cache entries.
1975  *
1976  * @note 'set ip arp' options (e.g. delete, static, 'fib-id <id>',
1977  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
1978  * any order and combination.
1979  *
1980  * @cliexpar
1981  * @parblock
1982  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
1983  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
1984  * @cliexcmd{set ip arp GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1985  * @cliexcmd{set ip arp delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
1986  *
1987  * To add or delete an IPv4 ARP cache entry to or from a specific fib
1988  * table:
1989  * @cliexcmd{set ip arp fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1990  * @cliexcmd{set ip arp fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1991  *
1992  * Add or delete IPv4 static ARP cache entries as follows:
1993  * @cliexcmd{set ip arp static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1994  * @cliexcmd{set ip arp static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1995  *
1996  * For testing / debugging purposes, the 'set ip arp' command can add or
1997  * delete multiple entries. Supply the 'count N' parameter:
1998  * @cliexcmd{set ip arp count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1999  * @endparblock
2000  ?*/
2002  .path = "set ip arp",
2003  .short_help =
2004  "set ip arp [del] <intfc> <ip-address> <mac-address> [static] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
2005  .function = ip_arp_add_del_command_fn,
2006 };
2007 /* *INDENT-ON* */
2008 
2009 static clib_error_t *
2012  input, vlib_cli_command_t * cmd)
2013 {
2014  vnet_main_t *vnm = vnet_get_main ();
2015  u32 sw_if_index;
2016  vnet_sw_interface_t *si;
2017  int enable = 0;
2018  int intfc_set = 0;
2019 
2020  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2021  {
2022  if (unformat (input, "%U", unformat_vnet_sw_interface,
2023  vnm, &sw_if_index))
2024  intfc_set = 1;
2025  else if (unformat (input, "enable") || unformat (input, "on"))
2026  enable = 1;
2027  else if (unformat (input, "disable") || unformat (input, "off"))
2028  enable = 0;
2029  else
2030  break;
2031  }
2032 
2033  if (intfc_set == 0)
2034  return clib_error_return (0, "unknown input '%U'",
2035  format_unformat_error, input);
2036 
2037  si = vnet_get_sw_interface (vnm, sw_if_index);
2038  ASSERT (si);
2039  if (enable)
2041  else
2043 
2044  return 0;
2045 }
2046 
2047 /* *INDENT-OFF* */
2048 /*?
2049  * Enable proxy-arp on an interface. The vpp stack will answer ARP
2050  * requests for the indicated address range. Multiple proxy-arp
2051  * ranges may be provisioned.
2052  *
2053  * @note Proxy ARP as a technology is infamous for blackholing traffic.
2054  * Also, the underlying implementation has not been performance-tuned.
2055  * Avoid creating an unnecessarily large set of ranges.
2056  *
2057  * @cliexpar
2058  * To enable proxy arp on a range of addresses, use:
2059  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11}
2060  * Append 'del' to delete a range of proxy ARP addresses:
2061  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11 del}
2062  * You must then specifically enable proxy arp on individual interfaces:
2063  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 enable}
2064  * To disable proxy arp on an individual interface:
2065  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 disable}
2066  ?*/
2068  .path = "set interface proxy-arp",
2069  .short_help =
2070  "set interface proxy-arp <intfc> [enable|disable]",
2071  .function = set_int_proxy_arp_command_fn,
2072 };
2073 /* *INDENT-ON* */
2074 
2075 
2076 /*
2077  * ARP/ND Termination in a L2 Bridge Domain based on IP4/IP6 to MAC
2078  * hash tables mac_by_ip4 and mac_by_ip6 for each BD.
2079  */
2080 typedef enum
2081 {
2085 } arp_term_next_t;
2086 
2088 
2089 static uword
2091  vlib_node_runtime_t * node, vlib_frame_t * frame)
2092 {
2093  l2input_main_t *l2im = &l2input_main;
2094  u32 n_left_from, next_index, *from, *to_next;
2095  u32 n_replies_sent = 0;
2096  u16 last_bd_index = ~0;
2097  l2_bridge_domain_t *last_bd_config = 0;
2098  l2_input_config_t *cfg0;
2099 
2100  from = vlib_frame_vector_args (frame);
2101  n_left_from = frame->n_vectors;
2102  next_index = node->cached_next_index;
2103 
2104  while (n_left_from > 0)
2105  {
2106  u32 n_left_to_next;
2107 
2108  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2109 
2110  while (n_left_from > 0 && n_left_to_next > 0)
2111  {
2112  vlib_buffer_t *p0;
2113  ethernet_header_t *eth0;
2114  ethernet_arp_header_t *arp0;
2115  ip6_header_t *iph0;
2116  u8 *l3h0;
2117  u32 pi0, error0, next0, sw_if_index0;
2118  u16 ethertype0;
2119  u16 bd_index0;
2120  u32 ip0;
2121  u8 *macp0;
2122 
2123  pi0 = from[0];
2124  to_next[0] = pi0;
2125  from += 1;
2126  to_next += 1;
2127  n_left_from -= 1;
2128  n_left_to_next -= 1;
2129 
2130  p0 = vlib_get_buffer (vm, pi0);
2131  eth0 = vlib_buffer_get_current (p0);
2132  l3h0 = (u8 *) eth0 + vnet_buffer (p0)->l2.l2_len;
2133  ethertype0 = clib_net_to_host_u16 (*(u16 *) (l3h0 - 2));
2134  arp0 = (ethernet_arp_header_t *) l3h0;
2135 
2136  if (PREDICT_FALSE ((ethertype0 != ETHERNET_TYPE_ARP) ||
2137  (arp0->opcode !=
2138  clib_host_to_net_u16
2139  (ETHERNET_ARP_OPCODE_request))))
2140  goto check_ip6_nd;
2141 
2142  /* Must be ARP request packet here */
2143  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
2144  (p0->flags & VLIB_BUFFER_IS_TRACED)))
2145  {
2146  u8 *t0 = vlib_add_trace (vm, node, p0,
2147  sizeof (ethernet_arp_input_trace_t));
2148  clib_memcpy (t0, l3h0, sizeof (ethernet_arp_input_trace_t));
2149  }
2150 
2151  error0 = ETHERNET_ARP_ERROR_replies_sent;
2152  error0 =
2153  (arp0->l2_type !=
2154  clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
2155  ? ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
2156  error0 =
2157  (arp0->l3_type !=
2158  clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
2159  ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
2160 
2161  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2162 
2163  if (error0)
2164  goto drop;
2165 
2166  /* Trash ARP packets whose ARP-level source addresses do not
2167  match their L2-frame-level source addresses */
2168  if (PREDICT_FALSE
2169  (memcmp
2170  (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
2171  sizeof (eth0->src_address))))
2172  {
2173  error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
2174  goto drop;
2175  }
2176 
2177  /* Check if anyone want ARP request events for L2 BDs */
2178  {
2181  uword *p = hash_get (am->mac_changes_by_address, 0);
2182  if (p && (vnet_buffer (p0)->l2.shg == 0))
2183  { // Only SHG 0 interface which is more likely local
2184  u32 next_index = p[0];
2185  while (next_index != (u32) ~ 0)
2186  {
2187  int (*fp) (u32, u8 *, u32, u32);
2188  int rv = 1;
2189  mc = pool_elt_at_index (am->mac_changes, next_index);
2190  fp = mc->data_callback;
2191  /* Call the callback, return 1 to suppress dup events */
2192  if (fp)
2193  rv = (*fp) (mc->data,
2194  arp0->ip4_over_ethernet[0].ethernet,
2195  sw_if_index0,
2196  arp0->ip4_over_ethernet[0].ip4.as_u32);
2197  /* Signal the resolver process */
2198  if (rv == 0)
2200  mc->type_opaque, mc->data);
2201  next_index = mc->next_index;
2202  }
2203  }
2204  }
2205 
2206  /* lookup BD mac_by_ip4 hash table for MAC entry */
2207  ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
2208  bd_index0 = vnet_buffer (p0)->l2.bd_index;
2209  if (PREDICT_FALSE ((bd_index0 != last_bd_index)
2210  || (last_bd_index == (u16) ~ 0)))
2211  {
2212  last_bd_index = bd_index0;
2213  last_bd_config = vec_elt_at_index (l2im->bd_configs, bd_index0);
2214  }
2215  macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
2216 
2217  if (PREDICT_FALSE (!macp0))
2218  goto next_l2_feature; /* MAC not found */
2219 
2220  /* MAC found, send ARP reply -
2221  Convert ARP request packet to ARP reply */
2222  arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
2223  arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
2224  arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
2225  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
2226  clib_memcpy (eth0->dst_address, eth0->src_address, 6);
2227  clib_memcpy (eth0->src_address, macp0, 6);
2228  n_replies_sent += 1;
2229 
2230  output_response:
2231  /* For BVI, need to use l2-fwd node to send ARP reply as
2232  l2-output node cannot output packet to BVI properly */
2233  cfg0 = vec_elt_at_index (l2im->configs, sw_if_index0);
2234  if (PREDICT_FALSE (cfg0->bvi))
2235  {
2236  vnet_buffer (p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
2237  vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
2238  goto next_l2_feature;
2239  }
2240 
2241  /* Send ARP/ND reply back out input interface through l2-output */
2242  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2243  next0 = ARP_TERM_NEXT_L2_OUTPUT;
2244  /* Note that output to VXLAN tunnel will fail due to SHG which
2245  is probably desireable since ARP termination is not intended
2246  for ARP requests from other hosts. If output to VXLAN tunnel is
2247  required, however, can just clear the SHG in packet as follows:
2248  vnet_buffer(p0)->l2.shg = 0; */
2249  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2250  to_next, n_left_to_next, pi0,
2251  next0);
2252  continue;
2253 
2254  check_ip6_nd:
2255  /* IP6 ND event notification or solicitation handling to generate
2256  local response instead of flooding */
2257  iph0 = (ip6_header_t *) l3h0;
2258  if (PREDICT_FALSE (ethertype0 == ETHERNET_TYPE_IP6 &&
2259  iph0->protocol == IP_PROTOCOL_ICMP6 &&
2261  (&iph0->src_address)))
2262  {
2263  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2264  if (vnet_ip6_nd_term
2265  (vm, node, p0, eth0, iph0, sw_if_index0,
2266  vnet_buffer (p0)->l2.bd_index, vnet_buffer (p0)->l2.shg))
2267  goto output_response;
2268  }
2269 
2270  next_l2_feature:
2271  {
2272  u32 feature_bitmap0 =
2273  vnet_buffer (p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM;
2274  vnet_buffer (p0)->l2.feature_bitmap = feature_bitmap0;
2275  next0 =
2276  feat_bitmap_get_next_node_index (arp_term_next_node_index,
2277  feature_bitmap0);
2278  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2279  to_next, n_left_to_next,
2280  pi0, next0);
2281  continue;
2282  }
2283 
2284  drop:
2285  if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
2286  (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
2287  arp0->ip4_over_ethernet[1].ip4.as_u32))
2288  {
2289  error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
2290  }
2291  next0 = ARP_TERM_NEXT_DROP;
2292  p0->error = node->errors[error0];
2293 
2294  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2295  to_next, n_left_to_next, pi0,
2296  next0);
2297  }
2298 
2299  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2300  }
2301 
2302  vlib_error_count (vm, node->node_index,
2303  ETHERNET_ARP_ERROR_replies_sent, n_replies_sent);
2304  return frame->n_vectors;
2305 }
2306 
2307 /* *INDENT-OFF* */
2309  .function = arp_term_l2bd,
2310  .name = "arp-term-l2bd",
2311  .vector_size = sizeof (u32),
2312  .n_errors = ETHERNET_ARP_N_ERROR,
2313  .error_strings = ethernet_arp_error_strings,
2314  .n_next_nodes = ARP_TERM_N_NEXT,
2315  .next_nodes = {
2316  [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
2317  [ARP_TERM_NEXT_DROP] = "error-drop",
2318  },
2319  .format_buffer = format_ethernet_arp_header,
2320  .format_trace = format_arp_term_input_trace,
2321 };
2322 /* *INDENT-ON* */
2323 
2324 clib_error_t *
2326 {
2327  // Initialize the feature next-node indexes
2329  arp_term_l2bd_node.index,
2332  arp_term_next_node_index);
2333  return 0;
2334 }
2335 
2337 
2338 void
2340 {
2341  if (e->sw_if_index == sw_if_index)
2342  {
2345  }
2346 }
2347 
2348 void
2350 {
2353 
2354  /* *INDENT-OFF* */
2355  pool_foreach (e, am->ip4_entry_pool,
2356  ({
2357  change_arp_mac (sw_if_index, e);
2358  }));
2359  /* *INDENT-ON* */
2360 }
2361 
2362 /*
2363  * fd.io coding-style-patch-verification: ON
2364  *
2365  * Local Variables:
2366  * eval: (c-set-style "gnu")
2367  * End:
2368  */
#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:459
fib_node_index_t fib_table_entry_update_one_path(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)
Update the entry to have just one path.
Definition: fib_table.c:726
#define vnet_rewrite_one_header(rw0, p0, most_likely_size)
Definition: rewrite.h:253
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:1700
vmrglw vmrglh hi
#define pool_next_index(P, I)
Return next occupied pool index after i, useful for safe iteration.
Definition: pool.h:377
#define VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST
Definition: rewrite.h:264
static uword arp_term_l2bd(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: arp.c:2090
#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
u8 * format_ethernet_arp_ip4_entry(u8 *s, va_list *va)
Definition: arp.c:237
ip4_add_del_interface_address_callback_t * add_del_interface_address_callbacks
Functions to call when interface address changes.
Definition: ip4.h:116
u32 fib_entry_get_resolving_interface_for_source(fib_node_index_t fib_entry_index, fib_source_t source)
#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:604
uword unformat_pg_arp_header(unformat_input_t *input, va_list *args)
Definition: arp.c:1393
static void pg_ethernet_arp_header_init(pg_ethernet_arp_header_t *p)
Definition: arp.c:1376
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:1622
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:1762
An indication that the rewrite is complete, i.e.
Definition: adj_nbr.h:98
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:410
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:1507
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:1301
vnet_interface_main_t interface_main
Definition: vnet.h:57
pending_resolution_t * pending_resolutions
Definition: arp.c:76
void fib_entry_get_prefix(fib_node_index_t fib_entry_index, fib_prefix_t *pfx)
Definition: fib_entry.c:1433
static void vlib_error_count(vlib_main_t *vm, uword node_index, uword counter, uword increment)
Definition: error_funcs.h:55
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
struct pg_ethernet_arp_header_t::@122 ip4_over_ethernet[2]
vnet_link_t adj_get_link_type(adj_index_t ai)
Return the link type of the adjacency.
Definition: adj.c:262
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: lookup.h:188
struct ethernet_arp_interface_t_ ethernet_arp_interface_t
Per-interface ARP configuration and state.
void change_arp_mac(u32 sw_if_index, ethernet_arp_ip4_entry_t *e)
Definition: arp.c:2339
static u8 * format_ethernet_arp_header(u8 *s, va_list *va)
Definition: arp.c:190
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:2010
clib_error_t * ip4_set_arp_limit(u32 arp_limit)
Definition: arp.c:1429
static uword arp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: arp.c:944
#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:1109
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:428
static uword unformat_ethernet_arp_opcode_host_byte_order(unformat_input_t *input, va_list *args)
Definition: arp.c:149
#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
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:576
pg_edit_t l2_type
Definition: arp.c:1365
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:105
uword * opcode_by_name
Definition: arp.c:72
format_function_t format_vlib_cpu_time
Definition: node_funcs.h:1107
unformat_function_t unformat_vnet_sw_interface
u64 cpu_time_last_updated
Definition: arp_packet.h:154
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
Definition: memory_vlib.c:1268
vlib_error_t * errors
Definition: node.h:419
Definition: fib_entry.h:218
#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:79
pg_edit_t ethernet
Definition: arp.c:1370
ip6_address_t src_address
Definition: ip6_packet.h:337
union ip_adjacency_t_::@175 sub_type
void * data_callback
Definition: arp.c:65
#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
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:1679
VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(ethernet_arp_sw_interface_up_down)
arp_input_next_t
Definition: arp.c:731
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
u32 ip4_fib_table_get_index_for_sw_if_index(u32 sw_if_index)
Definition: ip4_fib.c:212
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:117
pg_edit_t n_l3_address_bytes
Definition: arp.c:1366
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
Definition: buffer.h:78
u8 * format_ethernet_address(u8 *s, va_list *args)
Definition: format.c:44
#define VNET_SW_INTERFACE_FLAG_PROXY_ARP
Definition: interface.h:533
#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
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:527
static uword ethernet_address_cast(u8 *a)
Definition: packet.h:65
pending_resolution_t * mac_changes
Definition: arp.c:80
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
Definition: buffer.h:194
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:1267
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
int i32
Definition: types.h:81
#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:145
u8 * format_hex_bytes(u8 *s, va_list *va)
Definition: std-formats.c:84
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:273
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:1463
#define clib_warning(format, args...)
Definition: error.h:59
#define foreach_ethernet_arp_opcode
Definition: arp_packet.h:61
uword * pending_resolutions_by_address
Definition: arp.c:75
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:225
u16 fp_len
The mask length.
Definition: fib_types.h:149
#define vlib_call_init_function(vm, x)
Definition: init.h:161
static ethernet_arp_ip4_entry_t * arp_entry_find(ethernet_arp_interface_t *eai, const ip4_address_t *addr)
Definition: arp.c:391
This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string ...
Definition: lookup.h:78
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:1441
static vlib_cli_command_t ip_arp_add_del_command
(constructor) VLIB_CLI_COMMAND (ip_arp_add_del_command)
Definition: arp.c:2001
#define hash_create_string(elts, value_bytes)
Definition: hash.h:652
pg_edit_t l3_type
Definition: arp.c:1365
static adj_walk_rc_t arp_mk_complete_walk(adj_index_t ai, void *ctx)
Definition: arp.c:410
Per-interface ARP configuration and state.
Definition: arp.c:42
unformat_function_t unformat_ip4_address
Definition: format.h:76
Definition: fib_entry.h:221
#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:342
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:112
#define foreach_ethernet_arp_error
Definition: arp.c:738
vlib_main_t * vlib_main
Definition: vnet.h:79
static void arp_mk_complete(adj_index_t ai, ethernet_arp_ip4_entry_t *e)
Definition: arp.c:367
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
Definition: node_funcs.h:931
Adjacency source.
Definition: fib_entry.h:88
ip46_address_t fp_addr
The address type is not deriveable from the fp_addr member.
Definition: fib_types.h:168
uword type_opaque
Definition: arp.c:62
#define ETHERNET_ARP_ARGS_FLUSH
Definition: arp.c:104
ip4_address_t ip4_address
Definition: arp_packet.h:146
u32 sw_if_index
Definition: arp_packet.h:145
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
u8 ethernet_address[6]
Definition: arp_packet.h:148
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
static vlib_cli_command_t show_ip4_arp_command
(constructor) VLIB_CLI_COMMAND (show_ip4_arp_command)
Definition: arp.c:1356
static int arp_unnumbered(vlib_buffer_t *p0, u32 pi0, ethernet_header_t *eth0, u32 sw_if_index)
Definition: arp.c:795
static void unset_random_arp_entry(void)
Definition: arp.c:764
#define PREDICT_FALSE(x)
Definition: clib.h:97
ethernet_arp_interface_t * ethernet_arp_by_sw_if_index
Per interface state.
Definition: arp.c:89
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:472
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
Definition: main.c:196
static clib_error_t * ethernet_arp_init(vlib_main_t *vm)
Definition: arp.c:1562
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:350
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:576
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:121
static clib_error_t * ethernet_init(vlib_main_t *vm)
Definition: init.c:82
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1301
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:1877
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)
The IPv4 FIB.
Definition: ip4_fib.c:285
ethernet_proxy_arp_t * proxy_arps
Definition: arp.c:92
u16 n_vectors
Definition: node.h:344
static void arp_mk_incomplete(adj_index_t ai)
Definition: arp.c:377
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:1366
void fib_table_entry_delete_index(fib_node_index_t fib_entry_index, fib_source_t source)
Delete a FIB entry.
Definition: fib_table.c:831
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
ip4_add_del_interface_address_function_t * function
Definition: ip4.h:82
static ethernet_arp_main_t ethernet_arp_main
Definition: arp.c:95
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
Definition: ip4_fib.h:71
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
static char * ethernet_arp_error_strings[]
Definition: arp.c:1242
#define ETHERNET_ARP_ARGS_POPULATE
Definition: arp.c:105
struct ip_adjacency_t_::@175::@176 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
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
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
Definition: buffer.h:207
#define ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC
Definition: arp_packet.h:151
unformat_function_t * unformat_edit
Definition: pg.h:307
uword * mac_changes_by_address
Definition: arp.c:79
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
uword unformat_vlib_number_by_name(unformat_input_t *input, va_list *args)
Definition: format.c:157
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:618
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:1720
#define ETHERNET_ARP_IP4_ENTRY_FLAG_DYNAMIC
Definition: arp_packet.h:152
char ** l2input_get_feat_names(void)
Return an array of strings containing graph node names of each feature.
Definition: l2_input.c:57
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:1802
static u8 * format_ethernet_arp_opcode(u8 *s, va_list *va)
Definition: arp.c:131
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:154
enum fib_entry_flag_t_ fib_entry_flag_t
int vnet_arp_set_ip4_over_ethernet(vnet_main_t *vnm, u32 sw_if_index, void *a_arg, int is_static)
Definition: arp.c:1785
clib_error_t * arp_term_init(vlib_main_t *vm)
Definition: arp.c:2325
vlib_packet_template_t ip4_arp_request_packet_template
Template used to generate IP4 ARP packets.
Definition: ip4.h:119
#define hash_create(elts, value_bytes)
Definition: hash.h:658
#define ETHERNET_ARP_ARGS_REMOVE
Definition: arp.c:103
u16 cached_next_index
Definition: node.h:463
#define VNET_SW_INTERFACE_FLAG_ADMIN_UP
Definition: interface.h:528
uword unformat_ethernet_address(unformat_input_t *input, va_list *args)
Definition: format.c:245
#define ASSERT(truth)
u32 arp_term_next_node_index[32]
Definition: arp.c:2087
unsigned int u32
Definition: types.h:88
adj_index_t fib_entry_get_adj_for_source(fib_node_index_t fib_entry_index, fib_source_t source)
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
#define vnet_buffer(b)
Definition: buffer.h:361
#define vec_delete(V, N, M)
Delete N elements starting at element M.
Definition: vec.h:745
IPv4 main type.
Definition: ip4.h:95
static void pg_free_edit_group(pg_stream_t *s)
Definition: pg.h:278
u32 arp_delete_rotor
Definition: arp.c:85
#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.
Route added as a result of interface configuration.
Definition: fib_entry.h:50
static void arp_nbr_probe(ip_adjacency_t *adj)
Definition: arp.c:304
Definition: pg.h:96
#define VLIB_BUFFER_IS_TRACED
Definition: buffer.h:95
ethernet_arp_ip4_over_ethernet_address_t a
Definition: arp.c:100
void ethernet_register_input_type(vlib_main_t *vm, ethernet_type_t type, u32 node_index)
Definition: node.c:1282
static vlib_node_registration_t arp_term_l2bd_node
(constructor) VLIB_REGISTER_NODE (arp_term_l2bd_node)
Definition: arp.c:2308
uword * arp_entries
Hash table of ARP entries.
Definition: arp.c:48
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)
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:87
static vlib_node_registration_t arp_input_node
(constructor) VLIB_REGISTER_NODE (arp_input_node)
Definition: arp.c:1249
int vnet_proxy_arp_fib_reset(u32 fib_id)
Definition: arp.c:1843
fib_node_index_t fib_entry_index
The index of the adj-fib entry created.
Definition: arp_packet.h:159
#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
Definition: lookup.h:199
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
Definition: fib_entry.h:217
static vlib_cli_command_t set_int_proxy_enable_command
(constructor) VLIB_CLI_COMMAND (set_int_proxy_enable_command)
Definition: arp.c:2067
#define vec_sort_with_function(vec, f)
Sort a vector using the supplied element comparison function.
Definition: vec.h:920
static u8 * format_arp_term_input_trace(u8 *s, va_list *va)
Definition: arp.c:287
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:1646
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:606
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
Definition: node_funcs.h:253
static u8 * format_ethernet_arp_hardware_type(u8 *s, va_list *va)
Definition: arp.c:113
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:59
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:1612
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, u8 shg)
pg_edit_t opcode
Definition: arp.c:1367
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
ethernet_arp_input_error_t
Definition: arp.c:754
arp_term_next_t
Definition: arp.c:2080
u16 flags
Definition: arp_packet.h:150
u32 limit_arp_cache_size
Definition: arp.c:86
void * vlib_packet_template_get_packet(vlib_main_t *vm, vlib_packet_template_t *t, u32 *bi_result)
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
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1099
uword node_index
Definition: arp.c:61
#define vec_foreach(var, vec)
Vector iterator.
static uword ip6_address_is_unspecified(ip6_address_t *a)
Definition: ip6_packet.h:273
uword * mac_by_ip4
Definition: l2_bd.h:83
ethernet_arp_ip4_entry_t * ip4_neighbor_entries(u32 sw_if_index)
Definition: arp.c:1282
vhost_vring_addr_t addr
Definition: vhost-user.h:81
#define clib_error_return(e, args...)
Definition: error.h:111
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:1486
struct _unformat_input_t unformat_input_t
format_function_t format_ip6_header
Definition: format.h:98
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
Definition: main.c:187
u32 flags
Definition: vhost-user.h:75
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:177
#define ETHERNET_ADDRESS_UNICAST
Definition: packet.h:60
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:252
void ethernet_arp_change_mac(u32 sw_if_index)
Definition: arp.c:2349
ethernet_arp_ip4_entry_t * ip4_entry_pool
Definition: arp.c:82
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:649
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
Definition: defs.h:46
Definition: arp_packet.h:143
fib_entry_flag_t fib_entry_get_flags(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:278
static adj_walk_rc_t arp_mk_incomplete_walk(adj_index_t ai, void *ctx)
Definition: arp.c:420
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:201
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109