summaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/ethernet/arp.c83
-rw-r--r--src/vnet/ethernet/arp_packet.h9
-rw-r--r--src/vnet/ip/ip6.h2
-rw-r--r--src/vnet/ip/ip6_neighbor.c53
4 files changed, 147 insertions, 0 deletions
diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c
index d5dc9cceb39..df68175055e 100644
--- a/src/vnet/ethernet/arp.c
+++ b/src/vnet/ethernet/arp.c
@@ -110,6 +110,9 @@ typedef struct
static const u8 vrrp_prefix[] = { 0x00, 0x00, 0x5E, 0x00, 0x01 };
+/* Node index for send_garp_na_process */
+u32 send_garp_na_process_node_index;
+
static void
set_ip4_over_ethernet_rpc_callback (vnet_arp_set_ip4_over_ethernet_rpc_args_t
* a);
@@ -2378,6 +2381,86 @@ ethernet_arp_change_mac (u32 sw_if_index)
/* *INDENT-ON* */
}
+void static
+send_ip4_garp (vlib_main_t * vm, vnet_hw_interface_t * hi)
+{
+ ip4_main_t *i4m = &ip4_main;
+ u32 sw_if_index = hi->sw_if_index;
+ ip4_address_t *ip4_addr = ip4_interface_first_address (i4m, sw_if_index, 0);
+
+ 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);
+ clib_memcpy (h->ip4_over_ethernet[0].ethernet, hi->hw_address,
+ sizeof (h->ip4_over_ethernet[0].ethernet));
+ clib_memcpy (h->ip4_over_ethernet[1].ethernet, hi->hw_address,
+ sizeof (h->ip4_over_ethernet[1].ethernet));
+ 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);
+ vlib_buffer_advance (b, -sizeof (ethernet_header_t));
+ ethernet_header_t *e = vlib_buffer_get_current (b);
+ e->type = clib_host_to_net_u16 (ETHERNET_TYPE_ARP);
+ clib_memcpy (e->src_address, hi->hw_address, sizeof (e->src_address));
+ memset (e->dst_address, 0xff, sizeof (e->dst_address));
+
+ /* 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);
+ }
+}
+
+static vlib_node_registration_t send_garp_na_proc_node;
+
+static uword
+send_garp_na_process (vlib_main_t * vm,
+ vlib_node_runtime_t * rt, vlib_frame_t * f)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ uword event_type, *event_data = 0;
+
+ send_garp_na_process_node_index = send_garp_na_proc_node.index;
+
+ while (1)
+ {
+ vlib_process_wait_for_event (vm);
+ event_type = vlib_process_get_events (vm, &event_data);
+ if ((event_type == SEND_GARP_NA) && (vec_len (event_data) >= 1))
+ {
+ u32 hw_if_index = event_data[0];
+ vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
+ send_ip4_garp (vm, hi);
+ send_ip6_na (vm, hi);
+ }
+ vec_reset_length (event_data);
+ }
+ return 0;
+}
+
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (send_garp_na_proc_node, static) = {
+ .function = send_garp_na_process,
+ .type = VLIB_NODE_TYPE_PROCESS,
+ .name = "send-garp-na-process",
+};
+/* *INDENT-ON* */
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/vnet/ethernet/arp_packet.h b/src/vnet/ethernet/arp_packet.h
index 17e64f43049..d740b844e12 100644
--- a/src/vnet/ethernet/arp_packet.h
+++ b/src/vnet/ethernet/arp_packet.h
@@ -167,6 +167,15 @@ typedef struct
ethernet_arp_ip4_entry_t *ip4_neighbor_entries (u32 sw_if_index);
u8 *format_ethernet_arp_ip4_entry (u8 * s, va_list * va);
+/* Node index for send_garp_na_process */
+extern u32 send_garp_na_process_node_index;
+
+/* Even type for send_garp_na_process */
+enum
+{
+ SEND_GARP_NA = 1,
+} dpdk_send_garp_na_process_event_t;
+
#endif /* included_ethernet_arp_packet_h */
/*
diff --git a/src/vnet/ip/ip6.h b/src/vnet/ip/ip6.h
index d623c95f52f..cf52994e720 100644
--- a/src/vnet/ip/ip6.h
+++ b/src/vnet/ip/ip6.h
@@ -375,6 +375,8 @@ int vnet_ip6_nd_term (vlib_main_t * vm,
ethernet_header_t * eth,
ip6_header_t * ip, u32 sw_if_index, u16 bd_index);
+void send_ip6_na (vlib_main_t * vm, vnet_hw_interface_t * hi);
+
u8 *format_ip6_forward_next_trace (u8 * s, va_list * args);
u32 ip6_tcp_udp_icmp_validate_checksum (vlib_main_t * vm, vlib_buffer_t * p0);
diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c
index ba7ea143318..b8f6f9b10e7 100644
--- a/src/vnet/ip/ip6_neighbor.c
+++ b/src/vnet/ip/ip6_neighbor.c
@@ -4192,6 +4192,59 @@ ethernet_ndp_change_mac (u32 sw_if_index)
/* *INDENT-ON* */
}
+void
+send_ip6_na (vlib_main_t * vm, vnet_hw_interface_t * hi)
+{
+ ip6_main_t *i6m = &ip6_main;
+ u32 sw_if_index = hi->sw_if_index;
+ ip6_address_t *ip6_addr = ip6_interface_first_address (i6m, sw_if_index);
+ if (ip6_addr)
+ {
+ clib_warning
+ ("Sending unsolicitated NA IP6 address %U on sw_if_idex %d",
+ format_ip6_address, ip6_addr, sw_if_index);
+
+ /* Form unsolicited neighbor advertisement packet from NS pkt template */
+ int bogus_length;
+ u32 bi = 0;
+ icmp6_neighbor_solicitation_header_t *h =
+ vlib_packet_template_get_packet (vm,
+ &i6m->discover_neighbor_packet_template,
+ &bi);
+ ip6_set_reserved_multicast_address (&h->ip.dst_address,
+ IP6_MULTICAST_SCOPE_link_local,
+ IP6_MULTICAST_GROUP_ID_all_hosts);
+ h->ip.src_address = ip6_addr[0];
+ h->neighbor.icmp.type = ICMP6_neighbor_advertisement;
+ h->neighbor.target_address = ip6_addr[0];
+ h->neighbor.advertisement_flags = clib_host_to_net_u32
+ (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE);
+ clib_memcpy (h->link_layer_option.ethernet_address,
+ hi->hw_address, vec_len (hi->hw_address));
+ h->neighbor.icmp.checksum =
+ ip6_tcp_udp_icmp_compute_checksum (vm, 0, &h->ip, &bogus_length);
+ ASSERT (bogus_length == 0);
+
+ /* Setup MAC header with IP6 Etype and mcast DMAC */
+ vlib_buffer_t *b = vlib_get_buffer (vm, bi);
+ vlib_buffer_advance (b, -sizeof (ethernet_header_t));
+ ethernet_header_t *e = vlib_buffer_get_current (b);
+ e->type = clib_host_to_net_u16 (ETHERNET_TYPE_IP6);
+ clib_memcpy (e->src_address, hi->hw_address, sizeof (e->src_address));
+ ip6_multicast_ethernet_address (e->dst_address,
+ IP6_MULTICAST_GROUP_ID_all_hosts);
+
+ /* Send unsolicited ND advertisement 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);
+ }
+}
+
/*
* fd.io coding-style-patch-verification: ON
*