Fix DHCP client crash with worker threads 89/10489/2
authorMatthew Smith <mgsmith@netgate.com>
Sat, 10 Feb 2018 17:11:45 +0000 (11:11 -0600)
committerDave Barach <openvpp@barachs.net>
Mon, 12 Feb 2018 19:34:17 +0000 (19:34 +0000)
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 <mgsmith@netgate.com>
src/vnet/dhcp/client.c
src/vnet/dhcp/dhcp4_proxy_node.c
src/vnet/dhcp/dhcp6_proxy_node.c

index 03fc268..511b23c 100644 (file)
@@ -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;
index e84d72c..6b15c51 100644 (file)
@@ -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;
index 5a3a99e..2a1ac12 100644 (file)
@@ -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;