From fdb47ad887957cf677de39c31a7e9d8656ce61fb Mon Sep 17 00:00:00 2001 From: Matthew Smith Date: Sat, 10 Feb 2018 11:11:45 -0600 Subject: Fix DHCP client crash with worker threads Crash occurring With a worker thread configured and dhcp client active on an interface. When a DHCP reply packet is received, call to ethernet_get_main() from dhcp_proxy_to_client_input() was causing a crash. Replaced with a call to vnet_get_ethernet_main(). Once that was resolved, calling dhcp_client_acquire_address() from a worker thread also caused a crash. Changed so the main thread will do the address/route configuration. Change-Id: Ib23984787102dea8cf6cfcde86188a751f15c1e1 Signed-off-by: Matthew Smith --- src/vnet/dhcp/client.c | 88 ++++++++++++++++++++++++---------------- src/vnet/dhcp/dhcp4_proxy_node.c | 2 +- src/vnet/dhcp/dhcp6_proxy_node.c | 2 +- 3 files changed, 54 insertions(+), 38 deletions(-) diff --git a/src/vnet/dhcp/client.c b/src/vnet/dhcp/client.c index e2cbc3281ca..f8f92a5d9f9 100644 --- a/src/vnet/dhcp/client.c +++ b/src/vnet/dhcp/client.c @@ -139,6 +139,56 @@ dhcp_client_proc_callback (uword * client_index) EVENT_DHCP_CLIENT_WAKEUP, *client_index); } +static void +dhcp_client_addr_callback (dhcp_client_t * c) +{ + dhcp_client_main_t *dcm = &dhcp_client_main; + void (*fp) (u32, u32, u8 *, u8, u8, u8 *, u8 *, u8 *) = c->event_callback; + + /* replace the temporary RX address with the correct subnet */ + dhcp_client_remove_rx_address (dcm, c); + dhcp_client_acquire_address (dcm, c); + + /* + * Configure default IP route: + */ + if (c->router_address.as_u32) + { + fib_prefix_t all_0s = { + .fp_len = 0, + .fp_addr.ip4.as_u32 = 0x0, + .fp_proto = FIB_PROTOCOL_IP4, + }; + ip46_address_t nh = { + .ip4 = c->router_address, + }; + + /* *INDENT-OFF* */ + fib_table_entry_path_add ( + fib_table_get_index_for_sw_if_index ( + FIB_PROTOCOL_IP4, + c->sw_if_index), + &all_0s, + FIB_SOURCE_DHCP, + FIB_ENTRY_FLAG_NONE, + DPO_PROTO_IP4, + &nh, c->sw_if_index, + ~0, 1, NULL, // no label stack + FIB_ROUTE_PATH_FLAG_NONE); + /* *INDENT-ON* */ + } + + /* + * Call the user's event callback to report DHCP information + */ + if (fp) + (*fp) (c->client_index, /* clinet index */ + c->pid, c->hostname, c->subnet_mask_width, 0, /* is_ipv6 */ + (u8 *) & c->leased_address, /* host IP address */ + (u8 *) & c->router_address, /* router IP address */ + (u8 *) (c->l2_rewrite + 6)); /* host MAC address */ +} + /* * dhcp_client_for_us - server-to-client callback. * Called from proxy_node.c:dhcp_proxy_to_client_input(). @@ -286,42 +336,8 @@ dhcp_client_for_us (u32 bi, vlib_buffer_t * b, } /* OK, we own the address (etc), add to the routing table(s) */ if (c->state == DHCP_REQUEST) - { - void (*fp) (u32, u32, u8 *, u8, u8, u8 *, u8 *, u8 *) = - c->event_callback; - - /* replace the temporary RX address with the correct subnet */ - dhcp_client_remove_rx_address (dcm, c); - dhcp_client_acquire_address (dcm, c); - - /* - * Configure default IP route: - */ - if (c->router_address.as_u32) - { - fib_prefix_t all_0s = { - .fp_len = 0, - .fp_addr.ip4.as_u32 = 0x0, - .fp_proto = FIB_PROTOCOL_IP4, - }; - ip46_address_t nh = { - .ip4 = c->router_address, - }; - - fib_table_entry_path_add (fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4, c->sw_if_index), &all_0s, FIB_SOURCE_DHCP, FIB_ENTRY_FLAG_NONE, DPO_PROTO_IP4, &nh, c->sw_if_index, ~0, 1, NULL, // no label stack - FIB_ROUTE_PATH_FLAG_NONE); - } - - /* - * Call the user's event callback to report DHCP information - */ - if (fp) - (*fp) (c->client_index, /* clinet index */ - c->pid, c->hostname, c->subnet_mask_width, 0, /* is_ipv6 */ - (u8 *) & c->leased_address, /* host IP address */ - (u8 *) & c->router_address, /* router IP address */ - (u8 *) (c->l2_rewrite + 6)); /* host MAC address */ - } + vl_api_rpc_call_main_thread (dhcp_client_addr_callback, + (u8 *) c, sizeof (*c)); c->state = DHCP_BOUND; c->retry_count = 0; diff --git a/src/vnet/dhcp/dhcp4_proxy_node.c b/src/vnet/dhcp/dhcp4_proxy_node.c index e84d72c0afb..6b15c51b38f 100644 --- a/src/vnet/dhcp/dhcp4_proxy_node.c +++ b/src/vnet/dhcp/dhcp4_proxy_node.c @@ -477,7 +477,7 @@ dhcp_proxy_to_client_input (vlib_main_t * vm, vlib_frame_t * from_frame) { u32 n_left_from, *from; - ethernet_main_t *em = ethernet_get_main (vm); + ethernet_main_t *em = vnet_get_ethernet_main (); dhcp_proxy_main_t *dpm = &dhcp_proxy_main; vnet_main_t *vnm = vnet_get_main (); ip4_main_t *im = &ip4_main; diff --git a/src/vnet/dhcp/dhcp6_proxy_node.c b/src/vnet/dhcp/dhcp6_proxy_node.c index 5a3a99e2e5d..2a1ac12e535 100644 --- a/src/vnet/dhcp/dhcp6_proxy_node.c +++ b/src/vnet/dhcp/dhcp6_proxy_node.c @@ -563,7 +563,7 @@ dhcpv6_proxy_to_client_input (vlib_main_t * vm, { u32 n_left_from, *from; - ethernet_main_t *em = ethernet_get_main (vm); + ethernet_main_t *em = vnet_get_ethernet_main (); dhcp_proxy_main_t *dm = &dhcp_proxy_main; dhcp_proxy_t *proxy; dhcp_server_t *server; -- cgit 1.2.3-korg