FD.io VPP  v17.01.1-3-gc6833f8
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  _ (interface_not_ip_enabled, "Interface is not IP enabled") \
754 
755 typedef enum
756 {
757 #define _(sym,string) ETHERNET_ARP_ERROR_##sym,
759 #undef _
762 
763 
764 static void
766 {
769  vnet_main_t *vnm = vnet_get_main ();
770  ethernet_arp_ip4_over_ethernet_address_t delme;
771  u32 index;
772 
774  am->arp_delete_rotor = index;
775 
776  /* Try again from elt 0, could happen if an intfc goes down */
777  if (index == ~0)
778  {
780  am->arp_delete_rotor = index;
781  }
782 
783  /* Nothing left in the pool */
784  if (index == ~0)
785  return;
786 
787  e = pool_elt_at_index (am->ip4_entry_pool, index);
788 
789  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
790  delme.ip4.as_u32 = e->ip4_address.as_u32;
791 
793 }
794 
795 static int
797  u32 pi0, ethernet_header_t * eth0, u32 sw_if_index)
798 {
799  vlib_main_t *vm = vlib_get_main ();
800  vnet_main_t *vnm = vnet_get_main ();
804  u32 unnum_src_sw_if_index;
805  u32 *broadcast_swifs = 0;
806  u32 *buffers = 0;
807  u32 n_alloc = 0;
808  vlib_buffer_t *b0;
809  int i;
810  u8 dst_mac_address[6];
811  i16 header_size;
812  ethernet_arp_header_t *arp0;
813 
814  /* Save the dst mac address */
815  clib_memcpy (dst_mac_address, eth0->dst_address, sizeof (dst_mac_address));
816 
817  /* Figure out which sw_if_index supplied the address */
818  unnum_src_sw_if_index = sw_if_index;
819 
820  /* Track down all users of the unnumbered source */
821  /* *INDENT-OFF* */
822  pool_foreach (si, vim->sw_interfaces,
823  ({
824  if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
825  (si->unnumbered_sw_if_index == unnum_src_sw_if_index))
826  {
827  vec_add1 (broadcast_swifs, si->sw_if_index);
828  }
829  }));
830  /* *INDENT-ON* */
831 
832  /* If there are no interfaces un-unmbered to this interface,
833  we are done here. */
834  if (0 == vec_len (broadcast_swifs))
835  return 0;
836 
837  /* Allocate buffering if we need it */
838  if (vec_len (broadcast_swifs) > 1)
839  {
840  vec_validate (buffers, vec_len (broadcast_swifs) - 2);
841  n_alloc = vlib_buffer_alloc (vm, buffers, vec_len (buffers));
842  _vec_len (buffers) = n_alloc;
843  for (i = 0; i < n_alloc; i++)
844  {
845  b0 = vlib_get_buffer (vm, buffers[i]);
846 
847  /* xerox (partially built) ARP pkt */
848  clib_memcpy (b0->data, p0->data,
849  p0->current_length + p0->current_data);
850  b0->current_data = p0->current_data;
851  b0->current_length = p0->current_length;
852  vnet_buffer (b0)->sw_if_index[VLIB_RX] =
853  vnet_buffer (p0)->sw_if_index[VLIB_RX];
854  }
855  }
856 
857  vec_insert (buffers, 1, 0);
858  buffers[0] = pi0;
859 
860  for (i = 0; i < vec_len (buffers); i++)
861  {
862  b0 = vlib_get_buffer (vm, buffers[i]);
863  arp0 = vlib_buffer_get_current (b0);
864 
865  hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[i]);
866  si = vnet_get_sw_interface (vnm, broadcast_swifs[i]);
867 
868  /* For decoration, most likely */
869  vnet_buffer (b0)->sw_if_index[VLIB_TX] = hi->sw_if_index;
870 
871  /* Fix ARP pkt src address */
872  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, hi->hw_address, 6);
873 
874  /* Build L2 encaps for this swif */
875  header_size = sizeof (ethernet_header_t);
876  if (si->sub.eth.flags.one_tag)
877  header_size += 4;
878  else if (si->sub.eth.flags.two_tags)
879  header_size += 8;
880 
881  vlib_buffer_advance (b0, -header_size);
882  eth0 = vlib_buffer_get_current (b0);
883 
884  if (si->sub.eth.flags.one_tag)
885  {
886  ethernet_vlan_header_t *outer = (void *) (eth0 + 1);
887 
888  eth0->type = si->sub.eth.flags.dot1ad ?
889  clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
890  clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
891  outer->priority_cfi_and_id =
892  clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
893  outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
894 
895  }
896  else if (si->sub.eth.flags.two_tags)
897  {
898  ethernet_vlan_header_t *outer = (void *) (eth0 + 1);
899  ethernet_vlan_header_t *inner = (void *) (outer + 1);
900 
901  eth0->type = si->sub.eth.flags.dot1ad ?
902  clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
903  clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
904  outer->priority_cfi_and_id =
905  clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
906  outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
907  inner->priority_cfi_and_id =
908  clib_host_to_net_u16 (si->sub.eth.inner_vlan_id);
909  inner->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
910 
911  }
912  else
913  {
914  eth0->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
915  }
916 
917  /* Restore the original dst address, set src address */
918  clib_memcpy (eth0->dst_address, dst_mac_address,
919  sizeof (eth0->dst_address));
920  clib_memcpy (eth0->src_address, hi->hw_address,
921  sizeof (eth0->src_address));
922 
923  /* Transmit replicas */
924  if (i > 0)
925  {
926  vlib_frame_t *f =
927  vlib_get_frame_to_node (vm, hi->output_node_index);
928  u32 *to_next = vlib_frame_vector_args (f);
929  to_next[0] = buffers[i];
930  f->n_vectors = 1;
931  vlib_put_frame_to_node (vm, hi->output_node_index, f);
932  }
933  }
934 
935  /* The regular path outputs the original pkt.. */
936  vnet_buffer (p0)->sw_if_index[VLIB_TX] = broadcast_swifs[0];
937 
938  vec_free (broadcast_swifs);
939  vec_free (buffers);
940 
941  return !0;
942 }
943 
944 static uword
946 {
948  vnet_main_t *vnm = vnet_get_main ();
949  ip4_main_t *im4 = &ip4_main;
950  u32 n_left_from, next_index, *from, *to_next;
951  u32 n_replies_sent = 0, n_proxy_arp_replies_sent = 0;
952 
953  from = vlib_frame_vector_args (frame);
954  n_left_from = frame->n_vectors;
955  next_index = node->cached_next_index;
956 
957  if (node->flags & VLIB_NODE_FLAG_TRACE)
958  vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
959  /* stride */ 1,
960  sizeof (ethernet_arp_input_trace_t));
961 
962  while (n_left_from > 0)
963  {
964  u32 n_left_to_next;
965 
966  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
967 
968  while (n_left_from > 0 && n_left_to_next > 0)
969  {
970  vlib_buffer_t *p0;
971  vnet_hw_interface_t *hw_if0;
972  ethernet_arp_header_t *arp0;
973  ethernet_header_t *eth0;
974  ip_adjacency_t *adj0;
975  ip4_address_t *if_addr0, proxy_src;
976  u32 pi0, error0, next0, sw_if_index0, conn_sw_if_index0, fib_index0;
977  u8 is_request0, dst_is_local0, is_unnum0;
979  fib_node_index_t dst_fei, src_fei;
980  fib_prefix_t pfx0;
981  fib_entry_flag_t src_flags, dst_flags;
982 
983  pi0 = from[0];
984  to_next[0] = pi0;
985  from += 1;
986  to_next += 1;
987  n_left_from -= 1;
988  n_left_to_next -= 1;
989  pa = 0;
990 
991  p0 = vlib_get_buffer (vm, pi0);
992  arp0 = vlib_buffer_get_current (p0);
993 
994  is_request0 = arp0->opcode
995  == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
996 
997  error0 = ETHERNET_ARP_ERROR_replies_sent;
998 
999  error0 =
1000  (arp0->l2_type !=
1001  clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ?
1002  ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
1003  error0 =
1004  (arp0->l3_type !=
1005  clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
1006  ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
1007 
1008  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1009 
1010  /* not playing the ARP game if the interface is not IPv4 enabled */
1011  error0 =
1012  (im4->ip_enabled_by_sw_if_index[sw_if_index0] == 0 ?
1013  ETHERNET_ARP_ERROR_interface_not_ip_enabled : error0);
1014 
1015  if (error0)
1016  goto drop2;
1017 
1018  /* Check that IP address is local and matches incoming interface. */
1019  fib_index0 = ip4_fib_table_get_index_for_sw_if_index (sw_if_index0);
1020  if (~0 == fib_index0)
1021  {
1022  error0 = ETHERNET_ARP_ERROR_interface_no_table;
1023  goto drop2;
1024 
1025  }
1026  dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1027  &arp0->ip4_over_ethernet[1].ip4,
1028  32);
1029  dst_flags = fib_entry_get_flags_for_source (dst_fei,
1031 
1032  conn_sw_if_index0 =
1035 
1036  if (!(FIB_ENTRY_FLAG_CONNECTED & dst_flags))
1037  {
1038  error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
1039  goto drop1;
1040  }
1041 
1042  /* Honor unnumbered interface, if any */
1043  is_unnum0 = sw_if_index0 != conn_sw_if_index0;
1044 
1045  /* Source must also be local to subnet of matching interface address. */
1046  src_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
1047  &arp0->ip4_over_ethernet[0].ip4,
1048  32);
1049  src_flags = fib_entry_get_flags (src_fei);
1050 
1051  if (!((FIB_ENTRY_FLAG_ATTACHED & src_flags) ||
1052  (FIB_ENTRY_FLAG_CONNECTED & src_flags)))
1053  {
1054  /*
1055  * The packet was sent from an address that is not connected nor attached
1056  * i.e. it is not from an address that is covered by a link's sub-net,
1057  * nor is it a already learned host resp.
1058  */
1059  error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
1060  goto drop2;
1061  }
1062  if (sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
1063  {
1064  /*
1065  * The interface the ARP was received on is not the interface
1066  * on which the covering prefix is configured. Maybe this is a case
1067  * for unnumbered.
1068  */
1069  is_unnum0 = 1;
1070  }
1071 
1072  /* Reject requests/replies with our local interface address. */
1073  if (FIB_ENTRY_FLAG_LOCAL & src_flags)
1074  {
1075  error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
1076  goto drop2;
1077  }
1078 
1079  dst_is_local0 = (FIB_ENTRY_FLAG_LOCAL & dst_flags);
1080  fib_entry_get_prefix (dst_fei, &pfx0);
1081  if_addr0 = &pfx0.fp_addr.ip4;
1082 
1083  /* Fill in ethernet header. */
1084  eth0 = ethernet_buffer_get_header (p0);
1085 
1086  /* Trash ARP packets whose ARP-level source addresses do not
1087  match their L2-frame-level source addresses */
1088  if (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
1089  sizeof (eth0->src_address)))
1090  {
1091  error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1092  goto drop2;
1093  }
1094 
1095  /* Learn or update sender's mapping only for requests or unicasts
1096  that don't match local interface address. */
1097  if (ethernet_address_cast (eth0->dst_address) ==
1098  ETHERNET_ADDRESS_UNICAST || is_request0)
1099  {
1100  if (am->limit_arp_cache_size &&
1103 
1104  vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index0,
1105  &arp0->ip4_over_ethernet[0],
1106  0 /* is_static */ );
1107  error0 = ETHERNET_ARP_ERROR_l3_src_address_learned;
1108  }
1109 
1110  /* Only send a reply for requests sent which match a local interface. */
1111  if (!(is_request0 && dst_is_local0))
1112  {
1113  error0 =
1114  (arp0->opcode ==
1115  clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply) ?
1116  ETHERNET_ARP_ERROR_replies_received : error0);
1117  goto drop1;
1118  }
1119 
1120  /* Send a reply. */
1121  send_reply:
1122  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1123  hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1124 
1125  /* Send reply back through input interface */
1126  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1127  next0 = ARP_INPUT_NEXT_REPLY_TX;
1128 
1129  arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1130 
1131  arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1132 
1133  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet,
1134  hw_if0->hw_address, 6);
1135  clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) =
1136  if_addr0->data_u32;
1137 
1138  /* Hardware must be ethernet-like. */
1139  ASSERT (vec_len (hw_if0->hw_address) == 6);
1140 
1141  clib_memcpy (eth0->dst_address, eth0->src_address, 6);
1142  clib_memcpy (eth0->src_address, hw_if0->hw_address, 6);
1143 
1144  /* Figure out how much to rewind current data from adjacency. */
1145  /* get the adj from the destination's covering connected */
1146  if (NULL == pa)
1147  {
1148  adj0 =
1151  (ip4_fib_get (fib_index0),
1152  &arp0->ip4_over_ethernet[1].ip4, 31),
1155  {
1156  error0 = ETHERNET_ARP_ERROR_missing_interface_address;
1157  goto drop2;
1158  }
1159  if (is_unnum0)
1160  {
1161  if (!arp_unnumbered (p0, pi0, eth0, conn_sw_if_index0))
1162  goto drop2;
1163  }
1164  else
1165  vlib_buffer_advance (p0, -adj0->rewrite_header.data_bytes);
1166  }
1167  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1168  n_left_to_next, pi0, next0);
1169 
1170  n_replies_sent += 1;
1171  continue;
1172 
1173  drop1:
1174  if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1175  (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1176  arp0->ip4_over_ethernet[1].ip4.as_u32))
1177  {
1178  error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1179  goto drop2;
1180  }
1181  /* See if proxy arp is configured for the address */
1182  if (is_request0)
1183  {
1184  vnet_sw_interface_t *si;
1185  u32 this_addr = clib_net_to_host_u32
1186  (arp0->ip4_over_ethernet[1].ip4.as_u32);
1187  u32 fib_index0;
1188 
1189  si = vnet_get_sw_interface (vnm, sw_if_index0);
1190 
1192  goto drop2;
1193 
1194  fib_index0 = vec_elt (im4->fib_index_by_sw_if_index,
1195  sw_if_index0);
1196 
1197  vec_foreach (pa, am->proxy_arps)
1198  {
1199  u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
1200  u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
1201 
1202  /* an ARP request hit in the proxy-arp table? */
1203  if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1204  (fib_index0 == pa->fib_index))
1205  {
1206  eth0 = ethernet_buffer_get_header (p0);
1207  proxy_src.as_u32 =
1208  arp0->ip4_over_ethernet[1].ip4.data_u32;
1209 
1210  /*
1211  * Rewind buffer, direct code above not to
1212  * think too hard about it.
1213  */
1214  if_addr0 = &proxy_src;
1215  is_unnum0 = 0;
1216  i32 ethernet_start =
1217  vnet_buffer (p0)->ethernet.start_of_ethernet_header;
1218  i32 rewind = p0->current_data - ethernet_start;
1219  vlib_buffer_advance (p0, -rewind);
1220  n_proxy_arp_replies_sent++;
1221  goto send_reply;
1222  }
1223  }
1224  }
1225 
1226  drop2:
1227 
1228  next0 = ARP_INPUT_NEXT_DROP;
1229  p0->error = node->errors[error0];
1230 
1231  vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1232  n_left_to_next, pi0, next0);
1233  }
1234 
1235  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1236  }
1237 
1238  vlib_error_count (vm, node->node_index,
1239  ETHERNET_ARP_ERROR_replies_sent,
1240  n_replies_sent - n_proxy_arp_replies_sent);
1241 
1242  vlib_error_count (vm, node->node_index,
1243  ETHERNET_ARP_ERROR_proxy_arp_replies_sent,
1244  n_proxy_arp_replies_sent);
1245  return frame->n_vectors;
1246 }
1247 
1248 static char *ethernet_arp_error_strings[] = {
1249 #define _(sym,string) string,
1251 #undef _
1252 };
1253 
1254 /* *INDENT-OFF* */
1256 {
1257  .function = arp_input,
1258  .name = "arp-input",
1259  .vector_size = sizeof (u32),
1260  .n_errors = ETHERNET_ARP_N_ERROR,
1261  .error_strings = ethernet_arp_error_strings,
1262  .n_next_nodes = ARP_INPUT_N_NEXT,
1263  .next_nodes = {
1264  [ARP_INPUT_NEXT_DROP] = "error-drop",
1265  [ARP_INPUT_NEXT_REPLY_TX] = "interface-output",
1266  },
1267  .format_buffer = format_ethernet_arp_header,
1268  .format_trace = format_ethernet_arp_input_trace,
1269 };
1270 /* *INDENT-ON* */
1271 
1272 static int
1273 ip4_arp_entry_sort (void *a1, void *a2)
1274 {
1275  ethernet_arp_ip4_entry_t *e1 = a1;
1276  ethernet_arp_ip4_entry_t *e2 = a2;
1277 
1278  int cmp;
1279  vnet_main_t *vnm = vnet_get_main ();
1280 
1281  cmp = vnet_sw_interface_compare (vnm, e1->sw_if_index, e2->sw_if_index);
1282  if (!cmp)
1283  cmp = ip4_address_compare (&e1->ip4_address, &e2->ip4_address);
1284  return cmp;
1285 }
1286 
1289 {
1291  ethernet_arp_ip4_entry_t *n, *ns = 0;
1292 
1293  /* *INDENT-OFF* */
1294  pool_foreach (n, am->ip4_entry_pool, ({
1295  if (sw_if_index != ~0 && n->sw_if_index != sw_if_index)
1296  continue;
1297  vec_add1 (ns, n[0]);
1298  }));
1299  /* *INDENT-ON* */
1300 
1301  if (ns)
1303  return ns;
1304 }
1305 
1306 static clib_error_t *
1308  unformat_input_t * input, vlib_cli_command_t * cmd)
1309 {
1310  vnet_main_t *vnm = vnet_get_main ();
1312  ethernet_arp_ip4_entry_t *e, *es;
1314  clib_error_t *error = 0;
1315  u32 sw_if_index;
1316 
1317  /* Filter entries by interface if given. */
1318  sw_if_index = ~0;
1319  (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1320 
1321  es = ip4_neighbor_entries (sw_if_index);
1322  if (es)
1323  {
1324  vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1325  vec_foreach (e, es)
1326  {
1327  vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1328  }
1329  vec_free (es);
1330  }
1331 
1332  if (vec_len (am->proxy_arps))
1333  {
1334  vlib_cli_output (vm, "Proxy arps enabled for:");
1335  vec_foreach (pa, am->proxy_arps)
1336  {
1337  vlib_cli_output (vm, "Fib_index %d %U - %U ",
1338  pa->fib_index,
1340  format_ip4_address, &pa->hi_addr);
1341  }
1342  }
1343 
1344  return error;
1345 }
1346 
1347 /*?
1348  * Display all the IPv4 ARP entries.
1349  *
1350  * @cliexpar
1351  * Example of how to display the IPv4 ARP table:
1352  * @cliexstart{show ip arp}
1353  * Time FIB IP4 Flags Ethernet Interface
1354  * 346.3028 0 6.1.1.3 de:ad:be:ef:ba:be GigabitEthernet2/0/0
1355  * 3077.4271 0 6.1.1.4 S de:ad:be:ef:ff:ff GigabitEthernet2/0/0
1356  * 2998.6409 1 6.2.2.3 de:ad:be:ef:00:01 GigabitEthernet2/0/0
1357  * Proxy arps enabled for:
1358  * Fib_index 0 6.0.0.1 - 6.0.0.11
1359  * @cliexend
1360  ?*/
1361 /* *INDENT-OFF* */
1363  .path = "show ip arp",
1364  .function = show_ip4_arp,
1365  .short_help = "show ip arp",
1366 };
1367 /* *INDENT-ON* */
1368 
1369 typedef struct
1370 {
1371  pg_edit_t l2_type, l3_type;
1372  pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1374  struct
1375  {
1378  } ip4_over_ethernet[2];
1380 
1381 static inline void
1383 {
1384  /* Initialize fields that are not bit fields in the IP header. */
1385 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1386  _(l2_type);
1387  _(l3_type);
1388  _(n_l2_address_bytes);
1389  _(n_l3_address_bytes);
1390  _(opcode);
1391  _(ip4_over_ethernet[0].ethernet);
1392  _(ip4_over_ethernet[0].ip4);
1393  _(ip4_over_ethernet[1].ethernet);
1394  _(ip4_over_ethernet[1].ip4);
1395 #undef _
1396 }
1397 
1398 uword
1399 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1400 {
1401  pg_stream_t *s = va_arg (*args, pg_stream_t *);
1403  u32 group_index;
1404 
1405  p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1406  &group_index);
1408 
1409  /* Defaults. */
1410  pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1411  pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1414 
1415  if (!unformat (input, "%U: %U/%U -> %U/%U",
1426  {
1427  /* Free up any edits we may have added. */
1428  pg_free_edit_group (s);
1429  return 0;
1430  }
1431  return 1;
1432 }
1433 
1434 clib_error_t *
1436 {
1438 
1439  am->limit_arp_cache_size = arp_limit;
1440  return 0;
1441 }
1442 
1443 /**
1444  * @brief Control Plane hook to remove an ARP entry
1445  */
1446 int
1448  u32 sw_if_index, void *a_arg)
1449 {
1450  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1452 
1453  args.sw_if_index = sw_if_index;
1455  clib_memcpy (&args.a, a, sizeof (*a));
1456 
1458  (u8 *) & args, sizeof (args));
1459  return 0;
1460 }
1461 
1462 /**
1463  * @brief Internally generated event to flush the ARP cache on an
1464  * interface state change event.
1465  * A flush will remove dynamic ARP entries, and for statics remove the MAC
1466  * address from the corresponding adjacencies.
1467  */
1468 static int
1470  u32 sw_if_index, void *a_arg)
1471 {
1472  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1474 
1475  args.sw_if_index = sw_if_index;
1477  clib_memcpy (&args.a, a, sizeof (*a));
1478 
1480  (u8 *) & args, sizeof (args));
1481  return 0;
1482 }
1483 
1484 /**
1485  * @brief Internally generated event to populate the ARP cache on an
1486  * interface state change event.
1487  * For static entries this will re-source the adjacencies.
1488  *
1489  * @param sw_if_index The interface on which the ARP entires are acted
1490  */
1491 static int
1493  u32 sw_if_index, void *a_arg)
1494 {
1495  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1497 
1498  args.sw_if_index = sw_if_index;
1500  clib_memcpy (&args.a, a, sizeof (*a));
1501 
1503  (u8 *) & args, sizeof (args));
1504  return 0;
1505 }
1506 
1507 /*
1508  * arp_add_del_interface_address
1509  *
1510  * callback when an interface address is added or deleted
1511  */
1512 static void
1514  uword opaque,
1515  u32 sw_if_index,
1516  ip4_address_t * address,
1517  u32 address_length,
1518  u32 if_address_index, u32 is_del)
1519 {
1520  /*
1521  * Flush the ARP cache of all entries covered by the address
1522  * that is being removed.
1523  */
1526 
1527  if (vec_len (am->ethernet_arp_by_sw_if_index) <= sw_if_index)
1528  return;
1529 
1530  if (is_del)
1531  {
1533  u32 i, *to_delete = 0;
1534  hash_pair_t *pair;
1535 
1536  eai = &am->ethernet_arp_by_sw_if_index[sw_if_index];
1537 
1538  /* *INDENT-OFF* */
1539  hash_foreach_pair (pair, eai->arp_entries,
1540  ({
1541  e = pool_elt_at_index(am->ip4_entry_pool,
1542  pair->value[0]);
1543  if (ip4_destination_matches_route (im, &e->ip4_address,
1544  address, address_length))
1545  {
1546  vec_add1 (to_delete, e - am->ip4_entry_pool);
1547  }
1548  }));
1549  /* *INDENT-ON* */
1550 
1551  for (i = 0; i < vec_len (to_delete); i++)
1552  {
1553  ethernet_arp_ip4_over_ethernet_address_t delme;
1554  e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1555 
1556  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1557  delme.ip4.as_u32 = e->ip4_address.as_u32;
1558 
1560  e->sw_if_index, &delme);
1561  }
1562 
1563  vec_free (to_delete);
1564  }
1565 }
1566 
1567 static clib_error_t *
1569 {
1571  ip4_main_t *im = &ip4_main;
1572  clib_error_t *error;
1573  pg_node_t *pn;
1574 
1575  if ((error = vlib_call_init_function (vm, ethernet_init)))
1576  return error;
1577 
1578  ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
1579 
1580  pn = pg_get_node (arp_input_node.index);
1582 
1583  am->opcode_by_name = hash_create_string (0, sizeof (uword));
1584 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
1586 #undef _
1587 
1588  /* $$$ configurable */
1589  am->limit_arp_cache_size = 50000;
1590 
1591  am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
1592  am->mac_changes_by_address = hash_create (0, sizeof (uword));
1593 
1594  /* don't trace ARP error packets */
1595  {
1596  vlib_node_runtime_t *rt =
1598 
1599 #define _(a,b) \
1600  vnet_pcap_drop_trace_filter_add_del \
1601  (rt->errors[ETHERNET_ARP_ERROR_##a], \
1602  1 /* is_add */);
1604 #undef _
1605  }
1606 
1609  cb.function_opaque = 0;
1611 
1612  return 0;
1613 }
1614 
1616 
1617 static void
1619 {
1621 
1624  pool_put (am->ip4_entry_pool, e);
1625 }
1626 
1627 static inline int
1630  * args)
1631 {
1635 
1636  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1637 
1638  e = arp_entry_find (eai, &args->a.ip4);
1639 
1640  if (NULL != e)
1641  {
1642  arp_entry_free (eai, e);
1643 
1646  }
1647 
1648  return 0;
1649 }
1650 
1651 static int
1654  * args)
1655 {
1659 
1660  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1661 
1662  e = arp_entry_find (eai, &args->a.ip4);
1663 
1664  if (NULL != e)
1665  {
1668 
1669  /*
1670  * The difference between flush and unset, is that an unset
1671  * means delete for static and dynamic entries. A flush
1672  * means delete only for dynamic. Flushing is what the DP
1673  * does in response to interface events. unset is only done
1674  * by the control plane.
1675  */
1677  {
1678  arp_entry_free (eai, e);
1679  }
1680  }
1681  return (0);
1682 }
1683 
1684 static int
1687  * args)
1688 {
1692 
1693  eai = &am->ethernet_arp_by_sw_if_index[args->sw_if_index];
1694 
1695  e = arp_entry_find (eai, &args->a.ip4);
1696 
1697  if (NULL != e)
1698  {
1701  }
1702  return (0);
1703 }
1704 
1705 static void
1707  * a)
1708 {
1709  vnet_main_t *vm = vnet_get_main ();
1710  ASSERT (os_get_cpu_number () == 0);
1711 
1714  else if (a->flags & ETHERNET_ARP_ARGS_FLUSH)
1716  else if (a->flags & ETHERNET_ARP_ARGS_POPULATE)
1718  else
1720 }
1721 
1722 /**
1723  * @brief Invoked when the interface's admin state changes
1724  */
1725 static clib_error_t *
1727  u32 sw_if_index, u32 flags)
1728 {
1731  u32 i, *to_delete = 0;
1732 
1733  /* *INDENT-OFF* */
1734  pool_foreach (e, am->ip4_entry_pool,
1735  ({
1736  if (e->sw_if_index == sw_if_index)
1737  vec_add1 (to_delete,
1738  e - am->ip4_entry_pool);
1739  }));
1740  /* *INDENT-ON* */
1741 
1742  for (i = 0; i < vec_len (to_delete); i++)
1743  {
1744  ethernet_arp_ip4_over_ethernet_address_t delme;
1745  e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
1746 
1747  clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
1748  delme.ip4.as_u32 = e->ip4_address.as_u32;
1749 
1750  if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
1751  {
1753  }
1754  else
1755  {
1757  }
1758 
1759  }
1760  vec_free (to_delete);
1761 
1762  return 0;
1763 }
1764 
1766 
1767 static void
1768 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t * a)
1769 {
1770  u8 old;
1771  int i;
1772 
1773  for (i = 3; i >= 0; i--)
1774  {
1775  old = a->ip4.as_u8[i];
1776  a->ip4.as_u8[i] += 1;
1777  if (old < a->ip4.as_u8[i])
1778  break;
1779  }
1780 
1781  for (i = 5; i >= 0; i--)
1782  {
1783  old = a->ethernet[i];
1784  a->ethernet[i] += 1;
1785  if (old < a->ethernet[i])
1786  break;
1787  }
1788 }
1789 
1790 int
1792  u32 sw_if_index, void *a_arg, int is_static)
1793 {
1794  ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1796 
1797  args.sw_if_index = sw_if_index;
1798  args.is_static = is_static;
1799  args.flags = 0;
1800  clib_memcpy (&args.a, a, sizeof (*a));
1801 
1803  (u8 *) & args, sizeof (args));
1804  return 0;
1805 }
1806 
1807 int
1809  ip4_address_t * hi_addr, u32 fib_index, int is_del)
1810 {
1813  u32 found_at_index = ~0;
1814 
1815  vec_foreach (pa, am->proxy_arps)
1816  {
1817  if (pa->lo_addr == lo_addr->as_u32
1818  && pa->hi_addr == hi_addr->as_u32 && pa->fib_index == fib_index)
1819  {
1820  found_at_index = pa - am->proxy_arps;
1821  break;
1822  }
1823  }
1824 
1825  if (found_at_index != ~0)
1826  {
1827  /* Delete, otherwise it's already in the table */
1828  if (is_del)
1829  vec_delete (am->proxy_arps, 1, found_at_index);
1830  return 0;
1831  }
1832  /* delete, no such entry */
1833  if (is_del)
1834  return VNET_API_ERROR_NO_SUCH_ENTRY;
1835 
1836  /* add, not in table */
1837  vec_add2 (am->proxy_arps, pa, 1);
1838  pa->lo_addr = lo_addr->as_u32;
1839  pa->hi_addr = hi_addr->as_u32;
1840  pa->fib_index = fib_index;
1841  return 0;
1842 }
1843 
1844 /*
1845  * Remove any proxy arp entries asdociated with the
1846  * specificed fib.
1847  */
1848 int
1850 {
1851  ip4_main_t *im = &ip4_main;
1854  u32 *entries_to_delete = 0;
1855  u32 fib_index;
1856  uword *p;
1857  int i;
1858 
1859  p = hash_get (im->fib_index_by_table_id, fib_id);
1860  if (!p)
1861  return VNET_API_ERROR_NO_SUCH_ENTRY;
1862  fib_index = p[0];
1863 
1864  vec_foreach (pa, am->proxy_arps)
1865  {
1866  if (pa->fib_index == fib_index)
1867  {
1868  vec_add1 (entries_to_delete, pa - am->proxy_arps);
1869  }
1870  }
1871 
1872  for (i = 0; i < vec_len (entries_to_delete); i++)
1873  {
1874  vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
1875  }
1876 
1877  vec_free (entries_to_delete);
1878 
1879  return 0;
1880 }
1881 
1882 static clib_error_t *
1884  unformat_input_t * input, vlib_cli_command_t * cmd)
1885 {
1886  vnet_main_t *vnm = vnet_get_main ();
1887  u32 sw_if_index;
1888  ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
1889  int addr_valid = 0;
1890  int is_del = 0;
1891  int count = 1;
1892  u32 fib_index = 0;
1893  u32 fib_id;
1894  int is_static = 0;
1895  int is_proxy = 0;
1896 
1897  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1898  {
1899  /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
1900  if (unformat (input, "%U %U %U",
1901  unformat_vnet_sw_interface, vnm, &sw_if_index,
1902  unformat_ip4_address, &addr.ip4,
1903  unformat_ethernet_address, &addr.ethernet))
1904  addr_valid = 1;
1905 
1906  else if (unformat (input, "delete") || unformat (input, "del"))
1907  is_del = 1;
1908 
1909  else if (unformat (input, "static"))
1910  is_static = 1;
1911 
1912  else if (unformat (input, "count %d", &count))
1913  ;
1914 
1915  else if (unformat (input, "fib-id %d", &fib_id))
1916  {
1917  ip4_main_t *im = &ip4_main;
1918  uword *p = hash_get (im->fib_index_by_table_id, fib_id);
1919  if (!p)
1920  return clib_error_return (0, "fib ID %d doesn't exist\n", fib_id);
1921  fib_index = p[0];
1922  }
1923 
1924  else if (unformat (input, "proxy %U - %U",
1925  unformat_ip4_address, &lo_addr.ip4,
1926  unformat_ip4_address, &hi_addr.ip4))
1927  is_proxy = 1;
1928  else
1929  break;
1930  }
1931 
1932  if (is_proxy)
1933  {
1934  (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4,
1935  fib_index, is_del);
1936  return 0;
1937  }
1938 
1939  if (addr_valid)
1940  {
1941  int i;
1942 
1943  for (i = 0; i < count; i++)
1944  {
1945  if (is_del == 0)
1946  {
1947  uword event_type, *event_data = 0;
1948 
1949  /* Park the debug CLI until the arp entry is installed */
1951  (vnm, &addr.ip4, vlib_current_process (vm),
1952  1 /* type */ , 0 /* data */ );
1953 
1955  (vnm, sw_if_index, &addr, is_static);
1956 
1958  event_type = vlib_process_get_events (vm, &event_data);
1959  vec_reset_length (event_data);
1960  if (event_type != 1)
1961  clib_warning ("event type %d unexpected", event_type);
1962  }
1963  else
1964  vnet_arp_unset_ip4_over_ethernet (vnm, sw_if_index, &addr);
1965 
1967  }
1968  }
1969  else
1970  {
1971  return clib_error_return (0, "unknown input `%U'",
1972  format_unformat_error, input);
1973  }
1974 
1975  return 0;
1976 }
1977 
1978 /* *INDENT-OFF* */
1979 /*?
1980  * Add or delete IPv4 ARP cache entries.
1981  *
1982  * @note 'set ip arp' options (e.g. delete, static, 'fib-id <id>',
1983  * 'count <number>', 'interface ip4_addr mac_addr') can be added in
1984  * any order and combination.
1985  *
1986  * @cliexpar
1987  * @parblock
1988  * Add or delete IPv4 ARP cache entries as follows. MAC Address can be in
1989  * either aa:bb:cc:dd:ee:ff format or aabb.ccdd.eeff format.
1990  * @cliexcmd{set ip arp GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1991  * @cliexcmd{set ip arp delete GigabitEthernet2/0/0 6.0.0.3 de:ad:be:ef:ba:be}
1992  *
1993  * To add or delete an IPv4 ARP cache entry to or from a specific fib
1994  * table:
1995  * @cliexcmd{set ip arp fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1996  * @cliexcmd{set ip arp fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
1997  *
1998  * Add or delete IPv4 static ARP cache entries as follows:
1999  * @cliexcmd{set ip arp static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2000  * @cliexcmd{set ip arp static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2001  *
2002  * For testing / debugging purposes, the 'set ip arp' command can add or
2003  * delete multiple entries. Supply the 'count N' parameter:
2004  * @cliexcmd{set ip arp count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe}
2005  * @endparblock
2006  ?*/
2008  .path = "set ip arp",
2009  .short_help =
2010  "set ip arp [del] <intfc> <ip-address> <mac-address> [static] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
2011  .function = ip_arp_add_del_command_fn,
2012 };
2013 /* *INDENT-ON* */
2014 
2015 static clib_error_t *
2018  input, vlib_cli_command_t * cmd)
2019 {
2020  vnet_main_t *vnm = vnet_get_main ();
2021  u32 sw_if_index;
2022  vnet_sw_interface_t *si;
2023  int enable = 0;
2024  int intfc_set = 0;
2025 
2026  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2027  {
2028  if (unformat (input, "%U", unformat_vnet_sw_interface,
2029  vnm, &sw_if_index))
2030  intfc_set = 1;
2031  else if (unformat (input, "enable") || unformat (input, "on"))
2032  enable = 1;
2033  else if (unformat (input, "disable") || unformat (input, "off"))
2034  enable = 0;
2035  else
2036  break;
2037  }
2038 
2039  if (intfc_set == 0)
2040  return clib_error_return (0, "unknown input '%U'",
2041  format_unformat_error, input);
2042 
2043  si = vnet_get_sw_interface (vnm, sw_if_index);
2044  ASSERT (si);
2045  if (enable)
2047  else
2049 
2050  return 0;
2051 }
2052 
2053 /* *INDENT-OFF* */
2054 /*?
2055  * Enable proxy-arp on an interface. The vpp stack will answer ARP
2056  * requests for the indicated address range. Multiple proxy-arp
2057  * ranges may be provisioned.
2058  *
2059  * @note Proxy ARP as a technology is infamous for blackholing traffic.
2060  * Also, the underlying implementation has not been performance-tuned.
2061  * Avoid creating an unnecessarily large set of ranges.
2062  *
2063  * @cliexpar
2064  * To enable proxy arp on a range of addresses, use:
2065  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11}
2066  * Append 'del' to delete a range of proxy ARP addresses:
2067  * @cliexcmd{set ip arp proxy 6.0.0.1 - 6.0.0.11 del}
2068  * You must then specifically enable proxy arp on individual interfaces:
2069  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 enable}
2070  * To disable proxy arp on an individual interface:
2071  * @cliexcmd{set interface proxy-arp GigabitEthernet0/8/0 disable}
2072  ?*/
2074  .path = "set interface proxy-arp",
2075  .short_help =
2076  "set interface proxy-arp <intfc> [enable|disable]",
2077  .function = set_int_proxy_arp_command_fn,
2078 };
2079 /* *INDENT-ON* */
2080 
2081 
2082 /*
2083  * ARP/ND Termination in a L2 Bridge Domain based on IP4/IP6 to MAC
2084  * hash tables mac_by_ip4 and mac_by_ip6 for each BD.
2085  */
2086 typedef enum
2087 {
2091 } arp_term_next_t;
2092 
2094 
2095 static uword
2097  vlib_node_runtime_t * node, vlib_frame_t * frame)
2098 {
2099  l2input_main_t *l2im = &l2input_main;
2100  u32 n_left_from, next_index, *from, *to_next;
2101  u32 n_replies_sent = 0;
2102  u16 last_bd_index = ~0;
2103  l2_bridge_domain_t *last_bd_config = 0;
2104  l2_input_config_t *cfg0;
2105 
2106  from = vlib_frame_vector_args (frame);
2107  n_left_from = frame->n_vectors;
2108  next_index = node->cached_next_index;
2109 
2110  while (n_left_from > 0)
2111  {
2112  u32 n_left_to_next;
2113 
2114  vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
2115 
2116  while (n_left_from > 0 && n_left_to_next > 0)
2117  {
2118  vlib_buffer_t *p0;
2119  ethernet_header_t *eth0;
2120  ethernet_arp_header_t *arp0;
2121  ip6_header_t *iph0;
2122  u8 *l3h0;
2123  u32 pi0, error0, next0, sw_if_index0;
2124  u16 ethertype0;
2125  u16 bd_index0;
2126  u32 ip0;
2127  u8 *macp0;
2128 
2129  pi0 = from[0];
2130  to_next[0] = pi0;
2131  from += 1;
2132  to_next += 1;
2133  n_left_from -= 1;
2134  n_left_to_next -= 1;
2135 
2136  p0 = vlib_get_buffer (vm, pi0);
2137  eth0 = vlib_buffer_get_current (p0);
2138  l3h0 = (u8 *) eth0 + vnet_buffer (p0)->l2.l2_len;
2139  ethertype0 = clib_net_to_host_u16 (*(u16 *) (l3h0 - 2));
2140  arp0 = (ethernet_arp_header_t *) l3h0;
2141 
2142  if (PREDICT_FALSE ((ethertype0 != ETHERNET_TYPE_ARP) ||
2143  (arp0->opcode !=
2144  clib_host_to_net_u16
2145  (ETHERNET_ARP_OPCODE_request))))
2146  goto check_ip6_nd;
2147 
2148  /* Must be ARP request packet here */
2149  if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
2150  (p0->flags & VLIB_BUFFER_IS_TRACED)))
2151  {
2152  u8 *t0 = vlib_add_trace (vm, node, p0,
2153  sizeof (ethernet_arp_input_trace_t));
2154  clib_memcpy (t0, l3h0, sizeof (ethernet_arp_input_trace_t));
2155  }
2156 
2157  error0 = ETHERNET_ARP_ERROR_replies_sent;
2158  error0 =
2159  (arp0->l2_type !=
2160  clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
2161  ? ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
2162  error0 =
2163  (arp0->l3_type !=
2164  clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
2165  ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
2166 
2167  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2168 
2169  if (error0)
2170  goto drop;
2171 
2172  /* Trash ARP packets whose ARP-level source addresses do not
2173  match their L2-frame-level source addresses */
2174  if (PREDICT_FALSE
2175  (memcmp
2176  (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
2177  sizeof (eth0->src_address))))
2178  {
2179  error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
2180  goto drop;
2181  }
2182 
2183  /* Check if anyone want ARP request events for L2 BDs */
2184  {
2187  uword *p = hash_get (am->mac_changes_by_address, 0);
2188  if (p && (vnet_buffer (p0)->l2.shg == 0))
2189  { // Only SHG 0 interface which is more likely local
2190  u32 next_index = p[0];
2191  while (next_index != (u32) ~ 0)
2192  {
2193  int (*fp) (u32, u8 *, u32, u32);
2194  int rv = 1;
2195  mc = pool_elt_at_index (am->mac_changes, next_index);
2196  fp = mc->data_callback;
2197  /* Call the callback, return 1 to suppress dup events */
2198  if (fp)
2199  rv = (*fp) (mc->data,
2200  arp0->ip4_over_ethernet[0].ethernet,
2201  sw_if_index0,
2202  arp0->ip4_over_ethernet[0].ip4.as_u32);
2203  /* Signal the resolver process */
2204  if (rv == 0)
2206  mc->type_opaque, mc->data);
2207  next_index = mc->next_index;
2208  }
2209  }
2210  }
2211 
2212  /* lookup BD mac_by_ip4 hash table for MAC entry */
2213  ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
2214  bd_index0 = vnet_buffer (p0)->l2.bd_index;
2215  if (PREDICT_FALSE ((bd_index0 != last_bd_index)
2216  || (last_bd_index == (u16) ~ 0)))
2217  {
2218  last_bd_index = bd_index0;
2219  last_bd_config = vec_elt_at_index (l2im->bd_configs, bd_index0);
2220  }
2221  macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
2222 
2223  if (PREDICT_FALSE (!macp0))
2224  goto next_l2_feature; /* MAC not found */
2225 
2226  /* MAC found, send ARP reply -
2227  Convert ARP request packet to ARP reply */
2228  arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
2229  arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
2230  arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
2231  clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
2232  clib_memcpy (eth0->dst_address, eth0->src_address, 6);
2233  clib_memcpy (eth0->src_address, macp0, 6);
2234  n_replies_sent += 1;
2235 
2236  output_response:
2237  /* For BVI, need to use l2-fwd node to send ARP reply as
2238  l2-output node cannot output packet to BVI properly */
2239  cfg0 = vec_elt_at_index (l2im->configs, sw_if_index0);
2240  if (PREDICT_FALSE (cfg0->bvi))
2241  {
2242  vnet_buffer (p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
2243  vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
2244  goto next_l2_feature;
2245  }
2246 
2247  /* Send ARP/ND reply back out input interface through l2-output */
2248  vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2249  next0 = ARP_TERM_NEXT_L2_OUTPUT;
2250  /* Note that output to VXLAN tunnel will fail due to SHG which
2251  is probably desireable since ARP termination is not intended
2252  for ARP requests from other hosts. If output to VXLAN tunnel is
2253  required, however, can just clear the SHG in packet as follows:
2254  vnet_buffer(p0)->l2.shg = 0; */
2255  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2256  to_next, n_left_to_next, pi0,
2257  next0);
2258  continue;
2259 
2260  check_ip6_nd:
2261  /* IP6 ND event notification or solicitation handling to generate
2262  local response instead of flooding */
2263  iph0 = (ip6_header_t *) l3h0;
2264  if (PREDICT_FALSE (ethertype0 == ETHERNET_TYPE_IP6 &&
2265  iph0->protocol == IP_PROTOCOL_ICMP6 &&
2267  (&iph0->src_address)))
2268  {
2269  sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2270  if (vnet_ip6_nd_term
2271  (vm, node, p0, eth0, iph0, sw_if_index0,
2272  vnet_buffer (p0)->l2.bd_index, vnet_buffer (p0)->l2.shg))
2273  goto output_response;
2274  }
2275 
2276  next_l2_feature:
2277  {
2278  u32 feature_bitmap0 =
2279  vnet_buffer (p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM;
2280  vnet_buffer (p0)->l2.feature_bitmap = feature_bitmap0;
2281  next0 =
2282  feat_bitmap_get_next_node_index (arp_term_next_node_index,
2283  feature_bitmap0);
2284  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2285  to_next, n_left_to_next,
2286  pi0, next0);
2287  continue;
2288  }
2289 
2290  drop:
2291  if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
2292  (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
2293  arp0->ip4_over_ethernet[1].ip4.as_u32))
2294  {
2295  error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
2296  }
2297  next0 = ARP_TERM_NEXT_DROP;
2298  p0->error = node->errors[error0];
2299 
2300  vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
2301  to_next, n_left_to_next, pi0,
2302  next0);
2303  }
2304 
2305  vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2306  }
2307 
2308  vlib_error_count (vm, node->node_index,
2309  ETHERNET_ARP_ERROR_replies_sent, n_replies_sent);
2310  return frame->n_vectors;
2311 }
2312 
2313 /* *INDENT-OFF* */
2315  .function = arp_term_l2bd,
2316  .name = "arp-term-l2bd",
2317  .vector_size = sizeof (u32),
2318  .n_errors = ETHERNET_ARP_N_ERROR,
2319  .error_strings = ethernet_arp_error_strings,
2320  .n_next_nodes = ARP_TERM_N_NEXT,
2321  .next_nodes = {
2322  [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
2323  [ARP_TERM_NEXT_DROP] = "error-drop",
2324  },
2325  .format_buffer = format_ethernet_arp_header,
2326  .format_trace = format_arp_term_input_trace,
2327 };
2328 /* *INDENT-ON* */
2329 
2330 clib_error_t *
2332 {
2333  // Initialize the feature next-node indexes
2335  arp_term_l2bd_node.index,
2338  arp_term_next_node_index);
2339  return 0;
2340 }
2341 
2343 
2344 void
2346 {
2347  if (e->sw_if_index == sw_if_index)
2348  {
2351  }
2352 }
2353 
2354 void
2356 {
2359 
2360  /* *INDENT-OFF* */
2361  pool_foreach (e, am->ip4_entry_pool,
2362  ({
2363  change_arp_mac (sw_if_index, e);
2364  }));
2365  /* *INDENT-ON* */
2366 }
2367 
2368 /*
2369  * fd.io coding-style-patch-verification: ON
2370  *
2371  * Local Variables:
2372  * eval: (c-set-style "gnu")
2373  * End:
2374  */
#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:1706
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:2096
#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:1399
static void pg_ethernet_arp_header_init(pg_ethernet_arp_header_t *p)
Definition: arp.c:1382
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:1628
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:1768
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:1513
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:1307
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:2345
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:2016
clib_error_t * ip4_set_arp_limit(u32 arp_limit)
Definition: arp.c:1435
static uword arp_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
Definition: arp.c:945
#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:1371
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:1376
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:1685
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:1372
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:1273
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:1469
#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:1447
static vlib_cli_command_t ip_arp_add_del_command
(constructor) VLIB_CLI_COMMAND (ip_arp_add_del_command)
Definition: arp.c:2007
#define hash_create_string(elts, value_bytes)
Definition: hash.h:652
pg_edit_t l3_type
Definition: arp.c:1371
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
u8 * ip_enabled_by_sw_if_index
Definition: ip4.h:108
#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:1362
static int arp_unnumbered(vlib_buffer_t *p0, u32 pi0, ethernet_header_t *eth0, u32 sw_if_index)
Definition: arp.c:796
static void unset_random_arp_entry(void)
Definition: arp.c:765
#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:1568
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:1883
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:1372
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:1248
#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:1726
#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:1808
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:1791
clib_error_t * arp_term_init(vlib_main_t *vm)
Definition: arp.c:2331
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:2093
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:2314
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:1255
int vnet_proxy_arp_fib_reset(u32 fib_id)
Definition: arp.c:1849
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:2073
#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:1652
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:1618
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:1373
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
ethernet_arp_input_error_t
Definition: arp.c:755
arp_term_next_t
Definition: arp.c:2086
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:1288
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:1492
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:2355
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:200
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109