+
+ ai = adj_glean_get (FIB_PROTOCOL_IP4, sw_if_index);
+
+ if (ADJ_INDEX_INVALID != ai)
+ adj_glean_update_rewrite (ai);
+}
+
+void
+send_ip4_garp (vlib_main_t * vm, u32 sw_if_index)
+{
+ ip4_main_t *i4m = &ip4_main;
+ ip4_address_t *ip4_addr = ip4_interface_first_address (i4m, sw_if_index, 0);
+
+ send_ip4_garp_w_addr (vm, ip4_addr, sw_if_index);
+}
+
+void
+send_ip4_garp_w_addr (vlib_main_t * vm,
+ const ip4_address_t * ip4_addr, u32 sw_if_index)
+{
+ ip4_main_t *i4m = &ip4_main;
+ vnet_main_t *vnm = vnet_get_main ();
+ u8 *rewrite, rewrite_len;
+ vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
+
+ if (ip4_addr)
+ {
+ clib_warning ("Sending GARP for IP4 address %U on sw_if_idex %d",
+ format_ip4_address, ip4_addr, sw_if_index);
+
+ /* Form GARP packet for output - Gratuitous ARP is an ARP request packet
+ where the interface IP/MAC pair is used for both source and request
+ MAC/IP pairs in the request */
+ u32 bi = 0;
+ ethernet_arp_header_t *h = vlib_packet_template_get_packet
+ (vm, &i4m->ip4_arp_request_packet_template, &bi);
+
+ if (!h)
+ return;
+
+ mac_address_from_bytes (&h->ip4_over_ethernet[0].mac, hi->hw_address);
+ mac_address_from_bytes (&h->ip4_over_ethernet[1].mac, hi->hw_address);
+ h->ip4_over_ethernet[0].ip4 = ip4_addr[0];
+ h->ip4_over_ethernet[1].ip4 = ip4_addr[0];
+
+ /* Setup MAC header with ARP Etype and broadcast DMAC */
+ vlib_buffer_t *b = vlib_get_buffer (vm, bi);
+ rewrite =
+ ethernet_build_rewrite (vnm, sw_if_index, VNET_LINK_ARP,
+ VNET_REWRITE_FOR_SW_INTERFACE_ADDRESS_BROADCAST);
+ rewrite_len = vec_len (rewrite);
+ vlib_buffer_advance (b, -rewrite_len);
+ ethernet_header_t *e = vlib_buffer_get_current (b);
+ clib_memcpy_fast (e->dst_address, rewrite, rewrite_len);
+ vec_free (rewrite);
+
+ /* Send GARP packet out the specified interface */
+ vnet_buffer (b)->sw_if_index[VLIB_RX] =
+ vnet_buffer (b)->sw_if_index[VLIB_TX] = sw_if_index;
+ vlib_frame_t *f = vlib_get_frame_to_node (vm, hi->output_node_index);
+ u32 *to_next = vlib_frame_vector_args (f);
+ to_next[0] = bi;
+ f->n_vectors = 1;
+ vlib_put_frame_to_node (vm, hi->output_node_index, f);
+ }
+}
+
+/*
+ * Remove any arp entries associated with the specified interface
+ */
+static clib_error_t *
+vnet_arp_delete_sw_interface (vnet_main_t * vnm, u32 sw_if_index, u32 is_add)
+{
+ ethernet_arp_main_t *am = ðernet_arp_main;
+
+ if (!is_add && sw_if_index != ~0)
+ {
+ ethernet_arp_ip4_entry_t *e;
+ /* *INDENT-OFF* */
+ pool_foreach (e, am->ip4_entry_pool, ({
+ if (e->sw_if_index != sw_if_index)
+ continue;
+ vnet_arp_set_ip4_over_ethernet_rpc_args_t args = {
+ .sw_if_index = sw_if_index,
+ .ip4 = e->ip4_address,
+ };
+ vnet_arp_unset_ip4_over_ethernet_internal (vnm, &args);
+ }));
+ /* *INDENT-ON* */
+ arp_disable (am, sw_if_index);
+ }
+ else if (is_add)
+ {
+ vnet_feature_enable_disable ("arp", "arp-disabled",
+ sw_if_index, 1, NULL, 0);
+ }
+
+ return (NULL);