VPP-1574: minimize RPC barrier sync calls 86/17886/2
authorDave Barach <dave@barachs.net>
Tue, 26 Feb 2019 22:04:40 +0000 (17:04 -0500)
committerDave Barach <dave@barachs.net>
Tue, 26 Feb 2019 22:12:29 +0000 (17:12 -0500)
Grab the thread barrier across a set of RPCs, to greatly increase
efficiency. Avoids running afoul of the barrier sync holddown
timer.

Change-Id: I782dfdb1bed398b290169c83266681c9edd57a3f
Signed-off-by: Dave Barach <dave@barachs.net>
src/vlibmemory/memory_api.c
src/vnet/ip/ip6_neighbor.c

index 1727c28..9fc26b9 100644 (file)
@@ -735,11 +735,28 @@ vl_mem_api_handle_rpc (vlib_main_t * vm, vlib_node_runtime_t * node)
   vm->pending_rpc_requests = tmp;
   clib_spinlock_unlock_if_init (&vm->pending_rpc_lock);
 
-  for (i = 0; i < vec_len (vm->processing_rpc_requests); i++)
+  /*
+   * RPCs are used to reflect function calls to thread 0
+   * when the underlying code is not thread-safe.
+   *
+   * Grabbing the thread barrier across a set of RPCs
+   * greatly increases efficiency, and avoids
+   * running afoul of the barrier sync holddown timer.
+   * The barrier sync code supports recursive locking.
+   *
+   * We really need to rewrite RPC-based code...
+   */
+  if (PREDICT_TRUE (vec_len (vm->processing_rpc_requests)))
     {
-      mp = vm->processing_rpc_requests[i];
-      vl_msg_api_handler_with_vm_node (am, (void *) mp, vm, node);
+      vl_msg_api_barrier_sync ();
+      for (i = 0; i < vec_len (vm->processing_rpc_requests); i++)
+       {
+         mp = vm->processing_rpc_requests[i];
+         vl_msg_api_handler_with_vm_node (am, (void *) mp, vm, node);
+       }
+      vl_msg_api_barrier_release ();
     }
+
   return 0;
 }
 
index ded5b86..649f4b7 100755 (executable)
@@ -1021,6 +1021,10 @@ show_ip6_neighbors (vlib_main_t * vm,
   ip6_neighbor_t *n, *ns;
   clib_error_t *error = 0;
   u32 sw_if_index;
+  int verbose = 0;
+
+  if (unformat (input, "verbose"))
+    verbose = 1;
 
   /* Filter entries by interface if given. */
   sw_if_index = ~0;
@@ -1029,13 +1033,29 @@ show_ip6_neighbors (vlib_main_t * vm,
   ns = ip6_neighbors_entries (sw_if_index);
   if (ns)
     {
-      vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, 0);
-      vec_foreach (n, ns)
-      {
-       vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, n);
-      }
+      /*
+       * Show the entire table if it's not too big, otherwise just
+       * show the size of the table.
+       */
+      if (vec_len (ns) < 50)
+       verbose = 1;
+      if (verbose)
+       {
+         vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, 0);
+         vec_foreach (n, ns)
+         {
+           vlib_cli_output (vm, "%U", format_ip6_neighbor_ip6_entry, vm, n);
+         }
+       }
+      else
+       vlib_cli_output
+         (vm, "There are %u ip6 neighbors, "
+          "'show ip6 neighbors verbose' to display the entire table...",
+          vec_len (ns));
       vec_free (ns);
     }
+  else
+    vlib_cli_output (vm, "No ip6 neighbors");
 
   return error;
 }