From: Matthew Smith Date: Sat, 10 Feb 2018 17:11:45 +0000 (-0600) Subject: Fix DHCP client crash with worker threads X-Git-Tag: v18.04-rc1~337 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;ds=sidebyside;h=7a1928342109cd05cccf9969e61b5fe8f00a18cf;p=vpp.git 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 --- diff --git a/src/vnet/dhcp/client.c b/src/vnet/dhcp/client.c index 03fc2689abf..511b23cb248 100644 --- a/src/vnet/dhcp/client.c +++ b/src/vnet/dhcp/client.c @@ -66,6 +66,58 @@ 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; + + /* add the advertised subnet and disable the feature */ + dhcp_client_acquire_address (dcm, c); + vnet_feature_enable_disable ("ip4-unicast", + "ip4-dhcp-client-detect", + c->sw_if_index, 0, 0, 0); + + /* + * 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(). @@ -206,55 +258,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; - - /* add the advertised subnet and disable the feature */ - dhcp_client_acquire_address (dcm, c); - vnet_feature_enable_disable ("ip4-unicast", - "ip4-dhcp-client-detect", - c->sw_if_index, 0, 0, 0); - - /* - * 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 */ - } + 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;