2 * ethernet/arp.c: IP v4 ARP node
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <vnet/ip/ip.h>
19 #include <vnet/ip/ip6.h>
20 #include <vnet/ethernet/ethernet.h>
21 #include <vnet/ethernet/arp_packet.h>
22 #include <vnet/l2/l2_input.h>
23 #include <vppinfra/mhash.h>
25 void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
31 ip4_address_t ip4_address;
32 } ethernet_arp_ip4_key_t;
36 ethernet_arp_ip4_key_t key;
37 u8 ethernet_address[6];
40 #define ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC (1 << 0)
41 #define ETHERNET_ARP_IP4_ENTRY_FLAG_GLEAN (2 << 0)
43 u64 cpu_time_last_updated;
46 } ethernet_arp_ip4_entry_t;
53 } ethernet_proxy_arp_t;
61 /* Used for arp event notification only */
64 } pending_resolution_t;
68 /* Hash tables mapping name to opcode. */
69 uword *opcode_by_name;
71 /* lite beer "glean" adjacency handling */
72 uword *pending_resolutions_by_address;
73 pending_resolution_t *pending_resolutions;
75 /* Mac address change notification */
76 uword *mac_changes_by_address;
77 pending_resolution_t *mac_changes;
79 ethernet_arp_ip4_entry_t *ip4_entry_pool;
81 mhash_t ip4_entry_by_key;
83 /* ARP attack mitigation */
85 u32 limit_arp_cache_size;
87 /* Proxy arp vector */
88 ethernet_proxy_arp_t *proxy_arps;
89 } ethernet_arp_main_t;
91 static ethernet_arp_main_t ethernet_arp_main;
94 format_ethernet_arp_hardware_type (u8 * s, va_list * va)
96 ethernet_arp_hardware_type_t h = va_arg (*va, ethernet_arp_hardware_type_t);
100 #define _(n,f) case n: t = #f; break;
101 foreach_ethernet_arp_hardware_type;
105 return format (s, "unknown 0x%x", h);
108 return format (s, "%s", t);
112 format_ethernet_arp_opcode (u8 * s, va_list * va)
114 ethernet_arp_opcode_t o = va_arg (*va, ethernet_arp_opcode_t);
118 #define _(f) case ETHERNET_ARP_OPCODE_##f: t = #f; break;
119 foreach_ethernet_arp_opcode;
123 return format (s, "unknown 0x%x", o);
126 return format (s, "%s", t);
130 unformat_ethernet_arp_opcode_host_byte_order (unformat_input_t * input,
133 int *result = va_arg (*args, int *);
134 ethernet_arp_main_t *am = ðernet_arp_main;
137 /* Numeric opcode. */
138 if (unformat (input, "0x%x", &x) || unformat (input, "%d", &x))
147 if (unformat_user (input, unformat_vlib_number_by_name,
148 am->opcode_by_name, &i))
158 unformat_ethernet_arp_opcode_net_byte_order (unformat_input_t * input,
161 int *result = va_arg (*args, int *);
163 (input, unformat_ethernet_arp_opcode_host_byte_order, result))
166 *result = clib_host_to_net_u16 ((u16) * result);
171 format_ethernet_arp_header (u8 * s, va_list * va)
173 ethernet_arp_header_t *a = va_arg (*va, ethernet_arp_header_t *);
174 u32 max_header_bytes = va_arg (*va, u32);
176 u16 l2_type, l3_type;
178 if (max_header_bytes != 0 && sizeof (a[0]) > max_header_bytes)
179 return format (s, "ARP header truncated");
181 l2_type = clib_net_to_host_u16 (a->l2_type);
182 l3_type = clib_net_to_host_u16 (a->l3_type);
184 indent = format_get_indent (s);
186 s = format (s, "%U, type %U/%U, address size %d/%d",
187 format_ethernet_arp_opcode, clib_net_to_host_u16 (a->opcode),
188 format_ethernet_arp_hardware_type, l2_type,
189 format_ethernet_type, l3_type,
190 a->n_l2_address_bytes, a->n_l3_address_bytes);
192 if (l2_type == ETHERNET_ARP_HARDWARE_TYPE_ethernet
193 && l3_type == ETHERNET_TYPE_IP4)
195 s = format (s, "\n%U%U/%U -> %U/%U",
196 format_white_space, indent,
197 format_ethernet_address, a->ip4_over_ethernet[0].ethernet,
198 format_ip4_address, &a->ip4_over_ethernet[0].ip4,
199 format_ethernet_address, a->ip4_over_ethernet[1].ethernet,
200 format_ip4_address, &a->ip4_over_ethernet[1].ip4);
204 uword n2 = a->n_l2_address_bytes;
205 uword n3 = a->n_l3_address_bytes;
206 s = format (s, "\n%U%U/%U -> %U/%U",
207 format_white_space, indent,
208 format_hex_bytes, a->data + 0 * n2 + 0 * n3, n2,
209 format_hex_bytes, a->data + 1 * n2 + 0 * n3, n3,
210 format_hex_bytes, a->data + 1 * n2 + 1 * n3, n2,
211 format_hex_bytes, a->data + 2 * n2 + 1 * n3, n3);
218 format_ethernet_arp_ip4_entry (u8 * s, va_list * va)
220 vnet_main_t *vnm = va_arg (*va, vnet_main_t *);
221 ethernet_arp_ip4_entry_t *e = va_arg (*va, ethernet_arp_ip4_entry_t *);
222 vnet_sw_interface_t *si;
227 return format (s, "%=12s%=6s%=16s%=6s%=20s%=24s", "Time", "FIB", "IP4",
228 "Flags", "Ethernet", "Interface");
230 fib = find_ip4_fib_by_table_index_or_id (&ip4_main, e->key.fib_index,
231 IP4_ROUTE_FLAG_FIB_INDEX);
232 si = vnet_get_sw_interface (vnm, e->key.sw_if_index);
234 if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_GLEAN)
235 flags = format (flags, "G");
237 if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
238 flags = format (flags, "S");
240 s = format (s, "%=12U%=6u%=16U%=6s%=20U%=24U",
241 format_vlib_cpu_time, vnm->vlib_main, e->cpu_time_last_updated,
243 format_ip4_address, &e->key.ip4_address,
244 flags ? (char *) flags : "",
245 format_ethernet_address, e->ethernet_address,
246 format_vnet_sw_interface_name, vnm, si);
255 } ethernet_arp_input_trace_t;
258 format_ethernet_arp_input_trace (u8 * s, va_list * va)
260 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
261 CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
262 ethernet_arp_input_trace_t *t = va_arg (*va, ethernet_arp_input_trace_t *);
265 format_ethernet_arp_header,
266 t->packet_data, sizeof (t->packet_data));
272 format_arp_term_input_trace (u8 * s, va_list * va)
274 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
275 CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
276 ethernet_arp_input_trace_t *t = va_arg (*va, ethernet_arp_input_trace_t *);
278 /* arp-term trace data saved is either arp or ip6/icmp6 packet:
279 - for arp, the 1st 16-bit field is hw type of value of 0x0001.
280 - for ip6, the first nibble has value of 6. */
281 s = format (s, "%U", t->packet_data[0] == 0 ?
282 format_ethernet_arp_header : format_ip6_header,
283 t->packet_data, sizeof (t->packet_data));
289 ethernet_arp_sw_interface_up_down (vnet_main_t * vnm,
290 u32 sw_if_index, u32 flags)
292 ethernet_arp_main_t *am = ðernet_arp_main;
293 ethernet_arp_ip4_entry_t *e;
298 pool_foreach (e, am->ip4_entry_pool, ({
299 if (e->key.sw_if_index == sw_if_index)
300 vec_add1 (to_add_del, e - am->ip4_entry_pool);
304 for (i = 0; i < vec_len (to_add_del); i++)
306 ethernet_arp_ip4_over_ethernet_address_t arp_add;
307 e = pool_elt_at_index (am->ip4_entry_pool, to_add_del[i]);
309 clib_memcpy (&arp_add.ethernet, e->ethernet_address, 6);
310 arp_add.ip4.as_u32 = e->key.ip4_address.as_u32;
312 if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
314 vnet_arp_set_ip4_over_ethernet (vnm,
316 e->key.fib_index, &arp_add,
318 ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC);
320 else if ((e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) == 0)
322 vnet_arp_unset_ip4_over_ethernet (vnm,
324 e->key.fib_index, &arp_add);
328 vec_free (to_add_del);
332 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_arp_sw_interface_up_down);
335 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
338 void *a_arg, int is_static);
341 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
343 u32 fib_index, void *a_arg);
349 ethernet_arp_ip4_over_ethernet_address_t a;
351 int is_remove; /* set is_remove=1 to clear arp entry */
352 } vnet_arp_set_ip4_over_ethernet_rpc_args_t;
354 static void set_ip4_over_ethernet_rpc_callback
355 (vnet_arp_set_ip4_over_ethernet_rpc_args_t * a)
357 vnet_main_t *vm = vnet_get_main ();
358 ASSERT (os_get_cpu_number () == 0);
361 vnet_arp_unset_ip4_over_ethernet_internal (vm,
363 a->fib_index, &(a->a));
365 vnet_arp_set_ip4_over_ethernet_internal (vm,
368 &(a->a), a->is_static);
372 vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
374 u32 fib_index, void *a_arg, int is_static)
376 ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
377 vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
379 args.sw_if_index = sw_if_index;
380 args.fib_index = fib_index;
381 args.is_static = is_static;
383 clib_memcpy (&args.a, a, sizeof (*a));
385 vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
386 (u8 *) & args, sizeof (args));
391 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
394 void *a_arg, int is_static)
396 ethernet_arp_ip4_key_t k;
397 ethernet_arp_ip4_entry_t *e = 0;
398 ethernet_arp_main_t *am = ðernet_arp_main;
399 ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
400 vlib_main_t *vm = vlib_get_main ();
401 ip4_main_t *im = &ip4_main;
402 ip_lookup_main_t *lm = &im->lookup_main;
403 int make_new_arp_cache_entry = 1;
405 ip4_add_del_route_args_t args;
406 ip_adjacency_t adj, *existing_adj;
407 pending_resolution_t *pr, *mc;
412 fib_index = (fib_index != (u32) ~ 0)
413 ? fib_index : im->fib_index_by_sw_if_index[sw_if_index];
415 k.sw_if_index = sw_if_index;
416 k.ip4_address = a->ip4;
417 k.fib_index = fib_index;
419 p = mhash_get (&am->ip4_entry_by_key, &k);
422 e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
424 /* Refuse to over-write static arp. */
425 if (!is_static && (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC))
427 make_new_arp_cache_entry = 0;
430 /* Note: always install the route. It might have been deleted */
431 memset (&adj, 0, sizeof (adj));
432 adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
433 adj.n_adj = 1; /* otherwise signature compare fails */
435 vnet_rewrite_for_sw_interface (vnm, VNET_L3_PACKET_TYPE_IP4, sw_if_index, ip4_rewrite_node.index, a->ethernet, /* destination address */
437 sizeof (adj.rewrite_data));
439 /* result of this lookup should be next-hop adjacency */
440 adj_index = ip4_fib_lookup_with_table (im, fib_index, &a->ip4, 0);
441 existing_adj = ip_get_adjacency (lm, adj_index);
443 if (existing_adj->lookup_next_index == IP_LOOKUP_NEXT_ARP &&
444 existing_adj->arp.next_hop.ip4.as_u32 == a->ip4.as_u32)
447 u32 *adjs = vec_dup (e->adjacencies);
448 /* Update all adj assigned to this arp entry */
449 vec_foreach (ai, adjs)
452 ip_adjacency_t *uadj = ip_get_adjacency (lm, *ai);
453 for (i = 0; i < uadj->n_adj; i++)
454 if (uadj[i].lookup_next_index == IP_LOOKUP_NEXT_ARP &&
455 uadj[i].arp.next_hop.ip4.as_u32 == a->ip4.as_u32)
456 ip_update_adjacency (lm, *ai + i, &adj);
462 /* Check that new adjacency actually isn't exactly the same as
463 * what is already there. If we over-write the adjacency with
464 * exactly the same info, its technically a new adjacency with
465 * new counters, but to user it appears as counters reset.
467 if (vnet_ip_adjacency_share_compare (&adj, existing_adj) == 0)
470 args.table_index_or_table_id = fib_index;
472 IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_ADD |
473 IP4_ROUTE_FLAG_NEIGHBOR;
474 args.dst_address = a->ip4;
475 args.dst_address_length = 32;
479 ip4_add_del_route (im, &args);
483 if (make_new_arp_cache_entry)
485 pool_get (am->ip4_entry_pool, e);
486 mhash_set (&am->ip4_entry_by_key, &k, e - am->ip4_entry_pool,
491 /* Update time stamp and ethernet address. */
492 clib_memcpy (e->ethernet_address, a->ethernet,
493 sizeof (e->ethernet_address));
494 e->cpu_time_last_updated = clib_cpu_time_now ();
496 e->flags |= ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC;
498 /* Customer(s) waiting for this address to be resolved? */
499 p = hash_get (am->pending_resolutions_by_address, a->ip4.as_u32);
504 while (next_index != (u32) ~ 0)
506 pr = pool_elt_at_index (am->pending_resolutions, next_index);
507 vlib_process_signal_event (vm, pr->node_index,
508 pr->type_opaque, pr->data);
509 next_index = pr->next_index;
510 pool_put (am->pending_resolutions, pr);
513 hash_unset (am->pending_resolutions_by_address, a->ip4.as_u32);
516 /* Customer(s) requesting ARP event for this address? */
517 p = hash_get (am->mac_changes_by_address, a->ip4.as_u32);
522 while (next_index != (u32) ~ 0)
524 int (*fp) (u32, u8 *, u32, u32);
526 mc = pool_elt_at_index (am->mac_changes, next_index);
527 fp = mc->data_callback;
529 /* Call the user's data callback, return 1 to suppress dup events */
531 rv = (*fp) (mc->data, a->ethernet, sw_if_index, 0);
534 * Signal the resolver process, as long as the user
535 * says they want to be notified
538 vlib_process_signal_event (vm, mc->node_index,
539 mc->type_opaque, mc->data);
540 next_index = mc->next_index;
548 vnet_register_ip4_arp_resolution_event (vnet_main_t * vnm,
551 uword type_opaque, uword data)
553 ethernet_arp_main_t *am = ðernet_arp_main;
554 ip4_address_t *address = address_arg;
556 pending_resolution_t *pr;
558 pool_get (am->pending_resolutions, pr);
561 pr->node_index = node_index;
562 pr->type_opaque = type_opaque;
564 pr->data_callback = 0;
566 p = hash_get (am->pending_resolutions_by_address, address->as_u32);
569 /* Insert new resolution at the head of the list */
570 pr->next_index = p[0];
571 hash_unset (am->pending_resolutions_by_address, address->as_u32);
574 hash_set (am->pending_resolutions_by_address, address->as_u32,
575 pr - am->pending_resolutions);
579 vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm,
584 uword type_opaque, uword data, int is_add)
586 ethernet_arp_main_t *am = ðernet_arp_main;
587 ip4_address_t *address = address_arg;
589 pending_resolution_t *mc;
590 void (*fp) (u32, u8 *) = data_callback;
594 pool_get (am->mac_changes, mc);
597 mc->node_index = node_index;
598 mc->type_opaque = type_opaque;
600 mc->data_callback = data_callback;
603 p = hash_get (am->mac_changes_by_address, address->as_u32);
606 /* Insert new resolution at the head of the list */
607 mc->next_index = p[0];
608 hash_unset (am->mac_changes_by_address, address->as_u32);
611 hash_set (am->mac_changes_by_address, address->as_u32,
612 mc - am->mac_changes);
618 pending_resolution_t *mc_last = 0;
620 p = hash_get (am->mac_changes_by_address, address->as_u32);
622 return VNET_API_ERROR_NO_SUCH_ENTRY;
626 while (index != (u32) ~ 0)
628 mc = pool_elt_at_index (am->mac_changes, index);
629 if (mc->node_index == node_index &&
630 mc->type_opaque == type_opaque && mc->pid == pid)
632 /* Clients may need to clean up pool entries, too */
634 (*fp) (mc->data, 0 /* no new mac addrs */ );
637 hash_unset (am->mac_changes_by_address, address->as_u32);
638 if (mc->next_index != ~0)
639 hash_set (am->mac_changes_by_address, address->as_u32,
641 pool_put (am->mac_changes, mc);
647 mc_last->next_index = mc->next_index;
648 pool_put (am->mac_changes, mc);
653 index = mc->next_index;
656 return VNET_API_ERROR_NO_SUCH_ENTRY;
660 /* Either we drop the packet or we send a reply to the sender. */
664 ARP_INPUT_NEXT_REPLY_TX,
668 #define foreach_ethernet_arp_error \
669 _ (replies_sent, "ARP replies sent") \
670 _ (l2_type_not_ethernet, "L2 type not ethernet") \
671 _ (l3_type_not_ip4, "L3 type not IP4") \
672 _ (l3_src_address_not_local, "IP4 source address not local to subnet") \
673 _ (l3_dst_address_not_local, "IP4 destination address not local to subnet") \
674 _ (l3_src_address_is_local, "IP4 source address matches local interface") \
675 _ (l3_src_address_learned, "ARP request IP4 source address learned") \
676 _ (replies_received, "ARP replies received") \
677 _ (opcode_not_request, "ARP opcode not request") \
678 _ (proxy_arp_replies_sent, "Proxy ARP replies sent") \
679 _ (l2_address_mismatch, "ARP hw addr does not match L2 frame src addr") \
680 _ (missing_interface_address, "ARP missing interface address") \
681 _ (gratuitous_arp, "ARP probe or announcement dropped") \
685 #define _(sym,string) ETHERNET_ARP_ERROR_##sym,
686 foreach_ethernet_arp_error
688 ETHERNET_ARP_N_ERROR,
689 } ethernet_arp_input_error_t;
691 /* get first interface address */
693 ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index,
694 ip_interface_address_t ** result_ia)
696 ip_lookup_main_t *lm = &im->lookup_main;
697 ip_interface_address_t *ia = 0;
698 ip4_address_t *result = 0;
701 foreach_ip_interface_address (lm, ia, sw_if_index,
702 1 /* honor unnumbered */ ,
705 ip_interface_address_get_address (lm, ia);
711 *result_ia = result ? ia : 0;
716 unset_random_arp_entry (void)
718 ethernet_arp_main_t *am = ðernet_arp_main;
719 ethernet_arp_ip4_entry_t *e;
720 vnet_main_t *vnm = vnet_get_main ();
721 ethernet_arp_ip4_over_ethernet_address_t delme;
724 index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
725 am->arp_delete_rotor = index;
727 /* Try again from elt 0, could happen if an intfc goes down */
730 index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
731 am->arp_delete_rotor = index;
734 /* Nothing left in the pool */
738 e = pool_elt_at_index (am->ip4_entry_pool, index);
740 clib_memcpy (&delme.ethernet, e->ethernet_address, 6);
741 delme.ip4.as_u32 = e->key.ip4_address.as_u32;
743 vnet_arp_unset_ip4_over_ethernet (vnm, e->key.sw_if_index,
744 e->key.fib_index, &delme);
748 arp_unnumbered (vlib_buffer_t * p0,
750 ethernet_header_t * eth0, ip_interface_address_t * ifa0)
752 vlib_main_t *vm = vlib_get_main ();
753 vnet_main_t *vnm = vnet_get_main ();
754 vnet_interface_main_t *vim = &vnm->interface_main;
755 vnet_sw_interface_t *si;
756 vnet_hw_interface_t *hi;
757 u32 unnum_src_sw_if_index;
758 u32 *broadcast_swifs = 0;
763 u8 dst_mac_address[6];
765 ethernet_arp_header_t *arp0;
767 /* Save the dst mac address */
768 clib_memcpy (dst_mac_address, eth0->dst_address, sizeof (dst_mac_address));
770 /* Figure out which sw_if_index supplied the address */
771 unnum_src_sw_if_index = ifa0->sw_if_index;
773 /* Track down all users of the unnumbered source */
775 pool_foreach (si, vim->sw_interfaces,
777 if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
778 (si->unnumbered_sw_if_index == unnum_src_sw_if_index))
780 vec_add1 (broadcast_swifs, si->sw_if_index);
785 ASSERT (vec_len (broadcast_swifs));
787 /* Allocate buffering if we need it */
788 if (vec_len (broadcast_swifs) > 1)
790 vec_validate (buffers, vec_len (broadcast_swifs) - 2);
791 n_alloc = vlib_buffer_alloc (vm, buffers, vec_len (buffers));
792 _vec_len (buffers) = n_alloc;
793 for (i = 0; i < n_alloc; i++)
795 b0 = vlib_get_buffer (vm, buffers[i]);
797 /* xerox (partially built) ARP pkt */
798 clib_memcpy (b0->data, p0->data,
799 p0->current_length + p0->current_data);
800 b0->current_data = p0->current_data;
801 b0->current_length = p0->current_length;
802 vnet_buffer (b0)->sw_if_index[VLIB_RX] =
803 vnet_buffer (p0)->sw_if_index[VLIB_RX];
807 vec_insert (buffers, 1, 0);
810 for (i = 0; i < vec_len (buffers); i++)
812 b0 = vlib_get_buffer (vm, buffers[i]);
813 arp0 = vlib_buffer_get_current (b0);
815 hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[i]);
816 si = vnet_get_sw_interface (vnm, broadcast_swifs[i]);
818 /* For decoration, most likely */
819 vnet_buffer (b0)->sw_if_index[VLIB_TX] = hi->sw_if_index;
821 /* Fix ARP pkt src address */
822 clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, hi->hw_address, 6);
824 /* Build L2 encaps for this swif */
825 header_size = sizeof (ethernet_header_t);
826 if (si->sub.eth.flags.one_tag)
828 else if (si->sub.eth.flags.two_tags)
831 vlib_buffer_advance (b0, -header_size);
832 eth0 = vlib_buffer_get_current (b0);
834 if (si->sub.eth.flags.one_tag)
836 ethernet_vlan_header_t *outer = (void *) (eth0 + 1);
838 eth0->type = si->sub.eth.flags.dot1ad ?
839 clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
840 clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
841 outer->priority_cfi_and_id =
842 clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
843 outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
846 else if (si->sub.eth.flags.two_tags)
848 ethernet_vlan_header_t *outer = (void *) (eth0 + 1);
849 ethernet_vlan_header_t *inner = (void *) (outer + 1);
851 eth0->type = si->sub.eth.flags.dot1ad ?
852 clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
853 clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
854 outer->priority_cfi_and_id =
855 clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
856 outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
857 inner->priority_cfi_and_id =
858 clib_host_to_net_u16 (si->sub.eth.inner_vlan_id);
859 inner->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
864 eth0->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
867 /* Restore the original dst address, set src address */
868 clib_memcpy (eth0->dst_address, dst_mac_address,
869 sizeof (eth0->dst_address));
870 clib_memcpy (eth0->src_address, hi->hw_address,
871 sizeof (eth0->src_address));
873 /* Transmit replicas */
877 vlib_get_frame_to_node (vm, hi->output_node_index);
878 u32 *to_next = vlib_frame_vector_args (f);
879 to_next[0] = buffers[i];
881 vlib_put_frame_to_node (vm, hi->output_node_index, f);
885 /* The regular path outputs the original pkt.. */
886 vnet_buffer (p0)->sw_if_index[VLIB_TX] = broadcast_swifs[0];
888 vec_free (broadcast_swifs);
893 arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
895 ethernet_arp_main_t *am = ðernet_arp_main;
896 vnet_main_t *vnm = vnet_get_main ();
897 ip4_main_t *im4 = &ip4_main;
898 u32 n_left_from, next_index, *from, *to_next;
899 u32 n_replies_sent = 0, n_proxy_arp_replies_sent = 0;
901 from = vlib_frame_vector_args (frame);
902 n_left_from = frame->n_vectors;
903 next_index = node->cached_next_index;
905 if (node->flags & VLIB_NODE_FLAG_TRACE)
906 vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
908 sizeof (ethernet_arp_input_trace_t));
910 while (n_left_from > 0)
914 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
916 while (n_left_from > 0 && n_left_to_next > 0)
919 vnet_hw_interface_t *hw_if0;
920 ethernet_arp_header_t *arp0;
921 ethernet_header_t *eth0;
922 ip_interface_address_t *ifa0;
923 ip_adjacency_t *adj0;
924 ip4_address_t *if_addr0;
925 ip4_address_t proxy_src;
926 u32 pi0, error0, next0, sw_if_index0;
927 u8 is_request0, src_is_local0, dst_is_local0, is_unnum0;
928 ethernet_proxy_arp_t *pa;
937 p0 = vlib_get_buffer (vm, pi0);
938 arp0 = vlib_buffer_get_current (p0);
940 is_request0 = arp0->opcode
941 == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
943 error0 = ETHERNET_ARP_ERROR_replies_sent;
947 clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ?
948 ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
951 clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
952 ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
954 sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
959 /* Check that IP address is local and matches incoming interface. */
961 ip4_interface_address_matching_destination (im4,
963 ip4_over_ethernet[1].
968 error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
972 /* Honor unnumbered interface, if any */
973 is_unnum0 = sw_if_index0 != ifa0->sw_if_index;
975 /* Source must also be local to subnet of matching interface address. */
976 if (!ip4_destination_matches_interface
977 (im4, &arp0->ip4_over_ethernet[0].ip4, ifa0))
979 error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
983 /* Reject requests/replies with our local interface address. */
985 if_addr0->as_u32 == arp0->ip4_over_ethernet[0].ip4.as_u32;
988 error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
993 if_addr0->as_u32 == arp0->ip4_over_ethernet[1].ip4.as_u32;
995 /* Fill in ethernet header. */
996 eth0 = ethernet_buffer_get_header (p0);
998 /* Trash ARP packets whose ARP-level source addresses do not
999 match their L2-frame-level source addresses */
1000 if (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
1001 sizeof (eth0->src_address)))
1003 error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1007 /* Learn or update sender's mapping only for requests or unicasts
1008 that don't match local interface address. */
1009 if (ethernet_address_cast (eth0->dst_address) ==
1010 ETHERNET_ADDRESS_UNICAST || is_request0)
1012 if (am->limit_arp_cache_size &&
1013 pool_elts (am->ip4_entry_pool) >= am->limit_arp_cache_size)
1014 unset_random_arp_entry ();
1016 vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index0,
1017 (u32) ~ 0 /* default fib */ ,
1018 &arp0->ip4_over_ethernet[0],
1019 0 /* is_static */ );
1020 error0 = ETHERNET_ARP_ERROR_l3_src_address_learned;
1023 /* Only send a reply for requests sent which match a local interface. */
1024 if (!(is_request0 && dst_is_local0))
1028 clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply) ?
1029 ETHERNET_ARP_ERROR_replies_received : error0);
1035 vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1036 hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
1038 /* Send reply back through input interface */
1039 vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1040 next0 = ARP_INPUT_NEXT_REPLY_TX;
1042 arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1044 arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1046 clib_memcpy (arp0->ip4_over_ethernet[0].ethernet,
1047 hw_if0->hw_address, 6);
1048 clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) =
1051 /* Hardware must be ethernet-like. */
1052 ASSERT (vec_len (hw_if0->hw_address) == 6);
1054 clib_memcpy (eth0->dst_address, eth0->src_address, 6);
1055 clib_memcpy (eth0->src_address, hw_if0->hw_address, 6);
1057 /* Figure out how much to rewind current data from adjacency. */
1060 adj0 = ip_get_adjacency (&ip4_main.lookup_main,
1061 ifa0->neighbor_probe_adj_index);
1062 if (adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP)
1064 error0 = ETHERNET_ARP_ERROR_missing_interface_address;
1068 arp_unnumbered (p0, pi0, eth0, ifa0);
1070 vlib_buffer_advance (p0, -adj0->rewrite_header.data_bytes);
1073 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1074 n_left_to_next, pi0, next0);
1076 n_replies_sent += 1;
1080 if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1081 (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1082 arp0->ip4_over_ethernet[1].ip4.as_u32))
1084 error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1087 /* See if proxy arp is configured for the address */
1090 vnet_sw_interface_t *si;
1091 u32 this_addr = clib_net_to_host_u32
1092 (arp0->ip4_over_ethernet[1].ip4.as_u32);
1095 si = vnet_get_sw_interface (vnm, sw_if_index0);
1097 if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP))
1100 fib_index0 = vec_elt (im4->fib_index_by_sw_if_index,
1103 vec_foreach (pa, am->proxy_arps)
1105 u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
1106 u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
1108 /* an ARP request hit in the proxy-arp table? */
1109 if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1110 (fib_index0 == pa->fib_index))
1112 eth0 = ethernet_buffer_get_header (p0);
1114 arp0->ip4_over_ethernet[1].ip4.data_u32;
1117 * Rewind buffer, direct code above not to
1118 * think too hard about it.
1119 * $$$ is the answer ever anything other than
1120 * vlib_buffer_reset(..)?
1123 if_addr0 = &proxy_src;
1124 vlib_buffer_reset (p0);
1125 n_proxy_arp_replies_sent++;
1133 next0 = ARP_INPUT_NEXT_DROP;
1134 p0->error = node->errors[error0];
1136 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
1137 n_left_to_next, pi0, next0);
1140 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1143 vlib_error_count (vm, node->node_index,
1144 ETHERNET_ARP_ERROR_replies_sent,
1145 n_replies_sent - n_proxy_arp_replies_sent);
1147 vlib_error_count (vm, node->node_index,
1148 ETHERNET_ARP_ERROR_proxy_arp_replies_sent,
1149 n_proxy_arp_replies_sent);
1150 return frame->n_vectors;
1153 static char *ethernet_arp_error_strings[] = {
1154 #define _(sym,string) string,
1155 foreach_ethernet_arp_error
1160 VLIB_REGISTER_NODE (arp_input_node, static) =
1162 .function = arp_input,
1163 .name = "arp-input",
1164 .vector_size = sizeof (u32),
1165 .n_errors = ETHERNET_ARP_N_ERROR,
1166 .error_strings = ethernet_arp_error_strings,
1167 .n_next_nodes = ARP_INPUT_N_NEXT,
1169 [ARP_INPUT_NEXT_DROP] = "error-drop",
1170 [ARP_INPUT_NEXT_REPLY_TX] = "interface-output",
1172 .format_buffer = format_ethernet_arp_header,
1173 .format_trace = format_ethernet_arp_input_trace,
1178 ip4_arp_entry_sort (void *a1, void *a2)
1180 ethernet_arp_ip4_entry_t *e1 = a1;
1181 ethernet_arp_ip4_entry_t *e2 = a2;
1184 vnet_main_t *vnm = vnet_get_main ();
1186 cmp = vnet_sw_interface_compare
1187 (vnm, e1->key.sw_if_index, e2->key.sw_if_index);
1189 cmp = ip4_address_compare (&e1->key.ip4_address, &e2->key.ip4_address);
1193 static clib_error_t *
1194 show_ip4_arp (vlib_main_t * vm,
1195 unformat_input_t * input, vlib_cli_command_t * cmd)
1197 vnet_main_t *vnm = vnet_get_main ();
1198 ethernet_arp_main_t *am = ðernet_arp_main;
1199 ethernet_arp_ip4_entry_t *e, *es;
1200 ethernet_proxy_arp_t *pa;
1201 clib_error_t *error = 0;
1204 /* Filter entries by interface if given. */
1206 (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1210 pool_foreach (e, am->ip4_entry_pool,
1212 vec_add1 (es, e[0]);
1218 vec_sort_with_function (es, ip4_arp_entry_sort);
1219 vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1222 if (sw_if_index != ~0 && e->key.sw_if_index != sw_if_index)
1224 vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1229 if (vec_len (am->proxy_arps))
1231 vlib_cli_output (vm, "Proxy arps enabled for:");
1232 vec_foreach (pa, am->proxy_arps)
1234 vlib_cli_output (vm, "Fib_index %d %U - %U ",
1236 format_ip4_address, &pa->lo_addr,
1237 format_ip4_address, &pa->hi_addr);
1245 VLIB_CLI_COMMAND (show_ip4_arp_command, static) = {
1246 .path = "show ip arp",
1247 .function = show_ip4_arp,
1248 .short_help = "Show ARP table",
1254 pg_edit_t l2_type, l3_type;
1255 pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1261 } ip4_over_ethernet[2];
1262 } pg_ethernet_arp_header_t;
1265 pg_ethernet_arp_header_init (pg_ethernet_arp_header_t * p)
1267 /* Initialize fields that are not bit fields in the IP header. */
1268 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1271 _(n_l2_address_bytes);
1272 _(n_l3_address_bytes);
1274 _(ip4_over_ethernet[0].ethernet);
1275 _(ip4_over_ethernet[0].ip4);
1276 _(ip4_over_ethernet[1].ethernet);
1277 _(ip4_over_ethernet[1].ip4);
1282 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1284 pg_stream_t *s = va_arg (*args, pg_stream_t *);
1285 pg_ethernet_arp_header_t *p;
1288 p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1290 pg_ethernet_arp_header_init (p);
1293 pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1294 pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1295 pg_edit_set_fixed (&p->n_l2_address_bytes, 6);
1296 pg_edit_set_fixed (&p->n_l3_address_bytes, 4);
1298 if (!unformat (input, "%U: %U/%U -> %U/%U",
1300 unformat_ethernet_arp_opcode_net_byte_order, &p->opcode,
1302 unformat_ethernet_address, &p->ip4_over_ethernet[0].ethernet,
1304 unformat_ip4_address, &p->ip4_over_ethernet[0].ip4,
1306 unformat_ethernet_address, &p->ip4_over_ethernet[1].ethernet,
1308 unformat_ip4_address, &p->ip4_over_ethernet[1].ip4))
1310 /* Free up any edits we may have added. */
1311 pg_free_edit_group (s);
1318 ip4_set_arp_limit (u32 arp_limit)
1320 ethernet_arp_main_t *am = ðernet_arp_main;
1322 am->limit_arp_cache_size = arp_limit;
1327 arp_ip4_entry_del_adj (ethernet_arp_ip4_entry_t * e, u32 adj_index)
1334 vec_foreach_index (i, e->adjacencies)
1335 if (vec_elt (e->adjacencies, i) == adj_index)
1337 vec_del1 (e->adjacencies, i);
1345 arp_ip4_entry_add_adj (ethernet_arp_ip4_entry_t * e, u32 adj_index)
1348 vec_foreach_index (i, e->adjacencies)
1349 if (vec_elt (e->adjacencies, i) == adj_index)
1351 vec_add1 (e->adjacencies, adj_index);
1355 arp_add_del_adj_cb (struct ip_lookup_main_t *lm,
1356 u32 adj_index, ip_adjacency_t * adj, u32 is_del)
1358 ethernet_arp_main_t *am = ðernet_arp_main;
1359 ip4_main_t *im = &ip4_main;
1360 ethernet_arp_ip4_key_t k;
1361 ethernet_arp_ip4_entry_t *e = 0;
1365 for (ai = adj->heap_handle; ai < adj->heap_handle + adj->n_adj; ai++)
1367 adj = ip_get_adjacency (lm, ai);
1368 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP
1369 && adj->arp.next_hop.ip4.as_u32)
1371 k.sw_if_index = adj->rewrite_header.sw_if_index;
1372 k.ip4_address.as_u32 = adj->arp.next_hop.ip4.as_u32;
1374 im->fib_index_by_sw_if_index[adj->rewrite_header.sw_if_index];
1375 p = mhash_get (&am->ip4_entry_by_key, &k);
1377 e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
1385 clib_warning ("Adjacency contains unknown ARP next hop %U (del)",
1386 format_ip46_address, &adj->arp.next_hop,
1389 arp_ip4_entry_del_adj (e, adj->heap_handle);
1394 clib_warning ("Adjacency contains unknown ARP next hop %U (add)",
1395 format_ip46_address, &adj->arp.next_hop,
1398 arp_ip4_entry_add_adj (e, adj->heap_handle);
1403 static clib_error_t *
1404 ethernet_arp_init (vlib_main_t * vm)
1406 ethernet_arp_main_t *am = ðernet_arp_main;
1408 clib_error_t *error;
1409 ip4_main_t *im = &ip4_main;
1410 ip_lookup_main_t *lm = &im->lookup_main;
1412 if ((error = vlib_call_init_function (vm, ethernet_init)))
1415 ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
1417 pn = pg_get_node (arp_input_node.index);
1418 pn->unformat_edit = unformat_pg_arp_header;
1420 am->opcode_by_name = hash_create_string (0, sizeof (uword));
1421 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
1422 foreach_ethernet_arp_opcode;
1425 mhash_init (&am->ip4_entry_by_key,
1426 /* value size */ sizeof (uword),
1427 /* key size */ sizeof (ethernet_arp_ip4_key_t));
1429 /* $$$ configurable */
1430 am->limit_arp_cache_size = 50000;
1432 am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
1433 am->mac_changes_by_address = hash_create (0, sizeof (uword));
1435 /* don't trace ARP error packets */
1437 vlib_node_runtime_t *rt =
1438 vlib_node_get_runtime (vm, arp_input_node.index);
1441 vnet_pcap_drop_trace_filter_add_del \
1442 (rt->errors[ETHERNET_ARP_ERROR_##a], \
1444 foreach_ethernet_arp_error
1448 ip_register_add_del_adjacency_callback (lm, arp_add_del_adj_cb);
1453 VLIB_INIT_FUNCTION (ethernet_arp_init);
1456 vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
1457 u32 sw_if_index, u32 fib_index, void *a_arg)
1459 ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1460 vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1462 args.sw_if_index = sw_if_index;
1463 args.fib_index = fib_index;
1465 clib_memcpy (&args.a, a, sizeof (*a));
1467 vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1468 (u8 *) & args, sizeof (args));
1473 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
1475 u32 fib_index, void *a_arg)
1477 ethernet_arp_ip4_entry_t *e;
1478 ethernet_arp_main_t *am = ðernet_arp_main;
1479 ethernet_arp_ip4_over_ethernet_address_t *a = a_arg;
1480 ethernet_arp_ip4_key_t k;
1482 ip4_add_del_route_args_t args;
1483 ip4_main_t *im = &ip4_main;
1484 ip_lookup_main_t *lm = &im->lookup_main;
1486 ip_adjacency_t *adj;
1488 k.sw_if_index = sw_if_index;
1489 k.ip4_address = a->ip4;
1490 k.fib_index = fib_index;
1491 p = mhash_get (&am->ip4_entry_by_key, &k);
1495 memset (&args, 0, sizeof (args));
1498 * Make sure that the route actually exists before we try to delete it,
1499 * and make sure that it's a rewrite adjacency.
1501 * If we point 1-N unnumbered interfaces at a loopback interface and
1502 * shut down the loopback before shutting down 1-N unnumbered
1503 * interfaces, the ARP cache will still have an entry,
1504 * but the route will have disappeared.
1506 * See also ip4_del_interface_routes (...)
1507 * -> ip4_delete_matching_routes (...).
1510 adj_index = ip4_fib_lookup_with_table
1511 (im, fib_index, &a->ip4, 1 /* disable default route */ );
1513 /* Miss adj? Forget it... */
1514 if (adj_index != lm->miss_adj_index)
1516 adj = ip_get_adjacency (lm, adj_index);
1518 * Stupid control-plane trick:
1519 * admin down an interface (removes arp routes from fib),
1520 * bring the interface back up (does not reinstall them)
1521 * then remove the arp cache entry (yuck). When that happens,
1522 * the adj we find here will be the interface subnet ARP adj.
1524 if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE)
1526 args.table_index_or_table_id = fib_index;
1527 args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL
1528 | IP4_ROUTE_FLAG_NEIGHBOR;
1529 args.dst_address = a->ip4;
1530 args.dst_address_length = 32;
1531 ip4_add_del_route (im, &args);
1532 ip4_maybe_remap_adjacencies (im, fib_index, args.flags);
1536 e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
1537 mhash_unset (&am->ip4_entry_by_key, &e->key, 0);
1538 pool_put (am->ip4_entry_pool, e);
1543 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t * a)
1548 for (i = 3; i >= 0; i--)
1550 old = a->ip4.as_u8[i];
1551 a->ip4.as_u8[i] += 1;
1552 if (old < a->ip4.as_u8[i])
1556 for (i = 5; i >= 0; i--)
1558 old = a->ethernet[i];
1559 a->ethernet[i] += 1;
1560 if (old < a->ethernet[i])
1566 vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
1567 ip4_address_t * hi_addr, u32 fib_index, int is_del)
1569 ethernet_arp_main_t *am = ðernet_arp_main;
1570 ethernet_proxy_arp_t *pa;
1571 u32 found_at_index = ~0;
1573 vec_foreach (pa, am->proxy_arps)
1575 if (pa->lo_addr == lo_addr->as_u32
1576 && pa->hi_addr == hi_addr->as_u32 && pa->fib_index == fib_index)
1578 found_at_index = pa - am->proxy_arps;
1583 if (found_at_index != ~0)
1585 /* Delete, otherwise it's already in the table */
1587 vec_delete (am->proxy_arps, 1, found_at_index);
1590 /* delete, no such entry */
1592 return VNET_API_ERROR_NO_SUCH_ENTRY;
1594 /* add, not in table */
1595 vec_add2 (am->proxy_arps, pa, 1);
1596 pa->lo_addr = lo_addr->as_u32;
1597 pa->hi_addr = hi_addr->as_u32;
1598 pa->fib_index = fib_index;
1603 * Remove any proxy arp entries asdociated with the
1607 vnet_proxy_arp_fib_reset (u32 fib_id)
1609 ip4_main_t *im = &ip4_main;
1610 ethernet_arp_main_t *am = ðernet_arp_main;
1611 ethernet_proxy_arp_t *pa;
1612 u32 *entries_to_delete = 0;
1617 p = hash_get (im->fib_index_by_table_id, fib_id);
1619 return VNET_API_ERROR_NO_SUCH_ENTRY;
1622 vec_foreach (pa, am->proxy_arps)
1624 if (pa->fib_index == fib_index)
1626 vec_add1 (entries_to_delete, pa - am->proxy_arps);
1630 for (i = 0; i < vec_len (entries_to_delete); i++)
1632 vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
1635 vec_free (entries_to_delete);
1641 vnet_arp_glean_add (u32 fib_index, void *next_hop_arg)
1643 ethernet_arp_main_t *am = ðernet_arp_main;
1644 ip4_main_t *im = &ip4_main;
1645 ip_lookup_main_t *lm = &im->lookup_main;
1646 ip4_address_t *next_hop = next_hop_arg;
1647 ip_adjacency_t add_adj, *adj;
1648 ip4_add_del_route_args_t args;
1649 ethernet_arp_ip4_entry_t *e;
1650 ethernet_arp_ip4_key_t k;
1653 adj_index = ip4_fib_lookup_with_table (im, fib_index, next_hop, 0);
1654 adj = ip_get_adjacency (lm, adj_index);
1656 if (!adj || adj->lookup_next_index != IP_LOOKUP_NEXT_ARP)
1659 if (adj->arp.next_hop.ip4.as_u32 != 0)
1662 k.sw_if_index = adj->rewrite_header.sw_if_index;
1663 k.fib_index = fib_index;
1664 k.ip4_address.as_u32 = next_hop->as_u32;
1666 if (mhash_get (&am->ip4_entry_by_key, &k))
1669 pool_get (am->ip4_entry_pool, e);
1670 mhash_set (&am->ip4_entry_by_key, &k, e - am->ip4_entry_pool,
1673 e->cpu_time_last_updated = clib_cpu_time_now ();
1674 e->flags = ETHERNET_ARP_IP4_ENTRY_FLAG_GLEAN;
1676 memset (&args, 0, sizeof (args));
1677 clib_memcpy (&add_adj, adj, sizeof (add_adj));
1678 ip46_address_set_ip4 (&add_adj.arp.next_hop, next_hop); /* install neighbor /32 route */
1679 args.table_index_or_table_id = fib_index;
1681 IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_ADD | IP4_ROUTE_FLAG_NEIGHBOR;
1682 args.dst_address.as_u32 = next_hop->as_u32;
1683 args.dst_address_length = 32;
1684 args.adj_index = ~0;
1685 args.add_adj = &add_adj;
1687 ip4_add_del_route (im, &args);
1688 return ip4_fib_lookup_with_table (im, fib_index, next_hop, 0);
1691 static clib_error_t *
1692 ip_arp_add_del_command_fn (vlib_main_t * vm,
1693 unformat_input_t * input, vlib_cli_command_t * cmd)
1695 vnet_main_t *vnm = vnet_get_main ();
1697 ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
1706 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1708 /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
1709 if (unformat (input, "%U %U %U",
1710 unformat_vnet_sw_interface, vnm, &sw_if_index,
1711 unformat_ip4_address, &addr.ip4,
1712 unformat_ethernet_address, &addr.ethernet))
1715 else if (unformat (input, "delete") || unformat (input, "del"))
1718 else if (unformat (input, "static"))
1721 else if (unformat (input, "count %d", &count))
1724 else if (unformat (input, "fib-id %d", &fib_id))
1726 ip4_main_t *im = &ip4_main;
1727 uword *p = hash_get (im->fib_index_by_table_id, fib_id);
1729 return clib_error_return (0, "fib ID %d doesn't exist\n", fib_id);
1733 else if (unformat (input, "proxy %U - %U",
1734 unformat_ip4_address, &lo_addr.ip4,
1735 unformat_ip4_address, &hi_addr.ip4))
1743 (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4,
1752 for (i = 0; i < count; i++)
1756 uword event_type, *event_data = 0;
1758 /* Park the debug CLI until the arp entry is installed */
1759 vnet_register_ip4_arp_resolution_event
1760 (vnm, &addr.ip4, vlib_current_process (vm),
1761 1 /* type */ , 0 /* data */ );
1763 vnet_arp_set_ip4_over_ethernet
1764 (vnm, sw_if_index, fib_index, &addr, is_static);
1766 vlib_process_wait_for_event (vm);
1767 event_type = vlib_process_get_events (vm, &event_data);
1768 vec_reset_length (event_data);
1769 if (event_type != 1)
1770 clib_warning ("event type %d unexpected", event_type);
1773 vnet_arp_unset_ip4_over_ethernet
1774 (vnm, sw_if_index, fib_index, &addr);
1776 increment_ip4_and_mac_address (&addr);
1781 return clib_error_return (0, "unknown input `%U'",
1782 format_unformat_error, input);
1791 * Add or delete ip4 ARP cache entries
1794 * @cliexstart{set ip arp}
1795 * Add or delete ip4 ARP cache entries as follows:
1796 * vpp# set ip arp GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe
1797 * vpp# set ip arp delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe
1798 * Add or delete ip4 ARP cache entries to a specific fib table:
1799 * vpp# set ip arp fib-id 1 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe
1800 * vpp# set ip arp fib-id 1 delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe
1801 * Add or delete ip4 static ARP cache entries as follows:
1802 * vpp# set ip arp static GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe
1803 * vpp# set ip arp static delete GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe
1804 * For testing / debugging purposes, the 'set ip arps command can add or delete multiple entries. Supply the 'count N' parameter:
1805 * vpp# set ip arp count 10 GigabitEthernet2/0/0 6.0.0.3 dead.beef.babe
1806 * @NOTE: 'set ip arp' options
1807 * (e.g. delete, static, 'fib-id <id>', 'count <number>', 'interface ip4_addr mac_addr')
1808 * can be added in any order and combination.
1811 VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = {
1812 .path = "set ip arp",
1814 "set ip arp [del] <intfc> <ip-address> <mac-address> [static] [count <count>] [fib-id <fib-id>] [proxy <lo-addr> - <hi-addr>]",
1815 .function = ip_arp_add_del_command_fn,
1819 static clib_error_t *
1820 set_int_proxy_arp_command_fn (vlib_main_t * vm,
1821 unformat_input_t * input,
1822 vlib_cli_command_t * cmd)
1824 vnet_main_t *vnm = vnet_get_main ();
1826 vnet_sw_interface_t *si;
1830 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1832 if (unformat (input, "%U", unformat_vnet_sw_interface,
1835 else if (unformat (input, "enable") || unformat (input, "on"))
1837 else if (unformat (input, "disable") || unformat (input, "off"))
1844 return clib_error_return (0, "unknown input '%U'",
1845 format_unformat_error, input);
1847 si = vnet_get_sw_interface (vnm, sw_if_index);
1850 si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1852 si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1860 * Enable proxy-arp on an interface.
1863 * @cliexstart{set interface proxy-arp}
1864 * To enable proxy arp on a range of addresses, use:
1865 * vpp# set ip arp proxy 6.0.0.1 - 6.0.0.11
1866 * You must specifically enable proxy arp on individual interfaces:
1867 * vpp# set interface proxy-arp <intfc> [enable|disable]
1868 * The vpp stack will answer ARP requests for the indicated address range.
1869 * Use with caution. Proxy ARP as a technology is infamous for blackholing traffic.
1870 * Multiple proxy-arp ranges may be provisioned.
1871 * The underlying implementation has not been performance-tuned; avoid creating an unnecessarily large set of ranges.
1874 VLIB_CLI_COMMAND (set_int_proxy_enable_command, static) = {
1875 .path = "set interface proxy-arp",
1877 "set interface proxy-arp <intfc> [enable|disable]",
1878 .function = set_int_proxy_arp_command_fn,
1884 * ARP/ND Termination in a L2 Bridge Domain based on IP4/IP6 to MAC
1885 * hash tables mac_by_ip4 and mac_by_ip6 for each BD.
1889 ARP_TERM_NEXT_L2_OUTPUT,
1894 u32 arp_term_next_node_index[32];
1897 arp_term_l2bd (vlib_main_t * vm,
1898 vlib_node_runtime_t * node, vlib_frame_t * frame)
1900 l2input_main_t *l2im = &l2input_main;
1901 u32 n_left_from, next_index, *from, *to_next;
1902 u32 n_replies_sent = 0;
1903 u16 last_bd_index = ~0;
1904 l2_bridge_domain_t *last_bd_config = 0;
1905 l2_input_config_t *cfg0;
1907 from = vlib_frame_vector_args (frame);
1908 n_left_from = frame->n_vectors;
1909 next_index = node->cached_next_index;
1911 while (n_left_from > 0)
1915 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1917 while (n_left_from > 0 && n_left_to_next > 0)
1920 ethernet_header_t *eth0;
1921 ethernet_arp_header_t *arp0;
1924 u32 pi0, error0, next0, sw_if_index0;
1935 n_left_to_next -= 1;
1937 p0 = vlib_get_buffer (vm, pi0);
1938 eth0 = vlib_buffer_get_current (p0);
1939 l3h0 = (u8 *) eth0 + vnet_buffer (p0)->l2.l2_len;
1940 ethertype0 = clib_net_to_host_u16 (*(u16 *) (l3h0 - 2));
1941 arp0 = (ethernet_arp_header_t *) l3h0;
1943 if (PREDICT_FALSE ((ethertype0 != ETHERNET_TYPE_ARP) ||
1945 clib_host_to_net_u16
1946 (ETHERNET_ARP_OPCODE_request))))
1949 /* Must be ARP request packet here */
1950 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
1951 (p0->flags & VLIB_BUFFER_IS_TRACED)))
1953 u8 *t0 = vlib_add_trace (vm, node, p0,
1954 sizeof (ethernet_arp_input_trace_t));
1955 clib_memcpy (t0, l3h0, sizeof (ethernet_arp_input_trace_t));
1958 error0 = ETHERNET_ARP_ERROR_replies_sent;
1961 clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet) ?
1962 ETHERNET_ARP_ERROR_l2_type_not_ethernet : error0);
1965 clib_net_to_host_u16 (ETHERNET_TYPE_IP4) ?
1966 ETHERNET_ARP_ERROR_l3_type_not_ip4 : error0);
1968 sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1973 /* Trash ARP packets whose ARP-level source addresses do not
1974 match their L2-frame-level source addresses */
1977 (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
1978 sizeof (eth0->src_address))))
1980 error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1984 /* Check if anyone want ARP request events for L2 BDs */
1986 pending_resolution_t *mc;
1987 ethernet_arp_main_t *am = ðernet_arp_main;
1988 uword *p = hash_get (am->mac_changes_by_address, 0);
1989 if (p && (vnet_buffer (p0)->l2.shg == 0))
1990 { // Only SHG 0 interface which is more likely local
1991 u32 next_index = p[0];
1992 while (next_index != (u32) ~ 0)
1994 int (*fp) (u32, u8 *, u32, u32);
1996 mc = pool_elt_at_index (am->mac_changes, next_index);
1997 fp = mc->data_callback;
1998 /* Call the callback, return 1 to suppress dup events */
2000 rv = (*fp) (mc->data,
2001 arp0->ip4_over_ethernet[0].ethernet,
2003 arp0->ip4_over_ethernet[0].ip4.as_u32);
2004 /* Signal the resolver process */
2006 vlib_process_signal_event (vm, mc->node_index,
2007 mc->type_opaque, mc->data);
2008 next_index = mc->next_index;
2013 /* lookup BD mac_by_ip4 hash table for MAC entry */
2014 ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
2015 bd_index0 = vnet_buffer (p0)->l2.bd_index;
2016 if (PREDICT_FALSE ((bd_index0 != last_bd_index)
2017 || (last_bd_index == (u16) ~ 0)))
2019 last_bd_index = bd_index0;
2020 last_bd_config = vec_elt_at_index (l2im->bd_configs, bd_index0);
2022 macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
2024 if (PREDICT_FALSE (!macp0))
2025 goto next_l2_feature; /* MAC not found */
2027 /* MAC found, send ARP reply -
2028 Convert ARP request packet to ARP reply */
2029 arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
2030 arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
2031 arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
2032 clib_memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
2033 clib_memcpy (eth0->dst_address, eth0->src_address, 6);
2034 clib_memcpy (eth0->src_address, macp0, 6);
2035 n_replies_sent += 1;
2038 /* For BVI, need to use l2-fwd node to send ARP reply as
2039 l2-output node cannot output packet to BVI properly */
2040 cfg0 = vec_elt_at_index (l2im->configs, sw_if_index0);
2041 if (PREDICT_FALSE (cfg0->bvi))
2043 vnet_buffer (p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
2044 vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
2045 goto next_l2_feature;
2048 /* Send ARP/ND reply back out input interface through l2-output */
2049 vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
2050 next0 = ARP_TERM_NEXT_L2_OUTPUT;
2051 /* Note that output to VXLAN tunnel will fail due to SHG which
2052 is probably desireable since ARP termination is not intended
2053 for ARP requests from other hosts. If output to VXLAN tunnel is
2054 required, however, can just clear the SHG in packet as follows:
2055 vnet_buffer(p0)->l2.shg = 0; */
2056 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2057 n_left_to_next, pi0, next0);
2061 /* IP6 ND event notification or solicitation handling to generate
2062 local response instead of flooding */
2063 iph0 = (ip6_header_t *) l3h0;
2064 if (PREDICT_FALSE (ethertype0 == ETHERNET_TYPE_IP6 &&
2065 iph0->protocol == IP_PROTOCOL_ICMP6 &&
2066 !ip6_address_is_link_local_unicast
2067 (&iph0->src_address)
2069 !ip6_address_is_unspecified
2070 (&iph0->src_address)))
2072 sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
2073 if (vnet_ip6_nd_term (vm, node, p0, eth0, iph0, sw_if_index0,
2074 vnet_buffer (p0)->l2.bd_index,
2075 vnet_buffer (p0)->l2.shg))
2076 goto output_response;
2081 u32 feature_bitmap0 =
2082 vnet_buffer (p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM;
2083 vnet_buffer (p0)->l2.feature_bitmap = feature_bitmap0;
2084 next0 = feat_bitmap_get_next_node_index (arp_term_next_node_index,
2086 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2087 n_left_to_next, pi0, next0);
2092 if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
2093 (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
2094 arp0->ip4_over_ethernet[1].ip4.as_u32))
2096 error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
2098 next0 = ARP_TERM_NEXT_DROP;
2099 p0->error = node->errors[error0];
2101 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
2102 n_left_to_next, pi0, next0);
2105 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
2108 vlib_error_count (vm, node->node_index,
2109 ETHERNET_ARP_ERROR_replies_sent, n_replies_sent);
2110 return frame->n_vectors;
2114 VLIB_REGISTER_NODE (arp_term_l2bd_node, static) = {
2115 .function = arp_term_l2bd,
2116 .name = "arp-term-l2bd",
2117 .vector_size = sizeof (u32),
2118 .n_errors = ETHERNET_ARP_N_ERROR,
2119 .error_strings = ethernet_arp_error_strings,
2120 .n_next_nodes = ARP_TERM_N_NEXT,
2122 [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
2123 [ARP_TERM_NEXT_DROP] = "error-drop",
2125 .format_buffer = format_ethernet_arp_header,
2126 .format_trace = format_arp_term_input_trace,
2131 arp_term_init (vlib_main_t * vm)
2132 { // Initialize the feature next-node indexes
2133 feat_bitmap_init_next_nodes (vm,
2134 arp_term_l2bd_node.index,
2136 l2input_get_feat_names (),
2137 arp_term_next_node_index);
2141 VLIB_INIT_FUNCTION (arp_term_init);
2144 * fd.io coding-style-patch-verification: ON
2147 * eval: (c-set-style "gnu")