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/ethernet/ethernet.h>
20 #include <vnet/ethernet/arp_packet.h>
21 #include <vnet/l2/l2_input.h>
22 #include <vppinfra/mhash.h>
24 void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length);
29 ip4_address_t ip4_address;
30 } ethernet_arp_ip4_key_t;
33 ethernet_arp_ip4_key_t key;
34 u8 ethernet_address[6];
37 #define ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC (1 << 0)
38 #define ETHERNET_ARP_IP4_ENTRY_FLAG_GLEAN (2 << 0)
40 u64 cpu_time_last_updated;
43 } ethernet_arp_ip4_entry_t;
49 } ethernet_proxy_arp_t;
56 /* Used for arp event notification only */
59 } pending_resolution_t;
62 /* Hash tables mapping name to opcode. */
63 uword * opcode_by_name;
65 /* lite beer "glean" adjacency handling */
66 uword * pending_resolutions_by_address;
67 pending_resolution_t * pending_resolutions;
69 /* Mac address change notification */
70 uword * mac_changes_by_address;
71 pending_resolution_t * mac_changes;
73 u32 * arp_input_next_index_by_hw_if_index;
75 ethernet_arp_ip4_entry_t * ip4_entry_pool;
77 mhash_t ip4_entry_by_key;
79 /* ARP attack mitigation */
81 u32 limit_arp_cache_size;
83 /* Proxy arp vector */
84 ethernet_proxy_arp_t * proxy_arps;
85 } ethernet_arp_main_t;
87 static ethernet_arp_main_t ethernet_arp_main;
89 static u8 * format_ethernet_arp_hardware_type (u8 * s, va_list * va)
91 ethernet_arp_hardware_type_t h = va_arg (*va, ethernet_arp_hardware_type_t);
95 #define _(n,f) case n: t = #f; break;
96 foreach_ethernet_arp_hardware_type;
100 return format (s, "unknown 0x%x", h);
103 return format (s, "%s", t);
106 static u8 * format_ethernet_arp_opcode (u8 * s, va_list * va)
108 ethernet_arp_opcode_t o = va_arg (*va, ethernet_arp_opcode_t);
112 #define _(f) case ETHERNET_ARP_OPCODE_##f: t = #f; break;
113 foreach_ethernet_arp_opcode;
117 return format (s, "unknown 0x%x", o);
120 return format (s, "%s", t);
124 unformat_ethernet_arp_opcode_host_byte_order (unformat_input_t * input,
127 int * result = va_arg (*args, int *);
128 ethernet_arp_main_t * am = ðernet_arp_main;
131 /* Numeric opcode. */
132 if (unformat (input, "0x%x", &x)
133 || unformat (input, "%d", &x))
142 if (unformat_user (input, unformat_vlib_number_by_name,
143 am->opcode_by_name, &i))
153 unformat_ethernet_arp_opcode_net_byte_order (unformat_input_t * input,
156 int * result = va_arg (*args, int *);
157 if (! unformat_user (input, unformat_ethernet_arp_opcode_host_byte_order, result))
160 *result = clib_host_to_net_u16 ((u16) *result);
164 static u8 * format_ethernet_arp_header (u8 * s, va_list * va)
166 ethernet_arp_header_t * a = va_arg (*va, ethernet_arp_header_t *);
167 u32 max_header_bytes = va_arg (*va, u32);
169 u16 l2_type, l3_type;
171 if (max_header_bytes != 0 && sizeof (a[0]) > max_header_bytes)
172 return format (s, "ARP header truncated");
174 l2_type = clib_net_to_host_u16 (a->l2_type);
175 l3_type = clib_net_to_host_u16 (a->l3_type);
177 indent = format_get_indent (s);
179 s = format (s, "%U, type %U/%U, address size %d/%d",
180 format_ethernet_arp_opcode, clib_net_to_host_u16 (a->opcode),
181 format_ethernet_arp_hardware_type, l2_type,
182 format_ethernet_type, l3_type,
183 a->n_l2_address_bytes, a->n_l3_address_bytes);
185 if (l2_type == ETHERNET_ARP_HARDWARE_TYPE_ethernet
186 && l3_type == ETHERNET_TYPE_IP4)
188 s = format (s, "\n%U%U/%U -> %U/%U",
189 format_white_space, indent,
190 format_ethernet_address, a->ip4_over_ethernet[0].ethernet,
191 format_ip4_address, &a->ip4_over_ethernet[0].ip4,
192 format_ethernet_address, a->ip4_over_ethernet[1].ethernet,
193 format_ip4_address, &a->ip4_over_ethernet[1].ip4);
197 uword n2 = a->n_l2_address_bytes;
198 uword n3 = a->n_l3_address_bytes;
199 s = format (s, "\n%U%U/%U -> %U/%U",
200 format_white_space, indent,
201 format_hex_bytes, a->data + 0*n2 + 0*n3, n2,
202 format_hex_bytes, a->data + 1*n2 + 0*n3, n3,
203 format_hex_bytes, a->data + 1*n2 + 1*n3, n2,
204 format_hex_bytes, a->data + 2*n2 + 1*n3, n3);
210 static u8 * format_ethernet_arp_ip4_entry (u8 * s, va_list * va)
212 vnet_main_t * vnm = va_arg (*va, vnet_main_t *);
213 ethernet_arp_ip4_entry_t * e = va_arg (*va, ethernet_arp_ip4_entry_t *);
214 vnet_sw_interface_t * si;
219 return format (s, "%=12s%=6s%=16s%=6s%=20s%=24s", "Time", "FIB", "IP4",
220 "Flags", "Ethernet", "Interface");
222 fib = find_ip4_fib_by_table_index_or_id (&ip4_main, e->key.fib_index,
223 IP4_ROUTE_FLAG_FIB_INDEX);
224 si = vnet_get_sw_interface (vnm, e->key.sw_if_index);
226 if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_GLEAN)
227 flags = format(flags, "G");
229 if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
230 flags = format(flags, "S");
232 s = format (s, "%=12U%=6u%=16U%=6s%=20U%=24U",
233 format_vlib_cpu_time, vnm->vlib_main, e->cpu_time_last_updated,
235 format_ip4_address, &e->key.ip4_address,
236 flags ? (char *) flags : "",
237 format_ethernet_address, e->ethernet_address,
238 format_vnet_sw_interface_name, vnm, si);
246 } ethernet_arp_input_trace_t;
248 static u8 * format_ethernet_arp_input_trace (u8 * s, va_list * va)
250 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
251 CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
252 ethernet_arp_input_trace_t * t = va_arg (*va, ethernet_arp_input_trace_t *);
255 format_ethernet_arp_header,
256 t->packet_data, sizeof (t->packet_data));
262 ethernet_arp_sw_interface_up_down (vnet_main_t * vnm,
266 ethernet_arp_main_t * am = ðernet_arp_main;
267 ethernet_arp_ip4_entry_t * e;
269 if (! (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
271 u32 i, * to_delete = 0;
273 pool_foreach (e, am->ip4_entry_pool, ({
274 if (e->key.sw_if_index == sw_if_index)
275 vec_add1 (to_delete, e - am->ip4_entry_pool);
278 for (i = 0; i < vec_len (to_delete); i++)
280 ethernet_arp_ip4_over_ethernet_address_t delme;
281 e = pool_elt_at_index (am->ip4_entry_pool, to_delete[i]);
283 memcpy (&delme.ethernet, e->ethernet_address, 6);
284 delme.ip4.as_u32 = e->key.ip4_address.as_u32;
286 vnet_arp_unset_ip4_over_ethernet (vnm, e->key.sw_if_index,
287 e->key.fib_index, &delme);
290 vec_free (to_delete);
296 VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ethernet_arp_sw_interface_up_down);
299 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
306 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
314 ethernet_arp_ip4_over_ethernet_address_t a;
316 int is_remove; /* set is_remove=1 to clear arp entry */
317 } vnet_arp_set_ip4_over_ethernet_rpc_args_t;
319 static void set_ip4_over_ethernet_rpc_callback
320 ( vnet_arp_set_ip4_over_ethernet_rpc_args_t * a)
322 vnet_main_t * vm = vnet_get_main();
323 ASSERT(os_get_cpu_number() == 0);
326 vnet_arp_unset_ip4_over_ethernet_internal(vm,
331 vnet_arp_set_ip4_over_ethernet_internal (vm,
339 vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm,
345 ethernet_arp_ip4_over_ethernet_address_t * a = a_arg;
346 vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
348 args.sw_if_index = sw_if_index;
349 args.fib_index = fib_index;
350 args.is_static = is_static;
352 memcpy (&args.a, a, sizeof (*a));
354 vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
355 (u8 *) &args, sizeof (args));
360 vnet_arp_set_ip4_over_ethernet_internal (vnet_main_t * vnm,
366 ethernet_arp_ip4_key_t k;
367 ethernet_arp_ip4_entry_t * e = 0;
368 ethernet_arp_main_t * am = ðernet_arp_main;
369 ethernet_arp_ip4_over_ethernet_address_t * a = a_arg;
370 vlib_main_t * vm = vlib_get_main();
371 ip4_main_t * im = &ip4_main;
372 ip_lookup_main_t * lm = &im->lookup_main;
373 int make_new_arp_cache_entry=1;
375 ip4_add_del_route_args_t args;
376 ip_adjacency_t adj, * existing_adj;
377 pending_resolution_t * pr, * mc;
382 fib_index = (fib_index != (u32)~0)
383 ? fib_index : im->fib_index_by_sw_if_index[sw_if_index];
385 k.sw_if_index = sw_if_index;
386 k.ip4_address = a->ip4;
387 k.fib_index = fib_index;
389 p = mhash_get (&am->ip4_entry_by_key, &k);
392 e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
394 /* Refuse to over-write static arp. */
395 if (e->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC)
397 make_new_arp_cache_entry = 0;
400 /* Note: always install the route. It might have been deleted */
401 memset(&adj, 0, sizeof(adj));
402 adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
404 vnet_rewrite_for_sw_interface
406 VNET_L3_PACKET_TYPE_IP4,
408 ip4_rewrite_node.index,
409 a->ethernet, /* destination address */
411 sizeof (adj.rewrite_data));
413 /* result of this lookup should be next-hop adjacency */
414 adj_index = ip4_fib_lookup_with_table (im, fib_index, &a->ip4, 0);
415 existing_adj = ip_get_adjacency(lm, adj_index);
417 if (existing_adj->lookup_next_index == IP_LOOKUP_NEXT_ARP &&
418 existing_adj->arp.next_hop.ip4.as_u32 == a->ip4.as_u32)
421 u32 * adjs = vec_dup(e->adjacencies);
422 /* Update all adj assigned to this arp entry */
423 vec_foreach(ai, adjs)
426 ip_adjacency_t * uadj = ip_get_adjacency(lm, *ai);
427 for (i = 0; i < uadj->n_adj; i++)
428 if (uadj[i].lookup_next_index == IP_LOOKUP_NEXT_ARP &&
429 uadj[i].arp.next_hop.ip4.as_u32 == a->ip4.as_u32)
430 ip_update_adjacency (lm, *ai + i, &adj);
437 args.table_index_or_table_id = fib_index;
438 args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_ADD | IP4_ROUTE_FLAG_NEIGHBOR;
439 args.dst_address = a->ip4;
440 args.dst_address_length = 32;
444 ip4_add_del_route (im, &args);
447 if (make_new_arp_cache_entry)
449 pool_get (am->ip4_entry_pool, e);
450 mhash_set (&am->ip4_entry_by_key, &k,
451 e - am->ip4_entry_pool,
456 /* Update time stamp and ethernet address. */
457 memcpy (e->ethernet_address, a->ethernet, sizeof (e->ethernet_address));
458 e->cpu_time_last_updated = clib_cpu_time_now ();
460 e->flags |= ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC;
462 /* Customer(s) waiting for this address to be resolved? */
463 p = hash_get (am->pending_resolutions_by_address, a->ip4.as_u32);
468 while (next_index != (u32)~0)
470 pr = pool_elt_at_index (am->pending_resolutions, next_index);
471 vlib_process_signal_event (vm, pr->node_index,
474 next_index = pr->next_index;
475 pool_put (am->pending_resolutions, pr);
478 hash_unset (am->pending_resolutions_by_address, a->ip4.as_u32);
481 /* Customer(s) requesting ARP event for this address? */
482 p = hash_get (am->mac_changes_by_address, a->ip4.as_u32);
487 while (next_index != (u32)~0)
489 int (*fp)(u32, u8 *, u32, u32);
491 mc = pool_elt_at_index (am->mac_changes, next_index);
492 fp = mc->data_callback;
494 /* Call the user's data callback, return 1 to suppress dup events */
496 rv = (*fp)(mc->data, a->ethernet, sw_if_index, 0);
499 * Signal the resolver process, as long as the user
500 * says they want to be notified
503 vlib_process_signal_event (vm, mc->node_index,
506 next_index = mc->next_index;
513 void vnet_register_ip4_arp_resolution_event (vnet_main_t * vnm,
519 ethernet_arp_main_t * am = ðernet_arp_main;
520 ip4_address_t * address = address_arg;
522 pending_resolution_t * pr;
524 pool_get (am->pending_resolutions, pr);
527 pr->node_index = node_index;
528 pr->type_opaque = type_opaque;
530 pr->data_callback = 0;
532 p = hash_get (am->pending_resolutions_by_address, address->as_u32);
535 /* Insert new resolution at the head of the list */
536 pr->next_index = p[0];
537 hash_unset (am->pending_resolutions_by_address, address->as_u32);
540 hash_set (am->pending_resolutions_by_address, address->as_u32,
541 pr - am->pending_resolutions);
544 int vnet_add_del_ip4_arp_change_event (vnet_main_t * vnm,
545 void * data_callback,
550 uword data, int is_add)
552 ethernet_arp_main_t * am = ðernet_arp_main;
553 ip4_address_t * address = address_arg;
555 pending_resolution_t * mc;
556 void (*fp)(u32, u8 *) = data_callback;
560 pool_get (am->mac_changes, mc);
563 mc->node_index = node_index;
564 mc->type_opaque = type_opaque;
566 mc->data_callback = data_callback;
569 p = hash_get (am->mac_changes_by_address, address->as_u32);
572 /* Insert new resolution at the head of the list */
573 mc->next_index = p[0];
574 hash_unset (am->mac_changes_by_address, address->as_u32);
577 hash_set (am->mac_changes_by_address, address->as_u32,
578 mc - am->mac_changes);
584 pending_resolution_t * mc_last = 0;
586 p = hash_get (am->mac_changes_by_address, address->as_u32);
588 return VNET_API_ERROR_NO_SUCH_ENTRY;
592 while (index != (u32)~0)
594 mc = pool_elt_at_index (am->mac_changes, index);
595 if (mc->node_index == node_index &&
596 mc->type_opaque == type_opaque &&
599 /* Clients may need to clean up pool entries, too */
601 (*fp)(mc->data, 0 /* no new mac addrs */);
604 hash_unset (am->mac_changes_by_address, address->as_u32);
605 if (mc->next_index != ~0)
606 hash_set (am->mac_changes_by_address, address->as_u32,
608 pool_put (am->mac_changes, mc);
614 mc_last->next_index = mc->next_index;
615 pool_put (am->mac_changes, mc);
620 index = mc->next_index;
623 return VNET_API_ERROR_NO_SUCH_ENTRY;
627 /* Either we drop the packet or we send a reply to the sender. */
633 #define foreach_ethernet_arp_error \
634 _ (replies_sent, "ARP replies sent") \
635 _ (l2_type_not_ethernet, "L2 type not ethernet") \
636 _ (l3_type_not_ip4, "L3 type not IP4") \
637 _ (l3_src_address_not_local, "IP4 source address not local to subnet") \
638 _ (l3_dst_address_not_local, "IP4 destination address not local to subnet") \
639 _ (l3_src_address_is_local, "IP4 source address matches local interface") \
640 _ (l3_src_address_learned, "ARP request IP4 source address learned") \
641 _ (replies_received, "ARP replies received") \
642 _ (opcode_not_request, "ARP opcode not request") \
643 _ (proxy_arp_replies_sent, "Proxy ARP replies sent") \
644 _ (l2_address_mismatch, "ARP hw addr does not match L2 frame src addr") \
645 _ (missing_interface_address, "ARP missing interface address") \
646 _ (gratuitous_arp, "ARP probe or announcement dropped") \
649 #define _(sym,string) ETHERNET_ARP_ERROR_##sym,
650 foreach_ethernet_arp_error
652 ETHERNET_ARP_N_ERROR,
653 } ethernet_arp_input_error_t;
655 /* get first interface address */
657 ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index,
658 ip_interface_address_t ** result_ia)
660 ip_lookup_main_t * lm = &im->lookup_main;
661 ip_interface_address_t * ia = 0;
662 ip4_address_t * result = 0;
664 foreach_ip_interface_address (lm, ia, sw_if_index,
665 1 /* honor unnumbered */,
667 ip4_address_t * a = ip_interface_address_get_address (lm, ia);
672 *result_ia = result ? ia : 0;
676 static void unset_random_arp_entry (void)
678 ethernet_arp_main_t * am = ðernet_arp_main;
679 ethernet_arp_ip4_entry_t * e;
680 vnet_main_t * vnm = vnet_get_main();
681 ethernet_arp_ip4_over_ethernet_address_t delme;
684 index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
685 am->arp_delete_rotor = index;
687 /* Try again from elt 0, could happen if an intfc goes down */
690 index = pool_next_index (am->ip4_entry_pool, am->arp_delete_rotor);
691 am->arp_delete_rotor = index;
694 /* Nothing left in the pool */
698 e = pool_elt_at_index (am->ip4_entry_pool, index);
700 memcpy (&delme.ethernet, e->ethernet_address, 6);
701 delme.ip4.as_u32 = e->key.ip4_address.as_u32;
703 vnet_arp_unset_ip4_over_ethernet (vnm, e->key.sw_if_index,
704 e->key.fib_index, &delme);
707 static u32 arp_unnumbered (vlib_buffer_t * p0,
709 ethernet_header_t * eth0,
710 ip_interface_address_t * ifa0)
712 ethernet_arp_main_t * am = ðernet_arp_main;
713 vlib_main_t * vm = vlib_get_main();
714 vnet_main_t * vnm = vnet_get_main();
715 vnet_interface_main_t * vim = &vnm->interface_main;
716 vnet_sw_interface_t * si;
717 vnet_hw_interface_t * hi;
718 u32 unnum_src_sw_if_index;
719 u32 * broadcast_swifs = 0;
724 u8 dst_mac_address[6];
726 ethernet_arp_header_t * arp0;
728 /* Save the dst mac address */
729 memcpy(dst_mac_address, eth0->dst_address, sizeof (dst_mac_address));
731 /* Figure out which sw_if_index supplied the address */
732 unnum_src_sw_if_index = ifa0->sw_if_index;
734 /* Track down all users of the unnumbered source */
735 pool_foreach (si, vim->sw_interfaces,
737 if (si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED &&
738 (si->unnumbered_sw_if_index == unnum_src_sw_if_index))
740 vec_add1 (broadcast_swifs, si->sw_if_index);
745 ASSERT (vec_len(broadcast_swifs));
747 /* Allocate buffering if we need it */
748 if (vec_len(broadcast_swifs) > 1)
750 vec_validate (buffers, vec_len(broadcast_swifs)-2);
751 n_alloc = vlib_buffer_alloc (vm, buffers, vec_len(buffers));
752 _vec_len (buffers) = n_alloc;
753 for (i = 0; i < n_alloc; i++)
755 b0 = vlib_get_buffer (vm, buffers[i]);
757 /* xerox (partially built) ARP pkt */
758 memcpy (b0->data, p0->data, p0->current_length + p0->current_data);
759 b0->current_data = p0->current_data;
760 b0->current_length = p0->current_length;
761 vnet_buffer(b0)->sw_if_index[VLIB_RX] =
762 vnet_buffer(p0)->sw_if_index[VLIB_RX];
766 vec_insert (buffers, 1, 0);
769 for (i = 0; i < vec_len(buffers); i++)
771 b0 = vlib_get_buffer(vm, buffers[i]);
772 arp0 = vlib_buffer_get_current (b0);
774 hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[i]);
775 si = vnet_get_sw_interface (vnm, broadcast_swifs[i]);
777 /* For decoration, most likely */
778 vnet_buffer(b0)->sw_if_index[VLIB_TX] = hi->sw_if_index;
780 /* Fix ARP pkt src address */
781 memcpy (arp0->ip4_over_ethernet[0].ethernet, hi->hw_address, 6);
783 /* Build L2 encaps for this swif */
784 header_size = sizeof (ethernet_header_t);
785 if (si->sub.eth.flags.one_tag)
787 else if (si->sub.eth.flags.two_tags)
790 vlib_buffer_advance (b0, -header_size);
791 eth0 = vlib_buffer_get_current (b0);
793 if (si->sub.eth.flags.one_tag) {
794 ethernet_vlan_header_t * outer = (void *) (eth0 + 1);
796 eth0->type = si->sub.eth.flags.dot1ad ?
797 clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
798 clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
799 outer->priority_cfi_and_id =
800 clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
801 outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
803 } else if (si->sub.eth.flags.two_tags) {
804 ethernet_vlan_header_t * outer = (void *) (eth0 + 1);
805 ethernet_vlan_header_t * inner = (void *) (outer + 1);
807 eth0->type = si->sub.eth.flags.dot1ad ?
808 clib_host_to_net_u16 (ETHERNET_TYPE_DOT1AD) :
809 clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
810 outer->priority_cfi_and_id =
811 clib_host_to_net_u16 (si->sub.eth.outer_vlan_id);
812 outer->type = clib_host_to_net_u16 (ETHERNET_TYPE_VLAN);
813 inner->priority_cfi_and_id =
814 clib_host_to_net_u16 (si->sub.eth.inner_vlan_id);
815 inner->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
818 eth0->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
821 /* Restore the original dst address, set src address */
822 memcpy (eth0->dst_address, dst_mac_address, sizeof (eth0->dst_address));
823 memcpy (eth0->src_address, hi->hw_address, sizeof (eth0->src_address));
825 /* Transmit replicas */
828 vlib_frame_t * f = vlib_get_frame_to_node (vm, hi->output_node_index);
829 u32 * to_next = vlib_frame_vector_args (f);
830 to_next[0] = buffers[i];
832 vlib_put_frame_to_node (vm, hi->output_node_index, f);
836 hi = vnet_get_sup_hw_interface (vnm, broadcast_swifs[0]);
838 vec_free (broadcast_swifs);
841 /* The regular path outputs the original pkt.. */
842 return vec_elt (am->arp_input_next_index_by_hw_if_index, hi->hw_if_index);
846 arp_input (vlib_main_t * vm,
847 vlib_node_runtime_t * node,
848 vlib_frame_t * frame)
850 ethernet_arp_main_t * am = ðernet_arp_main;
851 vnet_main_t * vnm = vnet_get_main();
852 ip4_main_t * im4 = &ip4_main;
853 u32 n_left_from, next_index, * from, * to_next;
854 u32 n_replies_sent = 0, n_proxy_arp_replies_sent = 0;
856 from = vlib_frame_vector_args (frame);
857 n_left_from = frame->n_vectors;
858 next_index = node->cached_next_index;
860 if (node->flags & VLIB_NODE_FLAG_TRACE)
861 vlib_trace_frame_buffers_only (vm, node, from, frame->n_vectors,
863 sizeof (ethernet_arp_input_trace_t));
865 while (n_left_from > 0)
869 vlib_get_next_frame (vm, node, next_index,
870 to_next, n_left_to_next);
872 while (n_left_from > 0 && n_left_to_next > 0)
875 vnet_hw_interface_t * hw_if0;
876 ethernet_arp_header_t * arp0;
877 ethernet_header_t * eth0;
878 ip_interface_address_t * ifa0;
879 ip_adjacency_t * adj0;
880 ip4_address_t * if_addr0;
881 ip4_address_t proxy_src;
882 u32 pi0, error0, next0, sw_if_index0;
883 u8 is_request0, src_is_local0, dst_is_local0, is_unnum0;
884 ethernet_proxy_arp_t * pa;
893 p0 = vlib_get_buffer (vm, pi0);
894 arp0 = vlib_buffer_get_current (p0);
896 is_request0 = arp0->opcode
897 == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_request);
899 error0 = ETHERNET_ARP_ERROR_replies_sent;
901 error0 = (arp0->l2_type != clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
902 ? ETHERNET_ARP_ERROR_l2_type_not_ethernet
904 error0 = (arp0->l3_type != clib_net_to_host_u16 (ETHERNET_TYPE_IP4)
905 ? ETHERNET_ARP_ERROR_l3_type_not_ip4
908 sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
913 /* Check that IP address is local and matches incoming interface. */
914 if_addr0 = ip4_interface_address_matching_destination (im4,
915 &arp0->ip4_over_ethernet[1].ip4,
920 error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
924 /* Honor unnumbered interface, if any */
925 is_unnum0 = sw_if_index0 != ifa0->sw_if_index;
927 /* Source must also be local to subnet of matching interface address. */
928 if (! ip4_destination_matches_interface (im4, &arp0->ip4_over_ethernet[0].ip4, ifa0))
930 error0 = ETHERNET_ARP_ERROR_l3_src_address_not_local;
934 /* Reject requests/replies with our local interface address. */
935 src_is_local0 = if_addr0->as_u32 == arp0->ip4_over_ethernet[0].ip4.as_u32;
938 error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
942 dst_is_local0 = if_addr0->as_u32 == arp0->ip4_over_ethernet[1].ip4.as_u32;
944 /* Fill in ethernet header. */
945 eth0 = ethernet_buffer_get_header (p0);
947 /* Trash ARP packets whose ARP-level source addresses do not
948 match their L2-frame-level source addresses */
949 if (memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
950 sizeof (eth0->src_address)))
952 error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
956 /* Learn or update sender's mapping only for requests or unicasts
957 that don't match local interface address. */
958 if (ethernet_address_cast (eth0->dst_address) == ETHERNET_ADDRESS_UNICAST
961 if (am->limit_arp_cache_size &&
962 pool_elts (am->ip4_entry_pool) >= am->limit_arp_cache_size)
963 unset_random_arp_entry();
965 vnet_arp_set_ip4_over_ethernet (vnm, sw_if_index0,
966 (u32)~0 /* default fib */,
967 &arp0->ip4_over_ethernet[0],
969 error0 = ETHERNET_ARP_ERROR_l3_src_address_learned;
972 /* Only send a reply for requests sent which match a local interface. */
973 if (! (is_request0 && dst_is_local0))
975 error0 = (arp0->opcode == clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply)
976 ? ETHERNET_ARP_ERROR_replies_received : error0);
982 vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
983 hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
985 /* Can happen in a multi-core env. */
986 if (PREDICT_FALSE(hw_if0->hw_if_index >= vec_len (am->arp_input_next_index_by_hw_if_index)))
988 error0 = ETHERNET_ARP_ERROR_missing_interface_address;
992 next0 = vec_elt (am->arp_input_next_index_by_hw_if_index, hw_if0->hw_if_index);
994 arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
996 arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
998 memcpy (arp0->ip4_over_ethernet[0].ethernet, hw_if0->hw_address, 6);
999 clib_mem_unaligned (&arp0->ip4_over_ethernet[0].ip4.data_u32, u32) = if_addr0->data_u32;
1001 /* Hardware must be ethernet-like. */
1002 ASSERT (vec_len (hw_if0->hw_address) == 6);
1004 memcpy (eth0->dst_address, eth0->src_address, 6);
1005 memcpy (eth0->src_address, hw_if0->hw_address, 6);
1007 /* Figure out how much to rewind current data from adjacency. */
1010 adj0 = ip_get_adjacency (&ip4_main.lookup_main,
1011 ifa0->neighbor_probe_adj_index);
1012 if (adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP)
1014 error0 = ETHERNET_ARP_ERROR_missing_interface_address;
1018 next0 = arp_unnumbered (p0, pi0, eth0, ifa0);
1020 vlib_buffer_advance (p0, -adj0->rewrite_header.data_bytes);
1023 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1024 n_left_to_next,pi0,next0);
1026 n_replies_sent += 1;
1030 if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1031 (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1032 arp0->ip4_over_ethernet[1].ip4.as_u32))
1034 error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1037 /* See if proxy arp is configured for the address */
1040 vnet_sw_interface_t * si;
1041 u32 this_addr = clib_net_to_host_u32
1042 (arp0->ip4_over_ethernet[1].ip4.as_u32);
1045 si = vnet_get_sw_interface (vnm, sw_if_index0);
1047 if (!(si->flags & VNET_SW_INTERFACE_FLAG_PROXY_ARP))
1050 fib_index0 = vec_elt (im4->fib_index_by_sw_if_index,
1053 vec_foreach (pa, am->proxy_arps)
1055 u32 lo_addr = clib_net_to_host_u32 (pa->lo_addr);
1056 u32 hi_addr = clib_net_to_host_u32 (pa->hi_addr);
1058 /* an ARP request hit in the proxy-arp table? */
1059 if ((this_addr >= lo_addr && this_addr <= hi_addr) &&
1060 (fib_index0 == pa->fib_index))
1062 eth0 = ethernet_buffer_get_header (p0);
1064 arp0->ip4_over_ethernet[1].ip4.data_u32;
1067 * Rewind buffer, direct code above not to
1068 * think too hard about it.
1069 * $$$ is the answer ever anything other than
1070 * vlib_buffer_reset(..)?
1073 if_addr0 = &proxy_src;
1074 vlib_buffer_reset (p0);
1075 n_proxy_arp_replies_sent++;
1083 next0 = ARP_INPUT_NEXT_DROP;
1084 p0->error = node->errors[error0];
1086 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1087 n_left_to_next,pi0,next0);
1090 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1093 vlib_error_count (vm, node->node_index,
1094 ETHERNET_ARP_ERROR_replies_sent,
1095 n_replies_sent - n_proxy_arp_replies_sent);
1097 vlib_error_count (vm, node->node_index,
1098 ETHERNET_ARP_ERROR_proxy_arp_replies_sent,
1099 n_proxy_arp_replies_sent);
1100 return frame->n_vectors;
1103 static char * ethernet_arp_error_strings[] = {
1104 #define _(sym,string) string,
1105 foreach_ethernet_arp_error
1109 VLIB_REGISTER_NODE (arp_input_node,static) = {
1110 .function = arp_input,
1111 .name = "arp-input",
1112 .vector_size = sizeof (u32),
1114 .n_errors = ETHERNET_ARP_N_ERROR,
1115 .error_strings = ethernet_arp_error_strings,
1117 .n_next_nodes = ARP_INPUT_N_NEXT,
1119 [ARP_INPUT_NEXT_DROP] = "error-drop",
1122 .format_buffer = format_ethernet_arp_header,
1123 .format_trace = format_ethernet_arp_input_trace,
1127 ethernet_arp_hw_interface_link_up_down (vnet_main_t * vnm,
1131 ethernet_arp_main_t * am = ðernet_arp_main;
1132 vnet_hw_interface_t * hw_if;
1134 hw_if = vnet_get_hw_interface (vnm, hw_if_index);
1136 /* Fill in lookup tables with default table (0). */
1137 vec_validate_init_empty (am->arp_input_next_index_by_hw_if_index, hw_if_index, ~0);
1138 am->arp_input_next_index_by_hw_if_index[hw_if_index]
1139 = vlib_node_add_next (vnm->vlib_main, arp_input_node.index, hw_if->output_node_index);
1144 VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (ethernet_arp_hw_interface_link_up_down);
1147 ip4_arp_entry_sort (void *a1, void *a2)
1149 ethernet_arp_ip4_entry_t * e1 = a1;
1150 ethernet_arp_ip4_entry_t * e2 = a2;
1153 vnet_main_t * vnm = vnet_get_main();
1155 cmp = vnet_sw_interface_compare
1156 (vnm, e1->key.sw_if_index, e2->key.sw_if_index);
1158 cmp = ip4_address_compare (&e1->key.ip4_address, &e2->key.ip4_address);
1162 static clib_error_t *
1163 show_ip4_arp (vlib_main_t * vm,
1164 unformat_input_t * input,
1165 vlib_cli_command_t * cmd)
1167 vnet_main_t * vnm = vnet_get_main();
1168 ethernet_arp_main_t * am = ðernet_arp_main;
1169 ethernet_arp_ip4_entry_t * e, * es;
1170 ethernet_proxy_arp_t * pa;
1171 clib_error_t * error = 0;
1174 /* Filter entries by interface if given. */
1176 (void) unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index);
1179 pool_foreach (e, am->ip4_entry_pool, ({ vec_add1 (es, e[0]); }));
1182 vec_sort_with_function (es, ip4_arp_entry_sort);
1183 vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, 0);
1184 vec_foreach (e, es) {
1185 if (sw_if_index != ~0 && e->key.sw_if_index != sw_if_index)
1187 vlib_cli_output (vm, "%U", format_ethernet_arp_ip4_entry, vnm, e);
1192 if (vec_len (am->proxy_arps))
1194 vlib_cli_output (vm, "Proxy arps enabled for:");
1195 vec_foreach(pa, am->proxy_arps)
1197 vlib_cli_output (vm, "Fib_index %d %U - %U ",
1199 format_ip4_address, &pa->lo_addr,
1200 format_ip4_address, &pa->hi_addr);
1207 VLIB_CLI_COMMAND (show_ip4_arp_command, static) = {
1208 .path = "show ip arp",
1209 .function = show_ip4_arp,
1210 .short_help = "Show ARP table",
1214 pg_edit_t l2_type, l3_type;
1215 pg_edit_t n_l2_address_bytes, n_l3_address_bytes;
1220 } ip4_over_ethernet[2];
1221 } pg_ethernet_arp_header_t;
1224 pg_ethernet_arp_header_init (pg_ethernet_arp_header_t * p)
1226 /* Initialize fields that are not bit fields in the IP header. */
1227 #define _(f) pg_edit_init (&p->f, ethernet_arp_header_t, f);
1230 _ (n_l2_address_bytes);
1231 _ (n_l3_address_bytes);
1233 _ (ip4_over_ethernet[0].ethernet);
1234 _ (ip4_over_ethernet[0].ip4);
1235 _ (ip4_over_ethernet[1].ethernet);
1236 _ (ip4_over_ethernet[1].ip4);
1241 unformat_pg_arp_header (unformat_input_t * input, va_list * args)
1243 pg_stream_t * s = va_arg (*args, pg_stream_t *);
1244 pg_ethernet_arp_header_t * p;
1247 p = pg_create_edit_group (s, sizeof (p[0]), sizeof (ethernet_arp_header_t),
1249 pg_ethernet_arp_header_init (p);
1252 pg_edit_set_fixed (&p->l2_type, ETHERNET_ARP_HARDWARE_TYPE_ethernet);
1253 pg_edit_set_fixed (&p->l3_type, ETHERNET_TYPE_IP4);
1254 pg_edit_set_fixed (&p->n_l2_address_bytes, 6);
1255 pg_edit_set_fixed (&p->n_l3_address_bytes, 4);
1257 if (! unformat (input, "%U: %U/%U -> %U/%U",
1259 unformat_ethernet_arp_opcode_net_byte_order, &p->opcode,
1261 unformat_ethernet_address, &p->ip4_over_ethernet[0].ethernet,
1263 unformat_ip4_address, &p->ip4_over_ethernet[0].ip4,
1265 unformat_ethernet_address, &p->ip4_over_ethernet[1].ethernet,
1267 unformat_ip4_address, &p->ip4_over_ethernet[1].ip4))
1269 /* Free up any edits we may have added. */
1270 pg_free_edit_group (s);
1276 clib_error_t *ip4_set_arp_limit (u32 arp_limit)
1278 ethernet_arp_main_t * am = ðernet_arp_main;
1280 am->limit_arp_cache_size = arp_limit;
1285 arp_ip4_entry_del_adj(ethernet_arp_ip4_entry_t *e, u32 adj_index)
1292 vec_foreach_index(i, e->adjacencies)
1293 if (vec_elt(e->adjacencies, i) == adj_index)
1295 vec_del1(e->adjacencies, i);
1303 arp_ip4_entry_add_adj(ethernet_arp_ip4_entry_t *e, u32 adj_index)
1306 vec_foreach_index(i, e->adjacencies)
1307 if (vec_elt(e->adjacencies, i) == adj_index)
1309 vec_add1(e->adjacencies, adj_index);
1313 arp_add_del_adj_cb (struct ip_lookup_main_t * lm,
1315 ip_adjacency_t * adj,
1318 ethernet_arp_main_t * am = ðernet_arp_main;
1319 ip4_main_t * im = &ip4_main;
1320 ethernet_arp_ip4_key_t k;
1321 ethernet_arp_ip4_entry_t * e = 0;
1325 for(ai = adj->heap_handle; ai < adj->heap_handle + adj->n_adj ; ai++)
1327 adj = ip_get_adjacency (lm, ai);
1328 if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP && adj->arp.next_hop.ip4.as_u32)
1330 k.sw_if_index = adj->rewrite_header.sw_if_index;
1331 k.ip4_address.as_u32 = adj->arp.next_hop.ip4.as_u32;
1332 k.fib_index = im->fib_index_by_sw_if_index[adj->rewrite_header.sw_if_index];
1333 p = mhash_get (&am->ip4_entry_by_key, &k);
1335 e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
1343 clib_warning("Adjacency contains unknown ARP next hop %U (del)",
1344 format_ip4_address, &adj->arp.next_hop);
1346 arp_ip4_entry_del_adj(e, adj->heap_handle);
1351 clib_warning("Adjacency contains unknown ARP next hop %U (add)",
1352 format_ip4_address, &adj->arp.next_hop);
1354 arp_ip4_entry_add_adj(e, adj->heap_handle);
1359 static clib_error_t * ethernet_arp_init (vlib_main_t * vm)
1361 ethernet_arp_main_t * am = ðernet_arp_main;
1363 clib_error_t * error;
1364 ip4_main_t * im = &ip4_main;
1365 ip_lookup_main_t * lm = &im->lookup_main;
1367 if ((error = vlib_call_init_function (vm, ethernet_init)))
1370 ethernet_register_input_type (vm, ETHERNET_TYPE_ARP, arp_input_node.index);
1372 pn = pg_get_node (arp_input_node.index);
1373 pn->unformat_edit = unformat_pg_arp_header;
1375 am->opcode_by_name = hash_create_string (0, sizeof (uword));
1376 #define _(o) hash_set_mem (am->opcode_by_name, #o, ETHERNET_ARP_OPCODE_##o);
1377 foreach_ethernet_arp_opcode;
1380 mhash_init (&am->ip4_entry_by_key,
1381 /* value size */ sizeof (uword),
1382 /* key size */ sizeof (ethernet_arp_ip4_key_t));
1384 /* $$$ configurable */
1385 am->limit_arp_cache_size = 50000;
1387 am->pending_resolutions_by_address = hash_create (0, sizeof (uword));
1388 am->mac_changes_by_address = hash_create (0, sizeof (uword));
1390 /* don't trace ARP error packets */
1392 vlib_node_runtime_t *rt =
1393 vlib_node_get_runtime (vm, arp_input_node.index);
1396 vnet_pcap_drop_trace_filter_add_del \
1397 (rt->errors[ETHERNET_ARP_ERROR_##a], \
1399 foreach_ethernet_arp_error
1403 ip_register_add_del_adjacency_callback(lm, arp_add_del_adj_cb);
1408 VLIB_INIT_FUNCTION (ethernet_arp_init);
1411 vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm,
1412 u32 sw_if_index, u32 fib_index,
1415 ethernet_arp_ip4_over_ethernet_address_t * a = a_arg;
1416 vnet_arp_set_ip4_over_ethernet_rpc_args_t args;
1418 args.sw_if_index = sw_if_index;
1419 args.fib_index = fib_index;
1421 memcpy (&args.a, a, sizeof (*a));
1423 vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback,
1424 (u8 *) &args, sizeof (args));
1429 vnet_arp_unset_ip4_over_ethernet_internal (vnet_main_t * vnm,
1434 ethernet_arp_ip4_entry_t * e;
1435 ethernet_arp_main_t * am = ðernet_arp_main;
1436 ethernet_arp_ip4_over_ethernet_address_t * a = a_arg;
1437 ethernet_arp_ip4_key_t k;
1439 ip4_add_del_route_args_t args;
1440 ip4_main_t * im = &ip4_main;
1441 ip_lookup_main_t * lm = &im->lookup_main;
1443 ip_adjacency_t * adj;
1445 k.sw_if_index = sw_if_index;
1446 k.ip4_address = a->ip4;
1447 k.fib_index = fib_index;
1448 p = mhash_get (&am->ip4_entry_by_key, &k);
1452 memset(&args, 0, sizeof(args));
1455 * Make sure that the route actually exists before we try to delete it,
1456 * and make sure that it's a rewrite adjacency.
1458 * If we point 1-N unnumbered interfaces at a loopback interface and
1459 * shut down the loopback before shutting down 1-N unnumbered
1460 * interfaces, the ARP cache will still have an entry,
1461 * but the route will have disappeared.
1463 * See also ip4_del_interface_routes (...)
1464 * -> ip4_delete_matching_routes (...).
1467 adj_index = ip4_fib_lookup_with_table
1468 (im, fib_index, &a->ip4, 1 /* disable default route */);
1470 /* Miss adj? Forget it... */
1471 if (adj_index != lm->miss_adj_index) {
1472 adj = ip_get_adjacency (lm, adj_index);
1474 * Stupid control-plane trick:
1475 * admin down an interface (removes arp routes from fib),
1476 * bring the interface back up (does not reinstall them)
1477 * then remove the arp cache entry (yuck). When that happens,
1478 * the adj we find here will be the interface subnet ARP adj.
1480 if (adj->lookup_next_index == IP_LOOKUP_NEXT_REWRITE) {
1481 args.table_index_or_table_id = fib_index;
1482 args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_DEL
1483 | IP4_ROUTE_FLAG_NEIGHBOR;
1484 args.dst_address = a->ip4;
1485 args.dst_address_length = 32;
1486 ip4_add_del_route (im, &args);
1487 ip4_maybe_remap_adjacencies (im, fib_index, args.flags);
1491 e = pool_elt_at_index (am->ip4_entry_pool, p[0]);
1492 mhash_unset (&am->ip4_entry_by_key, &e->key, 0);
1493 pool_put (am->ip4_entry_pool, e);
1498 increment_ip4_and_mac_address (ethernet_arp_ip4_over_ethernet_address_t *a)
1503 for (i = 3; i >= 0; i--)
1505 old = a->ip4.as_u8[i];
1506 a->ip4.as_u8[i] += 1;
1507 if (old < a->ip4.as_u8[i])
1511 for (i = 5; i >= 0; i--)
1513 old = a->ethernet[i];
1514 a->ethernet[i] += 1;
1515 if (old < a->ethernet[i])
1520 int vnet_proxy_arp_add_del (ip4_address_t *lo_addr,
1521 ip4_address_t *hi_addr,
1522 u32 fib_index, int is_del)
1524 ethernet_arp_main_t *am = ðernet_arp_main;
1525 ethernet_proxy_arp_t *pa;
1526 u32 found_at_index = ~0;
1528 vec_foreach (pa, am->proxy_arps)
1530 if (pa->lo_addr == lo_addr->as_u32
1531 && pa->hi_addr == hi_addr->as_u32
1532 && pa->fib_index == fib_index)
1534 found_at_index = pa - am->proxy_arps;
1539 if (found_at_index != ~0)
1541 /* Delete, otherwise it's already in the table */
1543 vec_delete (am->proxy_arps, 1, found_at_index);
1546 /* delete, no such entry */
1548 return VNET_API_ERROR_NO_SUCH_ENTRY;
1550 /* add, not in table */
1551 vec_add2 (am->proxy_arps, pa, 1);
1552 pa->lo_addr = lo_addr->as_u32;
1553 pa->hi_addr = hi_addr->as_u32;
1554 pa->fib_index = fib_index;
1559 * Remove any proxy arp entries asdociated with the
1562 int vnet_proxy_arp_fib_reset (u32 fib_id)
1564 ip4_main_t * im = &ip4_main;
1565 ethernet_arp_main_t *am = ðernet_arp_main;
1566 ethernet_proxy_arp_t *pa;
1567 u32 * entries_to_delete = 0;
1572 p = hash_get (im->fib_index_by_table_id, fib_id);
1574 return VNET_API_ERROR_NO_SUCH_ENTRY;
1577 vec_foreach (pa, am->proxy_arps)
1579 if (pa->fib_index == fib_index)
1581 vec_add1 (entries_to_delete, pa - am->proxy_arps);
1585 for (i = 0; i < vec_len(entries_to_delete); i++)
1587 vec_delete (am->proxy_arps, 1, entries_to_delete[i]);
1590 vec_free (entries_to_delete);
1596 vnet_arp_glean_add(u32 fib_index, void * next_hop_arg)
1598 ethernet_arp_main_t * am = ðernet_arp_main;
1599 ip4_main_t * im = &ip4_main;
1600 ip_lookup_main_t * lm = &im->lookup_main;
1601 ip4_address_t * next_hop = next_hop_arg;
1602 ip_adjacency_t add_adj, *adj;
1603 ip4_add_del_route_args_t args;
1604 ethernet_arp_ip4_entry_t * e;
1605 ethernet_arp_ip4_key_t k;
1608 adj_index = ip4_fib_lookup_with_table(im, fib_index, next_hop, 0);
1609 adj = ip_get_adjacency(lm, adj_index);
1611 if (!adj || adj->lookup_next_index != IP_LOOKUP_NEXT_ARP)
1614 if (adj->arp.next_hop.ip4.as_u32 != 0)
1617 k.sw_if_index = adj->rewrite_header.sw_if_index;
1618 k.fib_index = fib_index;
1619 k.ip4_address.as_u32 = next_hop->as_u32;
1621 if (mhash_get (&am->ip4_entry_by_key, &k))
1624 pool_get (am->ip4_entry_pool, e);
1625 mhash_set (&am->ip4_entry_by_key, &k, e - am->ip4_entry_pool, /* old value */ 0);
1627 e->cpu_time_last_updated = clib_cpu_time_now ();
1628 e->flags = ETHERNET_ARP_IP4_ENTRY_FLAG_GLEAN;
1630 memset(&args, 0, sizeof(args));
1631 memcpy(&add_adj, adj, sizeof(add_adj));
1632 add_adj.arp.next_hop.ip4.as_u32 = next_hop->as_u32; /* install neighbor /32 route */
1633 args.table_index_or_table_id = fib_index;
1634 args.flags = IP4_ROUTE_FLAG_FIB_INDEX | IP4_ROUTE_FLAG_ADD| IP4_ROUTE_FLAG_NEIGHBOR;
1635 args.dst_address.as_u32 = next_hop->as_u32;
1636 args.dst_address_length = 32;
1637 args.adj_index = ~0;
1638 args.add_adj = &add_adj;
1640 ip4_add_del_route (im, &args);
1641 return ip4_fib_lookup_with_table (im, fib_index, next_hop, 0);
1644 static clib_error_t *
1645 ip_arp_add_del_command_fn (vlib_main_t * vm,
1646 unformat_input_t * input,
1647 vlib_cli_command_t * cmd)
1649 vnet_main_t * vnm = vnet_get_main();
1651 ethernet_arp_ip4_over_ethernet_address_t lo_addr, hi_addr, addr;
1660 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1662 /* set ip arp TenGigE1/1/0/1 1.2.3.4 aa:bb:... or aabb.ccdd... */
1663 if (unformat (input, "%U %U %U",
1664 unformat_vnet_sw_interface, vnm, &sw_if_index,
1665 unformat_ip4_address, &addr.ip4,
1666 unformat_ethernet_address, &addr.ethernet))
1669 else if (unformat (input, "delete") || unformat (input, "del"))
1672 else if (unformat (input, "static"))
1675 else if (unformat (input, "count %d", &count))
1678 else if (unformat (input, "fib-id %d", &fib_id))
1680 ip4_main_t * im = &ip4_main;
1681 uword * p = hash_get (im->fib_index_by_table_id, fib_id);
1683 return clib_error_return (0, "fib ID %d doesn't exist\n",
1688 else if (unformat (input, "proxy %U - %U",
1689 unformat_ip4_address, &lo_addr.ip4,
1690 unformat_ip4_address, &hi_addr.ip4))
1698 (void) vnet_proxy_arp_add_del (&lo_addr.ip4, &hi_addr.ip4,
1707 for (i = 0; i < count; i++)
1711 uword event_type, * event_data = 0;
1713 /* Park the debug CLI until the arp entry is installed */
1714 vnet_register_ip4_arp_resolution_event
1715 (vnm, &addr.ip4, vlib_current_process(vm),
1716 1 /* type */, 0 /* data */);
1718 vnet_arp_set_ip4_over_ethernet
1719 (vnm, sw_if_index, fib_index, &addr, is_static);
1721 vlib_process_wait_for_event (vm);
1722 event_type = vlib_process_get_events (vm, &event_data);
1723 vec_reset_length(event_data);
1724 if (event_type != 1)
1725 clib_warning ("event type %d unexpected", event_type);
1728 vnet_arp_unset_ip4_over_ethernet
1729 (vnm, sw_if_index, fib_index, &addr);
1731 increment_ip4_and_mac_address (&addr);
1736 return clib_error_return (0, "unknown input `%U'",
1737 format_unformat_error, input);
1743 VLIB_CLI_COMMAND (ip_arp_add_del_command, static) = {
1744 .path = "set ip arp",
1745 .short_help = "set ip arp [del] <intfc> <ip-address> <mac-address>",
1746 .function = ip_arp_add_del_command_fn,
1749 static clib_error_t *
1750 set_int_proxy_arp_command_fn (vlib_main_t * vm,
1751 unformat_input_t * input,
1752 vlib_cli_command_t * cmd)
1754 vnet_main_t * vnm = vnet_get_main();
1756 vnet_sw_interface_t * si;
1760 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1762 if (unformat (input, "%U", unformat_vnet_sw_interface,
1765 else if (unformat (input, "enable") || unformat (input, "on"))
1767 else if (unformat (input, "disable") || unformat (input, "off"))
1774 return clib_error_return (0, "unknown input '%U'",
1775 format_unformat_error, input);
1777 si = vnet_get_sw_interface (vnm, sw_if_index);
1780 si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1782 si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
1787 VLIB_CLI_COMMAND (set_int_proxy_enable_command, static) = {
1788 .path = "set interface proxy-arp",
1789 .short_help = "set interface proxy-arp <intfc> [enable|disable]",
1790 .function = set_int_proxy_arp_command_fn,
1795 * ARP Termination in a L2 Bridge Domain based on an
1796 * IP4 to MAC hash table mac_by_ip4 for each BD.
1799 ARP_TERM_NEXT_L2_OUTPUT,
1804 u32 arp_term_next_node_index[32];
1807 arp_term_l2bd (vlib_main_t * vm,
1808 vlib_node_runtime_t * node,
1809 vlib_frame_t * frame)
1811 l2input_main_t * l2im = &l2input_main;
1812 u32 n_left_from, next_index, * from, * to_next;
1813 u32 n_replies_sent = 0;
1814 u16 last_bd_index = ~0;
1815 l2_bridge_domain_t * last_bd_config = 0;
1816 l2_input_config_t * cfg0;
1818 from = vlib_frame_vector_args (frame);
1819 n_left_from = frame->n_vectors;
1820 next_index = node->cached_next_index;
1822 while (n_left_from > 0)
1826 vlib_get_next_frame (vm, node, next_index,
1827 to_next, n_left_to_next);
1829 while (n_left_from > 0 && n_left_to_next > 0)
1832 ethernet_header_t * eth0;
1833 ethernet_arp_header_t * arp0;
1835 u32 pi0, error0, next0, sw_if_index0;
1846 n_left_to_next -= 1;
1848 p0 = vlib_get_buffer (vm, pi0);
1849 eth0 = vlib_buffer_get_current (p0);
1850 l3h0 = (u8 *)eth0 + vnet_buffer(p0)->l2.l2_len;
1851 ethertype0 = clib_net_to_host_u16(*(u16 *)(l3h0 - 2));
1852 arp0 = (ethernet_arp_header_t *) l3h0;
1854 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
1855 (p0->flags & VLIB_BUFFER_IS_TRACED)))
1857 u8 *t0 = vlib_add_trace (
1858 vm, node, p0, sizeof(ethernet_arp_input_trace_t));
1859 memcpy (t0, l3h0, sizeof(ethernet_arp_input_trace_t));
1863 (ethertype0 != ETHERNET_TYPE_ARP) ||
1864 (arp0->opcode != clib_host_to_net_u16(ETHERNET_ARP_OPCODE_request))))
1865 goto next_l2_feature;
1867 error0 = ETHERNET_ARP_ERROR_replies_sent;
1868 error0 = (arp0->l2_type != clib_net_to_host_u16 (ETHERNET_ARP_HARDWARE_TYPE_ethernet)
1869 ? ETHERNET_ARP_ERROR_l2_type_not_ethernet
1871 error0 = (arp0->l3_type != clib_net_to_host_u16 (ETHERNET_TYPE_IP4)
1872 ? ETHERNET_ARP_ERROR_l3_type_not_ip4
1875 sw_if_index0 = vnet_buffer (p0)->sw_if_index[VLIB_RX];
1880 // Trash ARP packets whose ARP-level source addresses do not
1881 // match their L2-frame-level source addresses */
1883 memcmp (eth0->src_address, arp0->ip4_over_ethernet[0].ethernet,
1884 sizeof (eth0->src_address))))
1886 error0 = ETHERNET_ARP_ERROR_l2_address_mismatch;
1890 // Check if anyone want ARP request events for L2 BDs
1892 pending_resolution_t * mc;
1893 ethernet_arp_main_t * am = ðernet_arp_main;
1894 uword *p = hash_get (am->mac_changes_by_address, 0);
1895 if (p && (vnet_buffer(p0)->l2.shg == 0))
1896 { // Only SHG 0 interface which is more likely local
1897 u32 next_index = p[0];
1898 while (next_index != (u32)~0)
1900 int (*fp)(u32, u8 *, u32, u32);
1902 mc = pool_elt_at_index (am->mac_changes, next_index);
1903 fp = mc->data_callback;
1904 // Call the callback, return 1 to suppress dup events */
1905 if (fp) rv = (*fp)(mc->data,
1906 arp0->ip4_over_ethernet[0].ethernet,
1908 arp0->ip4_over_ethernet[0].ip4.as_u32);
1909 // Signal the resolver process
1911 vlib_process_signal_event (vm, mc->node_index,
1914 next_index = mc->next_index;
1919 // lookup BD mac_by_ip4 hash table for MAC entry
1920 ip0 = arp0->ip4_over_ethernet[1].ip4.as_u32;
1921 bd_index0 = vnet_buffer(p0)->l2.bd_index;
1923 (bd_index0 != last_bd_index) || (last_bd_index == (u16) ~0)))
1925 last_bd_index = bd_index0;
1926 last_bd_config = vec_elt_at_index(l2im->bd_configs, bd_index0);
1928 macp0 = (u8 *) hash_get (last_bd_config->mac_by_ip4, ip0);
1930 if (PREDICT_FALSE(!macp0))
1931 goto next_l2_feature; // MAC not found
1933 // MAC found, send ARP reply -
1934 // Convert ARP request packet to ARP reply
1935 arp0->opcode = clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
1936 arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
1937 arp0->ip4_over_ethernet[0].ip4.as_u32 = ip0;
1938 memcpy (arp0->ip4_over_ethernet[0].ethernet, macp0, 6);
1939 memcpy (eth0->dst_address, eth0->src_address, 6);
1940 memcpy (eth0->src_address, macp0, 6);
1941 n_replies_sent += 1;
1943 // For BVI, need to use l2-fwd node to send ARP reply as
1944 // l2-output node cannot output packet to BVI properly
1945 cfg0 = vec_elt_at_index(l2im->configs, sw_if_index0);
1946 if (PREDICT_FALSE (cfg0->bvi))
1948 vnet_buffer(p0)->l2.feature_bitmap |= L2INPUT_FEAT_FWD;
1949 vnet_buffer (p0)->sw_if_index[VLIB_RX] = 0;
1950 goto next_l2_feature;
1953 // Send ARP reply back out input interface through l2-output
1954 vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
1955 next0 = ARP_TERM_NEXT_L2_OUTPUT;
1956 // Note that output to VXLAN tunnel will fail due to SHG which
1957 // is probably desireable since ARP termination is not intended
1958 // for ARP requests from other hosts. If output to VXLAN tunnel is
1959 // required, however, can just clear the SHG in packet as follows:
1960 // vnet_buffer(p0)->l2.shg = 0;
1962 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1963 n_left_to_next,pi0,next0);
1968 u32 feature_bitmap0 =
1969 vnet_buffer(p0)->l2.feature_bitmap & ~L2INPUT_FEAT_ARP_TERM;
1970 vnet_buffer(p0)->l2.feature_bitmap = feature_bitmap0;
1971 next0 = feat_bitmap_get_next_node_index(arp_term_next_node_index,
1973 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1974 n_left_to_next,pi0,next0);
1979 if (0 == arp0->ip4_over_ethernet[0].ip4.as_u32 ||
1980 (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
1981 arp0->ip4_over_ethernet[1].ip4.as_u32))
1983 error0 = ETHERNET_ARP_ERROR_gratuitous_arp;
1985 next0 = ARP_TERM_NEXT_DROP;
1986 p0->error = node->errors[error0];
1988 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,to_next,
1989 n_left_to_next,pi0,next0);
1992 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1995 vlib_error_count (vm, node->node_index,
1996 ETHERNET_ARP_ERROR_replies_sent,
1998 return frame->n_vectors;
2001 VLIB_REGISTER_NODE (arp_term_l2bd_node,static) = {
2002 .function = arp_term_l2bd,
2003 .name = "arp-term-l2bd",
2004 .vector_size = sizeof (u32),
2006 .n_errors = ETHERNET_ARP_N_ERROR,
2007 .error_strings = ethernet_arp_error_strings,
2009 .n_next_nodes = ARP_TERM_N_NEXT,
2011 [ARP_TERM_NEXT_L2_OUTPUT] = "l2-output",
2012 [ARP_TERM_NEXT_DROP] = "error-drop",
2015 .format_buffer = format_ethernet_arp_header,
2016 .format_trace = format_ethernet_arp_input_trace,
2019 clib_error_t *arp_term_init (vlib_main_t *vm)
2020 { // Initialize the feature next-node indexes
2021 feat_bitmap_init_next_nodes(vm,
2022 arp_term_l2bd_node.index,
2024 l2input_get_feat_names(),
2025 arp_term_next_node_index);
2029 VLIB_INIT_FUNCTION (arp_term_init);