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